about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml3
-rw-r--r--Cargo.lock86
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs11
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs121
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs31
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs7
-rw-r--r--compiler/rustc_borrowck/src/lib.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/example/example.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs3
-rw-r--r--compiler/rustc_codegen_gcc/example/example.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs40
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs17
-rw-r--r--compiler/rustc_hir/src/hir.rs159
-rw-r--r--compiler/rustc_hir/src/hir/tests.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs60
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs53
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs67
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs53
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs6
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs5
-rw-r--r--compiler/rustc_lint/src/shadowed_into_iter.rs4
-rw-r--r--compiler/rustc_lint/src/types.rs12
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs94
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp30
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs9
-rw-r--r--compiler/rustc_macros/src/hash_stable.rs2
-rw-r--r--compiler/rustc_macros/src/lift.rs1
-rw-r--r--compiler/rustc_macros/src/serialize.rs12
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs2
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs2
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs18
-rw-r--r--compiler/rustc_middle/src/query/mod.rs9
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs23
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs23
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs14
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs15
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs63
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/results.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/visitor.rs12
-rw-r--r--compiler/rustc_mir_dataflow/src/points.rs6
-rw-r--r--compiler/rustc_mir_transform/messages.ftl1
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs32
-rw-r--r--compiler/rustc_mir_transform/src/check_call_recursion.rs4
-rw-r--r--compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs100
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs6
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs8
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs20
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs6
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs40
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs46
-rw-r--r--compiler/rustc_parse/messages.ftl5
-rw-r--r--compiler/rustc_parse/src/errors.rs7
-rw-r--r--compiler/rustc_parse/src/lexer/diagnostics.rs28
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs7
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs45
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs26
-rw-r--r--compiler/rustc_parse/src/parser/item.rs11
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs26
-rw-r--r--compiler/rustc_parse/src/parser/path.rs20
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_smir/src/lib.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs35
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs269
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs2
-rw-r--r--compiler/rustc_smir/src/stable_mir/compiler_interface.rs428
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs23
-rw-r--r--compiler/rustc_target/src/target_features.rs12
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs10
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs7
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs27
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs117
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs16
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs104
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs240
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs79
-rw-r--r--compiler/rustc_transmute/Cargo.toml7
-rw-r--r--compiler/rustc_transmute/src/layout/dfa.rs433
-rw-r--r--compiler/rustc_transmute/src/layout/mod.rs72
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs8
-rw-r--r--compiler/rustc_transmute/src/lib.rs3
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/mod.rs218
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/query_context.rs14
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/tests.rs183
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs3
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/stalled_generators.rs54
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs22
-rw-r--r--compiler/rustc_type_ir/src/interner.rs8
-rw-r--r--library/Cargo.lock4
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/collections/btree/set.rs2
-rw-r--r--library/alloctests/tests/fmt.rs1
-rw-r--r--library/core/src/cell.rs4
-rw-r--r--library/core/src/char/convert.rs2
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/num/f128.rs26
-rw-r--r--library/core/src/num/f16.rs26
-rw-r--r--library/core/src/num/f32.rs29
-rw-r--r--library/core/src/num/f64.rs29
-rw-r--r--library/core/src/num/int_macros.rs2
-rw-r--r--library/core/src/num/mod.rs18
-rw-r--r--library/core/src/num/nonzero.rs4
-rw-r--r--library/core/src/num/uint_macros.rs2
-rw-r--r--library/coretests/tests/lib.rs1
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/collections/hash/map.rs3
-rw-r--r--library/std/src/os/unix/fs.rs36
-rw-r--r--library/std/src/os/unix/fs/tests.rs20
-rw-r--r--library/std/src/path.rs24
-rw-r--r--library/std/src/sys/env_consts.rs11
-rw-r--r--library/std/src/sys/fs/mod.rs2
-rw-r--r--library/std/src/sys/fs/unix.rs6
-rw-r--r--library/std/src/sys/pal/zkvm/env.rs9
-rw-r--r--library/std/src/sys/process/unix/unix.rs8
-rw-r--r--library/std/tests/floats/f128.rs2
-rw-r--r--library/std/tests/floats/f16.rs2
-rw-r--r--library/std/tests/floats/f32.rs2
-rw-r--r--library/std/tests/floats/f64.rs2
m---------library/stdarch0
-rw-r--r--src/bootstrap/Cargo.lock93
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs77
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs25
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs3
-rw-r--r--src/bootstrap/src/core/builder/tests.rs103
-rw-r--r--src/bootstrap/src/core/config/config.rs124
-rw-r--r--src/bootstrap/src/core/config/tests.rs245
-rw-r--r--src/bootstrap/src/core/download.rs20
-rw-r--r--src/bootstrap/src/utils/mod.rs2
-rw-r--r--src/bootstrap/src/utils/proc_macro_deps.rs4
-rw-r--r--src/bootstrap/src/utils/tests/git.rs152
-rw-r--r--src/bootstrap/src/utils/tests/mod.rs1
-rw-r--r--src/build_helper/src/git.rs312
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile3
-rwxr-xr-xsrc/ci/docker/scripts/add_dummy_commit.sh19
-rwxr-xr-xsrc/ci/docker/scripts/x86_64-gnu-llvm3.sh2
-rw-r--r--src/ci/github-actions/jobs.yml2
-rwxr-xr-xsrc/ci/scripts/setup-upstream-remote.sh24
m---------src/doc/nomicon0
m---------src/doc/reference0
-rw-r--r--src/doc/rustc-dev-guide/src/tests/minicore.md26
-rw-r--r--src/doc/rustc/src/platform-support.md12
-rw-r--r--src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md5
-rw-r--r--src/doc/unstable-book/src/language-features/deref-patterns.md21
-rw-r--r--src/tools/clippy/.github/workflows/clippy_changelog.yml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_mq.yml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_pr.yml2
-rw-r--r--src/tools/clippy/.github/workflows/deploy.yml4
-rw-r--r--src/tools/clippy/.github/workflows/lintcheck.yml4
-rw-r--r--src/tools/clippy/CHANGELOG.md70
-rw-r--r--src/tools/clippy/Cargo.toml9
-rw-r--r--src/tools/clippy/askama.toml (renamed from src/tools/clippy/rinja.toml)0
-rw-r--r--src/tools/clippy/book/src/SUMMARY.md1
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md22
-rw-r--r--src/tools/clippy/book/src/development/basics.md2
-rw-r--r--src/tools/clippy/book/src/development/common_tools_writing_lints.md10
-rw-r--r--src/tools/clippy/book/src/development/defining_lints.md3
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/benchmarking.md55
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/release.md3
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/sync.md2
-rw-r--r--src/tools/clippy/book/src/development/writing_tests.md38
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md56
-rw-r--r--src/tools/clippy/clippy.toml7
-rw-r--r--src/tools/clippy/clippy_config/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs206
-rw-r--r--src/tools/clippy/clippy_config/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_config/src/types.rs114
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs3
-rw-r--r--src/tools/clippy/clippy_dev/src/setup/toolchain.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/sync.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs171
-rw-r--r--src/tools/clippy/clippy_dev/src/utils.rs8
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml9
-rw-r--r--src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs81
-rw-r--r--src/tools/clippy/clippy_lints/src/as_conversions.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/assigning_clones.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs86
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs130
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs82
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_if.rs221
-rw-r--r--src/tools/clippy/clippy_lints/src/comparison_chain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs105
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_methods.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_types.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/markdown.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs136
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_line_after.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_with_brackets.rs233
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/fallible_impl_from.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs170
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/int_plus_one.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs84
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs116
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs85
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_string_with_formatting_args.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs141
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs74
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs137
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs269
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_abs_diff.rs152
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_div_ceil.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs192
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rotate.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_string_new.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs212
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_filter.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs294
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/needless_match.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/wild_in_or_pats.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs76
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs97
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_empty.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_filter.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs94
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs49
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs125
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs99
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/builtin_type_shadow.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/redundant_pattern.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mut.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs71
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_update.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/non_canonical_impls.rs112
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/identity_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/modulo_one.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/op_ref.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_to_none.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs75
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_async_block.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs161
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/serde_api.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/unicode.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs58
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs241
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs74
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs49
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/zombie_processes.rs2
-rw-r--r--src/tools/clippy/clippy_lints_internal/Cargo.toml14
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs)12
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/collapsible_calls.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs)10
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/interning_literals.rs102
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/invalid_paths.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs)40
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/lib.rs74
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs)51
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs)11
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/outer_expn_data_pass.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs)10
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/produce_ice.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs)12
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/unnecessary_def_path.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs)18
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs54
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/README.md2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs28
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs26
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs20
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs17
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs266
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs233
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs13
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs44
-rw-r--r--src/tools/clippy/clippy_utils/src/str_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs17
-rw-r--r--src/tools/clippy/clippy_utils/src/sym.rs54
-rw-r--r--src/tools/clippy/clippy_utils/src/sym_helper.rs7
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/mod.rs78
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs8
-rw-r--r--src/tools/clippy/lintcheck/ci-config/clippy.toml7
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs41
-rw-r--r--src/tools/clippy/lintcheck/src/recursive.rs2
-rw-r--r--src/tools/clippy/rust-toolchain.toml (renamed from src/tools/clippy/rust-toolchain)2
-rw-r--r--src/tools/clippy/rustc_tools_util/src/lib.rs2
-rw-r--r--src/tools/clippy/src/driver.rs32
-rw-r--r--src/tools/clippy/tests/clippy.toml1
-rw-r--r--src/tools/clippy/tests/compile-test.rs26
-rw-r--r--src/tools/clippy/tests/dogfood.rs7
-rw-r--r--src/tools/clippy/tests/ui-internal/auxiliary/paths.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs13
-rw-r--r--src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr13
-rw-r--r--src/tools/clippy/tests/ui-internal/check_formulation.rs3
-rw-r--r--src/tools/clippy/tests/ui-internal/check_formulation.stderr11
-rw-r--r--src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr5
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr2
-rw-r--r--src/tools/clippy/tests/ui-internal/default_lint.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/default_lint.stderr5
-rw-r--r--src/tools/clippy/tests/ui-internal/disallow_span_lint.rs1
-rw-r--r--src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr11
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed40
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs40
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr33
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_literals.fixed31
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_literals.rs31
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_literals.stderr64
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_literals_unfixable.rs16
-rw-r--r--src/tools/clippy/tests/ui-internal/interning_literals_unfixable.stderr40
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr5
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_paths.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_paths.stderr7
-rw-r--r--src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr5
-rw-r--r--src/tools/clippy/tests/ui-internal/outer_expn_data.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/outer_expn_data.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/outer_expn_data.stderr5
-rw-r--r--src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed24
-rw-r--r--src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs24
-rw-r--r--src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr23
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr5
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr7
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed26
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs26
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr39
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr12
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr30
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs8
-rw-r--r--src/tools/clippy/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr9
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.fixed34
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.rs38
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.stderr80
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed25
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs28
-rw-r--r--src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr64
-rw-r--r--src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs16
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed1
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_invalid_path/clippy.toml14
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs5
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr23
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr15
-rw-r--r--src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed2
-rw-r--r--src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr6
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax_not_x86.rs8
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax_x86.rs36
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax_x86.stderr36
-rw-r--r--src/tools/clippy/tests/ui/author/if.rs2
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_closure.rs2
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_loop.rs1
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macros.rs12
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.fixed23
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.rs23
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.stderr27
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions_2021.fixed25
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions_2021.rs25
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr23
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.fixed24
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.rs24
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.stderr18
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.fixed18
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.rs18
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.stderr35
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.fixed43
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.rs43
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.stderr8
-rw-r--r--src/tools/clippy/tests/ui/box_collection.rs1
-rw-r--r--src/tools/clippy/tests/ui/box_collection.stderr18
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed21
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs7
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr40
-rw-r--r--src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed65
-rw-r--r--src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs65
-rw-r--r--src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr130
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr3
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed9
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs9
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr14
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity.rs28
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity.stderr58
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed112
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs62
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr109
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if_let_chains.fixed29
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if_let_chains.rs32
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if_let_chains.stderr58
-rw-r--r--src/tools/clippy/tests/ui/collapsible_match.rs12
-rw-r--r--src/tools/clippy/tests/ui/crashes/enum-glob-import-crate.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-11230.fixed4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-11230.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-11230.stderr11
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-13544-original.rs45
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-13544-reduced.rs16
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1588.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1782.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1969.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3462.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-700.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7012.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7423.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice_exact_size.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_borrow_fp.rs1
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed1
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs1
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr5
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed7
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs7
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr38
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed14
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.rs14
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr50
-rw-r--r--src/tools/clippy/tests/ui/deprecated.rs1
-rw-r--r--src/tools/clippy/tests/ui/deprecated.stderr8
-rw-r--r--src/tools/clippy/tests/ui/derive.rs17
-rw-r--r--src/tools/clippy/tests/ui/derive.stderr20
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed3
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs3
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.stderr68
-rw-r--r--src/tools/clippy/tests/ui/doc_unsafe.rs2
-rw-r--r--src/tools/clippy/tests/ui/double_ended_iterator_last.fixed32
-rw-r--r--src/tools/clippy/tests/ui/double_ended_iterator_last.rs28
-rw-r--r--src/tools/clippy/tests/ui/double_ended_iterator_last.stderr52
-rw-r--r--src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs5
-rw-r--r--src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.fixed6
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.rs6
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.stderr16
-rw-r--r--src/tools/clippy/tests/ui/empty_docs.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed78
-rw-r--r--src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs78
-rw-r--r--src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr62
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed5
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed6
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs6
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr28
-rw-r--r--src/tools/clippy/tests/ui/entry.fixed22
-rw-r--r--src/tools/clippy/tests/ui/entry.rs22
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.rs2
-rw-r--r--src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.rs63
-rw-r--r--src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.stderr65
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next.rs2
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.fixed3
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.rs3
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.stderr4
-rw-r--r--src/tools/clippy/tests/ui/find_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/fn_params_excessive_bools.rs10
-rw-r--r--src/tools/clippy/tests/ui/formatting.rs3
-rw-r--r--src/tools/clippy/tests/ui/formatting.stderr15
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed43
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs43
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr56
-rw-r--r--src/tools/clippy/tests/ui/functions.rs2
-rw-r--r--src/tools/clippy/tests/ui/functions.stderr35
-rw-r--r--src/tools/clippy/tests/ui/if_not_else.fixed1
-rw-r--r--src/tools/clippy/tests/ui/if_not_else.rs1
-rw-r--r--src/tools/clippy/tests/ui/if_not_else.stderr12
-rw-r--r--src/tools/clippy/tests/ui/ignore_without_reason.rs14
-rw-r--r--src/tools/clippy/tests/ui/ignore_without_reason.stderr12
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.fixed43
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.rs43
-rw-r--r--src/tools/clippy/tests/ui/implicit_return.stderr90
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed1
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/root_module.rs1
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr2
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.fixed27
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.rs27
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.stderr8
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.fixed15
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.rs15
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.stderr8
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.stderr6
-rw-r--r--src/tools/clippy/tests/ui/large_futures.fixed9
-rw-r--r--src/tools/clippy/tests/ui/large_futures.rs9
-rw-r--r--src/tools/clippy/tests/ui/large_futures.stderr16
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty_expect.rs28
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty_expect.stderr11
-rw-r--r--src/tools/clippy/tests/ui/manual_abs_diff.fixed106
-rw-r--r--src/tools/clippy/tests/ui/manual_abs_diff.rs116
-rw-r--r--src/tools/clippy/tests/ui/manual_abs_diff.stderr83
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.fixed6
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.rs6
-rw-r--r--src/tools/clippy/tests/ui/manual_dangling_ptr.fixed44
-rw-r--r--src/tools/clippy/tests/ui/manual_dangling_ptr.rs44
-rw-r--r--src/tools/clippy/tests/ui/manual_dangling_ptr.stderr65
-rw-r--r--src/tools/clippy/tests/ui/manual_find.rs28
-rw-r--r--src/tools/clippy/tests/ui/manual_ignore_case_cmp.fixed10
-rw-r--r--src/tools/clippy/tests/ui/manual_ignore_case_cmp.rs10
-rw-r--r--src/tools/clippy/tests/ui/manual_ignore_case_cmp.stderr105
-rw-r--r--src/tools/clippy/tests/ui/manual_inspect.fixed13
-rw-r--r--src/tools/clippy/tests/ui/manual_inspect.rs11
-rw-r--r--src/tools/clippy/tests/ui/manual_inspect.stderr17
-rw-r--r--src/tools/clippy/tests/ui/manual_is_power_of_two.fixed34
-rw-r--r--src/tools/clippy/tests/ui/manual_is_power_of_two.rs34
-rw-r--r--src/tools/clippy/tests/ui/manual_is_power_of_two.stderr32
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.fixed6
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.rs6
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_err.fixed5
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_err.rs5
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_err.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.fixed10
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.rs10
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.stderr16
-rw-r--r--src/tools/clippy/tests/ui/manual_strip_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_strip_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_strip_fixable.stderr8
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.fixed30
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.rs15
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.stderr39
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed17
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.rs28
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr27
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed13
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.rs13
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr18
-rw-r--r--src/tools/clippy/tests/ui/match_on_vec_items.rs161
-rw-r--r--src/tools/clippy/tests/ui/match_on_vec_items.stderr53
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.fixed17
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.rs20
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.stderr44
-rw-r--r--src/tools/clippy/tests/ui/methods.rs4
-rw-r--r--src/tools/clippy/tests/ui/methods.stderr4
-rw-r--r--src/tools/clippy/tests/ui/min_max.rs1
-rw-r--r--src/tools/clippy/tests/ui/min_max.stderr29
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters.fixed24
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters.rs24
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters.stderr32
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters_2021.fixed24
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters_2021.rs24
-rw-r--r--src/tools/clippy/tests/ui/misnamed_getters_2021.stderr16
-rw-r--r--src/tools/clippy/tests/ui/missing_asserts_for_indexing.fixed27
-rw-r--r--src/tools/clippy/tests/ui/missing_asserts_for_indexing.rs27
-rw-r--r--src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr54
-rw-r--r--src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs13
-rw-r--r--src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr45
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed4
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs4
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr6
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.rs39
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.stderr62
-rw-r--r--src/tools/clippy/tests/ui/missing_transmute_annotations.fixed50
-rw-r--r--src/tools/clippy/tests/ui/missing_transmute_annotations.rs50
-rw-r--r--src/tools/clippy/tests/ui/missing_transmute_annotations.stderr56
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed8
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs8
-rw-r--r--src/tools/clippy/tests/ui/mut_from_ref.rs34
-rw-r--r--src/tools/clippy/tests/ui/mut_from_ref.stderr50
-rw-r--r--src/tools/clippy/tests/ui/mutex_atomic.rs1
-rw-r--r--src/tools/clippy/tests/ui/mutex_atomic.stderr22
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.fixed84
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.rs84
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs5
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr68
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut_2021.rs12
-rw-r--r--src/tools/clippy/tests/ui/neg_multiply.fixed29
-rw-r--r--src/tools/clippy/tests/ui/neg_multiply.rs29
-rw-r--r--src/tools/clippy/tests/ui/neg_multiply.stderr50
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs2
-rw-r--r--src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed33
-rw-r--r--src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs35
-rw-r--r--src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.stderr15
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names.rs3
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names.stderr12
-rw-r--r--src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs4
-rw-r--r--src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed14
-rw-r--r--src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs14
-rw-r--r--src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr14
-rw-r--r--src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs12
-rw-r--r--src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr12
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.rs20
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.stderr10
-rw-r--r--src/tools/clippy/tests/ui/obfuscated_if_else.fixed12
-rw-r--r--src/tools/clippy/tests/ui/obfuscated_if_else.rs12
-rw-r--r--src/tools/clippy/tests/ui/obfuscated_if_else.stderr42
-rw-r--r--src/tools/clippy/tests/ui/op_ref.fixed12
-rw-r--r--src/tools/clippy/tests/ui/op_ref.rs12
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed14
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs14
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed18
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs18
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr40
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.rs2
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.rs1
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr6
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.rs1
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr16
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.rs1
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr20
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.rs7
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr18
-rw-r--r--src/tools/clippy/tests/ui/patterns.fixed2
-rw-r--r--src/tools/clippy/tests/ui/patterns.rs2
-rw-r--r--src/tools/clippy/tests/ui/patterns.stderr6
-rw-r--r--src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs38
-rw-r--r--src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr22
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.fixed18
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.rs18
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.stderr42
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.fixed7
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.rs7
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.stderr26
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed8
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs10
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr68
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation.stderr40
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed4
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation_fixable.rs4
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed32
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.rs32
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed3
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs3
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr40
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed4
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs4
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr62
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr40
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed3
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs3
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr56
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.fixed8
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.rs8
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.stderr18
-rw-r--r--src/tools/clippy/tests/ui/redundant_test_prefix.fixed158
-rw-r--r--src/tools/clippy/tests/ui/redundant_test_prefix.rs158
-rw-r--r--src/tools/clippy/tests/ui/redundant_test_prefix.stderr119
-rw-r--r--src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.rs288
-rw-r--r--src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.stderr241
-rw-r--r--src/tools/clippy/tests/ui/ref_option/ref_option_traits.all.stderr8
-rw-r--r--src/tools/clippy/tests/ui/ref_option/ref_option_traits.private.stderr4
-rw-r--r--src/tools/clippy/tests/ui/ref_option/ref_option_traits.rs1
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed15
-rw-r--r--src/tools/clippy/tests/ui/rename.rs15
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr152
-rw-r--r--src/tools/clippy/tests/ui/repr_packed_without_abi.stderr4
-rw-r--r--src/tools/clippy/tests/ui/result_unit_error_no_std.rs2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed7
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.rs9
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr56
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.fixed14
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.rs16
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.stderr35
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed7
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.rs9
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr35
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.fixed11
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.rs11
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.stderr17
-rw-r--r--src/tools/clippy/tests/ui/shadow.rs15
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs1
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs1
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr30
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs1
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr30
-rw-r--r--src/tools/clippy/tests/ui/single_call_fn.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_match.fixed36
-rw-r--r--src/tools/clippy/tests/ui/single_match.rs42
-rw-r--r--src/tools/clippy/tests/ui/single_match.stderr20
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.fixed4
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.rs4
-rw-r--r--src/tools/clippy/tests/ui/swap.fixed5
-rw-r--r--src/tools/clippy/tests/ui/swap.rs5
-rw-r--r--src/tools/clippy/tests/ui/swap.stderr37
-rw-r--r--src/tools/clippy/tests/ui/swap_with_temporary.fixed74
-rw-r--r--src/tools/clippy/tests/ui/swap_with_temporary.rs74
-rw-r--r--src/tools/clippy/tests/ui/swap_with_temporary.stderr100
-rw-r--r--src/tools/clippy/tests/ui/swap_with_temporary_unfixable.rs62
-rw-r--r--src/tools/clippy/tests/ui/swap_with_temporary_unfixable.stderr125
-rw-r--r--src/tools/clippy/tests/ui/transmute.rs31
-rw-r--r--src/tools/clippy/tests/ui/transmute.stderr120
-rw-r--r--src/tools/clippy/tests/ui/transmute_float_to_int.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_float_to_int.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_null_to_fn.rs1
-rw-r--r--src/tools/clippy/tests/ui/transmute_null_to_fn.stderr12
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed4
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs4
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed104
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs104
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr120
-rw-r--r--src/tools/clippy/tests/ui/transmuting_null.rs1
-rw-r--r--src/tools/clippy/tests/ui/transmuting_null.stderr6
-rw-r--r--src/tools/clippy/tests/ui/type_complexity.rs3
-rw-r--r--src/tools/clippy/tests/ui/type_complexity.stderr30
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.rs12
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.stderr49
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast_unfixable.rs6
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast_unfixable.stderr6
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_filter_map.rs7
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_filter_map.stderr53
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_find_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_find_map.stderr30
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.fixed7
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.rs7
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.stderr40
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.rs1
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.stderr12
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs1
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.stderr18
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.fixed7
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.rs7
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.stderr174
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.fixed13
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.rs13
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.stderr38
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or.rs2
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_items.rs2
-rw-r--r--src/tools/clippy/triagebot.toml24
-rw-r--r--src/tools/compiletest/src/common.rs11
-rw-r--r--src/tools/compiletest/src/executor.rs8
-rw-r--r--src/tools/compiletest/src/executor/deadline.rs60
-rw-r--r--src/tools/compiletest/src/lib.rs9
-rw-r--r--src/tools/compiletest/src/runtest.rs8
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_bool.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_bool_op.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_char.rs1
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_char_op.rs1
-rw-r--r--src/tools/miri/tests/pass/float.rs1
-rw-r--r--src/tools/miri/tests/pass/fn_align.rs21
-rw-r--r--src/tools/miri/tests/pass/issues/issue-miri-184.rs1
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs2
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs1
-rw-r--r--tests/assembly/simd-bitmask.rs7
-rw-r--r--tests/assembly/simd-intrinsic-select.rs7
-rw-r--r--tests/assembly/x86-return-float.rs10
-rw-r--r--tests/codegen/align-struct.rs4
-rw-r--r--tests/codegen/autodiff/identical_fnc.rs45
-rw-r--r--tests/codegen/const-vector.rs25
-rw-r--r--tests/codegen/issues/issue-56927.rs3
-rw-r--r--tests/codegen/regparm-inreg.rs2
-rw-r--r--tests/codegen/repr/transparent.rs5
-rw-r--r--tests/codegen/simd/extract-insert-dyn.rs26
-rw-r--r--tests/pretty/autodiff/autodiff_forward.pp (renamed from tests/pretty/autodiff_forward.pp)0
-rw-r--r--tests/pretty/autodiff/autodiff_forward.rs (renamed from tests/pretty/autodiff_forward.rs)0
-rw-r--r--tests/pretty/autodiff/autodiff_reverse.pp (renamed from tests/pretty/autodiff_reverse.pp)0
-rw-r--r--tests/pretty/autodiff/autodiff_reverse.rs (renamed from tests/pretty/autodiff_reverse.rs)0
-rw-r--r--tests/pretty/autodiff/inherent_impl.pp41
-rw-r--r--tests/pretty/autodiff/inherent_impl.rs24
-rw-r--r--tests/run-make/simd-ffi/rmake.rs11
-rw-r--r--tests/ui-fulldeps/stable-mir/check_abi.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_allocation.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_assoc_items.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_attribute.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_binop.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_crate_defs.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_def_ty.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_defs.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_foreign.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_instance.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_intrinsics.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_item_kind.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_normalization.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_trait_queries.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_transform.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_ty_fold.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/compilation-result.rs26
-rw-r--r--tests/ui-fulldeps/stable-mir/crate-info.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/projections.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_internal.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_serde.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/smir_visitor.rs4
-rw-r--r--tests/ui/abi/simd-abi-checks-avx.rs36
-rw-r--r--tests/ui/abi/simd-abi-checks-avx.stderr203
-rw-r--r--tests/ui/abi/simd-abi-checks-empty-list.rs8
-rw-r--r--tests/ui/abi/simd-abi-checks-empty-list.stderr21
-rw-r--r--tests/ui/abi/simd-abi-checks-s390x.rs11
-rw-r--r--tests/ui/abi/simd-abi-checks-s390x.z10.stderr209
-rw-r--r--tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr209
-rw-r--r--tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr209
-rw-r--r--tests/ui/abi/simd-abi-checks-sse.rs6
-rw-r--r--tests/ui/abi/simd-abi-checks-sse.stderr21
-rw-r--r--tests/ui/async-await/async-closures/is-not-fn.next.stderr6
-rw-r--r--tests/ui/async-await/async-closures/is-not-fn.rs3
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.rs2
-rw-r--r--tests/ui/consts/const-eval/transmute-const-promotion.rs1
-rw-r--r--tests/ui/consts/const-eval/transmute-const-promotion.stderr2
-rw-r--r--tests/ui/consts/const-eval/transmute-const.rs1
-rw-r--r--tests/ui/consts/const-eval/transmute-const.stderr2
-rw-r--r--tests/ui/consts/const-eval/ub-enum.rs2
-rw-r--r--tests/ui/consts/const-eval/ub-wide-ptr.rs2
-rw-r--r--tests/ui/consts/extra-const-ub/detect-extra-ub.rs1
-rw-r--r--tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr16
-rw-r--r--tests/ui/consts/issue-69532.rs4
-rw-r--r--tests/ui/coroutine/clone-rpit.next.stderr47
-rw-r--r--tests/ui/coroutine/clone-rpit.rs3
-rw-r--r--tests/ui/generics/single-colon-path-not-const-generics.stderr4
-rw-r--r--tests/ui/issues/issue-25746-bool-transmute.rs1
-rw-r--r--tests/ui/lint/invalid_null_args.rs12
-rw-r--r--tests/ui/lint/invalid_null_args.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-enum.rs18
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr88
-rw-r--r--tests/ui/lint/wasm_c_abi_transition.rs12
-rw-r--r--tests/ui/lint/wasm_c_abi_transition.stderr31
-rw-r--r--tests/ui/macros/reparse-expr-issue-139495.rs14
-rw-r--r--tests/ui/macros/reparse-expr-issue-139495.stderr25
-rw-r--r--tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs22
-rw-r--r--tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr53
-rw-r--r--tests/ui/parser/expr-rarrow-call.fixed10
-rw-r--r--tests/ui/parser/expr-rarrow-call.rs10
-rw-r--r--tests/ui/parser/expr-rarrow-call.stderr20
-rw-r--r--tests/ui/parser/issues/issue-118530-ice.rs2
-rw-r--r--tests/ui/parser/issues/issue-118530-ice.stderr4
-rw-r--r--tests/ui/parser/ty-path-followed-by-single-colon.rs22
-rw-r--r--tests/ui/pattern/byte-string-mutability-mismatch.rs19
-rw-r--r--tests/ui/pattern/byte-string-mutability-mismatch.stderr25
-rw-r--r--tests/ui/pattern/deref-patterns/byte-string-type-errors.rs34
-rw-r--r--tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr52
-rw-r--r--tests/ui/pattern/deref-patterns/needs-gate.rs17
-rw-r--r--tests/ui/pattern/deref-patterns/needs-gate.stderr26
-rw-r--r--tests/ui/pattern/deref-patterns/strings.rs66
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.rs8
-rw-r--r--tests/ui/pattern/deref-patterns/typeck_fail.stderr26
-rw-r--r--tests/ui/suggestions/argument-list-from-path-sep-error-129273.fixed15
-rw-r--r--tests/ui/suggestions/argument-list-from-path-sep-error-129273.rs15
-rw-r--r--tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr13
-rw-r--r--tests/ui/suggestions/raw-c-string-prefix.rs10
-rw-r--r--tests/ui/suggestions/raw-c-string-prefix.stderr21
-rw-r--r--tests/ui/suggestions/struct-field-type-including-single-colon.rs8
-rw-r--r--tests/ui/suggestions/struct-field-type-including-single-colon.stderr45
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.fixed85
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.rs85
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.stderr235
-rw-r--r--triagebot.toml14
1047 files changed, 19091 insertions, 9860 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2e83bbf643f..efe4157aae2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -125,9 +125,6 @@ jobs:
           # which then uses log commands to actually set them.
           EXTRA_VARIABLES: ${{ toJson(matrix.env) }}
 
-      - name: setup upstream remote
-        run: src/ci/scripts/setup-upstream-remote.sh
-
       - name: ensure the channel matches the target branch
         run: src/ci/scripts/verify-channel.sh
 
diff --git a/Cargo.lock b/Cargo.lock
index 49c1eb5b45f..cfdd873e80f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -546,12 +546,14 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
 
 [[package]]
 name = "clippy"
-version = "0.1.87"
+version = "0.1.88"
 dependencies = [
  "anstream",
+ "askama",
  "cargo_metadata 0.18.1",
  "clippy_config",
  "clippy_lints",
+ "clippy_lints_internal",
  "clippy_utils",
  "color-print",
  "filetime",
@@ -562,7 +564,6 @@ dependencies = [
  "pulldown-cmark 0.11.3",
  "quote",
  "regex",
- "rinja",
  "rustc_tools_util 0.4.2",
  "serde",
  "serde_json",
@@ -577,7 +578,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_config"
-version = "0.1.87"
+version = "0.1.88"
 dependencies = [
  "clippy_utils",
  "itertools",
@@ -602,7 +603,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.87"
+version = "0.1.88"
 dependencies = [
  "arrayvec",
  "cargo_metadata 0.18.1",
@@ -610,12 +611,9 @@ dependencies = [
  "clippy_utils",
  "itertools",
  "quine-mc_cluskey",
- "regex",
  "regex-syntax 0.8.5",
  "semver",
  "serde",
- "serde_json",
- "tempfile",
  "toml 0.7.8",
  "unicode-normalization",
  "unicode-script",
@@ -624,8 +622,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "clippy_lints_internal"
+version = "0.0.1"
+dependencies = [
+ "clippy_config",
+ "clippy_utils",
+ "regex",
+ "rustc-semver",
+]
+
+[[package]]
 name = "clippy_utils"
-version = "0.1.87"
+version = "0.1.88"
 dependencies = [
  "arrayvec",
  "itertools",
@@ -2245,22 +2253,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "mime"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
-
-[[package]]
-name = "mime_guess"
-version = "2.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
-dependencies = [
- "mime",
- "unicase",
-]
-
-[[package]]
 name = "minifier"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3085,45 +3077,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rinja"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5"
-dependencies = [
- "itoa",
- "rinja_derive",
-]
-
-[[package]]
-name = "rinja_derive"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d9ed0146aef6e2825f1b1515f074510549efba38d71f4554eec32eb36ba18b"
-dependencies = [
- "basic-toml",
- "memchr",
- "mime",
- "mime_guess",
- "proc-macro2",
- "quote",
- "rinja_parser",
- "rustc-hash 2.1.1",
- "serde",
- "syn 2.0.100",
-]
-
-[[package]]
-name = "rinja_parser"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f9a866e2e00a7a1fb27e46e9e324a6f7c0e7edc4543cae1d38f4e4a100c610"
-dependencies = [
- "memchr",
- "nom",
- "serde",
-]
-
-[[package]]
 name = "run_make_support"
 version = "0.2.0"
 dependencies = [
@@ -3197,6 +3150,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc-semver"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84"
+
+[[package]]
 name = "rustc-stable-hash"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4562,6 +4521,7 @@ dependencies = [
  "rustc_hir",
  "rustc_middle",
  "rustc_span",
+ "smallvec",
  "tracing",
 ]
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index fc32c4efce5..c009abd729d 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -5,7 +5,7 @@ use rustc_ast::*;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
-use rustc_hir::{self as hir, HirId, IsAnonInPath, PredicateOrigin};
+use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin};
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -1868,7 +1868,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             GenericParamKind::Lifetime => {
                 let lt_id = self.next_node_id();
-                let lifetime = self.new_named_lifetime(id, lt_id, ident, IsAnonInPath::No);
+                let lifetime =
+                    self.new_named_lifetime(id, lt_id, ident, LifetimeSource::Other, ident.into());
                 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
                     lifetime,
                     bounds,
@@ -1901,7 +1902,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }),
             WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
                 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
-                    lifetime: self.lower_lifetime(lifetime),
+                    lifetime: self.lower_lifetime(
+                        lifetime,
+                        LifetimeSource::Other,
+                        lifetime.ident.into(),
+                    ),
                     bounds: self.lower_param_bounds(
                         bounds,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index c40987541f4..534e85e8bcb 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -54,8 +54,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
 use rustc_hir::{
-    self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName,
-    TraitCandidate,
+    self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, LifetimeSource,
+    LifetimeSyntax, ParamName, TraitCandidate,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -1079,7 +1079,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         itctx: ImplTraitContext,
     ) -> hir::GenericArg<'hir> {
         match arg {
-            ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
+            ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(
+                lt,
+                LifetimeSource::Path { with_angle_brackets: true },
+                lt.ident.into(),
+            )),
             ast::GenericArg::Type(ty) => {
                 // We cannot just match on `TyKind::Infer` as `(_)` is represented as
                 // `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer`
@@ -1198,35 +1202,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
             TyKind::Ref(region, mt) => {
-                let region = region.unwrap_or_else(|| {
-                    let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
-                        self.resolver.get_lifetime_res(t.id)
-                    {
-                        debug_assert_eq!(start.plus(1), end);
-                        start
-                    } else {
-                        self.next_node_id()
-                    };
-                    let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
-                    Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
-                });
-                let lifetime = self.lower_lifetime(&region);
+                let lifetime = self.lower_ty_direct_lifetime(t, *region);
                 hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))
             }
             TyKind::PinnedRef(region, mt) => {
-                let region = region.unwrap_or_else(|| {
-                    let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
-                        self.resolver.get_lifetime_res(t.id)
-                    {
-                        debug_assert_eq!(start.plus(1), end);
-                        start
-                    } else {
-                        self.next_node_id()
-                    };
-                    let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
-                    Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
-                });
-                let lifetime = self.lower_lifetime(&region);
+                let lifetime = self.lower_ty_direct_lifetime(t, *region);
                 let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));
                 let span = self.lower_span(t.span);
                 let arg = hir::Ty { kind, span, hir_id: self.next_id() };
@@ -1302,7 +1282,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             }
                             GenericBound::Outlives(lifetime) => {
                                 if lifetime_bound.is_none() {
-                                    lifetime_bound = Some(this.lower_lifetime(lifetime));
+                                    lifetime_bound = Some(this.lower_lifetime(
+                                        lifetime,
+                                        LifetimeSource::Other,
+                                        lifetime.ident.into(),
+                                    ));
                                 }
                                 None
                             }
@@ -1393,6 +1377,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
     }
 
+    fn lower_ty_direct_lifetime(
+        &mut self,
+        t: &Ty,
+        region: Option<Lifetime>,
+    ) -> &'hir hir::Lifetime {
+        let (region, syntax) = match region {
+            Some(region) => (region, region.ident.into()),
+
+            None => {
+                let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
+                    self.resolver.get_lifetime_res(t.id)
+                {
+                    debug_assert_eq!(start.plus(1), end);
+                    start
+                } else {
+                    self.next_node_id()
+                };
+                let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
+                let region = Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id };
+                (region, LifetimeSyntax::Hidden)
+            }
+        };
+        self.lower_lifetime(&region, LifetimeSource::Reference, syntax)
+    }
+
     /// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =
     /// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a
     /// HIR type that references the TAIT.
@@ -1474,9 +1483,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         precise_capturing_args: &[PreciseCapturingArg],
     ) -> &'hir [hir::PreciseCapturingArg<'hir>] {
         self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {
-            PreciseCapturingArg::Lifetime(lt) => {
-                hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
-            }
+            PreciseCapturingArg::Lifetime(lt) => hir::PreciseCapturingArg::Lifetime(
+                self.lower_lifetime(lt, LifetimeSource::PreciseCapturing, lt.ident.into()),
+            ),
             PreciseCapturingArg::Arg(path, id) => {
                 let [segment] = path.segments.as_slice() else {
                     panic!();
@@ -1739,9 +1748,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::GenericBound<'hir> {
         match tpb {
             GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
-            GenericBound::Outlives(lifetime) => {
-                hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
-            }
+            GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
+                lifetime,
+                LifetimeSource::OutlivesBound,
+                lifetime.ident.into(),
+            )),
             GenericBound::Use(args, span) => hir::GenericBound::Use(
                 self.lower_precise_capturing_args(args),
                 self.lower_span(*span),
@@ -1749,12 +1760,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
-        self.new_named_lifetime(l.id, l.id, l.ident, IsAnonInPath::No)
+    fn lower_lifetime(
+        &mut self,
+        l: &Lifetime,
+        source: LifetimeSource,
+        syntax: LifetimeSyntax,
+    ) -> &'hir hir::Lifetime {
+        self.new_named_lifetime(l.id, l.id, l.ident, source, syntax)
     }
 
-    fn lower_lifetime_anon_in_path(&mut self, id: NodeId, span: Span) -> &'hir hir::Lifetime {
-        self.new_named_lifetime(id, id, Ident::new(kw::UnderscoreLifetime, span), IsAnonInPath::Yes)
+    fn lower_lifetime_hidden_in_path(
+        &mut self,
+        id: NodeId,
+        span: Span,
+        with_angle_brackets: bool,
+    ) -> &'hir hir::Lifetime {
+        self.new_named_lifetime(
+            id,
+            id,
+            Ident::new(kw::UnderscoreLifetime, span),
+            LifetimeSource::Path { with_angle_brackets },
+            LifetimeSyntax::Hidden,
+        )
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -1763,7 +1790,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         id: NodeId,
         new_id: NodeId,
         ident: Ident,
-        is_anon_in_path: IsAnonInPath,
+        source: LifetimeSource,
+        syntax: LifetimeSyntax,
     ) -> &'hir hir::Lifetime {
         let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
         let res = match res {
@@ -1787,17 +1815,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         };
 
-        #[cfg(debug_assertions)]
-        if is_anon_in_path == IsAnonInPath::Yes {
-            debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
-        }
-
         debug!(?res);
         self.arena.alloc(hir::Lifetime::new(
             self.lower_node_id(new_id),
             self.lower_ident(ident),
             res,
-            is_anon_in_path,
+            source,
+            syntax,
         ))
     }
 
@@ -2389,7 +2413,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             self.next_id(),
             Ident::new(kw::UnderscoreLifetime, self.lower_span(span)),
             hir::LifetimeKind::ImplicitObjectLifetimeDefault,
-            IsAnonInPath::No,
+            LifetimeSource::Other,
+            LifetimeSyntax::Hidden,
         );
         debug!("elided_dyn_bound: r={:?}", r);
         self.arena.alloc(r)
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 0bd65aec10f..fabe40a9d04 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -1,11 +1,10 @@
 use std::sync::Arc;
 
 use rustc_ast::{self as ast, *};
-use rustc_hir as hir;
-use rustc_hir::GenericArg;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
-use rustc_middle::span_bug;
+use rustc_hir::{self as hir, GenericArg};
+use rustc_middle::{span_bug, ty};
 use rustc_session::parse::add_feature_diagnostics;
 use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
 use smallvec::{SmallVec, smallvec};
@@ -433,23 +432,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         // Note: these spans are used for diagnostics when they can't be inferred.
         // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
-        let elided_lifetime_span = if generic_args.span.is_empty() {
+        let (elided_lifetime_span, with_angle_brackets) = if generic_args.span.is_empty() {
             // If there are no brackets, use the identifier span.
             // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
             // originating from macros, since the segment's span might be from a macro arg.
-            segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span)
+            (segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span), false)
         } else if generic_args.is_empty() {
             // If there are brackets, but not generic arguments, then use the opening bracket
-            generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
+            (generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)), true)
         } else {
             // Else use an empty span right after the opening bracket.
-            generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
+            (generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(), true)
         };
 
         generic_args.args.insert_many(
             0,
             (start..end).map(|id| {
-                let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span);
+                let l = self.lower_lifetime_hidden_in_path(
+                    id,
+                    elided_lifetime_span,
+                    with_angle_brackets,
+                );
                 GenericArg::Lifetime(l)
             }),
         );
@@ -590,14 +593,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
     fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<DefId> {
         let lang_items = self.tcx.lang_items();
-        if Some(def_id) == lang_items.fn_trait() {
-            lang_items.async_fn_trait()
-        } else if Some(def_id) == lang_items.fn_mut_trait() {
-            lang_items.async_fn_mut_trait()
-        } else if Some(def_id) == lang_items.fn_once_trait() {
-            lang_items.async_fn_once_trait()
-        } else {
-            None
+        match self.tcx.fn_trait_kind_from_def_id(def_id)? {
+            ty::ClosureKind::Fn => lang_items.async_fn_trait(),
+            ty::ClosureKind::FnMut => lang_items.async_fn_mut_trait(),
+            ty::ClosureKind::FnOnce => lang_items.async_fn_once_trait(),
         }
     }
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 6959cbd87f1..62a50c73855 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -799,7 +799,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             has_bang,
             Some(*ident),
             macro_def.body.delim,
-            &macro_def.body.tokens.clone(),
+            &macro_def.body.tokens,
             true,
             sp,
         );
@@ -1468,7 +1468,7 @@ impl<'a> State<'a> {
             true,
             None,
             m.args.delim,
-            &m.args.tokens.clone(),
+            &m.args.tokens,
             true,
             m.span(),
         );
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index cf735815fd2..0f8acadb978 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1265,12 +1265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 && let CallKind::FnCall { fn_trait_id, self_ty } = kind
                 && let ty::Param(_) = self_ty.kind()
                 && ty == self_ty
-                && [
-                    self.infcx.tcx.lang_items().fn_once_trait(),
-                    self.infcx.tcx.lang_items().fn_mut_trait(),
-                    self.infcx.tcx.lang_items().fn_trait(),
-                ]
-                .contains(&Some(fn_trait_id))
+                && self.infcx.tcx.fn_trait_kind_from_def_id(fn_trait_id).is_some()
             {
                 // Do not suggest `F: FnOnce() + Clone`.
                 false
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 3b66142eb2c..83a9827e8f8 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -702,12 +702,12 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
 // 2. loans made in overlapping scopes do not conflict
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
-impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
+impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
     fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
         state: &BorrowckDomain,
-        stmt: &'a Statement<'tcx>,
+        stmt: &Statement<'tcx>,
         location: Location,
     ) {
         debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, state);
@@ -783,7 +783,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
         state: &BorrowckDomain,
-        term: &'a Terminator<'tcx>,
+        term: &Terminator<'tcx>,
         loc: Location,
     ) {
         debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, state);
@@ -896,7 +896,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
         state: &BorrowckDomain,
-        term: &'a Terminator<'tcx>,
+        term: &Terminator<'tcx>,
         loc: Location,
     ) {
         let span = term.source_info.span;
@@ -1363,7 +1363,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
     fn consume_rvalue(
         &mut self,
         location: Location,
-        (rvalue, span): (&'a Rvalue<'tcx>, Span),
+        (rvalue, span): (&Rvalue<'tcx>, Span),
         state: &BorrowckDomain,
     ) {
         match rvalue {
@@ -1636,7 +1636,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
     fn consume_operand(
         &mut self,
         location: Location,
-        (operand, span): (&'a Operand<'tcx>, Span),
+        (operand, span): (&Operand<'tcx>, Span),
         state: &BorrowckDomain,
     ) {
         match *operand {
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index e60efdbefd9..6d97dfa3a4d 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -217,14 +217,12 @@ mod llvm_enzyme {
                 ast::StmtKind::Item(iitem) => extract_item_info(iitem),
                 _ => None,
             },
-            Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
-                match &assoc_item.kind {
-                    ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
-                        Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
-                    }
-                    _ => None,
+            Annotatable::AssocItem(assoc_item, Impl { .. }) => match &assoc_item.kind {
+                ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
+                    Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
                 }
-            }
+                _ => None,
+            },
             _ => None,
         }) else {
             dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
@@ -365,7 +363,7 @@ mod llvm_enzyme {
                 }
                 Annotatable::Item(iitem.clone())
             }
-            Annotatable::AssocItem(ref mut assoc_item, i @ Impl { of_trait: false }) => {
+            Annotatable::AssocItem(ref mut assoc_item, i @ Impl { .. }) => {
                 if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
                     assoc_item.attrs.push(attr);
                 }
diff --git a/compiler/rustc_codegen_cranelift/example/example.rs b/compiler/rustc_codegen_cranelift/example/example.rs
index 1ef2aa5dd8e..aeb38331edb 100644
--- a/compiler/rustc_codegen_cranelift/example/example.rs
+++ b/compiler/rustc_codegen_cranelift/example/example.rs
@@ -1,6 +1,6 @@
 #![feature(no_core, unboxed_closures)]
 #![no_core]
-#![allow(dead_code)]
+#![allow(dead_code, unnecessary_transmutes)]
 
 extern crate mini_core;
 
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index ffdc6a7d484..2d9de2a5b8d 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -8,9 +8,6 @@
     unboxed_closures
 )]
 #![allow(internal_features)]
-// FIXME once abi_unsupported_vector_types is a hard error disable the foo test when the respective
-// target feature is not enabled.
-#![allow(abi_unsupported_vector_types)]
 
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
diff --git a/compiler/rustc_codegen_gcc/example/example.rs b/compiler/rustc_codegen_gcc/example/example.rs
index 03470b74d0a..888fa89201e 100644
--- a/compiler/rustc_codegen_gcc/example/example.rs
+++ b/compiler/rustc_codegen_gcc/example/example.rs
@@ -1,6 +1,6 @@
 #![feature(no_core, unboxed_closures)]
 #![no_core]
-#![allow(dead_code)]
+#![allow(dead_code, unnecessary_transmutes)]
 
 extern crate mini_core;
 
@@ -11,11 +11,7 @@ fn abc(a: u8) -> u8 {
 }
 
 fn bcd(b: bool, a: u8) -> u8 {
-    if b {
-        a * 2
-    } else {
-        a * 3
-    }
+    if b { a * 2 } else { a * 3 }
 }
 
 fn call() {
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index a8b49e9552c..925898d8173 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -584,12 +584,10 @@ fn thin_lto(
     }
 }
 
-fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen<ModuleLlvm>) {
+fn enable_autodiff_settings(ad: &[config::AutoDiff]) {
     for &val in ad {
+        // We intentionally don't use a wildcard, to not forget handling anything new.
         match val {
-            config::AutoDiff::PrintModBefore => {
-                unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
-            }
             config::AutoDiff::PrintPerf => {
                 llvm::set_print_perf(true);
             }
@@ -603,17 +601,23 @@ fn enable_autodiff_settings(ad: &[config::AutoDiff], module: &mut ModuleCodegen<
                 llvm::set_inline(true);
             }
             config::AutoDiff::LooseTypes => {
-                llvm::set_loose_types(false);
+                llvm::set_loose_types(true);
             }
             config::AutoDiff::PrintSteps => {
                 llvm::set_print(true);
             }
-            // We handle this below
+            // We handle this in the PassWrapper.cpp
+            config::AutoDiff::PrintPasses => {}
+            // We handle this in the PassWrapper.cpp
+            config::AutoDiff::PrintModBefore => {}
+            // We handle this in the PassWrapper.cpp
             config::AutoDiff::PrintModAfter => {}
-            // We handle this below
+            // We handle this in the PassWrapper.cpp
             config::AutoDiff::PrintModFinal => {}
             // This is required and already checked
             config::AutoDiff::Enable => {}
+            // We handle this below
+            config::AutoDiff::NoPostopt => {}
         }
     }
     // This helps with handling enums for now.
@@ -647,27 +651,27 @@ pub(crate) fn run_pass_manager(
     // We then run the llvm_optimize function a second time, to optimize the code which we generated
     // in the enzyme differentiation pass.
     let enable_ad = config.autodiff.contains(&config::AutoDiff::Enable);
-    let stage =
-        if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD };
+    let stage = if thin {
+        write::AutodiffStage::PreAD
+    } else {
+        if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD }
+    };
 
     if enable_ad {
-        enable_autodiff_settings(&config.autodiff, module);
+        enable_autodiff_settings(&config.autodiff);
     }
 
     unsafe {
         write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
     }
 
-    if cfg!(llvm_enzyme) && enable_ad {
-        // This is the post-autodiff IR, mainly used for testing and educational purposes.
-        if config.autodiff.contains(&config::AutoDiff::PrintModAfter) {
-            unsafe { llvm::LLVMDumpModule(module.module_llvm.llmod()) };
-        }
-
+    if cfg!(llvm_enzyme) && enable_ad && !thin {
         let opt_stage = llvm::OptStage::FatLTO;
         let stage = write::AutodiffStage::PostAD;
-        unsafe {
-            write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+        if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
+            unsafe {
+                write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+            }
         }
 
         // This is the final IR, so people should be able to inspect the optimized autodiff output,
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 18d221d232e..4ac77c8f7f1 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -572,6 +572,10 @@ pub(crate) unsafe fn llvm_optimize(
 
     let consider_ad = cfg!(llvm_enzyme) && config.autodiff.contains(&config::AutoDiff::Enable);
     let run_enzyme = autodiff_stage == AutodiffStage::DuringAD;
+    let print_before_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModBefore);
+    let print_after_enzyme = config.autodiff.contains(&config::AutoDiff::PrintModAfter);
+    let print_passes = config.autodiff.contains(&config::AutoDiff::PrintPasses);
+    let merge_functions;
     let unroll_loops;
     let vectorize_slp;
     let vectorize_loop;
@@ -579,13 +583,20 @@ pub(crate) unsafe fn llvm_optimize(
     // When we build rustc with enzyme/autodiff support, we want to postpone size-increasing
     // optimizations until after differentiation. Our pipeline is thus: (opt + enzyme), (full opt).
     // We therefore have two calls to llvm_optimize, if autodiff is used.
+    //
+    // We also must disable merge_functions, since autodiff placeholder/dummy bodies tend to be
+    // identical. We run opts before AD, so there is a chance that LLVM will merge our dummies.
+    // In that case, we lack some dummy bodies and can't replace them with the real AD code anymore.
+    // We then would need to abort compilation. This was especially common in test cases.
     if consider_ad && autodiff_stage != AutodiffStage::PostAD {
+        merge_functions = false;
         unroll_loops = false;
         vectorize_slp = false;
         vectorize_loop = false;
     } else {
         unroll_loops =
             opt_level != config::OptLevel::Size && opt_level != config::OptLevel::SizeMin;
+        merge_functions = config.merge_functions;
         vectorize_slp = config.vectorize_slp;
         vectorize_loop = config.vectorize_loop;
     }
@@ -663,13 +674,16 @@ pub(crate) unsafe fn llvm_optimize(
             thin_lto_buffer,
             config.emit_thin_lto,
             config.emit_thin_lto_summary,
-            config.merge_functions,
+            merge_functions,
             unroll_loops,
             vectorize_slp,
             vectorize_loop,
             config.no_builtins,
             config.emit_lifetime_markers,
             run_enzyme,
+            print_before_enzyme,
+            print_after_enzyme,
+            print_passes,
             sanitizer_options.as_ref(),
             pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
             pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 27f7f95f100..04c8118b616 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -594,6 +594,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value {
         unsafe {
             let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
+            let align = align.min(self.cx().tcx.sess.target.max_reliable_alignment());
             llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
             load
         }
@@ -807,6 +808,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         assert_eq!(self.cx.type_kind(self.cx.val_ty(ptr)), TypeKind::Pointer);
         unsafe {
             let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
+            let align = align.min(self.cx().tcx.sess.target.max_reliable_alignment());
             let align =
                 if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() as c_uint };
             llvm::LLVMSetAlignment(store, align);
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index e7c071d05aa..0147bd5a665 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -473,7 +473,7 @@ pub(crate) fn differentiate<'ll>(
         return Err(diag_handler.handle().emit_almost_fatal(AutoDiffWithoutEnable));
     }
 
-    // Before dumping the module, we want all the TypeTrees to become part of the module.
+    // Here we replace the placeholder code with the actual autodiff code, which calls Enzyme.
     for item in diff_items.iter() {
         let name = item.source.clone();
         let fn_def: Option<&llvm::Value> = cx.get_function(&name);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 9ff04f72903..ffb490dcdc2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2454,6 +2454,9 @@ unsafe extern "C" {
         DisableSimplifyLibCalls: bool,
         EmitLifetimeMarkers: bool,
         RunEnzyme: bool,
+        PrintBeforeEnzyme: bool,
+        PrintAfterEnzyme: bool,
+        PrintPasses: bool,
         SanitizerOptions: Option<&SanitizerOptions>,
         PGOGenPath: *const c_char,
         PGOUsePath: *const c_char,
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index d077900587e..9d8130661b0 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -872,8 +872,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
-        if self.get_fn_alloc(id).is_some() {
-            return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not);
+        if let Some(fn_val) = self.get_fn_alloc(id) {
+            let align = match fn_val {
+                FnVal::Instance(instance) => {
+                    // Function alignment can be set globally with the `-Zmin-function-alignment=<n>` flag;
+                    // the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
+                    let fn_align = self.tcx.codegen_fn_attrs(instance.def_id()).alignment;
+                    let global_align = self.tcx.sess.opts.unstable_opts.min_function_alignment;
+
+                    Ord::max(global_align, fn_align).unwrap_or(Align::ONE)
+                }
+                // Machine-specific extra functions currently do not support alignment restrictions.
+                FnVal::Other(_) => Align::ONE,
+            };
+
+            return AllocInfo::new(Size::ZERO, align, AllocKind::Function, Mutability::Not);
         }
 
         // # Global allocations
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index d02c767ea67..2f8a8534247 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -36,43 +36,110 @@ pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
 use crate::intravisit::{FnKind, VisitorExt};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
-pub enum IsAnonInPath {
-    No,
-    Yes,
+pub enum LifetimeSource {
+    /// E.g. `&Type`, `&'_ Type`, `&'a Type`, `&mut Type`, `&'_ mut Type`, `&'a mut Type`
+    Reference,
+
+    /// E.g. `ContainsLifetime`, `ContainsLifetime<'_>`, `ContainsLifetime<'a>`
+    Path {
+        /// - true for `ContainsLifetime<'_>`, `ContainsLifetime<'a>`,
+        ///   `ContainsLifetime<'_, T>`, `ContainsLifetime<'a, T>`
+        /// - false for `ContainsLifetime`
+        with_angle_brackets: bool,
+    },
+
+    /// E.g. `impl Trait + '_`, `impl Trait + 'a`
+    OutlivesBound,
+
+    /// E.g. `impl Trait + use<'_>`, `impl Trait + use<'a>`
+    PreciseCapturing,
+
+    /// Other usages which have not yet been categorized. Feel free to
+    /// add new sources that you find useful.
+    ///
+    /// Some non-exhaustive examples:
+    /// - `where T: 'a`
+    /// - `fn(_: dyn Trait + 'a)`
+    Other,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
+pub enum LifetimeSyntax {
+    /// E.g. `&Type`, `ContainsLifetime`
+    Hidden,
+
+    /// E.g. `&'_ Type`, `ContainsLifetime<'_>`, `impl Trait + '_`, `impl Trait + use<'_>`
+    Anonymous,
+
+    /// E.g. `&'a Type`, `ContainsLifetime<'a>`, `impl Trait + 'a`, `impl Trait + use<'a>`
+    Named,
 }
 
-/// A lifetime. The valid field combinations are non-obvious. The following
-/// example shows some of them. See also the comments on `LifetimeKind`.
+impl From<Ident> for LifetimeSyntax {
+    fn from(ident: Ident) -> Self {
+        let name = ident.name;
+
+        if name == kw::Empty {
+            unreachable!("A lifetime name should never be empty");
+        } else if name == kw::UnderscoreLifetime {
+            LifetimeSyntax::Anonymous
+        } else {
+            debug_assert!(name.as_str().starts_with('\''));
+            LifetimeSyntax::Named
+        }
+    }
+}
+
+/// A lifetime. The valid field combinations are non-obvious and not all
+/// combinations are possible. The following example shows some of
+/// them. See also the comments on `LifetimeKind` and `LifetimeSource`.
+///
 /// ```
 /// #[repr(C)]
-/// struct S<'a>(&'a u32);       // res=Param, name='a, IsAnonInPath::No
+/// struct S<'a>(&'a u32);       // res=Param, name='a, source=Reference, syntax=Named
 /// unsafe extern "C" {
-///     fn f1(s: S);             // res=Param, name='_, IsAnonInPath::Yes
-///     fn f2(s: S<'_>);         // res=Param, name='_, IsAnonInPath::No
-///     fn f3<'a>(s: S<'a>);     // res=Param, name='a, IsAnonInPath::No
+///     fn f1(s: S);             // res=Param, name='_, source=Path, syntax=Hidden
+///     fn f2(s: S<'_>);         // res=Param, name='_, source=Path, syntax=Anonymous
+///     fn f3<'a>(s: S<'a>);     // res=Param, name='a, source=Path, syntax=Named
 /// }
 ///
-/// struct St<'a> { x: &'a u32 } // res=Param, name='a, IsAnonInPath::No
+/// struct St<'a> { x: &'a u32 } // res=Param, name='a, source=Reference, syntax=Named
 /// fn f() {
-///     _ = St { x: &0 };        // res=Infer, name='_, IsAnonInPath::Yes
-///     _ = St::<'_> { x: &0 };  // res=Infer, name='_, IsAnonInPath::No
+///     _ = St { x: &0 };        // res=Infer, name='_, source=Path, syntax=Hidden
+///     _ = St::<'_> { x: &0 };  // res=Infer, name='_, source=Path, syntax=Anonymous
 /// }
 ///
-/// struct Name<'a>(&'a str);    // res=Param,  name='a, IsAnonInPath::No
-/// const A: Name = Name("a");   // res=Static, name='_, IsAnonInPath::Yes
-/// const B: &str = "";          // res=Static, name='_, IsAnonInPath::No
-/// static C: &'_ str = "";      // res=Static, name='_, IsAnonInPath::No
-/// static D: &'static str = ""; // res=Static, name='static, IsAnonInPath::No
+/// struct Name<'a>(&'a str);    // res=Param,  name='a, source=Reference, syntax=Named
+/// const A: Name = Name("a");   // res=Static, name='_, source=Path, syntax=Hidden
+/// const B: &str = "";          // res=Static, name='_, source=Reference, syntax=Hidden
+/// static C: &'_ str = "";      // res=Static, name='_, source=Reference, syntax=Anonymous
+/// static D: &'static str = ""; // res=Static, name='static, source=Reference, syntax=Named
 ///
 /// trait Tr {}
-/// fn tr(_: Box<dyn Tr>) {}     // res=ImplicitObjectLifetimeDefault, name='_, IsAnonInPath::No
+/// fn tr(_: Box<dyn Tr>) {}     // res=ImplicitObjectLifetimeDefault, name='_, source=Other, syntax=Hidden
+///
+/// fn capture_outlives<'a>() ->
+///     impl FnOnce() + 'a       // res=Param, ident='a, source=OutlivesBound, syntax=Named
+/// {
+///     || {}
+/// }
+///
+/// fn capture_precise<'a>() ->
+///     impl FnOnce() + use<'a>  // res=Param, ident='a, source=PreciseCapturing, syntax=Named
+/// {
+///     || {}
+/// }
 ///
 /// // (commented out because these cases trigger errors)
-/// // struct S1<'a>(&'a str);   // res=Param, name='a, IsAnonInPath::No
-/// // struct S2(S1);            // res=Error, name='_, IsAnonInPath::Yes
-/// // struct S3(S1<'_>);        // res=Error, name='_, IsAnonInPath::No
-/// // struct S4(S1<'a>);        // res=Error, name='a, IsAnonInPath::No
+/// // struct S1<'a>(&'a str);   // res=Param, name='a, source=Reference, syntax=Named
+/// // struct S2(S1);            // res=Error, name='_, source=Path, syntax=Hidden
+/// // struct S3(S1<'_>);        // res=Error, name='_, source=Path, syntax=Anonymous
+/// // struct S4(S1<'a>);        // res=Error, name='a, source=Path, syntax=Named
 /// ```
+///
+/// Some combinations that cannot occur are `LifetimeSyntax::Hidden` with
+/// `LifetimeSource::OutlivesBound` or `LifetimeSource::PreciseCapturing`
+/// — there's no way to "elide" these lifetimes.
 #[derive(Debug, Copy, Clone, HashStable_Generic)]
 pub struct Lifetime {
     #[stable_hasher(ignore)]
@@ -86,9 +153,13 @@ pub struct Lifetime {
     /// Semantics of this lifetime.
     pub kind: LifetimeKind,
 
-    /// Is the lifetime anonymous and in a path? Used only for error
-    /// suggestions. See `Lifetime::suggestion` for example use.
-    pub is_anon_in_path: IsAnonInPath,
+    /// The context in which the lifetime occurred. See `Lifetime::suggestion`
+    /// for example use.
+    pub source: LifetimeSource,
+
+    /// The syntax that the user used to declare this lifetime. See
+    /// `Lifetime::suggestion` for example use.
+    pub syntax: LifetimeSyntax,
 }
 
 #[derive(Debug, Copy, Clone, HashStable_Generic)]
@@ -185,9 +256,10 @@ impl Lifetime {
         hir_id: HirId,
         ident: Ident,
         kind: LifetimeKind,
-        is_anon_in_path: IsAnonInPath,
+        source: LifetimeSource,
+        syntax: LifetimeSyntax,
     ) -> Lifetime {
-        let lifetime = Lifetime { hir_id, ident, kind, is_anon_in_path };
+        let lifetime = Lifetime { hir_id, ident, kind, source, syntax };
 
         // Sanity check: elided lifetimes form a strict subset of anonymous lifetimes.
         #[cfg(debug_assertions)]
@@ -209,23 +281,44 @@ impl Lifetime {
         self.ident.name == kw::UnderscoreLifetime
     }
 
+    pub fn is_syntactically_hidden(&self) -> bool {
+        matches!(self.syntax, LifetimeSyntax::Hidden)
+    }
+
+    pub fn is_syntactically_anonymous(&self) -> bool {
+        matches!(self.syntax, LifetimeSyntax::Anonymous)
+    }
+
+    pub fn is_static(&self) -> bool {
+        self.kind == LifetimeKind::Static
+    }
+
     pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
+        use LifetimeSource::*;
+        use LifetimeSyntax::*;
+
         debug_assert!(new_lifetime.starts_with('\''));
 
-        match (self.is_anon_in_path, self.ident.span.is_empty()) {
+        match (self.syntax, self.source) {
+            // The user wrote `'a` or `'_`.
+            (Named | Anonymous, _) => (self.ident.span, format!("{new_lifetime}")),
+
             // The user wrote `Path<T>`, and omitted the `'_,`.
-            (IsAnonInPath::Yes, true) => (self.ident.span, format!("{new_lifetime}, ")),
+            (Hidden, Path { with_angle_brackets: true }) => {
+                (self.ident.span, format!("{new_lifetime}, "))
+            }
 
             // The user wrote `Path` and omitted the `<'_>`.
-            (IsAnonInPath::Yes, false) => {
+            (Hidden, Path { with_angle_brackets: false }) => {
                 (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
             }
 
             // The user wrote `&type` or `&mut type`.
-            (IsAnonInPath::No, true) => (self.ident.span, format!("{new_lifetime} ")),
+            (Hidden, Reference) => (self.ident.span, format!("{new_lifetime} ")),
 
-            // The user wrote `'a` or `'_`.
-            (IsAnonInPath::No, false) => (self.ident.span, format!("{new_lifetime}")),
+            (Hidden, source) => {
+                unreachable!("can't suggest for a hidden lifetime of {source:?}")
+            }
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs
index fcd0eafa461..18f8c523f9d 100644
--- a/compiler/rustc_hir/src/hir/tests.rs
+++ b/compiler/rustc_hir/src/hir/tests.rs
@@ -58,7 +58,8 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
                     hir_id: HirId::INVALID,
                     ident: Ident::new(sym::name, DUMMY_SP),
                     kind: LifetimeKind::Static,
-                    is_anon_in_path: IsAnonInPath::No,
+                    source: LifetimeSource::Other,
+                    syntax: LifetimeSyntax::Hidden,
                 }
             },
             syntax,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 89fb35154b7..692784bf171 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -2,8 +2,7 @@
 
 use rustc_abi::ExternAbi;
 use rustc_errors::DiagMessage;
-use rustc_hir::{self as hir};
-use rustc_middle::bug;
+use rustc_hir::{self as hir, LangItem};
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
@@ -173,23 +172,22 @@ pub(crate) fn check_intrinsic_type(
         ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
     ]);
     let mk_va_list_ty = |mutbl| {
-        tcx.lang_items().va_list().map(|did| {
-            let region = ty::Region::new_bound(
-                tcx,
-                ty::INNERMOST,
-                ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
-            );
-            let env_region = ty::Region::new_bound(
-                tcx,
-                ty::INNERMOST,
-                ty::BoundRegion {
-                    var: ty::BoundVar::from_u32(2),
-                    kind: ty::BoundRegionKind::ClosureEnv,
-                },
-            );
-            let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
-            (Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
-        })
+        let did = tcx.require_lang_item(LangItem::VaList, Some(span));
+        let region = ty::Region::new_bound(
+            tcx,
+            ty::INNERMOST,
+            ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon },
+        );
+        let env_region = ty::Region::new_bound(
+            tcx,
+            ty::INNERMOST,
+            ty::BoundRegion {
+                var: ty::BoundVar::from_u32(2),
+                kind: ty::BoundRegionKind::ClosureEnv,
+            },
+        );
+        let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
+        (Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
     };
 
     let (n_tps, n_lts, n_cts, inputs, output, safety) = if name_str.starts_with("atomic_") {
@@ -548,23 +546,17 @@ pub(crate) fn check_intrinsic_type(
                 )
             }
 
-            sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
-                Some((va_list_ref_ty, _)) => (0, 0, vec![va_list_ref_ty], tcx.types.unit),
-                None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
-            },
+            sym::va_start | sym::va_end => {
+                (0, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], tcx.types.unit)
+            }
 
-            sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
-                Some((va_list_ref_ty, va_list_ty)) => {
-                    let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
-                    (0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
-                }
-                None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
-            },
+            sym::va_copy => {
+                let (va_list_ref_ty, va_list_ty) = mk_va_list_ty(hir::Mutability::Not);
+                let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
+                (0, 0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.types.unit)
+            }
 
-            sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
-                Some((va_list_ref_ty, _)) => (1, 0, vec![va_list_ref_ty], param(0)),
-                None => bug!("`va_list` lang item needed for C-variadic intrinsics"),
-            },
+            sym::va_arg => (1, 0, vec![mk_va_list_ty(hir::Mutability::Mut).0], param(0)),
 
             sym::nontemporal_store => {
                 (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 8ad9d80c6b5..52656fc2d90 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -750,7 +750,7 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
                         ObligationCause::misc(impl_span, checker.impl_def_id),
                         param_env,
                         nontrivial_field_ty,
-                        tcx.lang_items().pointer_like().unwrap(),
+                        tcx.require_lang_item(LangItem::PointerLike, Some(impl_span)),
                     );
                     // FIXME(dyn-star): We should regionck this implementation.
                     if ocx.select_all_or_error().is_empty() {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 02fd7367e2f..d770937bd66 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -37,7 +37,7 @@ pub(crate) fn check_legal_trait_for_method_call(
     body_id: DefId,
 ) -> Result<(), ErrorGuaranteed> {
     if tcx.is_lang_item(trait_id, LangItem::Drop)
-        && tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
+        && !tcx.is_lang_item(body_id, LangItem::FallbackSurfaceDrop)
     {
         let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
             errors::ExplicitDestructorCallSugg::Snippet {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index b8968b58769..8fd59999fce 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -163,7 +163,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Resume type defaults to `()` if the coroutine has no argument.
                 let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
 
-                let interior = self.next_ty_var(expr_span);
+                // In the new solver, we can just instantiate this eagerly
+                // with the witness. This will ensure that goals that don't need
+                // to stall on interior types will get processed eagerly.
+                let interior = if self.next_trait_solver() {
+                    Ty::new_coroutine_witness(tcx, expr_def_id.to_def_id(), parent_args)
+                } else {
+                    self.next_ty_var(expr_span)
+                };
+
                 self.deferred_coroutine_interiors.borrow_mut().push((expr_def_id, interior));
 
                 // Coroutines that come from coroutine closures have not yet determined
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index d6a7bfc446a..9c6d4ee096f 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3289,8 +3289,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.multipart_suggestion(
             format!("{val} is a raw pointer; try dereferencing it"),
             vec![
-                (base.span.shrink_to_lo(), "(*".to_string()),
-                (base.span.shrink_to_hi(), ")".to_string()),
+                (base.span.shrink_to_lo(), "(*".into()),
+                (base.span.between(field.span), format!(").")),
             ],
             Applicability::MaybeIncorrect,
         );
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 87d92b3fbde..cac8237f8f6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -635,34 +635,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut obligations = vec![];
 
-        for &(coroutine_def_id, interior) in coroutines.iter() {
-            debug!(?coroutine_def_id);
+        if !self.next_trait_solver() {
+            for &(coroutine_def_id, interior) in coroutines.iter() {
+                debug!(?coroutine_def_id);
+
+                // Create the `CoroutineWitness` type that we will unify with `interior`.
+                let args = ty::GenericArgs::identity_for_item(
+                    self.tcx,
+                    self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
+                );
+                let witness =
+                    Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
 
-            // Create the `CoroutineWitness` type that we will unify with `interior`.
-            let args = ty::GenericArgs::identity_for_item(
-                self.tcx,
-                self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
-            );
-            let witness = Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
-
-            // Unify `interior` with `witness` and collect all the resulting obligations.
-            let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
-            let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
-                span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
-            };
-            let ok = self
-                .at(&self.misc(span), self.param_env)
-                // Will never define opaque types, as all we do is instantiate a type variable.
-                .eq(DefineOpaqueTypes::Yes, interior, witness)
-                .expect("Failed to unify coroutine interior type");
-
-            obligations.extend(ok.obligations);
+                // Unify `interior` with `witness` and collect all the resulting obligations.
+                let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
+                let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
+                    span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
+                };
+                let ok = self
+                    .at(&self.misc(span), self.param_env)
+                    // Will never define opaque types, as all we do is instantiate a type variable.
+                    .eq(DefineOpaqueTypes::Yes, interior, witness)
+                    .expect("Failed to unify coroutine interior type");
+
+                obligations.extend(ok.obligations);
+            }
         }
 
-        // FIXME: Use a real visitor for unstalled obligations in the new solver.
         if !coroutines.is_empty() {
-            obligations
-                .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx));
+            obligations.extend(
+                self.fulfillment_cx
+                    .borrow_mut()
+                    .drain_stalled_obligations_for_coroutines(&self.infcx),
+            );
         }
 
         self.typeck_results
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index da0e8e362d6..8b2d9ab2979 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -925,7 +925,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let detect_dotdot = |err: &mut Diag<'_>, ty: Ty<'_>, expr: &hir::Expr<'_>| {
             if let ty::Adt(adt, _) = ty.kind()
-                && self.tcx().lang_items().get(hir::LangItem::RangeFull) == Some(adt.did())
+                && self.tcx().is_lang_item(adt.did(), hir::LangItem::RangeFull)
                 && let hir::ExprKind::Struct(
                     hir::QPath::LangItem(hir::LangItem::RangeFull, _),
                     [],
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index e5e4fc7f8b7..7520782930a 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -759,22 +759,54 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
+        // Additionally, when `deref_patterns` is enabled, byte string literal patterns may have
+        // types `[u8]` or `[u8; N]`, in order to type, e.g., `deref!(b"..."): Vec<u8>`.
         let mut pat_ty = ty;
         if let hir::PatExprKind::Lit {
             lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
         } = lt.kind
         {
+            let tcx = self.tcx;
             let expected = self.structurally_resolve_type(span, expected);
-            if let ty::Ref(_, inner_ty, _) = *expected.kind()
-                && self.try_structurally_resolve_type(span, inner_ty).is_slice()
-            {
-                let tcx = self.tcx;
-                trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
-                pat_ty =
-                    Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8));
+            match *expected.kind() {
+                // Allow `b"...": &[u8]`
+                ty::Ref(_, inner_ty, _)
+                    if self.try_structurally_resolve_type(span, inner_ty).is_slice() =>
+                {
+                    trace!(?lt.hir_id.local_id, "polymorphic byte string lit");
+                    pat_ty = Ty::new_imm_ref(
+                        tcx,
+                        tcx.lifetimes.re_static,
+                        Ty::new_slice(tcx, tcx.types.u8),
+                    );
+                }
+                // Allow `b"...": [u8; 3]` for `deref_patterns`
+                ty::Array(..) if tcx.features().deref_patterns() => {
+                    pat_ty = match *ty.kind() {
+                        ty::Ref(_, inner_ty, _) => inner_ty,
+                        _ => span_bug!(span, "found byte string literal with non-ref type {ty:?}"),
+                    }
+                }
+                // Allow `b"...": [u8]` for `deref_patterns`
+                ty::Slice(..) if tcx.features().deref_patterns() => {
+                    pat_ty = Ty::new_slice(tcx, tcx.types.u8);
+                }
+                // Otherwise, `b"...": &[u8; 3]`
+                _ => {}
             }
         }
 
+        // When `deref_patterns` is enabled, in order to allow `deref!("..."): String`, we allow
+        // string literal patterns to have type `str`. This is accounted for when lowering to MIR.
+        if self.tcx.features().deref_patterns()
+            && let hir::PatExprKind::Lit {
+                lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
+            } = lt.kind
+            && self.try_structurally_resolve_type(span, expected).is_str()
+        {
+            pat_ty = self.tcx.types.str_;
+        }
+
         if self.tcx.features().string_deref_patterns()
             && let hir::PatExprKind::Lit {
                 lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
@@ -1457,15 +1489,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             _ => (None, None),
                         };
 
-                        let ranges = &[
-                            self.tcx.lang_items().range_struct(),
-                            self.tcx.lang_items().range_from_struct(),
-                            self.tcx.lang_items().range_to_struct(),
-                            self.tcx.lang_items().range_full_struct(),
-                            self.tcx.lang_items().range_inclusive_struct(),
-                            self.tcx.lang_items().range_to_inclusive_struct(),
-                        ];
-                        if type_def_id != None && ranges.contains(&type_def_id) {
+                        let is_range = match type_def_id.and_then(|id| self.tcx.as_lang_item(id)) {
+                            Some(
+                                LangItem::Range
+                                | LangItem::RangeFrom
+                                | LangItem::RangeTo
+                                | LangItem::RangeFull
+                                | LangItem::RangeInclusiveStruct
+                                | LangItem::RangeToInclusive,
+                            ) => true,
+                            _ => false,
+                        };
+                        if is_range {
                             if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
                                 let msg = "constants only support matching by type, \
                                     if you meant to match against a range of values, \
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 5b4fc51cec8..56859eef45f 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -2,9 +2,8 @@ use std::cell::RefCell;
 use std::ops::Deref;
 
 use rustc_data_structures::unord::{UnordMap, UnordSet};
-use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::{HirId, HirIdMap};
+use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
@@ -84,7 +83,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
         let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
 
         let infcx =
-            tcx.infer_ctxt().ignoring_regions().build(TypingMode::analysis_in_body(tcx, def_id));
+            tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id));
         let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
 
         TypeckRootCtxt {
@@ -137,7 +136,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
             obligation.predicate.kind().skip_binder()
             && let Some(ty) =
                 self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
-            && self.tcx.lang_items().sized_trait().is_some_and(|st| st != tpred.trait_ref.def_id)
+            && !self.tcx.is_lang_item(tpred.trait_ref.def_id, LangItem::Sized)
         {
             let new_self_ty = self.tcx.types.unit;
 
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 6ba7435cb79..3caaa7f9a9d 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -8,6 +8,7 @@ use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::intravisit::{self, InferKind, Visitor};
 use rustc_hir::{self as hir, AmbigArg, HirId};
+use rustc_infer::traits::solve::Goal;
 use rustc_middle::span_bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@@ -763,7 +764,32 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let value = self.fcx.resolve_vars_if_possible(value);
-        let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true));
+
+        let mut goals = vec![];
+        let value =
+            value.fold_with(&mut Resolver::new(self.fcx, span, self.body, true, &mut goals));
+
+        // Ensure that we resolve goals we get from normalizing coroutine interiors,
+        // but we shouldn't expect those goals to need normalizing (or else we'd get
+        // into a somewhat awkward fixpoint situation, and we don't need it anyways).
+        let mut unexpected_goals = vec![];
+        self.typeck_results.coroutine_stalled_predicates.extend(
+            goals
+                .into_iter()
+                .map(|pred| {
+                    self.fcx.resolve_vars_if_possible(pred).fold_with(&mut Resolver::new(
+                        self.fcx,
+                        span,
+                        self.body,
+                        false,
+                        &mut unexpected_goals,
+                    ))
+                })
+                // FIXME: throwing away the param-env :(
+                .map(|goal| (goal.predicate, self.fcx.misc(span.to_span(self.fcx.tcx)))),
+        );
+        assert_eq!(unexpected_goals, vec![]);
+
         assert!(!value.has_infer());
 
         // We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -781,7 +807,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         let value = self.fcx.resolve_vars_if_possible(value);
-        let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false));
+
+        let mut goals = vec![];
+        let value =
+            value.fold_with(&mut Resolver::new(self.fcx, span, self.body, false, &mut goals));
+        assert_eq!(goals, vec![]);
+
         assert!(!value.has_infer());
 
         // We may have introduced e.g. `ty::Error`, if inference failed, make sure
@@ -818,6 +849,7 @@ struct Resolver<'cx, 'tcx> {
     /// Whether we should normalize using the new solver, disabled
     /// both when using the old solver and when resolving predicates.
     should_normalize: bool,
+    nested_goals: &'cx mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
 }
 
 impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -826,8 +858,9 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
         should_normalize: bool,
+        nested_goals: &'cx mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { fcx, span, body, should_normalize }
+        Resolver { fcx, span, body, nested_goals, should_normalize }
     }
 
     fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -864,12 +897,18 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
             let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
             let at = self.fcx.at(&cause, self.fcx.param_env);
             let universes = vec![None; outer_exclusive_binder(value).as_usize()];
-            solve::deeply_normalize_with_skipped_universes(at, value, universes).unwrap_or_else(
-                |errors| {
+            match solve::deeply_normalize_with_skipped_universes_and_ambiguous_goals(
+                at, value, universes,
+            ) {
+                Ok((value, goals)) => {
+                    self.nested_goals.extend(goals);
+                    value
+                }
+                Err(errors) => {
                     let guar = self.fcx.err_ctxt().report_fulfillment_errors(errors);
                     new_err(tcx, guar)
-                },
-            )
+                }
+            }
         } else {
             value
         };
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 529e996ad1e..c4698e5cbb4 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -967,7 +967,9 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
         debug_assert!(!self.next_trait_solver());
         match self.typing_mode() {
-            TypingMode::Analysis { defining_opaque_types }
+            TypingMode::Analysis {
+                defining_opaque_types_and_generators: defining_opaque_types,
+            }
             | TypingMode::Borrowck { defining_opaque_types } => {
                 id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
             }
@@ -1262,7 +1264,7 @@ impl<'tcx> InferCtxt<'tcx> {
             // to handle them without proper canonicalization. This means we may cause cycle
             // errors and fail to reveal opaques while inside of bodies. We should rename this
             // function and require explicit comments on all use-sites in the future.
-            ty::TypingMode::Analysis { defining_opaque_types: _ }
+            ty::TypingMode::Analysis { defining_opaque_types_and_generators: _ }
             | ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
                 TypingMode::non_body_analysis()
             }
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 1eae10673b6..9e51a53ae95 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -94,7 +94,7 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
     /// Among all pending obligations, collect those are stalled on a inference variable which has
     /// changed since the last call to `select_where_possible`. Those obligations are marked as
     /// successful and returned.
-    fn drain_unstalled_obligations(
+    fn drain_stalled_obligations_for_coroutines(
         &mut self,
         infcx: &InferCtxt<'tcx>,
     ) -> PredicateObligations<'tcx>;
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 212368bea82..daddd45d597 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -608,6 +608,11 @@ fn register_builtins(store: &mut LintStore) {
         "converted into hard error, see PR #139001 \
          <https://github.com/rust-lang/rust/issues/139001> for more information",
     );
+    store.register_removed(
+        "abi_unsupported_vector_types",
+        "converted into hard error, \
+         see <https://github.com/rust-lang/rust/issues/116558> for more information",
+    );
 }
 
 fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs
index 571cab934fd..00fa0499556 100644
--- a/compiler/rustc_lint/src/shadowed_into_iter.rs
+++ b/compiler/rustc_lint/src/shadowed_into_iter.rs
@@ -1,4 +1,4 @@
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_middle::ty::{self, Ty};
 use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, impl_lint_pass};
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
         let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
             return;
         };
-        if Some(method_def_id) != cx.tcx.lang_items().into_iter_fn() {
+        if !cx.tcx.is_lang_item(method_def_id, LangItem::IntoIterIntoIter) {
             return;
         }
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index a084dacfb5b..f9dce5a5198 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,7 +1,9 @@
 use std::iter;
 use std::ops::ControlFlow;
 
-use rustc_abi::{BackendRepr, TagEncoding, VariantIdx, Variants, WrappingRange};
+use rustc_abi::{
+    BackendRepr, Integer, IntegerType, TagEncoding, VariantIdx, Variants, WrappingRange,
+};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::intravisit::VisitorExt;
@@ -1243,6 +1245,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
+                        if let Some(IntegerType::Fixed(Integer::I128, _)) = def.repr().int {
+                            return FfiUnsafe {
+                                ty,
+                                reason: fluent::lint_improper_ctypes_128bit,
+                                help: None,
+                            };
+                        }
+
                         use improper_ctypes::check_non_exhaustive_variant;
 
                         let non_exhaustive = def.variant_list_has_applicable_non_exhaustive();
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b25d2a30681..17d501c5730 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -16,7 +16,6 @@ declare_lint_pass! {
     /// that are used by other parts of the compiler.
     HardwiredLints => [
         // tidy-alphabetical-start
-        ABI_UNSUPPORTED_VECTOR_TYPES,
         ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
         AMBIGUOUS_ASSOCIATED_ITEMS,
         AMBIGUOUS_GLOB_IMPORTS,
@@ -118,6 +117,7 @@ declare_lint_pass! {
         UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
         UNNAMEABLE_TEST_ITEMS,
         UNNAMEABLE_TYPES,
+        UNNECESSARY_TRANSMUTES,
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
         UNSAFE_ATTR_OUTSIDE_UNSAFE,
@@ -4911,6 +4911,30 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `unnecessary_transmutes` lint detects transmutations that have safer alternatives.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// fn bytes_at_home(x: [u8; 4]) -> u32 {
+    ///   unsafe { std::mem::transmute(x) }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Using an explicit method is preferable over calls to
+    /// [`transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) as
+    /// they more clearly communicate the intent, are easier to review, and
+    /// are less likely to accidentally result in unsoundness.
+    pub UNNECESSARY_TRANSMUTES,
+    Warn,
+    "detects transmutes that are shadowed by std methods"
+}
+
+declare_lint! {
     /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location,
     /// that runs a custom `Drop` destructor.
     /// Some of them may be dropped earlier in Edition 2024 that they used to in Edition 2021 and prior.
@@ -5028,74 +5052,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `abi_unsupported_vector_types` lint detects function definitions and calls
-    /// whose ABI depends on enabling certain target features, but those features are not enabled.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,ignore (fails on non-x86_64)
-    /// extern "C" fn missing_target_feature(_: std::arch::x86_64::__m256) {
-    ///   todo!()
-    /// }
-    ///
-    /// #[target_feature(enable = "avx")]
-    /// unsafe extern "C" fn with_target_feature(_: std::arch::x86_64::__m256) {
-    ///   todo!()
-    /// }
-    ///
-    /// fn main() {
-    ///   let v = unsafe { std::mem::zeroed() };
-    ///   unsafe { with_target_feature(v); }
-    /// }
-    /// ```
-    ///
-    /// This will produce:
-    ///
-    /// ```text
-    /// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
-    ///  --> lint_example.rs:18:12
-    ///   |
-    ///   |   unsafe { with_target_feature(v); }
-    ///   |            ^^^^^^^^^^^^^^^^^^^^^^ function called here
-    ///   |
-    ///   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-    ///   = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")])
-    ///   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-    ///
-    ///
-    /// warning: ABI error: this function definition uses a avx vector type, which is not enabled
-    ///  --> lint_example.rs:3:1
-    ///   |
-    ///   | pub extern "C" fn with_target_feature(_: std::arch::x86_64::__m256) {
-    ///   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-    ///   |
-    ///   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-    ///   = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")])
-    /// ```
-    ///
-    ///
-    ///
-    /// ### Explanation
-    ///
-    /// The C ABI for `__m256` requires the value to be passed in an AVX register,
-    /// which is only possible when the `avx` target feature is enabled.
-    /// Therefore, `missing_target_feature` cannot be compiled without that target feature.
-    /// A similar (but complementary) message is triggered when `with_target_feature` is called
-    /// by a function that does not enable the `avx` target feature.
-    ///
-    /// Note that this lint is very similar to the `-Wpsabi` warning in `gcc`/`clang`.
-    pub ABI_UNSUPPORTED_VECTOR_TYPES,
-    Warn,
-    "this function call or definition uses a vector type which is not enabled",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
-        reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
-    };
-}
-
-declare_lint! {
     /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
     /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
     /// of this target.
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index e02c80c50b1..8bee051dd4c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -14,6 +14,7 @@
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/Verifier.h"
+#include "llvm/IRPrinter/IRPrintingPasses.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -703,7 +704,8 @@ extern "C" LLVMRustResult LLVMRustOptimize(
     bool LintIR, LLVMRustThinLTOBuffer **ThinLTOBufferRef, bool EmitThinLTO,
     bool EmitThinLTOSummary, bool MergeFunctions, bool UnrollLoops,
     bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls,
-    bool EmitLifetimeMarkers, bool RunEnzyme,
+    bool EmitLifetimeMarkers, bool RunEnzyme, bool PrintBeforeEnzyme,
+    bool PrintAfterEnzyme, bool PrintPasses,
     LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath,
     const char *PGOUsePath, bool InstrumentCoverage,
     const char *InstrProfileOutput, const char *PGOSampleUsePath,
@@ -1048,14 +1050,38 @@ extern "C" LLVMRustResult LLVMRustOptimize(
   // now load "-enzyme" pass:
 #ifdef ENZYME
   if (RunEnzyme) {
-    registerEnzymeAndPassPipeline(PB, true);
+
+    if (PrintBeforeEnzyme) {
+      // Handle the Rust flag `-Zautodiff=PrintModBefore`.
+      std::string Banner = "Module before EnzymeNewPM";
+      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
+    }
+
+    registerEnzymeAndPassPipeline(PB, false);
     if (auto Err = PB.parsePassPipeline(MPM, "enzyme")) {
       std::string ErrMsg = toString(std::move(Err));
       LLVMRustSetLastError(ErrMsg.c_str());
       return LLVMRustResult::Failure;
     }
+
+    if (PrintAfterEnzyme) {
+      // Handle the Rust flag `-Zautodiff=PrintModAfter`.
+      std::string Banner = "Module after EnzymeNewPM";
+      MPM.addPass(PrintModulePass(outs(), Banner, true, false));
+    }
   }
 #endif
+  if (PrintPasses) {
+    // Print all passes from the PM:
+    std::string Pipeline;
+    raw_string_ostream SOS(Pipeline);
+    MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
+      auto PassName = PIC.getPassNameForClassName(ClassName);
+      return PassName.empty() ? ClassName : PassName;
+    });
+    outs() << Pipeline;
+    outs() << "\n";
+  }
 
   // Upgrade all calls to old intrinsics first.
   for (Module::iterator I = TheModule->begin(), E = TheModule->end(); I != E;)
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 91398f1a9da..55228248188 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -55,8 +55,7 @@ use synstructure::Structure;
 ///
 /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
-pub(super) fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
-    s.underscore_const(true);
+pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream {
     DiagnosticDerive::new(s).into_tokens()
 }
 
@@ -102,8 +101,7 @@ pub(super) fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
 ///
 /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
-pub(super) fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
-    s.underscore_const(true);
+pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
     LintDiagnosticDerive::new(s).into_tokens()
 }
 
@@ -153,7 +151,6 @@ pub(super) fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
 ///
 /// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
 /// ```
-pub(super) fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream {
-    s.underscore_const(true);
+pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
     SubdiagnosticDerive::new().into_tokens(s)
 }
diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs
index 6b3210cad7b..a6396ba687d 100644
--- a/compiler/rustc_macros/src/hash_stable.rs
+++ b/compiler/rustc_macros/src/hash_stable.rs
@@ -74,8 +74,6 @@ fn hash_stable_derive_with_mode(
         HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX),
     };
 
-    s.underscore_const(true);
-
     // no_context impl is able to derive by-field, which is closer to a perfect derive.
     s.add_bounds(match mode {
         HashStableMode::Normal | HashStableMode::Generic => synstructure::AddBounds::Generics,
diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs
index 341447f7e6f..03ea396a42c 100644
--- a/compiler/rustc_macros/src/lift.rs
+++ b/compiler/rustc_macros/src/lift.rs
@@ -4,7 +4,6 @@ use syn::parse_quote;
 pub(super) fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     s.add_bounds(synstructure::AddBounds::Generics);
     s.bind_with(|_| synstructure::BindStyle::Move);
-    s.underscore_const(true);
 
     let tcx: syn::Lifetime = parse_quote!('tcx);
     let newtcx: syn::GenericParam = parse_quote!('__lifted);
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index 673e6cd618f..c7aaaf0da46 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -12,7 +12,6 @@ pub(super) fn type_decodable_derive(
     let decoder_ty = quote! { __D };
     s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_middle::ty::codec::TyDecoder<'tcx> });
     s.add_bounds(synstructure::AddBounds::Fields);
-    s.underscore_const(true);
 
     decodable_body(s, decoder_ty)
 }
@@ -26,7 +25,6 @@ pub(super) fn meta_decodable_derive(
     s.add_impl_generic(parse_quote! { '__a });
     let decoder_ty = quote! { DecodeContext<'__a, 'tcx> };
     s.add_bounds(synstructure::AddBounds::Generics);
-    s.underscore_const(true);
 
     decodable_body(s, decoder_ty)
 }
@@ -35,7 +33,6 @@ pub(super) fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro
     let decoder_ty = quote! { __D };
     s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_span::SpanDecoder });
     s.add_bounds(synstructure::AddBounds::Generics);
-    s.underscore_const(true);
 
     decodable_body(s, decoder_ty)
 }
@@ -46,13 +43,12 @@ pub(super) fn decodable_nocontext_derive(
     let decoder_ty = quote! { __D };
     s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_serialize::Decoder });
     s.add_bounds(synstructure::AddBounds::Fields);
-    s.underscore_const(true);
 
     decodable_body(s, decoder_ty)
 }
 
 fn decodable_body(
-    mut s: synstructure::Structure<'_>,
+    s: synstructure::Structure<'_>,
     decoder_ty: TokenStream,
 ) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
@@ -98,7 +94,6 @@ fn decodable_body(
             }
         }
     };
-    s.underscore_const(true);
 
     s.bound_impl(
         quote!(::rustc_serialize::Decodable<#decoder_ty>),
@@ -133,7 +128,6 @@ pub(super) fn type_encodable_derive(
     }
     s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_middle::ty::codec::TyEncoder<'tcx> });
     s.add_bounds(synstructure::AddBounds::Fields);
-    s.underscore_const(true);
 
     encodable_body(s, encoder_ty, false)
 }
@@ -147,7 +141,6 @@ pub(super) fn meta_encodable_derive(
     s.add_impl_generic(parse_quote! { '__a });
     let encoder_ty = quote! { EncodeContext<'__a, 'tcx> };
     s.add_bounds(synstructure::AddBounds::Generics);
-    s.underscore_const(true);
 
     encodable_body(s, encoder_ty, true)
 }
@@ -156,7 +149,6 @@ pub(super) fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro
     let encoder_ty = quote! { __E };
     s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_span::SpanEncoder });
     s.add_bounds(synstructure::AddBounds::Generics);
-    s.underscore_const(true);
 
     encodable_body(s, encoder_ty, false)
 }
@@ -167,7 +159,6 @@ pub(super) fn encodable_nocontext_derive(
     let encoder_ty = quote! { __E };
     s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder });
     s.add_bounds(synstructure::AddBounds::Fields);
-    s.underscore_const(true);
 
     encodable_body(s, encoder_ty, false)
 }
@@ -181,7 +172,6 @@ fn encodable_body(
         panic!("cannot derive on union")
     }
 
-    s.underscore_const(true);
     s.bind_with(|binding| {
         // Handle the lack of a blanket reference impl.
         if let syn::Type::Reference(_) = binding.ast().ty {
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index 85051311bee..91b747f1856 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -6,8 +6,6 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
         panic!("cannot derive on union")
     }
 
-    s.underscore_const(true);
-
     if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
         s.add_impl_generic(parse_quote! { 'tcx });
     }
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index fb37e1a39ed..f99c5113a60 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -8,8 +8,6 @@ pub(super) fn type_visitable_derive(
         panic!("cannot derive on union")
     }
 
-    s.underscore_const(true);
-
     // ignore fields with #[type_visitable(ignore)]
     s.filter(|bi| {
         let mut ignored = false;
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 7a91bfad483..0f92c1910f1 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -35,11 +35,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// returns a corresponding [`ty::ClosureKind`].
     /// For any other [`DefId`] return `None`.
     pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
-        let items = self.lang_items();
-        match Some(id) {
-            x if x == items.fn_trait() => Some(ty::ClosureKind::Fn),
-            x if x == items.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
-            x if x == items.fn_once_trait() => Some(ty::ClosureKind::FnOnce),
+        match self.as_lang_item(id)? {
+            LangItem::Fn => Some(ty::ClosureKind::Fn),
+            LangItem::FnMut => Some(ty::ClosureKind::FnMut),
+            LangItem::FnOnce => Some(ty::ClosureKind::FnOnce),
             _ => None,
         }
     }
@@ -48,11 +47,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// returns a corresponding [`ty::ClosureKind`].
     /// For any other [`DefId`] return `None`.
     pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
-        let items = self.lang_items();
-        match Some(id) {
-            x if x == items.async_fn_trait() => Some(ty::ClosureKind::Fn),
-            x if x == items.async_fn_mut_trait() => Some(ty::ClosureKind::FnMut),
-            x if x == items.async_fn_once_trait() => Some(ty::ClosureKind::FnOnce),
+        match self.as_lang_item(id)? {
+            LangItem::AsyncFn => Some(ty::ClosureKind::Fn),
+            LangItem::AsyncFnMut => Some(ty::ClosureKind::FnMut),
+            LangItem::AsyncFnOnce => Some(ty::ClosureKind::FnOnce),
             _ => None,
         }
     }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index e94f088304b..3432648feab 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -387,6 +387,15 @@ rustc_queries! {
         }
     }
 
+    query stalled_generators_within(
+        key: LocalDefId
+    ) -> &'tcx ty::List<LocalDefId> {
+        desc {
+            |tcx| "computing the coroutines defined within `{}`",
+            tcx.def_path_str(key.to_def_id())
+        }
+    }
+
     /// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId`
     /// that must be proven true at definition site (and which can be assumed at usage sites).
     ///
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index a099f770417..69b6f88d72b 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -366,7 +366,7 @@ macro_rules! define_callbacks {
 
                 pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
 
-                // Ensure that keys grow no larger than 80 bytes by accident.
+                // Ensure that keys grow no larger than 88 bytes by accident.
                 // Increase this limit if necessary, but do try to keep the size low if possible
                 #[cfg(target_pointer_width = "64")]
                 const _: () = {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index fa2f1cf1a1c..98057a25f04 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -106,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     ) -> Self::PredefinedOpaques {
         self.mk_predefined_opaques_in_body(data)
     }
-    type DefiningOpaqueTypes = &'tcx ty::List<LocalDefId>;
+    type LocalDefIds = &'tcx ty::List<LocalDefId>;
     type CanonicalVars = CanonicalVarInfos<'tcx>;
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
         self.mk_canonical_var_infos(infos)
@@ -674,9 +674,24 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.anonymize_bound_vars(binder)
     }
 
-    fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
+    fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds {
         self.opaque_types_defined_by(defining_anchor)
     }
+
+    fn opaque_types_and_generators_defined_by(
+        self,
+        defining_anchor: Self::LocalDefId,
+    ) -> Self::LocalDefIds {
+        if self.next_trait_solver_globally() {
+            self.mk_local_def_ids_from_iter(
+                self.opaque_types_defined_by(defining_anchor)
+                    .iter()
+                    .chain(self.stalled_generators_within(defining_anchor)),
+            )
+        } else {
+            self.opaque_types_defined_by(defining_anchor)
+        }
+    }
 }
 
 macro_rules! bidirectional_lang_item_map {
@@ -2906,11 +2921,11 @@ impl<'tcx> TyCtxt<'tcx> {
         self.interners.intern_clauses(clauses)
     }
 
-    pub fn mk_local_def_ids(self, clauses: &[LocalDefId]) -> &'tcx List<LocalDefId> {
+    pub fn mk_local_def_ids(self, def_ids: &[LocalDefId]) -> &'tcx List<LocalDefId> {
         // FIXME consider asking the input slice to be sorted to avoid
         // re-interning permutations, in which case that would be asserted
         // here.
-        self.intern_local_def_ids(clauses)
+        self.intern_local_def_ids(def_ids)
     }
 
     pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 301ae604574..affb7b31ae1 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1774,9 +1774,7 @@ impl<'tcx> Ty<'tcx> {
             match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
                 Ok(metadata_ty) => metadata_ty,
                 Err(tail_ty) => {
-                    let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
-                        bug!("No metadata_type lang item while looking at {self:?}")
-                    };
+                    let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
                     Ty::new_projection(tcx, metadata_def_id, [tail_ty])
                 }
             }
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index 73cc3c86e22..210b9cce581 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -146,6 +146,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let mut place = place;
                 let mut block = block;
                 match ty.kind() {
+                    ty::Str => {
+                        // String literal patterns may have type `str` if `deref_patterns` is
+                        // enabled, in order to allow `deref!("..."): String`. In this case, `value`
+                        // is of type `&str`, so we compare it to `&place`.
+                        if !tcx.features().deref_patterns() {
+                            span_bug!(
+                                test.span,
+                                "matching on `str` went through without enabling deref_patterns"
+                            );
+                        }
+                        let re_erased = tcx.lifetimes.re_erased;
+                        let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
+                        let ref_place = self.temp(ref_str_ty, test.span);
+                        // `let ref_place: &str = &place;`
+                        self.cfg.push_assign(
+                            block,
+                            self.source_info(test.span),
+                            ref_place,
+                            Rvalue::Ref(re_erased, BorrowKind::Shared, place),
+                        );
+                        place = ref_place;
+                        ty = ref_str_ty;
+                    }
                     ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => {
                         if !tcx.features().string_deref_patterns() {
                             span_bug!(
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index b3210813703..b4fa55e1c1f 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -37,13 +37,23 @@ pub(crate) fn lit_to_const<'tcx>(
             let str_bytes = s.as_str().as_bytes();
             ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
+        (ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
+            // String literal patterns may have type `str` if `deref_patterns` is enabled, in order
+            // to allow `deref!("..."): String`.
+            let str_bytes = s.as_str().as_bytes();
+            ty::ValTree::from_raw_bytes(tcx, str_bytes)
+        }
         (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
-            if matches!(inner_ty.kind(), ty::Slice(_)) =>
+            if matches!(inner_ty.kind(), ty::Slice(_) | ty::Array(..)) =>
         {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
-        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+        (ast::LitKind::ByteStr(data, _), ty::Slice(_) | ty::Array(..))
+            if tcx.features().deref_patterns() =>
+        {
+            // Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
+            // enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
         }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index a40001bf745..b7d203e3cd7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -280,6 +280,16 @@ impl<'tcx> ConstToPat<'tcx> {
                 slice: None,
                 suffix: Box::new([]),
             },
+            ty::Str => {
+                // String literal patterns may have type `str` if `deref_patterns` is enabled, in
+                // order to allow `deref!("..."): String`. Since we need a `&str` for the comparison
+                // when lowering to MIR in `Builder::perform_test`, treat the constant as a `&str`.
+                // This works because `str` and `&str` have the same valtree representation.
+                let ref_str_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty);
+                PatKind::Constant {
+                    value: mir::Const::Ty(ref_str_ty, ty::Const::new_value(tcx, cv, ref_str_ty)),
+                }
+            }
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
                 // `&str` is represented as a valtree, let's keep using this
                 // optimization for now.
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index c46ae9775cf..d5005768b80 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -114,26 +114,11 @@ where
         self.reachable_blocks.insert_all()
     }
 
-    /// Returns the underlying `Results`.
-    pub fn results(&self) -> &Results<'tcx, A> {
-        &self.results
-    }
-
-    /// Returns the underlying `Results`.
-    pub fn mut_results(&mut self) -> &mut Results<'tcx, A> {
-        &mut self.results
-    }
-
     /// Returns the `Analysis` used to generate the underlying `Results`.
     pub fn analysis(&self) -> &A {
         &self.results.analysis
     }
 
-    /// Returns the `Analysis` used to generate the underlying `Results`.
-    pub fn mut_analysis(&mut self) -> &mut A {
-        &mut self.results.analysis
-    }
-
     /// Resets the cursor to hold the entry set for the given basic block.
     ///
     /// For forward dataflow analyses, this is the dataflow state prior to the first statement.
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 3d7f9e2d8e7..b8c26dad59f 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -43,7 +43,7 @@ pub trait Direction {
         block: BasicBlock,
         block_data: &'mir mir::BasicBlockData<'tcx>,
         results: &mut Results<'tcx, A>,
-        vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
+        vis: &mut impl ResultsVisitor<'tcx, A>,
     ) where
         A: Analysis<'tcx>;
 }
@@ -212,7 +212,7 @@ impl Direction for Backward {
         block: BasicBlock,
         block_data: &'mir mir::BasicBlockData<'tcx>,
         results: &mut Results<'tcx, A>,
-        vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
+        vis: &mut impl ResultsVisitor<'tcx, A>,
     ) where
         A: Analysis<'tcx>,
     {
@@ -394,7 +394,7 @@ impl Direction for Forward {
         block: BasicBlock,
         block_data: &'mir mir::BasicBlockData<'tcx>,
         results: &mut Results<'tcx, A>,
-        vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
+        vis: &mut impl ResultsVisitor<'tcx, A>,
     ) where
         A: Analysis<'tcx>,
     {
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 95f488a925b..b5e9a0b8932 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -201,11 +201,12 @@ struct Formatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
+    body: &'mir Body<'tcx>,
     // The `RefCell` is used because `<Formatter as Labeller>::node_label`
-    // takes `&self`, but it needs to modify the cursor. This is also the
+    // takes `&self`, but it needs to modify the results. This is also the
     // reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has
     // the operations that involve the mutation, i.e. within the `borrow_mut`.
-    cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
+    results: RefCell<&'mir mut Results<'tcx, A>>,
     style: OutputStyle,
     reachable: DenseBitSet<BasicBlock>,
 }
@@ -220,11 +221,7 @@ where
         style: OutputStyle,
     ) -> Self {
         let reachable = traversal::reachable_as_bitset(body);
-        Formatter { cursor: results.as_results_cursor(body).into(), style, reachable }
-    }
-
-    fn body(&self) -> &'mir Body<'tcx> {
-        self.cursor.borrow().body()
+        Formatter { body, results: results.into(), style, reachable }
     }
 }
 
@@ -253,7 +250,7 @@ where
     type Edge = CfgEdge;
 
     fn graph_id(&self) -> dot::Id<'_> {
-        let name = graphviz_safe_def_name(self.body().source.def_id());
+        let name = graphviz_safe_def_name(self.body.source.def_id());
         dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
     }
 
@@ -262,10 +259,16 @@ where
     }
 
     fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
-        let mut cursor = self.cursor.borrow_mut();
-        let mut fmt =
-            BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
-        let label = fmt.write_node_label(*block).unwrap();
+        let mut results = self.results.borrow_mut();
+
+        let diffs = StateDiffCollector::run(self.body, *block, *results, self.style);
+
+        let mut fmt = BlockFormatter {
+            cursor: results.as_results_cursor(self.body),
+            style: self.style,
+            bg: Background::Light,
+        };
+        let label = fmt.write_node_label(*block, diffs).unwrap();
 
         dot::LabelText::html(String::from_utf8(label).unwrap())
     }
@@ -275,7 +278,7 @@ where
     }
 
     fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
-        let label = &self.body()[e.source].terminator().kind.fmt_successor_labels()[e.index];
+        let label = &self.body[e.source].terminator().kind.fmt_successor_labels()[e.index];
         dot::LabelText::label(label.clone())
     }
 }
@@ -288,7 +291,7 @@ where
     type Edge = CfgEdge;
 
     fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
-        self.body()
+        self.body
             .basic_blocks
             .indices()
             .filter(|&idx| self.reachable.contains(idx))
@@ -297,10 +300,10 @@ where
     }
 
     fn edges(&self) -> dot::Edges<'_, Self::Edge> {
-        let body = self.body();
-        body.basic_blocks
+        self.body
+            .basic_blocks
             .indices()
-            .flat_map(|bb| dataflow_successors(body, bb))
+            .flat_map(|bb| dataflow_successors(self.body, bb))
             .collect::<Vec<_>>()
             .into()
     }
@@ -310,20 +313,20 @@ where
     }
 
     fn target(&self, edge: &Self::Edge) -> Self::Node {
-        self.body()[edge.source].terminator().successors().nth(edge.index).unwrap()
+        self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
     }
 }
 
-struct BlockFormatter<'a, 'mir, 'tcx, A>
+struct BlockFormatter<'mir, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
+    cursor: ResultsCursor<'mir, 'tcx, A>,
     bg: Background,
     style: OutputStyle,
 }
 
-impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
+impl<'tcx, A> BlockFormatter<'_, 'tcx, A>
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
@@ -336,7 +339,11 @@ where
         bg
     }
 
-    fn write_node_label(&mut self, block: BasicBlock) -> io::Result<Vec<u8>> {
+    fn write_node_label(
+        &mut self,
+        block: BasicBlock,
+        diffs: StateDiffCollector<A::Domain>,
+    ) -> io::Result<Vec<u8>> {
         use std::io::Write;
 
         //   Sample output:
@@ -392,7 +399,7 @@ where
         self.write_row_with_full_state(w, "", "(on start)")?;
 
         // D + E: Statement and terminator transfer functions
-        self.write_statements_and_terminator(w, block)?;
+        self.write_statements_and_terminator(w, block, diffs)?;
 
         // F: State at end of block
 
@@ -575,14 +582,8 @@ where
         &mut self,
         w: &mut impl io::Write,
         block: BasicBlock,
+        diffs: StateDiffCollector<A::Domain>,
     ) -> io::Result<()> {
-        let diffs = StateDiffCollector::run(
-            self.cursor.body(),
-            block,
-            self.cursor.mut_results(),
-            self.style,
-        );
-
         let mut diffs_before = diffs.before.map(|v| v.into_iter());
         let mut diffs_after = diffs.after.into_iter();
 
@@ -709,7 +710,7 @@ impl<D> StateDiffCollector<D> {
     }
 }
 
-impl<'tcx, A> ResultsVisitor<'_, 'tcx, A> for StateDiffCollector<A::Domain>
+impl<'tcx, A> ResultsVisitor<'tcx, A> for StateDiffCollector<A::Domain>
 where
     A: Analysis<'tcx>,
     A::Domain: DebugWithContext<A>,
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index 8e2c3afddb3..93dfc06a878 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -47,7 +47,7 @@ where
         &mut self,
         body: &'mir Body<'tcx>,
         blocks: impl IntoIterator<Item = BasicBlock>,
-        vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
+        vis: &mut impl ResultsVisitor<'tcx, A>,
     ) {
         visit_results(body, blocks, self, vis)
     }
@@ -55,7 +55,7 @@ where
     pub fn visit_reachable_with<'mir>(
         &mut self,
         body: &'mir Body<'tcx>,
-        vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
+        vis: &mut impl ResultsVisitor<'tcx, A>,
     ) {
         let blocks = traversal::reachable(body);
         visit_results(body, blocks.map(|(bb, _)| bb), self, vis)
diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
index a03aecee7be..c9fdf46c4f5 100644
--- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
@@ -8,7 +8,7 @@ pub fn visit_results<'mir, 'tcx, A>(
     body: &'mir mir::Body<'tcx>,
     blocks: impl IntoIterator<Item = BasicBlock>,
     results: &mut Results<'tcx, A>,
-    vis: &mut impl ResultsVisitor<'mir, 'tcx, A>,
+    vis: &mut impl ResultsVisitor<'tcx, A>,
 ) where
     A: Analysis<'tcx>,
 {
@@ -29,7 +29,7 @@ pub fn visit_results<'mir, 'tcx, A>(
 /// A visitor over the results of an `Analysis`. Use this when you want to inspect domain values in
 /// many or all locations; use `ResultsCursor` if you want to inspect domain values only in certain
 /// locations.
-pub trait ResultsVisitor<'mir, 'tcx, A>
+pub trait ResultsVisitor<'tcx, A>
 where
     A: Analysis<'tcx>,
 {
@@ -40,7 +40,7 @@ where
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
-        _statement: &'mir mir::Statement<'tcx>,
+        _statement: &mir::Statement<'tcx>,
         _location: Location,
     ) {
     }
@@ -50,7 +50,7 @@ where
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
-        _statement: &'mir mir::Statement<'tcx>,
+        _statement: &mir::Statement<'tcx>,
         _location: Location,
     ) {
     }
@@ -60,7 +60,7 @@ where
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
-        _terminator: &'mir mir::Terminator<'tcx>,
+        _terminator: &mir::Terminator<'tcx>,
         _location: Location,
     ) {
     }
@@ -72,7 +72,7 @@ where
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
-        _terminator: &'mir mir::Terminator<'tcx>,
+        _terminator: &mir::Terminator<'tcx>,
         _location: Location,
     ) {
     }
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
index 5d2a78acbf5..21590ff1bba 100644
--- a/compiler/rustc_mir_dataflow/src/points.rs
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -120,12 +120,12 @@ struct Visitor<'a, N: Idx> {
     values: SparseIntervalMatrix<N, PointIndex>,
 }
 
-impl<'mir, 'tcx, A, N> ResultsVisitor<'mir, 'tcx, A> for Visitor<'_, N>
+impl<'tcx, A, N> ResultsVisitor<'tcx, A> for Visitor<'_, N>
 where
     A: Analysis<'tcx, Domain = DenseBitSet<N>>,
     N: Idx,
 {
-    fn visit_after_primary_statement_effect(
+    fn visit_after_primary_statement_effect<'mir>(
         &mut self,
         _results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -139,7 +139,7 @@ where
         });
     }
 
-    fn visit_after_primary_terminator_effect(
+    fn visit_after_primary_terminator_effect<'mir>(
         &mut self,
         _results: &mut Results<'tcx, A>,
         state: &A::Domain,
diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl
index 5628f4c9381..a1264471a2d 100644
--- a/compiler/rustc_mir_transform/messages.ftl
+++ b/compiler/rustc_mir_transform/messages.ftl
@@ -84,3 +84,4 @@ mir_transform_undefined_transmute = pointers cannot be transmuted to integers du
     .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
 
 mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored
+mir_transform_unnecessary_transmute = unnecessary transmute
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index b70cca14840..5115583f37c 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,3 +1,4 @@
+use rustc_abi::Align;
 use rustc_index::IndexVec;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::PlaceContext;
@@ -11,10 +12,6 @@ pub(super) struct CheckAlignment;
 
 impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
     fn is_enabled(&self, sess: &Session) -> bool {
-        // FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows
-        if sess.target.llvm_target == "i686-pc-windows-msvc" {
-            return false;
-        }
         sess.ub_checks()
     }
 
@@ -87,6 +84,33 @@ fn insert_alignment_check<'tcx>(
         ))),
     });
 
+    // If this target does not have reliable alignment, further limit the mask by anding it with
+    // the mask for the highest reliable alignment.
+    #[allow(irrefutable_let_patterns)]
+    if let max_align = tcx.sess.target.max_reliable_alignment()
+        && max_align < Align::MAX
+    {
+        let max_mask = max_align.bytes() - 1;
+        let max_mask = Operand::Constant(Box::new(ConstOperand {
+            span: source_info.span,
+            user_ty: None,
+            const_: Const::Val(
+                ConstValue::Scalar(Scalar::from_target_usize(max_mask, &tcx)),
+                tcx.types.usize,
+            ),
+        }));
+        stmts.push(Statement {
+            source_info,
+            kind: StatementKind::Assign(Box::new((
+                alignment_mask,
+                Rvalue::BinaryOp(
+                    BinOp::BitAnd,
+                    Box::new((Operand::Copy(alignment_mask), max_mask)),
+                ),
+            ))),
+        });
+    }
+
     // BitAnd the alignment mask with the pointer
     let alignment_bits =
         local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs
index e49723a6c39..cace4cd6bba 100644
--- a/compiler/rustc_mir_transform/src/check_call_recursion.rs
+++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs
@@ -3,6 +3,7 @@ use std::ops::ControlFlow;
 use rustc_data_structures::graph::iterate::{
     NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
 };
+use rustc_hir::LangItem;
 use rustc_hir::def::DefKind;
 use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind};
 use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt};
@@ -44,8 +45,7 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
         if let DefKind::AssocFn = tcx.def_kind(def_id)
         && let Some(trait_ref) =
             tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
-        && let Some(drop_trait) = tcx.lang_items().drop_trait()
-        && drop_trait == trait_ref.instantiate_identity().def_id
+        && tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
         // avoid erroneous `Drop` impls from causing ICEs below
         && let sig = tcx.fn_sig(def_id).instantiate_identity()
         && sig.inputs().skip_binder().len() == 1
diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
new file mode 100644
index 00000000000..8be782dcbf0
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
@@ -0,0 +1,100 @@
+use rustc_middle::mir::visit::Visitor;
+use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind};
+use rustc_middle::ty::*;
+use rustc_session::lint::builtin::UNNECESSARY_TRANSMUTES;
+use rustc_span::source_map::Spanned;
+use rustc_span::{Span, sym};
+
+use crate::errors::UnnecessaryTransmute as Error;
+
+/// Check for transmutes that overlap with stdlib methods.
+/// For example, transmuting `[u8; 4]` to `u32`.
+pub(super) struct CheckUnnecessaryTransmutes;
+
+impl<'tcx> crate::MirLint<'tcx> for CheckUnnecessaryTransmutes {
+    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
+        let mut checker = UnnecessaryTransmuteChecker { body, tcx };
+        checker.visit_body(body);
+    }
+}
+
+struct UnnecessaryTransmuteChecker<'a, 'tcx> {
+    body: &'a Body<'tcx>,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
+    fn is_unnecessary_transmute(
+        &self,
+        function: &Operand<'tcx>,
+        arg: String,
+        span: Span,
+    ) -> Option<Error> {
+        let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
+        let [input] = fn_sig.inputs() else { return None };
+
+        let err = |sugg| Error { span, sugg, help: None };
+
+        Some(match (input.kind(), fn_sig.output().kind()) {
+            // dont check the length; transmute does that for us.
+            // [u8; _] => primitive
+            (Array(t, _), Uint(_) | Float(_) | Int(_)) if *t.kind() == Uint(UintTy::U8) => Error {
+                sugg: format!("{}::from_ne_bytes({arg})", fn_sig.output()),
+                help: Some(
+                    "there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order",
+                ),
+                span,
+            },
+            // primitive => [u8; _]
+            (Uint(_) | Float(_) | Int(_), Array(t, _)) if *t.kind() == Uint(UintTy::U8) => Error {
+                sugg: format!("{input}::to_ne_bytes({arg})"),
+                help: Some(
+                    "there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order",
+                ),
+                span,
+            },
+            // char → u32
+            (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")),
+            // u32 → char
+            (Uint(UintTy::U32), Char) => Error {
+                sugg: format!("char::from_u32_unchecked({arg})"),
+                help: Some("consider `char::from_u32(…).unwrap()`"),
+                span,
+            },
+            // uNN → iNN
+            (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())),
+            // iNN → uNN
+            (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())),
+            // fNN → uNN
+            (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())),
+            // uNN → fNN
+            (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())),
+            // bool → { x8 }
+            (Bool, Int(..) | Uint(..)) => err(format!("({arg}) as {}", fn_sig.output())),
+            // u8 → bool
+            (Uint(_), Bool) => err(format!("({arg} == 1)")),
+            _ => return None,
+        })
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
+    // Check each block's terminator for calls to pointer to integer transmutes
+    // in const functions or associated constants and emit a lint.
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+        if let TerminatorKind::Call { func, args, .. } = &terminator.kind
+            && let [Spanned { span: arg, .. }] = **args
+            && let Some((func_def_id, _)) = func.const_fn_def()
+            && self.tcx.is_intrinsic(func_def_id, sym::transmute)
+            && let span = self.body.source_info(location).span
+            && let Some(lint) = self.is_unnecessary_transmute(
+                func,
+                self.tcx.sess.source_map().span_to_snippet(arg).expect("ok"),
+                span,
+            )
+            && let Some(hir_id) = terminator.source_info.scope.lint_root(&self.body.source_scopes)
+        {
+            self.tcx.emit_node_span_lint(UNNECESSARY_TRANSMUTES, hir_id, span, lint);
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 92d5e152f58..0eed46c72f9 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -875,14 +875,14 @@ struct StorageConflictVisitor<'a, 'tcx> {
     eligible_storage_live: DenseBitSet<Local>,
 }
 
-impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
+impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage<'a, 'tcx>>
     for StorageConflictVisitor<'a, 'tcx>
 {
     fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
         state: &DenseBitSet<Local>,
-        _statement: &'a Statement<'tcx>,
+        _statement: &Statement<'tcx>,
         loc: Location,
     ) {
         self.apply_state(state, loc);
@@ -892,7 +892,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
         &mut self,
         _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
         state: &DenseBitSet<Local>,
-        _terminator: &'a Terminator<'tcx>,
+        _terminator: &Terminator<'tcx>,
         loc: Location,
     ) {
         self.apply_state(state, loc);
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 90173da17f0..a2103a004d2 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -958,13 +958,13 @@ fn try_write_constant<'tcx>(
     interp_ok(())
 }
 
-impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> {
+impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> {
     #[instrument(level = "trace", skip(self, results, statement))]
     fn visit_after_early_statement_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
-        statement: &'mir Statement<'tcx>,
+        statement: &Statement<'tcx>,
         location: Location,
     ) {
         match &statement.kind {
@@ -986,7 +986,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
-        statement: &'mir Statement<'tcx>,
+        statement: &Statement<'tcx>,
         location: Location,
     ) {
         match statement.kind {
@@ -1011,7 +1011,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
-        terminator: &'mir Terminator<'tcx>,
+        terminator: &Terminator<'tcx>,
         location: Location,
     ) {
         OperandCollector {
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 29698b0c2e4..5b03a4987ed 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -158,6 +158,26 @@ pub(crate) struct MustNotSuspendReason {
     pub reason: String,
 }
 
+pub(crate) struct UnnecessaryTransmute {
+    pub span: Span,
+    pub sugg: String,
+    pub help: Option<&'static str>,
+}
+
+// Needed for def_path_str
+impl<'a> LintDiagnostic<'a, ()> for UnnecessaryTransmute {
+    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
+        diag.primary_message(fluent::mir_transform_unnecessary_transmute);
+        diag.span_suggestion(
+            self.span,
+            "replace this with",
+            self.sugg,
+            lint::Applicability::MachineApplicable,
+        );
+        self.help.map(|help| diag.help(help));
+    }
+}
+
 #[derive(LintDiagnostic)]
 #[diag(mir_transform_undefined_transmute)]
 #[note]
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 4d74ecddfb0..6977d23bd0e 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -125,6 +125,7 @@ declare_passes! {
     mod check_null : CheckNull;
     mod check_packed_ref : CheckPackedRef;
     mod check_undefined_transmutes : CheckUndefinedTransmutes;
+    mod check_unnecessary_transmutes: CheckUnnecessaryTransmutes;
     // This pass is public to allow external drivers to perform MIR cleanup
     pub mod cleanup_post_borrowck : CleanupPostBorrowck;
 
@@ -391,6 +392,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
             &Lint(check_const_item_mutation::CheckConstItemMutation),
             &Lint(function_item_references::FunctionItemReferences),
             &Lint(check_undefined_transmutes::CheckUndefinedTransmutes),
+            &Lint(check_unnecessary_transmutes::CheckUnnecessaryTransmutes),
             // What we need to do constant evaluation.
             &simplify::SimplifyCfg::Initial,
             &Lint(sanity_check::SanityCheck),
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index adfe096f0cd..0dd20bbb35f 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -70,10 +70,11 @@ pub(crate) struct UnknownCguCollectionMode<'a> {
     pub mode: &'a str,
 }
 
-#[derive(LintDiagnostic)]
+#[derive(Diagnostic)]
 #[diag(monomorphize_abi_error_disabled_vector_type)]
 #[help]
 pub(crate) struct AbiErrorDisabledVectorType<'a> {
+    #[primary_span]
     #[label]
     pub span: Span,
     pub required_feature: &'a str,
@@ -82,9 +83,10 @@ pub(crate) struct AbiErrorDisabledVectorType<'a> {
     pub is_call: bool,
 }
 
-#[derive(LintDiagnostic)]
+#[derive(Diagnostic)]
 #[diag(monomorphize_abi_error_unsupported_vector_type)]
 pub(crate) struct AbiErrorUnsupportedVectorType<'a> {
+    #[primary_span]
     #[label]
     pub span: Span,
     pub ty: Ty<'a>,
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 94ee34c8b7b..cfeaee07776 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -5,7 +5,7 @@ use rustc_hir::{CRATE_HIR_ID, HirId};
 use rustc_middle::mir::{self, Location, traversal};
 use rustc_middle::ty::layout::LayoutCx;
 use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
-use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI};
+use rustc_session::lint::builtin::WASM_C_ABI;
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
@@ -50,34 +50,24 @@ fn do_check_simd_vector_abi<'tcx>(
             let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
                 Some((_, feature)) => feature,
                 None => {
-                    let (span, hir_id) = loc();
-                    tcx.emit_node_span_lint(
-                        ABI_UNSUPPORTED_VECTOR_TYPES,
-                        hir_id,
+                    let (span, _hir_id) = loc();
+                    tcx.dcx().emit_err(errors::AbiErrorUnsupportedVectorType {
                         span,
-                        errors::AbiErrorUnsupportedVectorType {
-                            span,
-                            ty: arg_abi.layout.ty,
-                            is_call,
-                        },
-                    );
+                        ty: arg_abi.layout.ty,
+                        is_call,
+                    });
                     continue;
                 }
             };
             if !have_feature(Symbol::intern(feature)) {
                 // Emit error.
-                let (span, hir_id) = loc();
-                tcx.emit_node_span_lint(
-                    ABI_UNSUPPORTED_VECTOR_TYPES,
-                    hir_id,
+                let (span, _hir_id) = loc();
+                tcx.dcx().emit_err(errors::AbiErrorDisabledVectorType {
                     span,
-                    errors::AbiErrorDisabledVectorType {
-                        span,
-                        required_feature: feature,
-                        ty: arg_abi.layout.ty,
-                        is_call,
-                    },
-                );
+                    required_feature: feature,
+                    ty: arg_abi.layout.ty,
+                    is_call,
+                });
             }
         }
     }
@@ -99,6 +89,12 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
         return true;
     }
 
+    // Both the old and the new ABIs treat vector types like `v128` the same
+    // way.
+    if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) {
+        return true;
+    }
+
     // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
     if arg.layout.is_aggregate() {
         let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index d7690a96e10..6bc8a0fc88c 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -223,7 +223,7 @@ where
         match mono_item.instantiation_mode(cx.tcx) {
             InstantiationMode::GloballyShared { .. } => {}
             InstantiationMode::LocalCopy => {
-                if Some(mono_item.def_id()) != cx.tcx.lang_items().start_fn() {
+                if !cx.tcx.is_lang_item(mono_item.def_id(), LangItem::Start) {
                     continue;
                 }
             }
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 7641e9a16ee..0695c5acdca 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -329,7 +329,7 @@ where
             TypingMode::Coherence | TypingMode::PostAnalysis => false,
             // During analysis, opaques are rigid unless they may be defined by
             // the current body.
-            TypingMode::Analysis { defining_opaque_types: non_rigid_opaques }
+            TypingMode::Analysis { defining_opaque_types_and_generators: non_rigid_opaques }
             | TypingMode::Borrowck { defining_opaque_types: non_rigid_opaques }
             | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
                 !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index aa89e77bb6f..ee439f1b3d0 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -33,11 +33,11 @@ where
                 );
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
             }
-            TypingMode::Analysis { defining_opaque_types } => {
+            TypingMode::Analysis { defining_opaque_types_and_generators } => {
                 let Some(def_id) = opaque_ty
                     .def_id
                     .as_local()
-                    .filter(|&def_id| defining_opaque_types.contains(&def_id))
+                    .filter(|&def_id| defining_opaque_types_and_generators.contains(&def_id))
                 else {
                     self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
                     return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 7bd1300f34e..3404c47bba2 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -208,6 +208,11 @@ where
             }
         }
 
+        // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
+        if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
+            return cand;
+        }
+
         ecx.probe_and_evaluate_goal_for_constituent_tys(
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
@@ -259,6 +264,11 @@ where
             return Err(NoSolution);
         }
 
+        // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
+        if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
+            return cand;
+        }
+
         ecx.probe_and_evaluate_goal_for_constituent_tys(
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
@@ -1298,18 +1308,6 @@ where
                     return true;
                 }
 
-                // We don't consider a trait-bound global if it has a projection bound.
-                //
-                // See ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs
-                // for an example where this is necessary.
-                for p in goal.param_env.caller_bounds().iter() {
-                    if let ty::ClauseKind::Projection(proj) = p.kind().skip_binder() {
-                        if proj.projection_term.trait_ref(self.cx()) == trait_pred.trait_ref {
-                            return true;
-                        }
-                    }
-                }
-
                 false
             }
             _ => false,
@@ -1368,4 +1366,28 @@ where
         let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
         self.merge_trait_candidates(goal, candidates)
     }
+
+    fn try_stall_coroutine_witness(
+        &mut self,
+        self_ty: I::Ty,
+    ) -> Option<Result<Candidate<I>, NoSolution>> {
+        if let ty::CoroutineWitness(def_id, _) = self_ty.kind() {
+            match self.typing_mode() {
+                TypingMode::Analysis {
+                    defining_opaque_types_and_generators: stalled_generators,
+                } => {
+                    if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
+                    {
+                        return Some(self.forced_ambiguity(MaybeCause::Ambiguity));
+                    }
+                }
+                TypingMode::Coherence
+                | TypingMode::PostAnalysis
+                | TypingMode::Borrowck { defining_opaque_types: _ }
+                | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
+            }
+        }
+
+        None
+    }
 }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index e7f17bb6f99..ae9143486ee 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -246,9 +246,9 @@ parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$tok
 
 parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
 
-parse_expr_rarrow_call = `->` used for field access or method call
+parse_expr_rarrow_call = `->` is not valid syntax for field accesses and method calls
     .suggestion = try using `.` instead
-    .help = the `.` operator will dereference the value if needed
+    .help = the `.` operator will automatically dereference the value, except if the value is a raw pointer
 
 parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
     .label = dash-separated idents are not valid
@@ -893,6 +893,7 @@ parse_unknown_prefix = prefix `{$prefix}` is unknown
     .label = unknown prefix
     .note =  prefixed identifiers and literals are reserved since Rust 2021
     .suggestion_br = use `br` for a raw byte string
+    .suggestion_cr = use `cr` for a raw C-string
     .suggestion_str = if you meant to write a string literal, use double quotes
     .suggestion_whitespace = consider inserting whitespace here
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 44b4e1a3e47..35cf4c1b00d 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2141,6 +2141,13 @@ pub(crate) enum UnknownPrefixSugg {
     )]
     UseBr(#[primary_span] Span),
     #[suggestion(
+        parse_suggestion_cr,
+        code = "cr",
+        applicability = "maybe-incorrect",
+        style = "verbose"
+    )]
+    UseCr(#[primary_span] Span),
+    #[suggestion(
         parse_suggestion_whitespace,
         code = " ",
         applicability = "maybe-incorrect",
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
index e1f19beb53a..0b97d4e6993 100644
--- a/compiler/rustc_parse/src/lexer/diagnostics.rs
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -1,14 +1,17 @@
 use rustc_ast::token::Delimiter;
 use rustc_errors::Diag;
+use rustc_session::parse::ParseSess;
 use rustc_span::Span;
 use rustc_span::source_map::SourceMap;
 
 use super::UnmatchedDelim;
+use crate::errors::MismatchedClosingDelimiter;
+use crate::pprust;
 
 #[derive(Default)]
 pub(super) struct TokenTreeDiagInfo {
     /// Stack of open delimiters and their spans. Used for error message.
-    pub open_braces: Vec<(Delimiter, Span)>,
+    pub open_delimiters: Vec<(Delimiter, Span)>,
     pub unmatched_delims: Vec<UnmatchedDelim>,
 
     /// Used only for error recovery when arriving to EOF with mismatched braces.
@@ -108,7 +111,7 @@ pub(super) fn report_suspicious_mismatch_block(
     } else {
         // If there is no suspicious span, give the last properly closed block may help
         if let Some(parent) = diag_info.matching_block_spans.last()
-            && diag_info.open_braces.last().is_none()
+            && diag_info.open_delimiters.last().is_none()
             && diag_info.empty_block_spans.iter().all(|&sp| sp != parent.0.to(parent.1))
         {
             err.span_label(parent.0, "this opening brace...");
@@ -116,3 +119,24 @@ pub(super) fn report_suspicious_mismatch_block(
         }
     }
 }
+
+pub(crate) fn make_unclosed_delims_error(
+    unmatched: UnmatchedDelim,
+    psess: &ParseSess,
+) -> Option<Diag<'_>> {
+    // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
+    // `unmatched_delims` only for error recovery in the `Parser`.
+    let found_delim = unmatched.found_delim?;
+    let mut spans = vec![unmatched.found_span];
+    if let Some(sp) = unmatched.unclosed_span {
+        spans.push(sp);
+    };
+    let err = psess.dcx().create_err(MismatchedClosingDelimiter {
+        spans,
+        delimiter: pprust::token_kind_to_string(&found_delim.as_close_token_kind()).to_string(),
+        unmatched: unmatched.found_span,
+        opening_candidate: unmatched.candidate_span,
+        unclosed: unmatched.unclosed_span,
+    });
+    Some(err)
+}
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index a8ec9a1e952..e8a5cae54cf 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,5 +1,6 @@
 use std::ops::Range;
 
+use diagnostics::make_unclosed_delims_error;
 use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
@@ -17,9 +18,9 @@ use rustc_session::parse::ParseSess;
 use rustc_span::{BytePos, Pos, Span, Symbol};
 use tracing::debug;
 
+use crate::errors;
 use crate::lexer::diagnostics::TokenTreeDiagInfo;
 use crate::lexer::unicode_chars::UNICODE_ARRAY;
-use crate::{errors, make_unclosed_delims_error};
 
 mod diagnostics;
 mod tokentrees;
@@ -256,7 +257,6 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     let lit_start = start + BytePos(prefix_len);
                     self.pos = lit_start;
                     self.cursor = Cursor::new(&str_before[prefix_len as usize..]);
-
                     self.report_unknown_prefix(start);
                     let prefix_span = self.mk_sp(start, lit_start);
                     return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace);
@@ -789,13 +789,14 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
     fn report_unknown_prefix(&self, start: BytePos) {
         let prefix_span = self.mk_sp(start, self.pos);
         let prefix = self.str_from_to(start, self.pos);
-
         let expn_data = prefix_span.ctxt().outer_expn_data();
 
         if expn_data.edition.at_least_rust_2021() {
             // In Rust 2021, this is a hard error.
             let sugg = if prefix == "rb" {
                 Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
+            } else if prefix == "rc" {
+                Some(errors::UnknownPrefixSugg::UseCr(prefix_span))
             } else if expn_data.is_root() {
                 if self.cursor.first() == '\''
                     && let Some(start) = self.last_lifetime
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 0ddd9a85df8..fbea958dcc5 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -54,8 +54,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         let mut err = self.dcx().struct_span_err(self.token.span, msg);
 
         let unclosed_delimiter_show_limit = 5;
-        let len = usize::min(unclosed_delimiter_show_limit, self.diag_info.open_braces.len());
-        for &(_, span) in &self.diag_info.open_braces[..len] {
+        let len = usize::min(unclosed_delimiter_show_limit, self.diag_info.open_delimiters.len());
+        for &(_, span) in &self.diag_info.open_delimiters[..len] {
             err.span_label(span, "unclosed delimiter");
             self.diag_info.unmatched_delims.push(UnmatchedDelim {
                 found_delim: None,
@@ -65,19 +65,19 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
             });
         }
 
-        if let Some((_, span)) = self.diag_info.open_braces.get(unclosed_delimiter_show_limit)
-            && self.diag_info.open_braces.len() >= unclosed_delimiter_show_limit + 2
+        if let Some((_, span)) = self.diag_info.open_delimiters.get(unclosed_delimiter_show_limit)
+            && self.diag_info.open_delimiters.len() >= unclosed_delimiter_show_limit + 2
         {
             err.span_label(
                 *span,
                 format!(
                     "another {} unclosed delimiters begin from here",
-                    self.diag_info.open_braces.len() - unclosed_delimiter_show_limit
+                    self.diag_info.open_delimiters.len() - unclosed_delimiter_show_limit
                 ),
             );
         }
 
-        if let Some((delim, _)) = self.diag_info.open_braces.last() {
+        if let Some((delim, _)) = self.diag_info.open_delimiters.last() {
             report_suspicious_mismatch_block(
                 &mut err,
                 &self.diag_info,
@@ -95,7 +95,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         // The span for beginning of the delimited section.
         let pre_span = self.token.span;
 
-        self.diag_info.open_braces.push((open_delim, self.token.span));
+        self.diag_info.open_delimiters.push((open_delim, self.token.span));
 
         // Lex the token trees within the delimiters.
         // We stop at any delimiter so we can try to recover if the user
@@ -109,11 +109,12 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         let close_spacing = if let Some(close_delim) = self.token.kind.close_delim() {
             if close_delim == open_delim {
                 // Correct delimiter.
-                let (open_brace, open_brace_span) = self.diag_info.open_braces.pop().unwrap();
-                let close_brace_span = self.token.span;
+                let (open_delimiter, open_delimiter_span) =
+                    self.diag_info.open_delimiters.pop().unwrap();
+                let close_delimiter_span = self.token.span;
 
                 if tts.is_empty() && close_delim == Delimiter::Brace {
-                    let empty_block_span = open_brace_span.to(close_brace_span);
+                    let empty_block_span = open_delimiter_span.to(close_delimiter_span);
                     if !sm.is_multiline(empty_block_span) {
                         // Only track if the block is in the form of `{}`, otherwise it is
                         // likely that it was written on purpose.
@@ -122,9 +123,11 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                 }
 
                 // only add braces
-                if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, open_delim) {
+                if let (Delimiter::Brace, Delimiter::Brace) = (open_delimiter, open_delim) {
                     // Add all the matching spans, we will sort by span later
-                    self.diag_info.matching_block_spans.push((open_brace_span, close_brace_span));
+                    self.diag_info
+                        .matching_block_spans
+                        .push((open_delimiter_span, close_delimiter_span));
                 }
 
                 // Move past the closing delimiter.
@@ -140,18 +143,18 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     // This is a conservative error: only report the last unclosed
                     // delimiter. The previous unclosed delimiters could actually be
                     // closed! The lexer just hasn't gotten to them yet.
-                    if let Some(&(_, sp)) = self.diag_info.open_braces.last() {
+                    if let Some(&(_, sp)) = self.diag_info.open_delimiters.last() {
                         unclosed_delimiter = Some(sp);
                     };
-                    for (brace, brace_span) in &self.diag_info.open_braces {
-                        if same_indentation_level(sm, self.token.span, *brace_span)
-                            && brace == &close_delim
+                    for (delimiter, delimiter_span) in &self.diag_info.open_delimiters {
+                        if same_indentation_level(sm, self.token.span, *delimiter_span)
+                            && delimiter == &close_delim
                         {
                             // high likelihood of these two corresponding
-                            candidate = Some(*brace_span);
+                            candidate = Some(*delimiter_span);
                         }
                     }
-                    let (_, _) = self.diag_info.open_braces.pop().unwrap();
+                    let (_, _) = self.diag_info.open_delimiters.pop().unwrap();
                     self.diag_info.unmatched_delims.push(UnmatchedDelim {
                         found_delim: Some(close_delim),
                         found_span: self.token.span,
@@ -159,7 +162,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                         candidate_span: candidate,
                     });
                 } else {
-                    self.diag_info.open_braces.pop();
+                    self.diag_info.open_delimiters.pop();
                 }
 
                 // If the incorrect delimiter matches an earlier opening
@@ -169,7 +172,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                 // fn foo() {
                 //     bar(baz(
                 // }  // Incorrect delimiter but matches the earlier `{`
-                if !self.diag_info.open_braces.iter().any(|&(b, _)| b == close_delim) {
+                if !self.diag_info.open_delimiters.iter().any(|&(d, _)| d == close_delim) {
                     self.bump_minimal()
                 } else {
                     // The choice of value here doesn't matter.
@@ -180,7 +183,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
             assert_eq!(self.token.kind, token::Eof);
             // Silently recover, the EOF token will be seen again
             // and an error emitted then. Thus we don't pop from
-            // self.open_braces here. The choice of spacing value here
+            // self.open_delimiters here. The choice of spacing value here
             // doesn't matter.
             Spacing::Alone
         };
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 2edc8c83017..896e348a12d 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -32,7 +32,7 @@ pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments");
 
 #[macro_use]
 pub mod parser;
-use parser::{Parser, make_unclosed_delims_error};
+use parser::Parser;
 pub mod lexer;
 pub mod validate_attr;
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index f3ed798eba4..370eb3f402d 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2146,6 +2146,17 @@ impl<'a> Parser<'a> {
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
     /// `Lit::from_token` (excluding unary negation).
     fn eat_token_lit(&mut self) -> Option<token::Lit> {
+        let check_expr = |expr: P<Expr>| {
+            if let ast::ExprKind::Lit(token_lit) = expr.kind {
+                Some(token_lit)
+            } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
+                && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
+            {
+                None
+            } else {
+                panic!("unexpected reparsed expr/literal: {:?}", expr.kind);
+            }
+        };
         match self.token.uninterpolate().kind {
             token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => {
                 self.bump();
@@ -2159,10 +2170,7 @@ impl<'a> Parser<'a> {
                 let lit = self
                     .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
                     .expect("metavar seq literal");
-                let ast::ExprKind::Lit(token_lit) = lit.kind else {
-                    panic!("didn't reparse a literal");
-                };
-                Some(token_lit)
+                check_expr(lit)
             }
             token::OpenInvisible(InvisibleOrigin::MetaVar(
                 mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. },
@@ -2170,15 +2178,7 @@ impl<'a> Parser<'a> {
                 let expr = self
                     .eat_metavar_seq(mv_kind, |this| this.parse_expr())
                     .expect("metavar seq expr");
-                if let ast::ExprKind::Lit(token_lit) = expr.kind {
-                    Some(token_lit)
-                } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
-                    && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
-                {
-                    None
-                } else {
-                    panic!("unexpected reparsed expr: {:?}", expr.kind);
-                }
+                check_expr(expr)
             }
             _ => None,
         }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 39251f1ce27..4be8a90368d 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2058,6 +2058,17 @@ impl<'a> Parser<'a> {
         }
         self.expect_field_ty_separator()?;
         let ty = self.parse_ty()?;
+        if self.token == token::Colon && self.look_ahead(1, |&t| t != token::Colon) {
+            self.dcx()
+                .struct_span_err(self.token.span, "found single colon in a struct field type path")
+                .with_span_suggestion_verbose(
+                    self.token.span,
+                    "write a path separator here",
+                    "::",
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
+        }
         let default = if self.token == token::Eq {
             self.bump();
             let const_expr = self.parse_expr_anon_const()?;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index d73adb39826..48df8b59d55 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -43,11 +43,8 @@ use token_type::TokenTypeSet;
 pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType};
 use tracing::debug;
 
-use crate::errors::{
-    self, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral,
-};
+use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral};
 use crate::exp;
-use crate::lexer::UnmatchedDelim;
 
 #[cfg(test)]
 mod tests;
@@ -1745,27 +1742,6 @@ impl<'a> Parser<'a> {
     }
 }
 
-pub(crate) fn make_unclosed_delims_error(
-    unmatched: UnmatchedDelim,
-    psess: &ParseSess,
-) -> Option<Diag<'_>> {
-    // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
-    // `unmatched_delims` only for error recovery in the `Parser`.
-    let found_delim = unmatched.found_delim?;
-    let mut spans = vec![unmatched.found_span];
-    if let Some(sp) = unmatched.unclosed_span {
-        spans.push(sp);
-    };
-    let err = psess.dcx().create_err(MismatchedClosingDelimiter {
-        spans,
-        delimiter: pprust::token_kind_to_string(&found_delim.as_close_token_kind()).to_string(),
-        unmatched: unmatched.found_span,
-        opening_candidate: unmatched.candidate_span,
-        unclosed: unmatched.unclosed_span,
-    });
-    Some(err)
-}
-
 /// A helper struct used when building an `AttrTokenStream` from
 /// a `LazyAttrTokenStream`. Both delimiter and non-delimited tokens
 /// are stored as `FlatToken::Token`. A vector of `FlatToken`s
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 1a02d45f0e3..1093e4f4af0 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -248,19 +248,13 @@ impl<'a> Parser<'a> {
             segments.push(segment);
 
             if self.is_import_coupler() || !self.eat_path_sep() {
-                let ok_for_recovery = self.may_recover()
-                    && match style {
-                        PathStyle::Expr => true,
-                        PathStyle::Type if let Some((ident, _)) = self.prev_token.ident() => {
-                            self.token == token::Colon
-                                && ident.as_str().chars().all(|c| c.is_lowercase())
-                                && self.token.span.lo() == self.prev_token.span.hi()
-                                && self
-                                    .look_ahead(1, |token| self.token.span.hi() == token.span.lo())
-                        }
-                        _ => false,
-                    };
-                if ok_for_recovery
+                // IMPORTANT: We can *only ever* treat single colons as typo'ed double colons in
+                // expression contexts (!) since only there paths cannot possibly be followed by
+                // a colon and still form a syntactically valid construct. In pattern contexts,
+                // a path may be followed by a type annotation. E.g., `let pat:ty`. In type
+                // contexts, a path may be followed by a list of bounds. E.g., `where ty:bound`.
+                if self.may_recover()
+                    && style == PathStyle::Expr // (!)
                     && self.token == token::Colon
                     && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
                 {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index bc92b95ce71..02c164a706c 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -246,6 +246,10 @@ pub enum AutoDiff {
     /// Print the module after running autodiff and optimizations.
     PrintModFinal,
 
+    /// Print all passes scheduled by LLVM
+    PrintPasses,
+    /// Disable extra opt run after running autodiff
+    NoPostopt,
     /// Enzyme's loose type debug helper (can cause incorrect gradients!!)
     /// Usable in cases where Enzyme errors with `can not deduce type of X`.
     LooseTypes,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 36eee5f3086..5f4695fb184 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -711,7 +711,7 @@ mod desc {
     pub(crate) const parse_list: &str = "a space-separated list of strings";
     pub(crate) const parse_list_with_polarity: &str =
         "a comma-separated list of strings, with elements beginning with + or -";
-    pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `LooseTypes`, `Inline`";
+    pub(crate) const parse_autodiff: &str = "a comma separated list of settings: `Enable`, `PrintSteps`, `PrintTA`, `PrintAA`, `PrintPerf`, `PrintModBefore`, `PrintModAfter`, `PrintModFinal`, `PrintPasses`, `NoPostopt`, `LooseTypes`, `Inline`";
     pub(crate) const parse_comma_list: &str = "a comma-separated list of strings";
     pub(crate) const parse_opt_comma_list: &str = parse_comma_list;
     pub(crate) const parse_number: &str = "a number";
@@ -1360,6 +1360,8 @@ pub mod parse {
                 "PrintModBefore" => AutoDiff::PrintModBefore,
                 "PrintModAfter" => AutoDiff::PrintModAfter,
                 "PrintModFinal" => AutoDiff::PrintModFinal,
+                "NoPostopt" => AutoDiff::NoPostopt,
+                "PrintPasses" => AutoDiff::PrintPasses,
                 "LooseTypes" => AutoDiff::LooseTypes,
                 "Inline" => AutoDiff::Inline,
                 _ => {
@@ -2098,6 +2100,8 @@ options! {
         `=PrintModBefore`
         `=PrintModAfter`
         `=PrintModFinal`
+        `=PrintPasses`,
+        `=NoPostopt`
         `=LooseTypes`
         `=Inline`
         Multiple options can be combined with commas."),
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index 77e5f3423d1..771ff98d58d 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -19,7 +19,6 @@
 
 pub mod rustc_internal;
 
-// Make this module private for now since external users should not call these directly.
-mod rustc_smir;
+pub mod rustc_smir;
 
 pub mod stable_mir;
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 146ba17d14f..2982a920b03 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -18,9 +18,10 @@ use rustc_span::def_id::{CrateNum, DefId};
 use scoped_tls::scoped_thread_local;
 use stable_mir::Error;
 use stable_mir::abi::Layout;
+use stable_mir::compiler_interface::SmirInterface;
 use stable_mir::ty::IndexedVal;
 
-use crate::rustc_smir::context::TablesWrapper;
+use crate::rustc_smir::context::SmirCtxt;
 use crate::rustc_smir::{Stable, Tables};
 use crate::stable_mir;
 
@@ -196,12 +197,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
 // datastructures and stable MIR datastructures
 scoped_thread_local! (static TLV: Cell<*const ()>);
 
-pub(crate) fn init<'tcx, F, T>(tables: &TablesWrapper<'tcx>, f: F) -> T
+pub(crate) fn init<'tcx, F, T>(cx: &SmirCtxt<'tcx>, f: F) -> T
 where
     F: FnOnce() -> T,
 {
     assert!(!TLV.is_set());
-    let ptr = tables as *const _ as *const ();
+    let ptr = cx as *const _ as *const ();
     TLV.set(&Cell::new(ptr), || f())
 }
 
@@ -212,8 +213,8 @@ pub(crate) fn with_tables<R>(f: impl for<'tcx> FnOnce(&mut Tables<'tcx>) -> R) -
     TLV.with(|tlv| {
         let ptr = tlv.get();
         assert!(!ptr.is_null());
-        let wrapper = ptr as *const TablesWrapper<'_>;
-        let mut tables = unsafe { (*wrapper).0.borrow_mut() };
+        let context = ptr as *const SmirCtxt<'_>;
+        let mut tables = unsafe { (*context).0.borrow_mut() };
         f(&mut *tables)
     })
 }
@@ -222,7 +223,7 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
 where
     F: FnOnce() -> T,
 {
-    let tables = TablesWrapper(RefCell::new(Tables {
+    let tables = SmirCtxt(RefCell::new(Tables {
         tcx,
         def_ids: IndexMap::default(),
         alloc_ids: IndexMap::default(),
@@ -233,7 +234,12 @@ where
         mir_consts: IndexMap::default(),
         layouts: IndexMap::default(),
     }));
-    stable_mir::compiler_interface::run(&tables, || init(&tables, f))
+
+    let interface = SmirInterface { cx: tables };
+
+    // Pass the `SmirInterface` to compiler_interface::run
+    // and initialize the rustc-specific TLS with tables.
+    stable_mir::compiler_interface::run(&interface, || init(&interface.cx, f))
 }
 
 /// Instantiate and run the compiler with the provided arguments and callback.
@@ -256,7 +262,7 @@ where
 ///         // Your code goes in here.
 /// #       ControlFlow::Continue(())
 ///     }
-/// #   let args = vec!["--verbose".to_string()];
+/// #   let args = &["--verbose".to_string()];
 ///     let result = run!(args, analyze_code);
 /// #   assert_eq!(result, Err(CompilerError::Skipped))
 /// # }
@@ -278,7 +284,7 @@ where
 ///         // Your code goes in here.
 /// #       ControlFlow::Continue(())
 ///     }
-/// #   let args = vec!["--verbose".to_string()];
+/// #   let args = &["--verbose".to_string()];
 /// #   let extra_args = vec![];
 ///     let result = run!(args, || analyze_code(extra_args));
 /// #   assert_eq!(result, Err(CompilerError::Skipped))
@@ -340,7 +346,6 @@ macro_rules! run_driver {
             C: Send,
             F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
         {
-            args: Vec<String>,
             callback: Option<F>,
             result: Option<ControlFlow<B, C>>,
         }
@@ -352,14 +357,14 @@ macro_rules! run_driver {
             F: FnOnce($(optional!($with_tcx TyCtxt))?) -> ControlFlow<B, C> + Send,
         {
             /// Creates a new `StableMir` instance, with given test_function and arguments.
-            pub fn new(args: Vec<String>, callback: F) -> Self {
-                StableMir { args, callback: Some(callback), result: None }
+            pub fn new(callback: F) -> Self {
+                StableMir { callback: Some(callback), result: None }
             }
 
             /// Runs the compiler against given target and tests it with `test_function`
-            pub fn run(&mut self) -> Result<C, CompilerError<B>> {
+            pub fn run(&mut self, args: &[String]) -> Result<C, CompilerError<B>> {
                 let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> {
-                    run_compiler(&self.args.clone(), self);
+                    run_compiler(&args, self);
                     Ok(())
                 });
                 match (compiler_result, self.result.take()) {
@@ -409,7 +414,7 @@ macro_rules! run_driver {
             }
         }
 
-        StableMir::new($args, $callback).run()
+        StableMir::new($callback).run($args)
     }};
 }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 240f6f7fe45..9a4cac243bd 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -1,7 +1,4 @@
-//! Implementation of `[stable_mir::compiler_interface::Context]` trait.
-//!
-//! This trait is currently the main interface between the Rust compiler,
-//! and the `stable_mir` crate.
+//! Implementation of StableMIR Context.
 
 #![allow(rustc::usage_of_qualified_ty)]
 
@@ -20,7 +17,6 @@ use rustc_middle::ty::{
 use rustc_middle::{mir, ty};
 use rustc_span::def_id::LOCAL_CRATE;
 use stable_mir::abi::{FnAbi, Layout, LayoutShape};
-use stable_mir::compiler_interface::Context;
 use stable_mir::mir::alloc::GlobalAlloc;
 use stable_mir::mir::mono::{InstanceDef, StaticDef};
 use stable_mir::mir::{BinOp, Body, Place, UnOp};
@@ -37,8 +33,14 @@ use crate::rustc_smir::builder::BodyBuilder;
 use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate};
 use crate::stable_mir;
 
-impl<'tcx> Context for TablesWrapper<'tcx> {
-    fn target_info(&self) -> MachineInfo {
+/// Provides direct access to rustc's internal queries.
+///
+/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through
+/// this context to obtain rustc-level information.
+pub struct SmirCtxt<'tcx>(pub RefCell<Tables<'tcx>>);
+
+impl<'tcx> SmirCtxt<'tcx> {
+    pub fn target_info(&self) -> MachineInfo {
         let mut tables = self.0.borrow_mut();
         MachineInfo {
             endian: tables.tcx.data_layout.endian.stable(&mut *tables),
@@ -48,31 +50,35 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
+    pub fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         Some(tables.crate_item(tcx.entry_fn(())?.0))
     }
 
-    fn all_local_items(&self) -> stable_mir::CrateItems {
+    /// Retrieve all items of the local crate that have a MIR associated with them.
+    pub fn all_local_items(&self) -> stable_mir::CrateItems {
         let mut tables = self.0.borrow_mut();
         tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
     }
 
-    fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
+    /// Retrieve the body of a function.
+    /// This function will panic if the body is not available.
+    pub fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[item];
         tables.tcx.instance_mir(rustc_middle::ty::InstanceKind::Item(def_id)).stable(&mut tables)
     }
 
-    fn has_body(&self, def: DefId) -> bool {
+    /// Check whether the body of a function is available.
+    pub fn has_body(&self, def: DefId) -> bool {
         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> {
+    pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         tcx.foreign_modules(crate_num.internal(&mut *tables, tcx))
@@ -81,21 +87,23 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
+    /// Retrieve all functions defined in this crate.
+    pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let krate = crate_num.internal(&mut *tables, tcx);
         filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id))
     }
 
-    fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
+    /// Retrieve all static items defined in this crate.
+    pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let krate = crate_num.internal(&mut *tables, tcx);
         filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id))
     }
 
-    fn foreign_module(
+    pub fn foreign_module(
         &self,
         mod_def: stable_mir::ty::ForeignModuleDef,
     ) -> stable_mir::ty::ForeignModule {
@@ -105,7 +113,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         mod_def.stable(&mut *tables)
     }
 
-    fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> {
+    pub fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[mod_def.def_id()];
         tables
@@ -119,12 +127,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn all_trait_decls(&self) -> stable_mir::TraitDecls {
+    pub fn all_trait_decls(&self) -> stable_mir::TraitDecls {
         let mut tables = self.0.borrow_mut();
         tables.tcx.all_traits().map(|trait_def_id| tables.trait_def(trait_def_id)).collect()
     }
 
-    fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
+    pub fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         tcx.traits(crate_num.internal(&mut *tables, tcx))
@@ -133,14 +141,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
+    pub fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[trait_def.0];
         let trait_def = tables.tcx.trait_def(def_id);
         trait_def.stable(&mut *tables)
     }
 
-    fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
+    pub fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         iter::once(LOCAL_CRATE)
@@ -150,7 +158,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
+    pub fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         tcx.trait_impls_in_crate(crate_num.internal(&mut *tables, tcx))
@@ -159,21 +167,21 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
+    pub fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[impl_def.0];
         let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
         impl_trait.stable(&mut *tables)
     }
 
-    fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
+    pub fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[def_id];
         let generics = tables.tcx.generics_of(def_id);
         generics.stable(&mut *tables)
     }
 
-    fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
+    pub fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[def_id];
         let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
@@ -191,7 +199,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn explicit_predicates_of(
+    pub fn explicit_predicates_of(
         &self,
         def_id: stable_mir::DefId,
     ) -> stable_mir::ty::GenericPredicates {
@@ -212,17 +220,20 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn local_crate(&self) -> stable_mir::Crate {
+    /// Get information about the local crate.
+    pub fn local_crate(&self) -> stable_mir::Crate {
         let tables = self.0.borrow();
         smir_crate(tables.tcx, LOCAL_CRATE)
     }
 
-    fn external_crates(&self) -> Vec<stable_mir::Crate> {
+    /// Retrieve a list of all external crates.
+    pub fn external_crates(&self) -> Vec<stable_mir::Crate> {
         let tables = self.0.borrow();
         tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
     }
 
-    fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
+    /// Find a crate with the given name.
+    pub fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
         let tables = self.0.borrow();
         let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
             .iter()
@@ -235,7 +246,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         crates
     }
 
-    fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
+    /// Returns the name of given `DefId`.
+    pub fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
         let tables = self.0.borrow();
         if trimmed {
             with_forced_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
@@ -244,7 +256,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn tool_attrs(
+    /// Return registered tool attributes with the given attribute name.
+    ///
+    /// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool
+    /// attributes will simply return an empty list.
+    ///
+    /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
+    /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
+    pub fn tool_attrs(
         &self,
         def_id: stable_mir::DefId,
         attr: &[stable_mir::Symbol],
@@ -268,7 +287,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn all_tool_attrs(&self, def_id: stable_mir::DefId) -> Vec<stable_mir::crate_def::Attribute> {
+    /// Get all tool attributes of a definition.
+    pub fn all_tool_attrs(
+        &self,
+        def_id: stable_mir::DefId,
+    ) -> Vec<stable_mir::crate_def::Attribute> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let did = tables[def_id];
@@ -292,12 +315,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
-    fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
+    /// Returns printable, human readable form of `Span`.
+    pub fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
         let tables = self.0.borrow();
         tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
     }
 
-    fn get_filename(&self, span: &Span) -> Filename {
+    /// Return filename from given `Span`, for diagnostic purposes.
+    pub fn get_filename(&self, span: &Span) -> Filename {
         let tables = self.0.borrow();
         tables
             .tcx
@@ -308,23 +333,27 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .to_string()
     }
 
-    fn get_lines(&self, span: &Span) -> LineInfo {
+    /// Return lines corresponding to this `Span`.
+    pub fn get_lines(&self, span: &Span) -> LineInfo {
         let tables = self.0.borrow();
         let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
         LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
     }
 
-    fn item_kind(&self, item: CrateItem) -> ItemKind {
+    /// Returns the `kind` of given `DefId`.
+    pub fn item_kind(&self, item: CrateItem) -> ItemKind {
         let tables = self.0.borrow();
         new_item_kind(tables.tcx.def_kind(tables[item.0]))
     }
 
-    fn is_foreign_item(&self, item: DefId) -> bool {
+    /// Returns whether this is a foreign item.
+    pub fn is_foreign_item(&self, item: DefId) -> bool {
         let tables = self.0.borrow();
         tables.tcx.is_foreign_item(tables[item])
     }
 
-    fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
+    /// Returns the kind of a given foreign item.
+    pub fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[def.def_id()];
         let tcx = tables.tcx;
@@ -339,32 +368,37 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn adt_kind(&self, def: AdtDef) -> AdtKind {
+    /// Returns the kind of a given algebraic data type.
+    pub fn adt_kind(&self, def: AdtDef) -> AdtKind {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         def.internal(&mut *tables, tcx).adt_kind().stable(&mut *tables)
     }
 
-    fn adt_is_box(&self, def: AdtDef) -> bool {
+    /// Returns if the ADT is a box.
+    pub fn adt_is_box(&self, def: AdtDef) -> bool {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         def.internal(&mut *tables, tcx).is_box()
     }
 
-    fn adt_is_simd(&self, def: AdtDef) -> bool {
+    /// Returns whether this ADT is simd.
+    pub fn adt_is_simd(&self, def: AdtDef) -> bool {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         def.internal(&mut *tables, tcx).repr().simd()
     }
 
-    fn adt_is_cstr(&self, def: AdtDef) -> bool {
+    /// Returns whether this definition is a C string.
+    pub fn adt_is_cstr(&self, def: AdtDef) -> bool {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
         tables.tcx.is_lang_item(def_id, LangItem::CStr)
     }
 
-    fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
+    /// Retrieve the function signature for the given generic arguments.
+    pub fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
@@ -373,7 +407,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         sig.stable(&mut *tables)
     }
 
-    fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
+    /// Retrieve the intrinsic definition if the item corresponds one.
+    pub fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = def.internal(&mut *tables, tcx);
@@ -381,14 +416,16 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         intrinsic.map(|_| IntrinsicDef(def))
     }
 
-    fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
+    /// Retrieve the plain function name of an intrinsic.
+    pub fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
         tcx.intrinsic(def_id).unwrap().name.to_string()
     }
 
-    fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
+    /// Retrieve the closure signature for the given generic arguments.
+    pub fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let args_ref = args.internal(&mut *tables, tcx);
@@ -396,25 +433,28 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         sig.stable(&mut *tables)
     }
 
-    fn adt_variants_len(&self, def: AdtDef) -> usize {
+    /// The number of variants in this ADT.
+    pub fn adt_variants_len(&self, def: AdtDef) -> usize {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         def.internal(&mut *tables, tcx).variants().len()
     }
 
-    fn variant_name(&self, def: VariantDef) -> Symbol {
+    /// The name of a variant.
+    pub fn variant_name(&self, def: VariantDef) -> Symbol {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         def.internal(&mut *tables, tcx).name.to_string()
     }
 
-    fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
+    pub fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect()
     }
 
-    fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
+    /// Evaluate constant as a target usize.
+    pub fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let mir_const = cnst.internal(&mut *tables, tcx);
@@ -422,7 +462,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized())
             .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
     }
-    fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
+    pub fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let mir_const = cnst.internal(&mut *tables, tcx);
@@ -431,7 +471,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
     }
 
-    fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
+    /// Create a new zero-sized constant.
+    pub fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty_internal = ty.internal(&mut *tables, tcx);
@@ -456,7 +497,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .stable(&mut *tables))
     }
 
-    fn new_const_str(&self, value: &str) -> MirConst {
+    /// Create a new constant that represents the given string value.
+    pub fn new_const_str(&self, value: &str) -> MirConst {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty::Ty::new_static_str(tcx);
@@ -467,12 +509,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         mir::Const::from_value(val, ty).stable(&mut tables)
     }
 
-    fn new_const_bool(&self, value: bool) -> MirConst {
+    /// Create a new constant that represents the given boolean value.
+    pub fn new_const_bool(&self, value: bool) -> MirConst {
         let mut tables = self.0.borrow_mut();
         mir::Const::from_bool(tables.tcx, value).stable(&mut tables)
     }
 
-    fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
+    /// Create a new constant that represents the given value.
+    pub fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx));
@@ -487,7 +531,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         Ok(mir::Const::from_scalar(tcx, mir::interpret::Scalar::Int(scalar), ty)
             .stable(&mut tables))
     }
-    fn try_new_ty_const_uint(
+    pub fn try_new_ty_const_uint(
         &self,
         value: u128,
         uint_ty: UintTy,
@@ -509,27 +553,35 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .stable(&mut *tables))
     }
 
-    fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
+    /// Create a new type from the given kind.
+    pub fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let internal_kind = kind.internal(&mut *tables, tcx);
         tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
     }
 
-    fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
+    /// Create a new box type, `Box<T>`, for the given inner type `T`.
+    pub fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let inner = ty.internal(&mut *tables, tcx);
         ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables)
     }
 
-    fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
+    /// Returns the type of given crate item.
+    pub fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         tcx.type_of(item.internal(&mut *tables, tcx)).instantiate_identity().stable(&mut *tables)
     }
 
-    fn def_ty_with_args(&self, item: stable_mir::DefId, args: &GenericArgs) -> stable_mir::ty::Ty {
+    /// Returns the type of given definition instantiated with the given arguments.
+    pub fn def_ty_with_args(
+        &self,
+        item: stable_mir::DefId,
+        args: &GenericArgs,
+    ) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let args = args.internal(&mut *tables, tcx);
@@ -544,33 +596,38 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .stable(&mut *tables)
     }
 
-    fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String {
+    /// Returns literal value of a const as a string.
+    pub fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         cnst.internal(&mut *tables, tcx).to_string()
     }
 
-    fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
+    /// `Span` of an item.
+    pub fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
         let mut tables = self.0.borrow_mut();
         tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
     }
 
-    fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String {
+    /// Obtain the representation of a type.
+    pub fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String {
         let tables = self.0.borrow_mut();
         tables.types[ty].to_string()
     }
 
-    fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
+    /// Obtain the representation of a type.
+    pub fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
         let mut tables = self.0.borrow_mut();
         tables.types[ty].kind().stable(&mut *tables)
     }
 
-    fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String {
+    pub fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String {
         let tables = self.0.borrow_mut();
         tables.ty_consts[ct].to_string()
     }
 
-    fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
+    /// Get the discriminant Ty for this Ty if there's one.
+    pub fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let internal_kind = ty.internal(&mut *tables, tcx);
@@ -578,7 +635,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables)
     }
 
-    fn instance_body(&self, def: InstanceDef) -> Option<Body> {
+    /// Get the body of an Instance which is already monomorphized.
+    pub fn instance_body(&self, def: InstanceDef) -> Option<Body> {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         tables
@@ -586,63 +644,74 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
     }
 
-    fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
+    /// Get the instance type with generic instantiations applied and lifetimes erased.
+    pub fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
         instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables)
     }
 
-    fn instance_args(&self, def: InstanceDef) -> GenericArgs {
+    /// Get the instantiation types.
+    pub fn instance_args(&self, def: InstanceDef) -> GenericArgs {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         instance.args.stable(&mut *tables)
     }
 
-    fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
+    /// Get an instance ABI.
+    pub fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables))
     }
 
-    fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
+    /// Get the ABI of a function pointer.
+    pub fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let sig = fn_ptr.internal(&mut *tables, tcx);
         Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables))
     }
 
-    fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
+    /// Get the instance.
+    pub fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
         let mut tables = self.0.borrow_mut();
         let def_id = tables.instances[def].def_id();
         tables.create_def_id(def_id)
     }
 
-    fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
+    /// Get the instance mangled name.
+    pub fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
         let tables = self.0.borrow_mut();
         let instance = tables.instances[instance];
         tables.tcx.symbol_name(instance).name.to_string()
     }
 
-    fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
+    /// Check if this is an empty DropGlue shim.
+    pub fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
         let tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         matches!(instance.def, ty::InstanceKind::DropGlue(_, None))
     }
 
-    fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
+    /// Check if this is an empty AsyncDropGlueCtor shim.
+    pub fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
         let tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         matches!(instance.def, ty::InstanceKind::AsyncDropGlueCtorShim(_, None))
     }
 
-    fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance {
+    /// Convert a non-generic crate item into an instance.
+    /// This function will panic if the item is generic.
+    pub fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance {
         let mut tables = self.0.borrow_mut();
         let def_id = tables[def_id];
         Instance::mono(tables.tcx, def_id).stable(&mut *tables)
     }
 
-    fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
+    /// Item requires monomorphization.
+    pub fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
         let tables = self.0.borrow();
         let def_id = tables[def_id];
         let generics = tables.tcx.generics_of(def_id);
@@ -650,7 +719,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         result
     }
 
-    fn resolve_instance(
+    /// Resolve an instance from the given function definition and generic arguments.
+    pub fn resolve_instance(
         &self,
         def: stable_mir::ty::FnDef,
         args: &stable_mir::ty::GenericArgs,
@@ -670,7 +740,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
+    /// Resolve an instance for drop_in_place for the given type.
+    pub fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let internal_ty = ty.internal(&mut *tables, tcx);
@@ -678,7 +749,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         instance.stable(&mut *tables)
     }
 
-    fn resolve_for_fn_ptr(
+    /// Resolve instance for a function pointer.
+    pub fn resolve_for_fn_ptr(
         &self,
         def: FnDef,
         args: &GenericArgs,
@@ -696,7 +768,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         .stable(&mut *tables)
     }
 
-    fn resolve_closure(
+    /// Resolve instance for a closure with the requested type.
+    pub fn resolve_closure(
         &self,
         def: ClosureDef,
         args: &GenericArgs,
@@ -713,7 +786,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         )
     }
 
-    fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
+    /// Try to evaluate an instance into a constant.
+    pub fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         let tcx = tables.tcx;
@@ -733,21 +807,24 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .map_err(|e| e.stable(&mut *tables))?
     }
 
-    fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
+    /// Evaluate a static's initializer.
+    pub fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
         tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
     }
 
-    fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
+    /// Retrieve global allocation for the given allocation ID.
+    pub fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let alloc_id = alloc.internal(&mut *tables, tcx);
         tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
     }
 
-    fn vtable_allocation(
+    /// Retrieve the id for the virtual table.
+    pub fn vtable_allocation(
         &self,
         global_alloc: &GlobalAlloc,
     ) -> Option<stable_mir::mir::alloc::AllocId> {
@@ -765,7 +842,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         Some(alloc_id.stable(&mut *tables))
     }
 
-    fn krate(&self, def_id: stable_mir::DefId) -> Crate {
+    pub fn krate(&self, def_id: stable_mir::DefId) -> Crate {
         let tables = self.0.borrow();
         smir_crate(tables.tcx, tables[def_id].krate)
     }
@@ -773,7 +850,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
     /// Retrieve the instance name for diagnostic messages.
     ///
     /// This will return the specialized name, e.g., `Vec<char>::new`.
-    fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
+    pub fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
         let tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         if trimmed {
@@ -787,7 +864,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
+    /// Get the layout of a type.
+    pub fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let ty = ty.internal(&mut *tables, tcx);
@@ -795,19 +873,22 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         Ok(layout.stable(&mut *tables))
     }
 
-    fn layout_shape(&self, id: Layout) -> LayoutShape {
+    /// Get the layout shape.
+    pub fn layout_shape(&self, id: Layout) -> LayoutShape {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         id.internal(&mut *tables, tcx).0.stable(&mut *tables)
     }
 
-    fn place_pretty(&self, place: &Place) -> String {
+    /// Get a debug string representation of a place.
+    pub fn place_pretty(&self, place: &Place) -> String {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         format!("{:?}", place.internal(&mut *tables, tcx))
     }
 
-    fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
+    /// Get the resulting type of binary operation.
+    pub fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let rhs_internal = rhs.internal(&mut *tables, tcx);
@@ -816,7 +897,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         ty.stable(&mut *tables)
     }
 
-    fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
+    /// Get the resulting type of unary operation.
+    pub fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let arg_internal = arg.internal(&mut *tables, tcx);
@@ -824,7 +906,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         ty.stable(&mut *tables)
     }
 
-    fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems {
+    /// Get all associated items of a definition.
+    pub fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = tables[def_id];
@@ -840,8 +923,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
     }
 }
 
-pub(crate) struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
-
 /// Implement error handling for extracting function ABI information.
 impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> {
     type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, ty::Ty<'tcx>>, Error>;
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index dea8f54a670..b5003baaf63 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -25,7 +25,7 @@ use crate::stable_mir;
 
 mod alloc;
 mod builder;
-pub(crate) mod context;
+pub mod context;
 mod convert;
 
 pub struct Tables<'tcx> {
diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
index 33d950bb951..cd61907dc6b 100644
--- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
+++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs
@@ -5,6 +5,7 @@
 
 use std::cell::Cell;
 
+use rustc_smir::context::SmirCtxt;
 use stable_mir::abi::{FnAbi, Layout, LayoutShape};
 use stable_mir::crate_def::Attribute;
 use stable_mir::mir::alloc::{AllocId, GlobalAlloc};
@@ -22,47 +23,116 @@ use stable_mir::{
     ItemKind, Symbol, TraitDecls, mir,
 };
 
-use crate::stable_mir;
+use crate::{rustc_smir, stable_mir};
+
+/// Stable public API for querying compiler information.
+///
+/// All queries are delegated to an internal [`SmirCtxt`] that provides
+/// similar APIs but based on internal rustc constructs.
+///
+/// Do not use this directly. This is currently used in the macro expansion.
+pub(crate) struct SmirInterface<'tcx> {
+    pub(crate) cx: SmirCtxt<'tcx>,
+}
+
+impl<'tcx> SmirInterface<'tcx> {
+    pub(crate) fn entry_fn(&self) -> Option<CrateItem> {
+        self.cx.entry_fn()
+    }
 
-/// This trait defines the interface between stable_mir and the Rust compiler.
-/// Do not use this directly.
-pub trait Context {
-    fn entry_fn(&self) -> Option<CrateItem>;
     /// Retrieve all items of the local crate that have a MIR associated with them.
-    fn all_local_items(&self) -> CrateItems;
+    pub(crate) fn all_local_items(&self) -> CrateItems {
+        self.cx.all_local_items()
+    }
+
     /// Retrieve the body of a function.
     /// This function will panic if the body is not available.
-    fn mir_body(&self, item: DefId) -> mir::Body;
+    pub(crate) fn mir_body(&self, item: DefId) -> mir::Body {
+        self.cx.mir_body(item)
+    }
+
     /// Check whether the body of a function is available.
-    fn has_body(&self, item: DefId) -> bool;
-    fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>;
+    pub(crate) fn has_body(&self, item: DefId) -> bool {
+        self.cx.has_body(item)
+    }
+
+    pub(crate) fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> {
+        self.cx.foreign_modules(crate_num)
+    }
 
     /// Retrieve all functions defined in this crate.
-    fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>;
+    pub(crate) fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
+        self.cx.crate_functions(crate_num)
+    }
 
     /// Retrieve all static items defined in this crate.
-    fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>;
-    fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule;
-    fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>;
-    fn all_trait_decls(&self) -> TraitDecls;
-    fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls;
-    fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
-    fn all_trait_impls(&self) -> ImplTraitDecls;
-    fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls;
-    fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
-    fn generics_of(&self, def_id: DefId) -> Generics;
-    fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
-    fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
+    pub(crate) fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
+        self.cx.crate_statics(crate_num)
+    }
+
+    pub(crate) fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule {
+        self.cx.foreign_module(mod_def)
+    }
+
+    pub(crate) fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef> {
+        self.cx.foreign_items(mod_def)
+    }
+
+    pub(crate) fn all_trait_decls(&self) -> TraitDecls {
+        self.cx.all_trait_decls()
+    }
+
+    pub(crate) fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls {
+        self.cx.trait_decls(crate_num)
+    }
+
+    pub(crate) fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl {
+        self.cx.trait_decl(trait_def)
+    }
+
+    pub(crate) fn all_trait_impls(&self) -> ImplTraitDecls {
+        self.cx.all_trait_impls()
+    }
+
+    pub(crate) fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls {
+        self.cx.trait_impls(crate_num)
+    }
+
+    pub(crate) fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait {
+        self.cx.trait_impl(trait_impl)
+    }
+
+    pub(crate) fn generics_of(&self, def_id: DefId) -> Generics {
+        self.cx.generics_of(def_id)
+    }
+
+    pub(crate) fn predicates_of(&self, def_id: DefId) -> GenericPredicates {
+        self.cx.predicates_of(def_id)
+    }
+
+    pub(crate) fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates {
+        self.cx.explicit_predicates_of(def_id)
+    }
+
     /// Get information about the local crate.
-    fn local_crate(&self) -> Crate;
+    pub(crate) fn local_crate(&self) -> Crate {
+        self.cx.local_crate()
+    }
+
     /// Retrieve a list of all external crates.
-    fn external_crates(&self) -> Vec<Crate>;
+    pub(crate) fn external_crates(&self) -> Vec<Crate> {
+        self.cx.external_crates()
+    }
 
     /// Find a crate with the given name.
-    fn find_crates(&self, name: &str) -> Vec<Crate>;
+    pub(crate) fn find_crates(&self, name: &str) -> Vec<Crate> {
+        self.cx.find_crates(name)
+    }
 
-    /// Returns the name of given `DefId`
-    fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
+    /// Returns the name of given `DefId`.
+    pub(crate) fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol {
+        self.cx.def_name(def_id, trimmed)
+    }
 
     /// Return registered tool attributes with the given attribute name.
     ///
@@ -71,218 +141,362 @@ pub trait Context {
     ///
     /// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
     /// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
-    fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>;
+    pub(crate) fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute> {
+        self.cx.tool_attrs(def_id, attr)
+    }
 
     /// Get all tool attributes of a definition.
-    fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute>;
+    pub(crate) fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute> {
+        self.cx.all_tool_attrs(def_id)
+    }
 
-    /// Returns printable, human readable form of `Span`
-    fn span_to_string(&self, span: Span) -> String;
+    /// Returns printable, human readable form of `Span`.
+    pub(crate) fn span_to_string(&self, span: Span) -> String {
+        self.cx.span_to_string(span)
+    }
 
-    /// Return filename from given `Span`, for diagnostic purposes
-    fn get_filename(&self, span: &Span) -> Filename;
+    /// Return filename from given `Span`, for diagnostic purposes.
+    pub(crate) fn get_filename(&self, span: &Span) -> Filename {
+        self.cx.get_filename(span)
+    }
 
-    /// Return lines corresponding to this `Span`
-    fn get_lines(&self, span: &Span) -> LineInfo;
+    /// Return lines corresponding to this `Span`.
+    pub(crate) fn get_lines(&self, span: &Span) -> LineInfo {
+        self.cx.get_lines(span)
+    }
 
-    /// Returns the `kind` of given `DefId`
-    fn item_kind(&self, item: CrateItem) -> ItemKind;
+    /// Returns the `kind` of given `DefId`.
+    pub(crate) fn item_kind(&self, item: CrateItem) -> ItemKind {
+        self.cx.item_kind(item)
+    }
 
     /// Returns whether this is a foreign item.
-    fn is_foreign_item(&self, item: DefId) -> bool;
+    pub(crate) fn is_foreign_item(&self, item: DefId) -> bool {
+        self.cx.is_foreign_item(item)
+    }
 
     /// Returns the kind of a given foreign item.
-    fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind;
+    pub(crate) fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind {
+        self.cx.foreign_item_kind(def)
+    }
 
-    /// Returns the kind of a given algebraic data type
-    fn adt_kind(&self, def: AdtDef) -> AdtKind;
+    /// Returns the kind of a given algebraic data type.
+    pub(crate) fn adt_kind(&self, def: AdtDef) -> AdtKind {
+        self.cx.adt_kind(def)
+    }
 
     /// Returns if the ADT is a box.
-    fn adt_is_box(&self, def: AdtDef) -> bool;
+    pub(crate) fn adt_is_box(&self, def: AdtDef) -> bool {
+        self.cx.adt_is_box(def)
+    }
 
     /// Returns whether this ADT is simd.
-    fn adt_is_simd(&self, def: AdtDef) -> bool;
+    pub(crate) fn adt_is_simd(&self, def: AdtDef) -> bool {
+        self.cx.adt_is_simd(def)
+    }
 
     /// Returns whether this definition is a C string.
-    fn adt_is_cstr(&self, def: AdtDef) -> bool;
+    pub(crate) fn adt_is_cstr(&self, def: AdtDef) -> bool {
+        self.cx.adt_is_cstr(def)
+    }
 
     /// Retrieve the function signature for the given generic arguments.
-    fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig;
+    pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
+        self.cx.fn_sig(def, args)
+    }
 
     /// Retrieve the intrinsic definition if the item corresponds one.
-    fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef>;
+    pub(crate) fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> {
+        self.cx.intrinsic(item)
+    }
 
     /// Retrieve the plain function name of an intrinsic.
-    fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol;
+    pub(crate) fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
+        self.cx.intrinsic_name(def)
+    }
 
     /// Retrieve the closure signature for the given generic arguments.
-    fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig;
+    pub(crate) fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
+        self.cx.closure_sig(args)
+    }
 
     /// The number of variants in this ADT.
-    fn adt_variants_len(&self, def: AdtDef) -> usize;
+    pub(crate) fn adt_variants_len(&self, def: AdtDef) -> usize {
+        self.cx.adt_variants_len(def)
+    }
 
     /// The name of a variant.
-    fn variant_name(&self, def: VariantDef) -> Symbol;
-    fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef>;
+    pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol {
+        self.cx.variant_name(def)
+    }
+
+    pub(crate) fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> {
+        self.cx.variant_fields(def)
+    }
 
     /// Evaluate constant as a target usize.
-    fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error>;
-    fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error>;
+    pub(crate) fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> {
+        self.cx.eval_target_usize(cnst)
+    }
+
+    pub(crate) fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> {
+        self.cx.eval_target_usize_ty(cnst)
+    }
 
     /// Create a new zero-sized constant.
-    fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error>;
+    pub(crate) fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> {
+        self.cx.try_new_const_zst(ty)
+    }
 
     /// Create a new constant that represents the given string value.
-    fn new_const_str(&self, value: &str) -> MirConst;
+    pub(crate) fn new_const_str(&self, value: &str) -> MirConst {
+        self.cx.new_const_str(value)
+    }
 
     /// Create a new constant that represents the given boolean value.
-    fn new_const_bool(&self, value: bool) -> MirConst;
+    pub(crate) fn new_const_bool(&self, value: bool) -> MirConst {
+        self.cx.new_const_bool(value)
+    }
 
     /// Create a new constant that represents the given value.
-    fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error>;
-    fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error>;
+    pub(crate) fn try_new_const_uint(
+        &self,
+        value: u128,
+        uint_ty: UintTy,
+    ) -> Result<MirConst, Error> {
+        self.cx.try_new_const_uint(value, uint_ty)
+    }
+
+    pub(crate) fn try_new_ty_const_uint(
+        &self,
+        value: u128,
+        uint_ty: UintTy,
+    ) -> Result<TyConst, Error> {
+        self.cx.try_new_ty_const_uint(value, uint_ty)
+    }
 
     /// Create a new type from the given kind.
-    fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
+    pub(crate) fn new_rigid_ty(&self, kind: RigidTy) -> Ty {
+        self.cx.new_rigid_ty(kind)
+    }
 
     /// Create a new box type, `Box<T>`, for the given inner type `T`.
-    fn new_box_ty(&self, ty: Ty) -> Ty;
+    pub(crate) fn new_box_ty(&self, ty: Ty) -> Ty {
+        self.cx.new_box_ty(ty)
+    }
 
     /// Returns the type of given crate item.
-    fn def_ty(&self, item: DefId) -> Ty;
+    pub(crate) fn def_ty(&self, item: DefId) -> Ty {
+        self.cx.def_ty(item)
+    }
 
     /// Returns the type of given definition instantiated with the given arguments.
-    fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty;
+    pub(crate) fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty {
+        self.cx.def_ty_with_args(item, args)
+    }
 
     /// Returns literal value of a const as a string.
-    fn mir_const_pretty(&self, cnst: &MirConst) -> String;
+    pub(crate) fn mir_const_pretty(&self, cnst: &MirConst) -> String {
+        self.cx.mir_const_pretty(cnst)
+    }
 
-    /// `Span` of an item
-    fn span_of_an_item(&self, def_id: DefId) -> Span;
+    /// `Span` of an item.
+    pub(crate) fn span_of_an_item(&self, def_id: DefId) -> Span {
+        self.cx.span_of_an_item(def_id)
+    }
 
-    fn ty_const_pretty(&self, ct: TyConstId) -> String;
+    pub(crate) fn ty_const_pretty(&self, ct: TyConstId) -> String {
+        self.cx.ty_const_pretty(ct)
+    }
 
     /// Obtain the representation of a type.
-    fn ty_pretty(&self, ty: Ty) -> String;
+    pub(crate) fn ty_pretty(&self, ty: Ty) -> String {
+        self.cx.ty_pretty(ty)
+    }
 
     /// Obtain the representation of a type.
-    fn ty_kind(&self, ty: Ty) -> TyKind;
+    pub(crate) fn ty_kind(&self, ty: Ty) -> TyKind {
+        self.cx.ty_kind(ty)
+    }
 
-    // Get the discriminant Ty for this Ty if there's one.
-    fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty;
+    /// Get the discriminant Ty for this Ty if there's one.
+    pub(crate) fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty {
+        self.cx.rigid_ty_discriminant_ty(ty)
+    }
 
     /// Get the body of an Instance which is already monomorphized.
-    fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
+    pub(crate) fn instance_body(&self, instance: InstanceDef) -> Option<Body> {
+        self.cx.instance_body(instance)
+    }
 
     /// Get the instance type with generic instantiations applied and lifetimes erased.
-    fn instance_ty(&self, instance: InstanceDef) -> Ty;
+    pub(crate) fn instance_ty(&self, instance: InstanceDef) -> Ty {
+        self.cx.instance_ty(instance)
+    }
 
     /// Get the instantiation types.
-    fn instance_args(&self, def: InstanceDef) -> GenericArgs;
+    pub(crate) fn instance_args(&self, def: InstanceDef) -> GenericArgs {
+        self.cx.instance_args(def)
+    }
 
     /// Get the instance.
-    fn instance_def_id(&self, instance: InstanceDef) -> DefId;
+    pub(crate) fn instance_def_id(&self, instance: InstanceDef) -> DefId {
+        self.cx.instance_def_id(instance)
+    }
 
     /// Get the instance mangled name.
-    fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol;
+    pub(crate) fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
+        self.cx.instance_mangled_name(instance)
+    }
 
     /// Check if this is an empty DropGlue shim.
-    fn is_empty_drop_shim(&self, def: InstanceDef) -> bool;
+    pub(crate) fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
+        self.cx.is_empty_drop_shim(def)
+    }
 
     /// Check if this is an empty AsyncDropGlueCtor shim.
-    fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool;
+    pub(crate) fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
+        self.cx.is_empty_async_drop_ctor_shim(def)
+    }
 
     /// Convert a non-generic crate item into an instance.
     /// This function will panic if the item is generic.
-    fn mono_instance(&self, def_id: DefId) -> Instance;
+    pub(crate) fn mono_instance(&self, def_id: DefId) -> Instance {
+        self.cx.mono_instance(def_id)
+    }
 
     /// Item requires monomorphization.
-    fn requires_monomorphization(&self, def_id: DefId) -> bool;
+    pub(crate) fn requires_monomorphization(&self, def_id: DefId) -> bool {
+        self.cx.requires_monomorphization(def_id)
+    }
 
     /// Resolve an instance from the given function definition and generic arguments.
-    fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
+    pub(crate) fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
+        self.cx.resolve_instance(def, args)
+    }
 
     /// Resolve an instance for drop_in_place for the given type.
-    fn resolve_drop_in_place(&self, ty: Ty) -> Instance;
+    pub(crate) fn resolve_drop_in_place(&self, ty: Ty) -> Instance {
+        self.cx.resolve_drop_in_place(ty)
+    }
 
     /// Resolve instance for a function pointer.
-    fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
+    pub(crate) fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> {
+        self.cx.resolve_for_fn_ptr(def, args)
+    }
 
     /// Resolve instance for a closure with the requested type.
-    fn resolve_closure(
+    pub(crate) fn resolve_closure(
         &self,
         def: ClosureDef,
         args: &GenericArgs,
         kind: ClosureKind,
-    ) -> Option<Instance>;
+    ) -> Option<Instance> {
+        self.cx.resolve_closure(def, args, kind)
+    }
 
     /// Evaluate a static's initializer.
-    fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
+    pub(crate) fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
+        self.cx.eval_static_initializer(def)
+    }
 
     /// Try to evaluate an instance into a constant.
-    fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error>;
+    pub(crate) fn eval_instance(
+        &self,
+        def: InstanceDef,
+        const_ty: Ty,
+    ) -> Result<Allocation, Error> {
+        self.cx.eval_instance(def, const_ty)
+    }
 
     /// Retrieve global allocation for the given allocation ID.
-    fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
+    pub(crate) fn global_alloc(&self, id: AllocId) -> GlobalAlloc {
+        self.cx.global_alloc(id)
+    }
 
     /// Retrieve the id for the virtual table.
-    fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
-    fn krate(&self, def_id: DefId) -> Crate;
-    fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
+    pub(crate) fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId> {
+        self.cx.vtable_allocation(global_alloc)
+    }
+
+    pub(crate) fn krate(&self, def_id: DefId) -> Crate {
+        self.cx.krate(def_id)
+    }
+
+    pub(crate) fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
+        self.cx.instance_name(def, trimmed)
+    }
 
     /// Return information about the target machine.
-    fn target_info(&self) -> MachineInfo;
+    pub(crate) fn target_info(&self) -> MachineInfo {
+        self.cx.target_info()
+    }
 
     /// Get an instance ABI.
-    fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>;
+    pub(crate) fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> {
+        self.cx.instance_abi(def)
+    }
 
     /// Get the ABI of a function pointer.
-    fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>;
+    pub(crate) fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> {
+        self.cx.fn_ptr_abi(fn_ptr)
+    }
 
     /// Get the layout of a type.
-    fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>;
+    pub(crate) fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
+        self.cx.ty_layout(ty)
+    }
 
     /// Get the layout shape.
-    fn layout_shape(&self, id: Layout) -> LayoutShape;
+    pub(crate) fn layout_shape(&self, id: Layout) -> LayoutShape {
+        self.cx.layout_shape(id)
+    }
 
     /// Get a debug string representation of a place.
-    fn place_pretty(&self, place: &Place) -> String;
+    pub(crate) fn place_pretty(&self, place: &Place) -> String {
+        self.cx.place_pretty(place)
+    }
 
     /// Get the resulting type of binary operation.
-    fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty;
+    pub(crate) fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty {
+        self.cx.binop_ty(bin_op, rhs, lhs)
+    }
 
     /// Get the resulting type of unary operation.
-    fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty;
+    pub(crate) fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
+        self.cx.unop_ty(un_op, arg)
+    }
 
     /// Get all associated items of a definition.
-    fn associated_items(&self, def_id: DefId) -> AssocItems;
+    pub(crate) fn associated_items(&self, def_id: DefId) -> AssocItems {
+        self.cx.associated_items(def_id)
+    }
 }
 
-// A thread local variable that stores a pointer to the tables mapping between TyCtxt
-// datastructures and stable MIR datastructures
+// A thread local variable that stores a pointer to [`SmirInterface`].
 scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>);
 
-pub fn run<F, T>(context: &dyn Context, f: F) -> Result<T, Error>
+pub(crate) fn run<'tcx, T, F>(interface: &SmirInterface<'tcx>, f: F) -> Result<T, Error>
 where
     F: FnOnce() -> T,
 {
     if TLV.is_set() {
         Err(Error::from("StableMIR already running"))
     } else {
-        let ptr: *const () = (&raw const context) as _;
+        let ptr: *const () = (interface as *const SmirInterface<'tcx>) as *const ();
         TLV.set(&Cell::new(ptr), || Ok(f()))
     }
 }
 
-/// Execute the given function with access the compiler [Context].
+/// Execute the given function with access the [`SmirInterface`].
 ///
-/// I.e., This function will load the current context and calls a function with it.
+/// I.e., This function will load the current interface and calls a function with it.
 /// Do not nest these, as that will ICE.
-pub(crate) fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
+pub(crate) fn with<R>(f: impl FnOnce(&SmirInterface<'_>) -> R) -> R {
     assert!(TLV.is_set());
     TLV.with(|tlv| {
         let ptr = tlv.get();
         assert!(!ptr.is_null());
-        f(unsafe { *(ptr as *const &dyn Context) })
+        f(unsafe { &*(ptr as *const SmirInterface<'_>) })
     })
 }
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 7ecc46cc69d..ae366e29e32 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -144,6 +144,7 @@ pub struct ArgAttributes {
     /// (corresponding to LLVM's dereferenceable_or_null attributes, i.e., it is okay for this to be
     /// set on a null pointer, but all non-null pointers must be dereferenceable).
     pub pointee_size: Size,
+    /// The minimum alignment of the pointee, if any.
     pub pointee_align: Option<Align>,
 }
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 3c769dad630..37ea0d6e7b5 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -42,7 +42,9 @@ use std::path::{Path, PathBuf};
 use std::str::FromStr;
 use std::{fmt, io};
 
-use rustc_abi::{Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors};
+use rustc_abi::{
+    Align, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
+};
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_fs_util::try_canonicalize;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
@@ -3599,6 +3601,25 @@ impl Target {
             _ => return None,
         })
     }
+
+    /// Returns whether this target is known to have unreliable alignment:
+    /// native C code for the target fails to align some data to the degree
+    /// required by the C standard. We can't *really* do anything about that
+    /// since unsafe Rust code may assume alignment any time, but we can at least
+    /// inhibit some optimizations, and we suppress the alignment checks that
+    /// would detect this unsoundness.
+    ///
+    /// Every target that returns less than `Align::MAX` here is still has a soundness bug.
+    pub fn max_reliable_alignment(&self) -> Align {
+        // FIXME(#112480) MSVC on x86-32 is unsound and fails to properly align many types with
+        // more-than-4-byte-alignment on the stack. This makes alignments larger than 4 generally
+        // unreliable on 32bit Windows.
+        if self.is_like_windows && self.arch == "x86" {
+            Align::from_bytes(4).unwrap()
+        } else {
+            Align::MAX
+        }
+    }
 }
 
 /// Either a target tuple string or a path to a JSON file.
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index aeace6a40c7..69c8b9119ab 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -516,7 +516,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zawrs", Unstable(sym::riscv_target_feature), &[]),
     ("zba", Stable, &[]),
     ("zbb", Stable, &[]),
-    ("zbc", Stable, &[]),
+    ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc
     ("zbkb", Stable, &[]),
     ("zbkc", Stable, &[]),
     ("zbkx", Stable, &[]),
@@ -545,20 +545,20 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zknd", Stable, &[]),
     ("zkne", Stable, &[]),
     ("zknh", Stable, &[]),
-    ("zkr", Stable, &["zicsr"]),
+    ("zkr", Stable, &[]),
     ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
     ("zksed", Stable, &[]),
     ("zksh", Stable, &[]),
     ("zkt", Stable, &[]),
     ("ztso", Unstable(sym::riscv_target_feature), &[]),
-    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]),
+    ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb
     ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]),
     ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]),
     ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]),
     ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]),
     ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]),
     ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]),
-    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zfhmin"]),
+    ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin
     ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]),
     ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]),
     ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]),
@@ -567,7 +567,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]),
     ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]),
     ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]),
-    ("zvknhb", Unstable(sym::riscv_target_feature), &["zve64x"]),
+    ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha
     ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]),
     ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]),
     ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]),
@@ -775,7 +775,7 @@ const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[
     (32768, "zvl32768b"),
     (65536, "zvl65536b"),
 ];
-// Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
+// Always error on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
 const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/];
 
 const HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
index 1c3e570b676..d8b405e904c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
@@ -81,9 +81,7 @@ pub fn call_kind<'tcx>(
         }
     });
 
-    let fn_call = parent.and_then(|p| {
-        lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
-    });
+    let fn_call = parent.filter(|&p| tcx.fn_trait_kind_from_def_id(p).is_some());
 
     let operator = if !from_hir_call && let Some(p) = parent {
         lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 5648021f613..df6e8fc4503 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             && 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()
+                            && !self.tcx.is_lang_item(root_pred.def_id(), LangItem::Unsize)
                         {
                             (
                                 self.resolve_vars_if_possible(
@@ -2274,10 +2274,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // auto-traits or fundamental traits that might not be exactly what
         // the user might expect to be presented with. Instead this is
         // useful for less general traits.
-        if peeled
-            && !self.tcx.trait_is_auto(def_id)
-            && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
-        {
+        if peeled && !self.tcx.trait_is_auto(def_id) && self.tcx.as_lang_item(def_id).is_none() {
             let impl_candidates = self.find_similar_impl_candidates(trait_pred);
             self.report_similar_impl_candidates(
                 &impl_candidates,
@@ -3013,8 +3010,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // This shouldn't be common unless manually implementing one of the
         // traits manually, but don't make it more confusing when it does
         // happen.
-        if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
-        {
+        if !self.tcx.is_lang_item(expected_trait_ref.def_id, LangItem::Coroutine) && not_tupled {
             return Ok(self.report_and_explain_type_error(
                 TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
                 obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 7d95a7b3fed..de251ae2893 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3844,12 +3844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     );
                     if let ty::PredicateKind::Clause(clause) = failed_pred.kind().skip_binder()
                         && let ty::ClauseKind::Trait(pred) = clause
-                        && [
-                            tcx.lang_items().fn_once_trait(),
-                            tcx.lang_items().fn_mut_trait(),
-                            tcx.lang_items().fn_trait(),
-                        ]
-                        .contains(&Some(pred.def_id()))
+                        && tcx.fn_trait_kind_from_def_id(pred.def_id()).is_some()
                     {
                         if let [stmt, ..] = block.stmts
                             && let hir::StmtKind::Semi(value) = stmt.kind
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 756d9a57b93..1063115ed23 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -9,7 +9,7 @@ use rustc_errors::{
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
-use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, IsAnonInPath, Node};
+use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
 use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt};
@@ -551,19 +551,6 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
 
             impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
                 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
-                    let make_suggestion = |lifetime: &hir::Lifetime| {
-                        if lifetime.is_anon_in_path == IsAnonInPath::Yes
-                            && lifetime.ident.span.is_empty()
-                        {
-                            format!("{}, ", self.suggestion_param_name)
-                        } else if lifetime.ident.name == kw::UnderscoreLifetime
-                            && lifetime.ident.span.is_empty()
-                        {
-                            format!("{} ", self.suggestion_param_name)
-                        } else {
-                            self.suggestion_param_name.clone()
-                        }
-                    };
                     match ty.kind {
                         hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
                             for segment in path.segments {
@@ -572,7 +559,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                                         matches!(
                                             arg,
                                             hir::GenericArg::Lifetime(lifetime)
-                                                if lifetime.is_anon_in_path == IsAnonInPath::Yes
+                                                if lifetime.is_syntactically_hidden()
                                         )
                                     }) {
                                         self.suggestions.push((
@@ -591,10 +578,10 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                                             if let hir::GenericArg::Lifetime(lifetime) = arg
                                                 && lifetime.is_anonymous()
                                             {
-                                                self.suggestions.push((
-                                                    lifetime.ident.span,
-                                                    make_suggestion(lifetime),
-                                                ));
+                                                self.suggestions.push(
+                                                    lifetime
+                                                        .suggestion(&self.suggestion_param_name),
+                                                );
                                             }
                                         }
                                     }
@@ -602,7 +589,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
                             }
                         }
                         hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
-                            self.suggestions.push((lifetime.ident.span, make_suggestion(lifetime)));
+                            self.suggestions.push(lifetime.suggestion(&self.suggestion_param_name));
                         }
                         _ => {}
                     }
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 84ac229b743..0dab3adadb0 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -34,7 +34,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
         // FIXME(#132279): This should be removed as it causes us to incorrectly
         // handle opaques in their defining scope.
-        if !(param_env, ty).has_infer() {
+        if !self.next_trait_solver() && !(param_env, ty).has_infer() {
             return self.tcx.type_is_copy_modulo_regions(self.typing_env(param_env), ty);
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve.rs b/compiler/rustc_trait_selection/src/solve.rs
index d425ab50ae0..0c2451a80a7 100644
--- a/compiler/rustc_trait_selection/src/solve.rs
+++ b/compiler/rustc_trait_selection/src/solve.rs
@@ -9,5 +9,8 @@ mod select;
 pub(crate) use delegate::SolverDelegate;
 pub use fulfill::{FulfillmentCtxt, NextSolverError};
 pub(crate) use normalize::deeply_normalize_for_diagnostics;
-pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
+pub use normalize::{
+    deeply_normalize, deeply_normalize_with_skipped_universes,
+    deeply_normalize_with_skipped_universes_and_ambiguous_goals,
+};
 pub use select::InferCtxtSelectExt;
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 192e632a2d5..848d0646d00 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -1,18 +1,26 @@
 use std::marker::PhantomData;
 use std::mem;
+use std::ops::ControlFlow;
 
 use rustc_data_structures::thinvec::ExtractIf;
+use rustc_hir::def_id::LocalDefId;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::{
     FromSolverError, PredicateObligation, PredicateObligations, TraitEngine,
 };
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode,
+};
 use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
+use rustc_span::Span;
+use rustc_type_ir::data_structures::DelayedSet;
 use tracing::instrument;
 
 use self::derive_errors::*;
 use super::Certainty;
 use super::delegate::SolverDelegate;
+use super::inspect::{self, ProofTreeInferCtxtExt};
 use crate::traits::{FulfillmentError, ScrubbedTraitError};
 
 mod derive_errors;
@@ -39,7 +47,7 @@ pub struct FulfillmentCtxt<'tcx, E: 'tcx> {
     _errors: PhantomData<E>,
 }
 
-#[derive(Default)]
+#[derive(Default, Debug)]
 struct ObligationStorage<'tcx> {
     /// Obligations which resulted in an overflow in fulfillment itself.
     ///
@@ -55,20 +63,23 @@ impl<'tcx> ObligationStorage<'tcx> {
         self.pending.push(obligation);
     }
 
+    fn has_pending_obligations(&self) -> bool {
+        !self.pending.is_empty() || !self.overflowed.is_empty()
+    }
+
     fn clone_pending(&self) -> PredicateObligations<'tcx> {
         let mut obligations = self.pending.clone();
         obligations.extend(self.overflowed.iter().cloned());
         obligations
     }
 
-    fn take_pending(&mut self) -> PredicateObligations<'tcx> {
-        let mut obligations = mem::take(&mut self.pending);
-        obligations.append(&mut self.overflowed);
-        obligations
-    }
-
-    fn unstalled_for_select(&mut self) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'tcx {
-        mem::take(&mut self.pending).into_iter()
+    fn drain_pending(
+        &mut self,
+        cond: impl Fn(&PredicateObligation<'tcx>) -> bool,
+    ) -> PredicateObligations<'tcx> {
+        let (unstalled, pending) = mem::take(&mut self.pending).into_iter().partition(cond);
+        self.pending = pending;
+        unstalled
     }
 
     fn on_fulfillment_overflow(&mut self, infcx: &InferCtxt<'tcx>) {
@@ -160,7 +171,7 @@ where
             }
 
             let mut has_changed = false;
-            for obligation in self.obligations.unstalled_for_select() {
+            for obligation in self.obligations.drain_pending(|_| true) {
                 let goal = obligation.as_goal();
                 let result = <&SolverDelegate<'tcx>>::from(infcx)
                     .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
@@ -196,15 +207,95 @@ where
     }
 
     fn has_pending_obligations(&self) -> bool {
-        !self.obligations.pending.is_empty() || !self.obligations.overflowed.is_empty()
+        self.obligations.has_pending_obligations()
     }
 
     fn pending_obligations(&self) -> PredicateObligations<'tcx> {
         self.obligations.clone_pending()
     }
 
-    fn drain_unstalled_obligations(&mut self, _: &InferCtxt<'tcx>) -> PredicateObligations<'tcx> {
-        self.obligations.take_pending()
+    fn drain_stalled_obligations_for_coroutines(
+        &mut self,
+        infcx: &InferCtxt<'tcx>,
+    ) -> PredicateObligations<'tcx> {
+        let stalled_generators = match infcx.typing_mode() {
+            TypingMode::Analysis { defining_opaque_types_and_generators } => {
+                defining_opaque_types_and_generators
+            }
+            TypingMode::Coherence
+            | TypingMode::Borrowck { defining_opaque_types: _ }
+            | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
+            | TypingMode::PostAnalysis => return Default::default(),
+        };
+
+        if stalled_generators.is_empty() {
+            return Default::default();
+        }
+
+        self.obligations.drain_pending(|obl| {
+            infcx.probe(|_| {
+                infcx
+                    .visit_proof_tree(
+                        obl.as_goal(),
+                        &mut StalledOnCoroutines {
+                            stalled_generators,
+                            span: obl.cause.span,
+                            cache: Default::default(),
+                        },
+                    )
+                    .is_break()
+            })
+        })
+    }
+}
+
+/// Detect if a goal is stalled on a coroutine that is owned by the current typeck root.
+///
+/// This function can (erroneously) fail to detect a predicate, i.e. it doesn't need to
+/// be complete. However, this will lead to ambiguity errors, so we want to make it
+/// accurate.
+///
+/// This function can be also return false positives, which will lead to poor diagnostics
+/// so we want to keep this visitor *precise* too.
+struct StalledOnCoroutines<'tcx> {
+    stalled_generators: &'tcx ty::List<LocalDefId>,
+    span: Span,
+    cache: DelayedSet<Ty<'tcx>>,
+}
+
+impl<'tcx> inspect::ProofTreeVisitor<'tcx> for StalledOnCoroutines<'tcx> {
+    type Result = ControlFlow<()>;
+
+    fn span(&self) -> rustc_span::Span {
+        self.span
+    }
+
+    fn visit_goal(&mut self, inspect_goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
+        inspect_goal.goal().predicate.visit_with(self)?;
+
+        if let Some(candidate) = inspect_goal.unique_applicable_candidate() {
+            candidate.visit_nested_no_probe(self)
+        } else {
+            ControlFlow::Continue(())
+        }
+    }
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
+    type Result = ControlFlow<()>;
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+        if !self.cache.insert(ty) {
+            return ControlFlow::Continue(());
+        }
+
+        if let ty::CoroutineWitness(def_id, _) = *ty.kind()
+            && def_id.as_local().is_some_and(|def_id| self.stalled_generators.contains(&def_id))
+        {
+            return ControlFlow::Break(());
+        }
+
+        ty.super_visit_with(self)
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index d8dcd12aecb..f6c650c68c0 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -1,5 +1,6 @@
 use std::ops::ControlFlow;
 
+use rustc_hir::LangItem;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
@@ -109,10 +110,16 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
                 false,
             ),
             Ok((_, Certainty::Yes)) => {
-                bug!("did not expect successful goal when collecting ambiguity errors")
+                bug!(
+                    "did not expect successful goal when collecting ambiguity errors for `{:?}`",
+                    infcx.resolve_vars_if_possible(root_obligation.predicate),
+                )
             }
             Err(_) => {
-                bug!("did not expect selection error when collecting ambiguity errors")
+                bug!(
+                    "did not expect selection error when collecting ambiguity errors for `{:?}`",
+                    infcx.resolve_vars_if_possible(root_obligation.predicate),
+                )
             }
         }
     });
@@ -452,9 +459,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
         // We do this as a separate loop so that we do not choose to tell the user about some nested
         // goal before we encounter a `T: FnPtr` nested goal.
         for nested_goal in &nested_goals {
-            if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait()
-                && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
-                && poly_trait_pred.def_id() == fn_ptr_trait
+            if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
+                && tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
                 && let Err(NoSolution) = nested_goal.result()
             {
                 return ControlFlow::Break(self.obligation.clone());
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 79fb044a67f..5f1e63ab225 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -1,10 +1,10 @@
 use std::assert_matches::assert_matches;
 use std::fmt::Debug;
-use std::marker::PhantomData;
 
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::at::At;
+use rustc_infer::traits::solve::Goal;
 use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{
@@ -45,11 +45,37 @@ where
     T: TypeFoldable<TyCtxt<'tcx>>,
     E: FromSolverError<'tcx, NextSolverError<'tcx>>,
 {
+    let (value, goals) =
+        deeply_normalize_with_skipped_universes_and_ambiguous_goals(at, value, universes)?;
+    assert_eq!(goals, vec![]);
+
+    Ok(value)
+}
+
+/// Deeply normalize all aliases in `value`. This does not handle inference and expects
+/// its input to be already fully resolved.
+///
+/// Additionally takes a list of universes which represents the binders which have been
+/// entered before passing `value` to the function. This is currently needed for
+/// `normalize_erasing_regions`, which skips binders as it walks through a type.
+///
+/// This returns a set of stalled obligations if the typing mode of the underlying infcx
+/// has any stalled coroutine def ids.
+pub fn deeply_normalize_with_skipped_universes_and_ambiguous_goals<'tcx, T, E>(
+    at: At<'_, 'tcx>,
+    value: T,
+    universes: Vec<Option<UniverseIndex>>,
+) -> Result<(T, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), Vec<E>>
+where
+    T: TypeFoldable<TyCtxt<'tcx>>,
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     let fulfill_cx = FulfillmentCtxt::new(at.infcx);
     let mut folder =
-        NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
-
-    value.try_fold_with(&mut folder)
+        NormalizationFolder { at, fulfill_cx, depth: 0, universes, stalled_goals: vec![] };
+    let value = value.try_fold_with(&mut folder)?;
+    let errors = folder.fulfill_cx.select_all_or_error(at.infcx);
+    if errors.is_empty() { Ok((value, folder.stalled_goals)) } else { Err(errors) }
 }
 
 struct NormalizationFolder<'me, 'tcx, E> {
@@ -57,7 +83,7 @@ struct NormalizationFolder<'me, 'tcx, E> {
     fulfill_cx: FulfillmentCtxt<'tcx, E>,
     depth: usize,
     universes: Vec<Option<UniverseIndex>>,
-    _errors: PhantomData<E>,
+    stalled_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
 }
 
 impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
@@ -98,10 +124,7 @@ where
         );
 
         self.fulfill_cx.register_predicate_obligation(infcx, obligation);
-        let errors = self.fulfill_cx.select_all_or_error(infcx);
-        if !errors.is_empty() {
-            return Err(errors);
-        }
+        self.select_all_and_stall_coroutine_predicates()?;
 
         // Alias is guaranteed to be fully structurally resolved,
         // so we can super fold here.
@@ -139,7 +162,7 @@ where
 
         let result = if infcx.predicate_may_hold(&obligation) {
             self.fulfill_cx.register_predicate_obligation(infcx, obligation);
-            let errors = self.fulfill_cx.select_all_or_error(infcx);
+            let errors = self.fulfill_cx.select_where_possible(infcx);
             if !errors.is_empty() {
                 return Err(errors);
             }
@@ -152,6 +175,27 @@ where
         self.depth -= 1;
         Ok(result)
     }
+
+    fn select_all_and_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> {
+        let errors = self.fulfill_cx.select_where_possible(self.at.infcx);
+        if !errors.is_empty() {
+            return Err(errors);
+        }
+
+        self.stalled_goals.extend(
+            self.fulfill_cx
+                .drain_stalled_obligations_for_coroutines(self.at.infcx)
+                .into_iter()
+                .map(|obl| obl.as_goal()),
+        );
+
+        let errors = self.fulfill_cx.collect_remaining_errors(self.at.infcx);
+        if !errors.is_empty() {
+            return Err(errors);
+        }
+
+        Ok(())
+    }
 }
 
 impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
@@ -254,27 +298,31 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let infcx = self.at.infcx;
-        infcx
-            .commit_if_ok(|_| {
-                deeply_normalize_with_skipped_universes(
-                    self.at,
-                    ty,
-                    vec![None; ty.outer_exclusive_binder().as_usize()],
-                )
-            })
-            .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
+        let result =
+            infcx.commit_if_ok(|_| {
+                deeply_normalize_with_skipped_universes_and_ambiguous_goals::<
+                    _,
+                    ScrubbedTraitError<'tcx>,
+                >(self.at, ty, vec![None; ty.outer_exclusive_binder().as_usize()])
+            });
+        match result {
+            Ok((ty, _)) => ty,
+            Err(_) => ty.super_fold_with(self),
+        }
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         let infcx = self.at.infcx;
-        infcx
-            .commit_if_ok(|_| {
-                deeply_normalize_with_skipped_universes(
-                    self.at,
-                    ct,
-                    vec![None; ct.outer_exclusive_binder().as_usize()],
-                )
-            })
-            .unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
+        let result =
+            infcx.commit_if_ok(|_| {
+                deeply_normalize_with_skipped_universes_and_ambiguous_goals::<
+                    _,
+                    ScrubbedTraitError<'tcx>,
+                >(self.at, ct, vec![None; ct.outer_exclusive_binder().as_usize()])
+            });
+        match result {
+            Ok((ct, _)) => ct,
+            Err(_) => ct.super_fold_with(self),
+        }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1b76d48e431..a11f8d3a9ec 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -162,7 +162,7 @@ where
         self.select(selcx)
     }
 
-    fn drain_unstalled_obligations(
+    fn drain_stalled_obligations_for_coroutines(
         &mut self,
         infcx: &InferCtxt<'tcx>,
     ) -> PredicateObligations<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0dce504903c..99fa791b375 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -965,36 +965,38 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 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(),
-                    lang_items.future_trait(),
-                    lang_items.iterator_trait(),
-                    lang_items.async_iterator_trait(),
-                    lang_items.fn_trait(),
-                    lang_items.fn_mut_trait(),
-                    lang_items.fn_once_trait(),
-                    lang_items.async_fn_trait(),
-                    lang_items.async_fn_mut_trait(),
-                    lang_items.async_fn_once_trait(),
-                ]
-                .contains(&Some(trait_ref.def_id))
-                {
-                    true
-                } 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()
-                        || obligation.predicate.args.type_at(5).is_ty_var()
-                    {
-                        candidate_set.mark_ambiguous();
-                        true
-                    } else {
-                        obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
-                            && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
+                match selcx.tcx().as_lang_item(trait_ref.def_id) {
+                    Some(
+                        LangItem::Coroutine
+                        | LangItem::Future
+                        | LangItem::Iterator
+                        | LangItem::AsyncIterator
+                        | LangItem::Fn
+                        | LangItem::FnMut
+                        | LangItem::FnOnce
+                        | LangItem::AsyncFn
+                        | LangItem::AsyncFnMut
+                        | LangItem::AsyncFnOnce,
+                    ) => true,
+                    Some(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()
+                            || obligation.predicate.args.type_at(5).is_ty_var()
+                        {
+                            candidate_set.mark_ambiguous();
+                            true
+                        } else {
+                            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 tcx.is_lang_item(trait_ref.def_id, LangItem::DiscriminantKind) {
-                    match self_ty.kind() {
+                    Some(LangItem::DiscriminantKind) => match self_ty.kind() {
                         ty::Bool
                         | ty::Char
                         | ty::Int(_)
@@ -1031,9 +1033,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Placeholder(..)
                         | ty::Infer(..)
                         | ty::Error(_) => false,
-                    }
-                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncDestruct) {
-                    match self_ty.kind() {
+                    },
+                    Some(LangItem::AsyncDestruct) => match self_ty.kind() {
                         ty::Bool
                         | ty::Char
                         | ty::Int(_)
@@ -1068,101 +1069,104 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Placeholder(..)
                         | ty::Infer(_)
                         | ty::Error(_) => false,
-                    }
-                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
-                    let tail = selcx.tcx().struct_tail_raw(
-                        self_ty,
-                        |ty| {
-                            // We throw away any obligations we get from this, since we normalize
-                            // and confirm these obligations once again during confirmation
-                            normalize_with_depth(
-                                selcx,
-                                obligation.param_env,
-                                obligation.cause.clone(),
-                                obligation.recursion_depth + 1,
-                                ty,
-                            )
-                            .value
-                        },
-                        || {},
-                    );
+                    },
+                    Some(LangItem::PointeeTrait) => {
+                        let tail = selcx.tcx().struct_tail_raw(
+                            self_ty,
+                            |ty| {
+                                // We throw away any obligations we get from this, since we normalize
+                                // and confirm these obligations once again during confirmation
+                                normalize_with_depth(
+                                    selcx,
+                                    obligation.param_env,
+                                    obligation.cause.clone(),
+                                    obligation.recursion_depth + 1,
+                                    ty,
+                                )
+                                .value
+                            },
+                            || {},
+                        );
 
-                    match tail.kind() {
-                        ty::Bool
-                        | ty::Char
-                        | ty::Int(_)
-                        | ty::Uint(_)
-                        | ty::Float(_)
-                        | ty::Str
-                        | ty::Array(..)
-                        | ty::Pat(..)
-                        | ty::Slice(_)
-                        | ty::RawPtr(..)
-                        | ty::Ref(..)
-                        | ty::FnDef(..)
-                        | ty::FnPtr(..)
-                        | ty::Dynamic(..)
-                        | ty::Closure(..)
-                        | ty::CoroutineClosure(..)
-                        | ty::Coroutine(..)
-                        | ty::CoroutineWitness(..)
-                        | ty::Never
-                        // Extern types have unit metadata, according to RFC 2850
-                        | ty::Foreign(_)
-                        // If returned by `struct_tail` this is a unit struct
-                        // without any fields, or not a struct, and therefore is Sized.
-                        | ty::Adt(..)
-                        // If returned by `struct_tail` this is the empty tuple.
-                        | ty::Tuple(..)
-                        // Integers and floats are always Sized, and so have unit type metadata.
-                        | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
-                        // This happens if we reach the recursion limit when finding the struct tail.
-                        | ty::Error(..) => true,
-
-                        // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
-                        // Otherwise, type parameters, opaques, and unnormalized projections have
-                        // unit metadata if they're known (e.g. by the param_env) to be sized.
-                        ty::Param(_) | ty::Alias(..)
-                            if self_ty != tail
-                                || selcx.infcx.predicate_must_hold_modulo_regions(
-                                    &obligation.with(
-                                        selcx.tcx(),
-                                        ty::TraitRef::new(
+                        match tail.kind() {
+                            ty::Bool
+                            | ty::Char
+                            | ty::Int(_)
+                            | ty::Uint(_)
+                            | ty::Float(_)
+                            | ty::Str
+                            | ty::Array(..)
+                            | ty::Pat(..)
+                            | ty::Slice(_)
+                            | ty::RawPtr(..)
+                            | ty::Ref(..)
+                            | ty::FnDef(..)
+                            | ty::FnPtr(..)
+                            | ty::Dynamic(..)
+                            | ty::Closure(..)
+                            | ty::CoroutineClosure(..)
+                            | ty::Coroutine(..)
+                            | ty::CoroutineWitness(..)
+                            | ty::Never
+                            // Extern types have unit metadata, according to RFC 2850
+                            | ty::Foreign(_)
+                            // If returned by `struct_tail` this is a unit struct
+                            // without any fields, or not a struct, and therefore is Sized.
+                            | ty::Adt(..)
+                            // If returned by `struct_tail` this is the empty tuple.
+                            | ty::Tuple(..)
+                            // Integers and floats are always Sized, and so have unit type metadata.
+                            | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..))
+                            // This happens if we reach the recursion limit when finding the struct tail.
+                            | ty::Error(..) => true,
+
+                            // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able.
+                            // Otherwise, type parameters, opaques, and unnormalized projections have
+                            // unit metadata if they're known (e.g. by the param_env) to be sized.
+                            ty::Param(_) | ty::Alias(..)
+                                if self_ty != tail
+                                    || selcx.infcx.predicate_must_hold_modulo_regions(
+                                        &obligation.with(
                                             selcx.tcx(),
-                                            selcx.tcx().require_lang_item(
-                                                LangItem::Sized,
-                                                Some(obligation.cause.span),
+                                            ty::TraitRef::new(
+                                                selcx.tcx(),
+                                                selcx.tcx().require_lang_item(
+                                                    LangItem::Sized,
+                                                    Some(obligation.cause.span),
+                                                ),
+                                                [self_ty],
                                             ),
-                                            [self_ty],
                                         ),
-                                    ),
-                                ) =>
-                        {
-                            true
-                        }
+                                    ) =>
+                            {
+                                true
+                            }
 
-                        ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
+                            ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
 
-                        // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
-                        ty::Param(_)
-                        | ty::Alias(..)
-                        | ty::Bound(..)
-                        | ty::Placeholder(..)
-                        | ty::Infer(..) => {
-                            if tail.has_infer_types() {
-                                candidate_set.mark_ambiguous();
+                            // FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
+                            ty::Param(_)
+                            | ty::Alias(..)
+                            | ty::Bound(..)
+                            | ty::Placeholder(..)
+                            | ty::Infer(..) => {
+                                if tail.has_infer_types() {
+                                    candidate_set.mark_ambiguous();
+                                }
+                                false
                             }
-                            false
                         }
                     }
-                } else if tcx.trait_is_auto(trait_ref.def_id) {
-                    tcx.dcx().span_delayed_bug(
-                        tcx.def_span(obligation.predicate.def_id),
-                        "associated types not allowed on auto traits",
-                    );
-                    false
-                } else {
-                    bug!("unexpected builtin trait with associated type: {trait_ref:?}")
+                    _ if tcx.trait_is_auto(trait_ref.def_id) => {
+                        tcx.dcx().span_delayed_bug(
+                            tcx.def_span(obligation.predicate.def_id),
+                            "associated types not allowed on auto traits",
+                        );
+                        false
+                    }
+                    _ => {
+                        bug!("unexpected builtin trait with associated type: {trait_ref:?}")
+                    }
                 }
             }
             ImplSource::Param(..) => {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index 4eecde00eaa..f059bd00768 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -117,8 +117,7 @@ fn relate_mir_and_user_args<'tcx>(
             CRATE_DEF_ID,
             ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
         );
-        let instantiated_predicate =
-            ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
+        let instantiated_predicate = ocx.normalize(&cause, param_env, instantiated_predicate);
 
         ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
     }
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 cf6d2bc151f..00101010f14 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -240,8 +240,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
                 continue;
             }
-            // FIXME(oli-obk): it is suspicious that we are dropping the constness and
-            // polarity here.
             let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
             if wc.may_apply() {
                 candidates.vec.push(ParamCandidate(bound));
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4d88a23250a..c7ce13c8014 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1498,7 +1498,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // However, if we disqualify *all* goals from being cached, perf suffers.
             // This is likely fixed by better caching in general in the new solver.
             // See: <https://github.com/rust-lang/rust/issues/132064>.
-            TypingMode::Analysis { defining_opaque_types }
+            TypingMode::Analysis {
+                defining_opaque_types_and_generators: defining_opaque_types,
+            }
             | TypingMode::Borrowck { defining_opaque_types } => {
                 defining_opaque_types.is_empty() || !pred.has_opaque_types()
             }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 54b6c22b2d8..cad7e42fd82 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -1,3 +1,8 @@
+//! Core logic responsible for determining what it means for various type system
+//! primitives to be "well formed". Actually checking whether these primitives are
+//! well formed is performed elsewhere (e.g. during type checking or item well formedness
+//! checking).
+
 use std::iter;
 
 use rustc_hir as hir;
@@ -15,12 +20,13 @@ use tracing::{debug, instrument, trace};
 
 use crate::infer::InferCtxt;
 use crate::traits;
+
 /// Returns the set of obligations needed to make `arg` well-formed.
 /// If `arg` contains unresolved inference variables, this may include
 /// further WF obligations. However, if `arg` IS an unresolved
 /// inference variable, returns `None`, because we are not able to
-/// make any progress at all. This is to prevent "livelock" where we
-/// say "$0 is WF if $0 is WF".
+/// make any progress at all. This is to prevent cycles where we
+/// say "?0 is WF if ?0 is WF".
 pub fn obligations<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -29,14 +35,14 @@ pub fn obligations<'tcx>(
     arg: GenericArg<'tcx>,
     span: Span,
 ) -> Option<PredicateObligations<'tcx>> {
-    // Handle the "livelock" case (see comment above) by bailing out if necessary.
+    // Handle the "cycle" case (see comment above) by bailing out if necessary.
     let arg = match arg.unpack() {
         GenericArgKind::Type(ty) => {
             match ty.kind() {
                 ty::Infer(ty::TyVar(_)) => {
                     let resolved_ty = infcx.shallow_resolve(ty);
                     if resolved_ty == ty {
-                        // No progress, bail out to prevent "livelock".
+                        // No progress, bail out to prevent cycles.
                         return None;
                     } else {
                         resolved_ty
@@ -51,7 +57,7 @@ pub fn obligations<'tcx>(
                 ty::ConstKind::Infer(_) => {
                     let resolved = infcx.shallow_resolve_const(ct);
                     if resolved == ct {
-                        // No progress.
+                        // No progress, bail out to prevent cycles.
                         return None;
                     } else {
                         resolved
@@ -74,7 +80,7 @@ pub fn obligations<'tcx>(
         recursion_depth,
         item: None,
     };
-    wf.compute(arg);
+    wf.add_wf_preds_for_generic_arg(arg);
     debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
 
     let result = wf.normalize(infcx);
@@ -97,7 +103,7 @@ pub fn unnormalized_obligations<'tcx>(
 
     // However, if `arg` IS an unresolved inference variable, returns `None`,
     // because we are not able to make any progress at all. This is to prevent
-    // "livelock" where we say "$0 is WF if $0 is WF".
+    // cycles where we say "?0 is WF if ?0 is WF".
     if arg.is_non_region_infer() {
         return None;
     }
@@ -115,7 +121,7 @@ pub fn unnormalized_obligations<'tcx>(
         recursion_depth: 0,
         item: None,
     };
-    wf.compute(arg);
+    wf.add_wf_preds_for_generic_arg(arg);
     Some(wf.out)
 }
 
@@ -140,7 +146,7 @@ pub fn trait_obligations<'tcx>(
         recursion_depth: 0,
         item: Some(item),
     };
-    wf.compute_trait_pred(trait_pred, Elaborate::All);
+    wf.add_wf_preds_for_trait_pred(trait_pred, Elaborate::All);
     debug!(obligations = ?wf.out);
     wf.normalize(infcx)
 }
@@ -171,7 +177,7 @@ pub fn clause_obligations<'tcx>(
     // It's ok to skip the binder here because wf code is prepared for it
     match clause.kind().skip_binder() {
         ty::ClauseKind::Trait(t) => {
-            wf.compute_trait_pred(t, Elaborate::None);
+            wf.add_wf_preds_for_trait_pred(t, Elaborate::None);
         }
         ty::ClauseKind::HostEffect(..) => {
             // Technically the well-formedness of this predicate is implied by
@@ -179,22 +185,22 @@ pub fn clause_obligations<'tcx>(
         }
         ty::ClauseKind::RegionOutlives(..) => {}
         ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
-            wf.compute(ty.into());
+            wf.add_wf_preds_for_generic_arg(ty.into());
         }
         ty::ClauseKind::Projection(t) => {
-            wf.compute_alias_term(t.projection_term);
-            wf.compute(t.term.into_arg());
+            wf.add_wf_preds_for_alias_term(t.projection_term);
+            wf.add_wf_preds_for_generic_arg(t.term.into_arg());
         }
         ty::ClauseKind::ConstArgHasType(ct, ty) => {
-            wf.compute(ct.into());
-            wf.compute(ty.into());
+            wf.add_wf_preds_for_generic_arg(ct.into());
+            wf.add_wf_preds_for_generic_arg(ty.into());
         }
         ty::ClauseKind::WellFormed(arg) => {
-            wf.compute(arg);
+            wf.add_wf_preds_for_generic_arg(arg);
         }
 
         ty::ClauseKind::ConstEvaluatable(ct) => {
-            wf.compute(ct.into());
+            wf.add_wf_preds_for_generic_arg(ct.into());
         }
     }
 
@@ -372,14 +378,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     }
 
     /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
-    fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
+    fn add_wf_preds_for_trait_pred(
+        &mut self,
+        trait_pred: ty::TraitPredicate<'tcx>,
+        elaborate: Elaborate,
+    ) {
         let tcx = self.tcx();
         let trait_ref = trait_pred.trait_ref;
 
         // Negative trait predicates don't require supertraits to hold, just
         // that their args are WF.
         if trait_pred.polarity == ty::PredicatePolarity::Negative {
-            self.compute_negative_trait_pred(trait_ref);
+            self.add_wf_preds_for_negative_trait_pred(trait_ref);
             return;
         }
 
@@ -445,15 +455,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     // Compute the obligations that are required for `trait_ref` to be WF,
     // given that it is a *negative* trait predicate.
-    fn compute_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
+    fn add_wf_preds_for_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
         for arg in trait_ref.args {
-            self.compute(arg);
+            self.add_wf_preds_for_generic_arg(arg);
         }
     }
 
     /// Pushes the obligations required for an alias (except inherent) to be WF
     /// into `self.out`.
-    fn compute_alias_term(&mut self, data: ty::AliasTerm<'tcx>) {
+    fn add_wf_preds_for_alias_term(&mut self, data: ty::AliasTerm<'tcx>) {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -478,13 +488,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         let obligations = self.nominal_obligations(data.def_id, data.args);
         self.out.extend(obligations);
 
-        self.compute_projection_args(data.args);
+        self.add_wf_preds_for_projection_args(data.args);
     }
 
     /// Pushes the obligations required for an inherent alias to be WF
     /// into `self.out`.
     // FIXME(inherent_associated_types): Merge this function with `fn compute_alias`.
-    fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
+    fn add_wf_preds_for_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
         // An inherent projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -511,7 +521,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         data.args.visit_with(self);
     }
 
-    fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
+    fn add_wf_preds_for_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
         let tcx = self.tcx();
         let cause = self.cause(ObligationCauseCode::WellFormed(None));
         let param_env = self.param_env;
@@ -557,7 +567,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
     #[instrument(level = "debug", skip(self))]
-    fn compute(&mut self, arg: GenericArg<'tcx>) {
+    fn add_wf_preds_for_generic_arg(&mut self, arg: GenericArg<'tcx>) {
         arg.visit_with(self);
         debug!(?self.out);
     }
@@ -596,7 +606,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
             .collect()
     }
 
-    fn from_object_ty(
+    fn add_wf_preds_for_dyn_ty(
         &mut self,
         ty: Ty<'tcx>,
         data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
@@ -651,6 +661,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     outlives,
                 ));
             }
+
+            // We don't add any wf predicates corresponding to the trait ref's generic arguments
+            // which allows code like this to compile:
+            // ```rust
+            // trait Trait<T: Sized> {}
+            // fn foo(_: &dyn Trait<[u32]>) {}
+            // ```
         }
     }
 }
@@ -761,7 +778,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 self.out.extend(obligations);
             }
             ty::Alias(ty::Inherent, data) => {
-                self.compute_inherent_projection(data);
+                self.add_wf_preds_for_inherent_projection(data);
                 return; // Subtree handled by compute_inherent_projection.
             }
 
@@ -895,7 +912,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 //
                 // Here, we defer WF checking due to higher-ranked
                 // regions. This is perhaps not ideal.
-                self.from_object_ty(t, data, r);
+                self.add_wf_preds_for_dyn_ty(t, data, r);
 
                 // FIXME(#27579) RFC also considers adding trait
                 // obligations that don't refer to Self and
@@ -917,11 +934,11 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             // 1. Check if they have been resolved, and if so proceed with
             //    THAT type.
             // 2. If not, we've at least simplified things (e.g., we went
-            //    from `Vec<$0>: WF` to `$0: WF`), so we can
+            //    from `Vec?0>: WF` to `?0: WF`), so we can
             //    register a pending obligation and keep
             //    moving. (Goal is that an "inductive hypothesis"
             //    is satisfied to ensure termination.)
-            // See also the comment on `fn obligations`, describing "livelock"
+            // See also the comment on `fn obligations`, describing cycle
             // prevention, which happens before this can be reached.
             ty::Infer(_) => {
                 let cause = self.cause(ObligationCauseCode::WellFormed(None));
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index f0c783b3002..0250cc0ea07 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -5,11 +5,13 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.12"
 rustc_abi = { path = "../rustc_abi", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir", optional = true }
 rustc_middle = { path = "../rustc_middle", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
+smallvec = "1.8.1"
 tracing = "0.1"
 # tidy-alphabetical-end
 
@@ -20,8 +22,3 @@ rustc = [
     "dep:rustc_middle",
     "dep:rustc_span",
 ]
-
-[dev-dependencies]
-# tidy-alphabetical-start
-itertools = "0.12"
-# tidy-alphabetical-end
diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs
index bb909c54d2b..d1f58157b69 100644
--- a/compiler/rustc_transmute/src/layout/dfa.rs
+++ b/compiler/rustc_transmute/src/layout/dfa.rs
@@ -1,8 +1,9 @@
 use std::fmt;
+use std::ops::RangeInclusive;
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use super::{Byte, Ref, Tree, Uninhabited};
-use crate::Map;
+use crate::{Map, Set};
 
 #[derive(PartialEq)]
 #[cfg_attr(test, derive(Clone))]
@@ -20,7 +21,7 @@ pub(crate) struct Transitions<R>
 where
     R: Ref,
 {
-    byte_transitions: Map<Byte, State>,
+    byte_transitions: EdgeSet<State>,
     ref_transitions: Map<R, State>,
 }
 
@@ -29,7 +30,7 @@ where
     R: Ref,
 {
     fn default() -> Self {
-        Self { byte_transitions: Map::default(), ref_transitions: Map::default() }
+        Self { byte_transitions: EdgeSet::empty(), ref_transitions: Map::default() }
     }
 }
 
@@ -56,15 +57,10 @@ where
 {
     #[cfg(test)]
     pub(crate) fn bool() -> Self {
-        let mut transitions: Map<State, Transitions<R>> = Map::default();
-        let start = State::new();
-        let accept = State::new();
-
-        transitions.entry(start).or_default().byte_transitions.insert(Byte::Init(0x00), accept);
-
-        transitions.entry(start).or_default().byte_transitions.insert(Byte::Init(0x01), accept);
-
-        Self { transitions, start, accept }
+        Self::from_transitions(|accept| Transitions {
+            byte_transitions: EdgeSet::new(Byte::new(0x00..=0x01), accept),
+            ref_transitions: Map::default(),
+        })
     }
 
     pub(crate) fn unit() -> Self {
@@ -76,23 +72,24 @@ where
     }
 
     pub(crate) fn from_byte(byte: Byte) -> Self {
-        let mut transitions: Map<State, Transitions<R>> = Map::default();
-        let start = State::new();
-        let accept = State::new();
-
-        transitions.entry(start).or_default().byte_transitions.insert(byte, accept);
-
-        Self { transitions, start, accept }
+        Self::from_transitions(|accept| Transitions {
+            byte_transitions: EdgeSet::new(byte, accept),
+            ref_transitions: Map::default(),
+        })
     }
 
     pub(crate) fn from_ref(r: R) -> Self {
-        let mut transitions: Map<State, Transitions<R>> = Map::default();
+        Self::from_transitions(|accept| Transitions {
+            byte_transitions: EdgeSet::empty(),
+            ref_transitions: [(r, accept)].into_iter().collect(),
+        })
+    }
+
+    fn from_transitions(f: impl FnOnce(State) -> Transitions<R>) -> Self {
         let start = State::new();
         let accept = State::new();
 
-        transitions.entry(start).or_default().ref_transitions.insert(r, accept);
-
-        Self { transitions, start, accept }
+        Self { transitions: [(start, f(accept))].into_iter().collect(), start, accept }
     }
 
     pub(crate) fn from_tree(tree: Tree<!, R>) -> Result<Self, Uninhabited> {
@@ -132,13 +129,16 @@ where
 
         for (source, transition) in other.transitions {
             let fix_state = |state| if state == other.start { self.accept } else { state };
-            let entry = transitions.entry(fix_state(source)).or_default();
-            for (edge, destination) in transition.byte_transitions {
-                entry.byte_transitions.insert(edge, fix_state(destination));
-            }
-            for (edge, destination) in transition.ref_transitions {
-                entry.ref_transitions.insert(edge, fix_state(destination));
-            }
+            let byte_transitions = transition.byte_transitions.map_states(&fix_state);
+            let ref_transitions = transition
+                .ref_transitions
+                .into_iter()
+                .map(|(r, state)| (r, fix_state(state)))
+                .collect();
+
+            let old = transitions
+                .insert(fix_state(source), Transitions { byte_transitions, ref_transitions });
+            assert!(old.is_none());
         }
 
         Self { transitions, start, accept }
@@ -170,67 +170,111 @@ where
 
         let start = mapped((Some(a.start), Some(b.start)));
         let mut transitions: Map<State, Transitions<R>> = Map::default();
-        let mut queue = vec![(Some(a.start), Some(b.start))];
         let empty_transitions = Transitions::default();
 
-        while let Some((a_src, b_src)) = queue.pop() {
+        struct WorkQueue {
+            queue: Vec<(Option<State>, Option<State>)>,
+            // Track all entries ever enqueued to avoid duplicating work. This
+            // gives us a guarantee that a given (a_state, b_state) pair will
+            // only ever be visited once.
+            enqueued: Set<(Option<State>, Option<State>)>,
+        }
+        impl WorkQueue {
+            fn enqueue(&mut self, a_state: Option<State>, b_state: Option<State>) {
+                if self.enqueued.insert((a_state, b_state)) {
+                    self.queue.push((a_state, b_state));
+                }
+            }
+        }
+        let mut queue = WorkQueue { queue: Vec::new(), enqueued: Set::default() };
+        queue.enqueue(Some(a.start), Some(b.start));
+
+        while let Some((a_src, b_src)) = queue.queue.pop() {
+            let src = mapped((a_src, b_src));
+            if src == accept {
+                // While it's possible to have a DFA whose accept state has
+                // out-edges, these do not affect the semantics of the DFA, and
+                // so there's no point in processing them. Continuing here also
+                // has the advantage of guaranteeing that we only ever process a
+                // given node in the output DFA once. In particular, with the
+                // exception of the accept state, we ensure that we only push a
+                // given node to the `queue` once. This allows the following
+                // code to assume that we're processing a node we've never
+                // processed before, which means we never need to merge two edge
+                // sets - we only ever need to construct a new edge set from
+                // whole cloth.
+                continue;
+            }
+
             let a_transitions =
                 a_src.and_then(|a_src| a.transitions.get(&a_src)).unwrap_or(&empty_transitions);
             let b_transitions =
                 b_src.and_then(|b_src| b.transitions.get(&b_src)).unwrap_or(&empty_transitions);
 
             let byte_transitions =
-                a_transitions.byte_transitions.keys().chain(b_transitions.byte_transitions.keys());
-
-            for byte_transition in byte_transitions {
-                let a_dst = a_transitions.byte_transitions.get(byte_transition).copied();
-                let b_dst = b_transitions.byte_transitions.get(byte_transition).copied();
+                a_transitions.byte_transitions.union(&b_transitions.byte_transitions);
 
+            let byte_transitions = byte_transitions.map_states(|(a_dst, b_dst)| {
                 assert!(a_dst.is_some() || b_dst.is_some());
 
-                let src = mapped((a_src, b_src));
-                let dst = mapped((a_dst, b_dst));
-
-                transitions.entry(src).or_default().byte_transitions.insert(*byte_transition, dst);
-
-                if !transitions.contains_key(&dst) {
-                    queue.push((a_dst, b_dst))
-                }
-            }
+                queue.enqueue(a_dst, b_dst);
+                mapped((a_dst, b_dst))
+            });
 
             let ref_transitions =
                 a_transitions.ref_transitions.keys().chain(b_transitions.ref_transitions.keys());
 
-            for ref_transition in ref_transitions {
-                let a_dst = a_transitions.ref_transitions.get(ref_transition).copied();
-                let b_dst = b_transitions.ref_transitions.get(ref_transition).copied();
+            let ref_transitions = ref_transitions
+                .map(|ref_transition| {
+                    let a_dst = a_transitions.ref_transitions.get(ref_transition).copied();
+                    let b_dst = b_transitions.ref_transitions.get(ref_transition).copied();
 
-                assert!(a_dst.is_some() || b_dst.is_some());
-
-                let src = mapped((a_src, b_src));
-                let dst = mapped((a_dst, b_dst));
+                    assert!(a_dst.is_some() || b_dst.is_some());
 
-                transitions.entry(src).or_default().ref_transitions.insert(*ref_transition, dst);
+                    queue.enqueue(a_dst, b_dst);
+                    (*ref_transition, mapped((a_dst, b_dst)))
+                })
+                .collect();
 
-                if !transitions.contains_key(&dst) {
-                    queue.push((a_dst, b_dst))
-                }
-            }
+            let old = transitions.insert(src, Transitions { byte_transitions, ref_transitions });
+            // See `if src == accept { ... }` above. The comment there explains
+            // why this assert is valid.
+            assert_eq!(old, None);
         }
 
         Self { transitions, start, accept }
     }
 
-    pub(crate) fn bytes_from(&self, start: State) -> Option<&Map<Byte, State>> {
-        Some(&self.transitions.get(&start)?.byte_transitions)
+    pub(crate) fn states_from(
+        &self,
+        state: State,
+        src_validity: RangeInclusive<u8>,
+    ) -> impl Iterator<Item = (Byte, State)> {
+        self.transitions
+            .get(&state)
+            .map(move |t| t.byte_transitions.states_from(src_validity))
+            .into_iter()
+            .flatten()
+    }
+
+    pub(crate) fn get_uninit_edge_dst(&self, state: State) -> Option<State> {
+        let transitions = self.transitions.get(&state)?;
+        transitions.byte_transitions.get_uninit_edge_dst()
     }
 
-    pub(crate) fn byte_from(&self, start: State, byte: Byte) -> Option<State> {
-        self.transitions.get(&start)?.byte_transitions.get(&byte).copied()
+    pub(crate) fn bytes_from(&self, start: State) -> impl Iterator<Item = (Byte, State)> {
+        self.transitions
+            .get(&start)
+            .into_iter()
+            .flat_map(|transitions| transitions.byte_transitions.iter())
     }
 
-    pub(crate) fn refs_from(&self, start: State) -> Option<&Map<R, State>> {
-        Some(&self.transitions.get(&start)?.ref_transitions)
+    pub(crate) fn refs_from(&self, start: State) -> impl Iterator<Item = (R, State)> {
+        self.transitions
+            .get(&start)
+            .into_iter()
+            .flat_map(|transitions| transitions.ref_transitions.iter())
+            .map(|(r, s)| (*r, *s))
     }
 
     #[cfg(test)]
@@ -241,15 +285,25 @@ where
     ) -> Self {
         let start = State(start);
         let accept = State(accept);
-        let mut transitions: Map<State, Transitions<R>> = Map::default();
+        let mut transitions: Map<State, Vec<(Byte, State)>> = Map::default();
 
-        for &(src, edge, dst) in edges {
-            let src = State(src);
-            let dst = State(dst);
-            let old = transitions.entry(src).or_default().byte_transitions.insert(edge.into(), dst);
-            assert!(old.is_none());
+        for (src, edge, dst) in edges.iter().copied() {
+            transitions.entry(State(src)).or_default().push((edge.into(), State(dst)));
         }
 
+        let transitions = transitions
+            .into_iter()
+            .map(|(src, edges)| {
+                (
+                    src,
+                    Transitions {
+                        byte_transitions: EdgeSet::from_edges(edges),
+                        ref_transitions: Map::default(),
+                    },
+                )
+            })
+            .collect();
+
         Self { start, accept, transitions }
     }
 }
@@ -277,3 +331,242 @@ where
         writeln!(f, "}}")
     }
 }
+
+use edge_set::EdgeSet;
+mod edge_set {
+    use std::cmp;
+
+    use run::*;
+    use smallvec::{SmallVec, smallvec};
+
+    use super::*;
+    mod run {
+        use std::ops::{Range, RangeInclusive};
+
+        use super::*;
+        use crate::layout::Byte;
+
+        /// A logical set of edges.
+        ///
+        /// A `Run` encodes one edge for every byte value in `start..=end`
+        /// pointing to `dst`.
+        #[derive(Eq, PartialEq, Copy, Clone, Debug)]
+        pub(super) struct Run<S> {
+            // `start` and `end` are both inclusive (ie, closed) bounds, as this
+            // is required in order to be able to store 0..=255. We provide
+            // setters and getters which operate on closed/open ranges, which
+            // are more intuitive and easier for performing offset math.
+            start: u8,
+            end: u8,
+            pub(super) dst: S,
+        }
+
+        impl<S> Run<S> {
+            pub(super) fn new(range: RangeInclusive<u8>, dst: S) -> Self {
+                Self { start: *range.start(), end: *range.end(), dst }
+            }
+
+            pub(super) fn from_inclusive_exclusive(range: Range<u16>, dst: S) -> Self {
+                Self {
+                    start: range.start.try_into().unwrap(),
+                    end: (range.end - 1).try_into().unwrap(),
+                    dst,
+                }
+            }
+
+            pub(super) fn contains(&self, idx: u16) -> bool {
+                idx >= u16::from(self.start) && idx <= u16::from(self.end)
+            }
+
+            pub(super) fn as_inclusive_exclusive(&self) -> (u16, u16) {
+                (u16::from(self.start), u16::from(self.end) + 1)
+            }
+
+            pub(super) fn as_byte(&self) -> Byte {
+                Byte::new(self.start..=self.end)
+            }
+
+            pub(super) fn map_state<SS>(self, f: impl FnOnce(S) -> SS) -> Run<SS> {
+                let Run { start, end, dst } = self;
+                Run { start, end, dst: f(dst) }
+            }
+
+            /// Produces a new `Run` whose lower bound is the greater of
+            /// `self`'s existing lower bound and `lower_bound`.
+            pub(super) fn clamp_lower(self, lower_bound: u8) -> Self {
+                let Run { start, end, dst } = self;
+                Run { start: cmp::max(start, lower_bound), end, dst }
+            }
+        }
+    }
+
+    /// The set of outbound byte edges associated with a DFA node (not including
+    /// reference edges).
+    #[derive(Eq, PartialEq, Clone, Debug)]
+    pub(super) struct EdgeSet<S = State> {
+        // A sequence of runs stored in ascending order. Since the graph is a
+        // DFA, these must be non-overlapping with one another.
+        runs: SmallVec<[Run<S>; 1]>,
+        // The edge labeled with the uninit byte, if any.
+        //
+        // FIXME(@joshlf): Make `State` a `NonZero` so that this is NPO'd.
+        uninit: Option<S>,
+    }
+
+    impl<S> EdgeSet<S> {
+        pub(crate) fn new(byte: Byte, dst: S) -> Self {
+            match byte.range() {
+                Some(range) => Self { runs: smallvec![Run::new(range, dst)], uninit: None },
+                None => Self { runs: SmallVec::new(), uninit: Some(dst) },
+            }
+        }
+
+        pub(crate) fn empty() -> Self {
+            Self { runs: SmallVec::new(), uninit: None }
+        }
+
+        #[cfg(test)]
+        pub(crate) fn from_edges(mut edges: Vec<(Byte, S)>) -> Self
+        where
+            S: Ord,
+        {
+            edges.sort();
+            Self {
+                runs: edges
+                    .into_iter()
+                    .map(|(byte, state)| Run::new(byte.range().unwrap(), state))
+                    .collect(),
+                uninit: None,
+            }
+        }
+
+        pub(crate) fn iter(&self) -> impl Iterator<Item = (Byte, S)>
+        where
+            S: Copy,
+        {
+            self.uninit
+                .map(|dst| (Byte::uninit(), dst))
+                .into_iter()
+                .chain(self.runs.iter().map(|run| (run.as_byte(), run.dst)))
+        }
+
+        pub(crate) fn states_from(
+            &self,
+            byte: RangeInclusive<u8>,
+        ) -> impl Iterator<Item = (Byte, S)>
+        where
+            S: Copy,
+        {
+            // FIXME(@joshlf): Optimize this. A manual scan over `self.runs` may
+            // permit us to more efficiently discard runs which will not be
+            // produced by this iterator.
+            self.iter().filter(move |(o, _)| Byte::new(byte.clone()).transmutable_into(&o))
+        }
+
+        pub(crate) fn get_uninit_edge_dst(&self) -> Option<S>
+        where
+            S: Copy,
+        {
+            self.uninit
+        }
+
+        pub(crate) fn map_states<SS>(self, mut f: impl FnMut(S) -> SS) -> EdgeSet<SS> {
+            EdgeSet {
+                // NOTE: It appears as through `<Vec<_> as
+                // IntoIterator>::IntoIter` and `std::iter::Map` both implement
+                // `TrustedLen`, which in turn means that this `.collect()`
+                // allocates the correct number of elements once up-front [1].
+                //
+                // [1] https://doc.rust-lang.org/1.85.0/src/alloc/vec/spec_from_iter_nested.rs.html#47
+                runs: self.runs.into_iter().map(|run| run.map_state(&mut f)).collect(),
+                uninit: self.uninit.map(f),
+            }
+        }
+
+        /// Unions two edge sets together.
+        ///
+        /// If `u = a.union(b)`, then for each byte value, `u` will have an edge
+        /// with that byte value and with the destination `(Some(_), None)`,
+        /// `(None, Some(_))`, or `(Some(_), Some(_))` depending on whether `a`,
+        /// `b`, or both have an edge with that byte value.
+        ///
+        /// If neither `a` nor `b` have an edge with a particular byte value,
+        /// then no edge with that value will be present in `u`.
+        pub(crate) fn union(&self, other: &Self) -> EdgeSet<(Option<S>, Option<S>)>
+        where
+            S: Copy,
+        {
+            let uninit = match (self.uninit, other.uninit) {
+                (None, None) => None,
+                (s, o) => Some((s, o)),
+            };
+
+            let mut runs = SmallVec::new();
+
+            // Iterate over `self.runs` and `other.runs` simultaneously,
+            // advancing `idx` as we go. At each step, we advance `idx` as far
+            // as we can without crossing a run boundary in either `self.runs`
+            // or `other.runs`.
+
+            // INVARIANT: `idx < s[0].end && idx < o[0].end`.
+            let (mut s, mut o) = (self.runs.as_slice(), other.runs.as_slice());
+            let mut idx = 0u16;
+            while let (Some((s_run, s_rest)), Some((o_run, o_rest))) =
+                (s.split_first(), o.split_first())
+            {
+                let (s_start, s_end) = s_run.as_inclusive_exclusive();
+                let (o_start, o_end) = o_run.as_inclusive_exclusive();
+
+                // Compute `end` as the end of the current run (which starts
+                // with `idx`).
+                let (end, dst) = match (s_run.contains(idx), o_run.contains(idx)) {
+                    // `idx` is in an existing run in both `s` and `o`, so `end`
+                    // is equal to the smallest of the two ends of those runs.
+                    (true, true) => (cmp::min(s_end, o_end), (Some(s_run.dst), Some(o_run.dst))),
+                    // `idx` is in an existing run in `s`, but not in any run in
+                    // `o`. `end` is either the end of the `s` run or the
+                    // beginning of the next `o` run, whichever comes first.
+                    (true, false) => (cmp::min(s_end, o_start), (Some(s_run.dst), None)),
+                    // The inverse of the previous case.
+                    (false, true) => (cmp::min(s_start, o_end), (None, Some(o_run.dst))),
+                    // `idx` is not in a run in either `s` or `o`, so advance it
+                    // to the beginning of the next run.
+                    (false, false) => {
+                        idx = cmp::min(s_start, o_start);
+                        continue;
+                    }
+                };
+
+                // FIXME(@joshlf): If this is contiguous with the previous run
+                // and has the same `dst`, just merge it into that run rather
+                // than adding a new one.
+                runs.push(Run::from_inclusive_exclusive(idx..end, dst));
+                idx = end;
+
+                if idx >= s_end {
+                    s = s_rest;
+                }
+                if idx >= o_end {
+                    o = o_rest;
+                }
+            }
+
+            // At this point, either `s` or `o` have been exhausted, so the
+            // remaining elements in the other slice are guaranteed to be
+            // non-overlapping. We can add all remaining runs to `runs` with no
+            // further processing.
+            if let Ok(idx) = u8::try_from(idx) {
+                let (slc, map) = if !s.is_empty() {
+                    let map: fn(_) -> _ = |st| (Some(st), None);
+                    (s, map)
+                } else {
+                    let map: fn(_) -> _ = |st| (None, Some(st));
+                    (o, map)
+                };
+                runs.extend(slc.iter().map(|run| run.clamp_lower(idx).map_state(map)));
+            }
+
+            EdgeSet { runs, uninit }
+        }
+    }
+}
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index c940f7c42a8..d555ea702a9 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -1,5 +1,6 @@
 use std::fmt::{self, Debug};
 use std::hash::Hash;
+use std::ops::RangeInclusive;
 
 pub(crate) mod tree;
 pub(crate) use tree::Tree;
@@ -10,18 +11,56 @@ pub(crate) use dfa::Dfa;
 #[derive(Debug)]
 pub(crate) struct Uninhabited;
 
-/// An instance of a byte is either initialized to a particular value, or uninitialized.
-#[derive(Hash, Eq, PartialEq, Clone, Copy)]
-pub(crate) enum Byte {
-    Uninit,
-    Init(u8),
+/// A range of byte values, or the uninit byte.
+#[derive(Hash, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
+pub(crate) struct Byte {
+    // An inclusive-inclusive range. We use this instead of `RangeInclusive`
+    // because `RangeInclusive: !Copy`.
+    //
+    // `None` means uninit.
+    //
+    // FIXME(@joshlf): Optimize this representation. Some pairs of values (where
+    // `lo > hi`) are illegal, and we could use these to represent `None`.
+    range: Option<(u8, u8)>,
+}
+
+impl Byte {
+    fn new(range: RangeInclusive<u8>) -> Self {
+        Self { range: Some((*range.start(), *range.end())) }
+    }
+
+    fn from_val(val: u8) -> Self {
+        Self { range: Some((val, val)) }
+    }
+
+    pub(crate) fn uninit() -> Byte {
+        Byte { range: None }
+    }
+
+    /// Returns `None` if `self` is the uninit byte.
+    pub(crate) fn range(&self) -> Option<RangeInclusive<u8>> {
+        self.range.map(|(lo, hi)| lo..=hi)
+    }
+
+    /// Are any of the values in `self` transmutable into `other`?
+    ///
+    /// Note two special cases: An uninit byte is only transmutable into another
+    /// uninit byte. Any byte is transmutable into an uninit byte.
+    pub(crate) fn transmutable_into(&self, other: &Byte) -> bool {
+        match (self.range, other.range) {
+            (None, None) => true,
+            (None, Some(_)) => false,
+            (Some(_), None) => true,
+            (Some((slo, shi)), Some((olo, ohi))) => slo <= ohi && olo <= shi,
+        }
+    }
 }
 
 impl fmt::Debug for Byte {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match &self {
-            Self::Uninit => f.write_str("??u8"),
-            Self::Init(b) => write!(f, "{b:#04x}u8"),
+        match self.range {
+            None => write!(f, "uninit"),
+            Some((lo, hi)) => write!(f, "{lo}..={hi}"),
         }
     }
 }
@@ -29,7 +68,7 @@ impl fmt::Debug for Byte {
 #[cfg(test)]
 impl From<u8> for Byte {
     fn from(src: u8) -> Self {
-        Self::Init(src)
+        Self::from_val(src)
     }
 }
 
@@ -62,6 +101,21 @@ impl Ref for ! {
     }
 }
 
+#[cfg(test)]
+impl<const N: usize> Ref for [(); N] {
+    fn min_align(&self) -> usize {
+        N
+    }
+
+    fn size(&self) -> usize {
+        N
+    }
+
+    fn is_mutable(&self) -> bool {
+        false
+    }
+}
+
 #[cfg(feature = "rustc")]
 pub mod rustc {
     use std::fmt::{self, Write};
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 70ecc75403f..6a09be18ef9 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -54,22 +54,22 @@ where
 
     /// A `Tree` containing a single, uninitialized byte.
     pub(crate) fn uninit() -> Self {
-        Self::Byte(Byte::Uninit)
+        Self::Byte(Byte::uninit())
     }
 
     /// A `Tree` representing the layout of `bool`.
     pub(crate) fn bool() -> Self {
-        Self::from_bits(0x00).or(Self::from_bits(0x01))
+        Self::Byte(Byte::new(0x00..=0x01))
     }
 
     /// A `Tree` whose layout matches that of a `u8`.
     pub(crate) fn u8() -> Self {
-        Self::Alt((0u8..=255).map(Self::from_bits).collect())
+        Self::Byte(Byte::new(0x00..=0xFF))
     }
 
     /// A `Tree` whose layout accepts exactly the given bit pattern.
     pub(crate) fn from_bits(bits: u8) -> Self {
-        Self::Byte(Byte::Init(bits))
+        Self::Byte(Byte::from_val(bits))
     }
 
     /// A `Tree` whose layout is a number of the given width.
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 76fa6ceabe7..ce18dad5517 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -1,8 +1,9 @@
 // tidy-alphabetical-start
+#![cfg_attr(test, feature(test))]
 #![feature(never_type)]
 // tidy-alphabetical-end
 
-pub(crate) use rustc_data_structures::fx::FxIndexMap as Map;
+pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
 
 pub mod layout;
 mod maybe_transmutable;
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
index db0e1ab8e98..0a19cccc2ed 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
@@ -1,10 +1,14 @@
+use std::rc::Rc;
+use std::{cmp, iter};
+
+use itertools::Either;
 use tracing::{debug, instrument, trace};
 
 pub(crate) mod query_context;
 #[cfg(test)]
 mod tests;
 
-use crate::layout::{self, Byte, Def, Dfa, Ref, Tree, Uninhabited, dfa};
+use crate::layout::{self, Byte, Def, Dfa, Ref, Tree, dfa};
 use crate::maybe_transmutable::query_context::QueryContext;
 use crate::{Answer, Condition, Map, Reason};
 
@@ -111,7 +115,7 @@ where
         // the `src` type do not exist.
         let src = match Dfa::from_tree(src) {
             Ok(src) => src,
-            Err(Uninhabited) => return Answer::Yes,
+            Err(layout::Uninhabited) => return Answer::Yes,
         };
 
         // Convert `dst` from a tree-based representation to an DFA-based
@@ -122,7 +126,7 @@ where
         // free of safety invariants.
         let dst = match Dfa::from_tree(dst) {
             Ok(dst) => dst,
-            Err(Uninhabited) => return Answer::No(Reason::DstMayHaveSafetyInvariants),
+            Err(layout::Uninhabited) => return Answer::No(Reason::DstMayHaveSafetyInvariants),
         };
 
         MaybeTransmutableQuery { src, dst, assume, context }.answer()
@@ -174,8 +178,8 @@ where
                 // are able to safely transmute, even with truncation.
                 Answer::Yes
             } else if src_state == self.src.accept {
-                // extension: `size_of(Src) >= size_of(Dst)`
-                if let Some(dst_state_prime) = self.dst.byte_from(dst_state, Byte::Uninit) {
+                // extension: `size_of(Src) <= size_of(Dst)`
+                if let Some(dst_state_prime) = self.dst.get_uninit_edge_dst(dst_state) {
                     self.answer_memo(cache, src_state, dst_state_prime)
                 } else {
                     Answer::No(Reason::DstIsTooBig)
@@ -193,26 +197,120 @@ where
                     Quantifier::ForAll
                 };
 
+                let c = &core::cell::RefCell::new(&mut *cache);
                 let bytes_answer = src_quantifier.apply(
-                    // for each of the byte transitions out of the `src_state`...
-                    self.src.bytes_from(src_state).unwrap_or(&Map::default()).into_iter().map(
-                        |(&src_validity, &src_state_prime)| {
-                            // ...try to find a matching transition out of `dst_state`.
-                            if let Some(dst_state_prime) =
-                                self.dst.byte_from(dst_state, src_validity)
-                            {
-                                self.answer_memo(cache, src_state_prime, dst_state_prime)
-                            } else if let Some(dst_state_prime) =
-                                // otherwise, see if `dst_state` has any outgoing `Uninit` transitions
-                                // (any init byte is a valid uninit byte)
-                                self.dst.byte_from(dst_state, Byte::Uninit)
-                            {
-                                self.answer_memo(cache, src_state_prime, dst_state_prime)
-                            } else {
-                                // otherwise, we've exhausted our options.
-                                // the DFAs, from this point onwards, are bit-incompatible.
-                                Answer::No(Reason::DstIsBitIncompatible)
+                    // for each of the byte set transitions out of the `src_state`...
+                    self.src.bytes_from(src_state).flat_map(
+                        move |(src_validity, src_state_prime)| {
+                            // ...find all matching transitions out of `dst_state`.
+
+                            let Some(src_validity) = src_validity.range() else {
+                                // NOTE: We construct an iterator here rather
+                                // than just computing the value directly (via
+                                // `self.answer_memo`) so that, if the iterator
+                                // we produce from this branch is
+                                // short-circuited, we don't waste time
+                                // computing `self.answer_memo` unnecessarily.
+                                // That will specifically happen if
+                                // `src_quantifier == Quantifier::ThereExists`,
+                                // since we emit `Answer::Yes` first (before
+                                // chaining `answer_iter`).
+                                let answer_iter = if let Some(dst_state_prime) =
+                                    self.dst.get_uninit_edge_dst(dst_state)
+                                {
+                                    Either::Left(iter::once_with(move || {
+                                        let mut c = c.borrow_mut();
+                                        self.answer_memo(&mut *c, src_state_prime, dst_state_prime)
+                                    }))
+                                } else {
+                                    Either::Right(iter::once(Answer::No(
+                                        Reason::DstIsBitIncompatible,
+                                    )))
+                                };
+
+                                // When `answer == Answer::No(...)`, there are
+                                // two cases to consider:
+                                // - If `assume.validity`, then we should
+                                //   succeed because the user is responsible for
+                                //   ensuring that the *specific* byte value
+                                //   appearing at runtime is valid for the
+                                //   destination type. When `assume.validity`,
+                                //   `src_quantifier ==
+                                //   Quantifier::ThereExists`, so adding an
+                                //   `Answer::Yes` has the effect of ensuring
+                                //   that the "there exists" is always
+                                //   satisfied.
+                                // - If `!assume.validity`, then we should fail.
+                                //   In this case, `src_quantifier ==
+                                //   Quantifier::ForAll`, so adding an
+                                //   `Answer::Yes` has no effect.
+                                return Either::Left(iter::once(Answer::Yes).chain(answer_iter));
+                            };
+
+                            #[derive(Copy, Clone, Debug)]
+                            struct Accum {
+                                // The number of matching byte edges that we
+                                // have found in the destination so far.
+                                sum: usize,
+                                found_uninit: bool,
                             }
+
+                            let accum1 = Rc::new(std::cell::Cell::new(Accum {
+                                sum: 0,
+                                found_uninit: false,
+                            }));
+                            let accum2 = Rc::clone(&accum1);
+                            let sv = src_validity.clone();
+                            let update_accum = move |mut accum: Accum, dst_validity: Byte| {
+                                if let Some(dst_validity) = dst_validity.range() {
+                                    // Only add the part of `dst_validity` that
+                                    // overlaps with `src_validity`.
+                                    let start = cmp::max(*sv.start(), *dst_validity.start());
+                                    let end = cmp::min(*sv.end(), *dst_validity.end());
+
+                                    // We add 1 here to account for the fact
+                                    // that `end` is an inclusive bound.
+                                    accum.sum += 1 + usize::from(end.saturating_sub(start));
+                                } else {
+                                    accum.found_uninit = true;
+                                }
+                                accum
+                            };
+
+                            let answers = self
+                                .dst
+                                .states_from(dst_state, src_validity.clone())
+                                .map(move |(dst_validity, dst_state_prime)| {
+                                    let mut c = c.borrow_mut();
+                                    accum1.set(update_accum(accum1.get(), dst_validity));
+                                    let answer =
+                                        self.answer_memo(&mut *c, src_state_prime, dst_state_prime);
+                                    answer
+                                })
+                                .chain(
+                                    iter::once_with(move || {
+                                        let src_validity_len = usize::from(*src_validity.end())
+                                            - usize::from(*src_validity.start())
+                                            + 1;
+                                        let accum = accum2.get();
+
+                                        // If this condition is false, then
+                                        // there are some byte values in the
+                                        // source which have no corresponding
+                                        // transition in the destination DFA. In
+                                        // that case, we add a `No` to our list
+                                        // of answers. When
+                                        // `!self.assume.validity`, this will
+                                        // cause the query to fail.
+                                        if accum.found_uninit || accum.sum == src_validity_len {
+                                            None
+                                        } else {
+                                            Some(Answer::No(Reason::DstIsBitIncompatible))
+                                        }
+                                    })
+                                    .flatten(),
+                                );
+                            Either::Right(answers)
                         },
                     ),
                 );
@@ -235,48 +333,38 @@ where
 
                 let refs_answer = src_quantifier.apply(
                     // for each reference transition out of `src_state`...
-                    self.src.refs_from(src_state).unwrap_or(&Map::default()).into_iter().map(
-                        |(&src_ref, &src_state_prime)| {
-                            // ...there exists a reference transition out of `dst_state`...
-                            Quantifier::ThereExists.apply(
-                                self.dst
-                                    .refs_from(dst_state)
-                                    .unwrap_or(&Map::default())
-                                    .into_iter()
-                                    .map(|(&dst_ref, &dst_state_prime)| {
-                                        if !src_ref.is_mutable() && dst_ref.is_mutable() {
-                                            Answer::No(Reason::DstIsMoreUnique)
-                                        } else if !self.assume.alignment
-                                            && src_ref.min_align() < dst_ref.min_align()
-                                        {
-                                            Answer::No(Reason::DstHasStricterAlignment {
-                                                src_min_align: src_ref.min_align(),
-                                                dst_min_align: dst_ref.min_align(),
-                                            })
-                                        } else if dst_ref.size() > src_ref.size() {
-                                            Answer::No(Reason::DstRefIsTooBig {
-                                                src: src_ref,
-                                                dst: dst_ref,
-                                            })
-                                        } else {
-                                            // ...such that `src` is transmutable into `dst`, if
-                                            // `src_ref` is transmutability into `dst_ref`.
-                                            and(
-                                                Answer::If(Condition::IfTransmutable {
-                                                    src: src_ref,
-                                                    dst: dst_ref,
-                                                }),
-                                                self.answer_memo(
-                                                    cache,
-                                                    src_state_prime,
-                                                    dst_state_prime,
-                                                ),
-                                            )
-                                        }
-                                    }),
-                            )
-                        },
-                    ),
+                    self.src.refs_from(src_state).map(|(src_ref, src_state_prime)| {
+                        // ...there exists a reference transition out of `dst_state`...
+                        Quantifier::ThereExists.apply(self.dst.refs_from(dst_state).map(
+                            |(dst_ref, dst_state_prime)| {
+                                if !src_ref.is_mutable() && dst_ref.is_mutable() {
+                                    Answer::No(Reason::DstIsMoreUnique)
+                                } else if !self.assume.alignment
+                                    && src_ref.min_align() < dst_ref.min_align()
+                                {
+                                    Answer::No(Reason::DstHasStricterAlignment {
+                                        src_min_align: src_ref.min_align(),
+                                        dst_min_align: dst_ref.min_align(),
+                                    })
+                                } else if dst_ref.size() > src_ref.size() {
+                                    Answer::No(Reason::DstRefIsTooBig {
+                                        src: src_ref,
+                                        dst: dst_ref,
+                                    })
+                                } else {
+                                    // ...such that `src` is transmutable into `dst`, if
+                                    // `src_ref` is transmutability into `dst_ref`.
+                                    and(
+                                        Answer::If(Condition::IfTransmutable {
+                                            src: src_ref,
+                                            dst: dst_ref,
+                                        }),
+                                        self.answer_memo(cache, src_state_prime, dst_state_prime),
+                                    )
+                                }
+                            },
+                        ))
+                    }),
                 );
 
                 if self.assume.validity {
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
index f8b59bdf326..214da101be3 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
@@ -8,9 +8,17 @@ pub(crate) trait QueryContext {
 
 #[cfg(test)]
 pub(crate) mod test {
+    use std::marker::PhantomData;
+
     use super::QueryContext;
 
-    pub(crate) struct UltraMinimal;
+    pub(crate) struct UltraMinimal<R = !>(PhantomData<R>);
+
+    impl<R> Default for UltraMinimal<R> {
+        fn default() -> Self {
+            Self(PhantomData)
+        }
+    }
 
     #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
     pub(crate) enum Def {
@@ -24,9 +32,9 @@ pub(crate) mod test {
         }
     }
 
-    impl QueryContext for UltraMinimal {
+    impl<R: crate::layout::Ref> QueryContext for UltraMinimal<R> {
         type Def = Def;
-        type Ref = !;
+        type Ref = R;
     }
 }
 
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index cc6a4dce17b..24e2a1acadd 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
@@ -1,3 +1,5 @@
+extern crate test;
+
 use itertools::Itertools;
 
 use super::query_context::test::{Def, UltraMinimal};
@@ -12,15 +14,25 @@ trait Representation {
 
 impl Representation for Tree {
     fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!> {
-        crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
-            .answer()
+        crate::maybe_transmutable::MaybeTransmutableQuery::new(
+            src,
+            dst,
+            assume,
+            UltraMinimal::default(),
+        )
+        .answer()
     }
 }
 
 impl Representation for Dfa {
     fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer<!> {
-        crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal)
-            .answer()
+        crate::maybe_transmutable::MaybeTransmutableQuery::new(
+            src,
+            dst,
+            assume,
+            UltraMinimal::default(),
+        )
+        .answer()
     }
 }
 
@@ -89,6 +101,36 @@ mod safety {
     }
 }
 
+mod size {
+    use super::*;
+
+    #[test]
+    fn size() {
+        let small = Tree::number(1);
+        let large = Tree::number(2);
+
+        for alignment in [false, true] {
+            for lifetimes in [false, true] {
+                for safety in [false, true] {
+                    for validity in [false, true] {
+                        let assume = Assume { alignment, lifetimes, safety, validity };
+                        assert_eq!(
+                            is_transmutable(&small, &large, assume),
+                            Answer::No(Reason::DstIsTooBig),
+                            "assume: {assume:?}"
+                        );
+                        assert_eq!(
+                            is_transmutable(&large, &small, assume),
+                            Answer::Yes,
+                            "assume: {assume:?}"
+                        );
+                    }
+                }
+            }
+        }
+    }
+}
+
 mod bool {
     use super::*;
 
@@ -113,6 +155,27 @@ mod bool {
     }
 
     #[test]
+    fn transmute_u8() {
+        let bool = &Tree::bool();
+        let u8 = &Tree::u8();
+        for (src, dst, assume_validity, answer) in [
+            (bool, u8, false, Answer::Yes),
+            (bool, u8, true, Answer::Yes),
+            (u8, bool, false, Answer::No(Reason::DstIsBitIncompatible)),
+            (u8, bool, true, Answer::Yes),
+        ] {
+            assert_eq!(
+                is_transmutable(
+                    src,
+                    dst,
+                    Assume { validity: assume_validity, ..Assume::default() }
+                ),
+                answer
+            );
+        }
+    }
+
+    #[test]
     fn should_permit_validity_expansion_and_reject_contraction() {
         let b0 = layout::Tree::<Def, !>::from_bits(0);
         let b1 = layout::Tree::<Def, !>::from_bits(1);
@@ -175,6 +238,62 @@ mod bool {
     }
 }
 
+mod uninit {
+    use super::*;
+
+    #[test]
+    fn size() {
+        let mu = Tree::uninit();
+        let u8 = Tree::u8();
+
+        for alignment in [false, true] {
+            for lifetimes in [false, true] {
+                for safety in [false, true] {
+                    for validity in [false, true] {
+                        let assume = Assume { alignment, lifetimes, safety, validity };
+
+                        let want = if validity {
+                            Answer::Yes
+                        } else {
+                            Answer::No(Reason::DstIsBitIncompatible)
+                        };
+
+                        assert_eq!(is_transmutable(&mu, &u8, assume), want, "assume: {assume:?}");
+                        assert_eq!(
+                            is_transmutable(&u8, &mu, assume),
+                            Answer::Yes,
+                            "assume: {assume:?}"
+                        );
+                    }
+                }
+            }
+        }
+    }
+}
+
+mod alt {
+    use super::*;
+    use crate::Answer;
+
+    #[test]
+    fn should_permit_identity_transmutation() {
+        type Tree = layout::Tree<Def, !>;
+
+        let x = Tree::Seq(vec![Tree::from_bits(0), Tree::from_bits(0)]);
+        let y = Tree::Seq(vec![Tree::bool(), Tree::from_bits(1)]);
+        let layout = Tree::Alt(vec![x, y]);
+
+        let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
+            layout.clone(),
+            layout.clone(),
+            crate::Assume::default(),
+            UltraMinimal::default(),
+        )
+        .answer();
+        assert_eq!(answer, Answer::Yes, "layout:{:#?}", layout);
+    }
+}
+
 mod union {
     use super::*;
 
@@ -203,3 +322,59 @@ mod union {
         assert_eq!(is_transmutable(&t, &u, Assume::default()), Answer::Yes);
     }
 }
+
+mod r#ref {
+    use super::*;
+
+    #[test]
+    fn should_permit_identity_transmutation() {
+        type Tree = crate::layout::Tree<Def, [(); 1]>;
+
+        let layout = Tree::Seq(vec![Tree::from_bits(0), Tree::Ref([()])]);
+
+        let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
+            layout.clone(),
+            layout,
+            Assume::default(),
+            UltraMinimal::default(),
+        )
+        .answer();
+        assert_eq!(answer, Answer::If(crate::Condition::IfTransmutable { src: [()], dst: [()] }));
+    }
+}
+
+mod benches {
+    use std::hint::black_box;
+
+    use test::Bencher;
+
+    use super::*;
+
+    #[bench]
+    fn bench_dfa_from_tree(b: &mut Bencher) {
+        let num = Tree::number(8).prune(&|_| false);
+        let num = black_box(num);
+
+        b.iter(|| {
+            let _ = black_box(Dfa::from_tree(num.clone()));
+        })
+    }
+
+    #[bench]
+    fn bench_transmute(b: &mut Bencher) {
+        let num = Tree::number(8).prune(&|_| false);
+        let dfa = black_box(Dfa::from_tree(num).unwrap());
+
+        b.iter(|| {
+            let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
+                dfa.clone(),
+                dfa.clone(),
+                Assume::default(),
+                UltraMinimal::default(),
+            )
+            .answer();
+            let answer = std::hint::black_box(answer);
+            assert_eq!(answer, Answer::Yes);
+        })
+    }
+}
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 3d4ab33240a..63ea035bd0e 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -347,7 +347,8 @@ fn adjust_for_rust_scalar<'tcx>(
             None
         };
         if let Some(kind) = kind {
-            attrs.pointee_align = Some(pointee.align);
+            attrs.pointee_align =
+                Some(pointee.align.min(cx.tcx().sess.target.max_reliable_alignment()));
 
             // `Box` are not necessarily dereferenceable for the entire duration of the function as
             // they can be deallocated at any time. Same for non-frozen shared references (see
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 35cc6f39856..57051e0df55 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -32,6 +32,7 @@ mod needs_drop;
 mod opaque_types;
 mod representability;
 pub mod sig_types;
+mod stalled_generators;
 mod structural_match;
 mod ty;
 
@@ -50,4 +51,5 @@ pub fn provide(providers: &mut Providers) {
     ty::provide(providers);
     instance::provide(providers);
     structural_match::provide(providers);
+    stalled_generators::provide(providers);
 }
diff --git a/compiler/rustc_ty_utils/src/stalled_generators.rs b/compiler/rustc_ty_utils/src/stalled_generators.rs
new file mode 100644
index 00000000000..8b45e8b0f6f
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/stalled_generators.rs
@@ -0,0 +1,54 @@
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit;
+use rustc_hir::intravisit::Visitor;
+use rustc_middle::query::Providers;
+use rustc_middle::ty::{self, TyCtxt};
+
+fn stalled_generators_within<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item: LocalDefId,
+) -> &'tcx ty::List<LocalDefId> {
+    if !tcx.next_trait_solver_globally() {
+        return ty::List::empty();
+    }
+
+    let body = tcx.hir_body_owned_by(item);
+    let mut collector =
+        StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] };
+    collector.visit_body(body);
+    tcx.mk_local_def_ids(&collector.stalled_coroutines)
+}
+
+struct StalledGeneratorVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    root_def_id: DefId,
+    stalled_coroutines: Vec<LocalDefId>,
+}
+
+impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> {
+    fn visit_nested_body(&mut self, id: hir::BodyId) {
+        if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id())
+            == self.root_def_id
+        {
+            let body = self.tcx.hir_body(id);
+            self.visit_body(body);
+        }
+    }
+
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
+        if let hir::ExprKind::Closure(&hir::Closure {
+            def_id,
+            kind: hir::ClosureKind::Coroutine(_),
+            ..
+        }) = ex.kind
+        {
+            self.stalled_coroutines.push(def_id);
+        }
+        intravisit::walk_expr(self, ex);
+    }
+}
+
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers { stalled_generators_within, ..*providers };
+}
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index fec6e24e2cb..8fa56c35999 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -65,7 +65,7 @@ pub enum TypingMode<I: Interner> {
     ///     let x: <() as Assoc>::Output = true;
     /// }
     /// ```
-    Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
+    Analysis { defining_opaque_types_and_generators: I::LocalDefIds },
     /// The behavior during MIR borrowck is identical to `TypingMode::Analysis`
     /// except that the initial value for opaque types is the type computed during
     /// HIR typeck with unique unconstrained region inference variables.
@@ -73,13 +73,13 @@ pub enum TypingMode<I: Interner> {
     /// This is currently only used with by the new solver as it results in new
     /// non-universal defining uses of opaque types, which is a breaking change.
     /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
-    Borrowck { defining_opaque_types: I::DefiningOpaqueTypes },
+    Borrowck { defining_opaque_types: I::LocalDefIds },
     /// Any analysis after borrowck for a given body should be able to use all the
     /// hidden types defined by borrowck, without being able to define any new ones.
     ///
     /// This is currently only used by the new solver, but should be implemented in
     /// the old solver as well.
-    PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes },
+    PostBorrowckAnalysis { defined_opaque_types: I::LocalDefIds },
     /// After analysis, mostly during codegen and MIR optimizations, we're able to
     /// reveal all opaque types. As the concrete type should *never* be observable
     /// directly by the user, this should not be used by checks which may expose
@@ -94,13 +94,25 @@ pub enum TypingMode<I: Interner> {
 impl<I: Interner> TypingMode<I> {
     /// Analysis outside of a body does not define any opaque types.
     pub fn non_body_analysis() -> TypingMode<I> {
-        TypingMode::Analysis { defining_opaque_types: Default::default() }
+        TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
+    }
+
+    pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
+        TypingMode::Analysis {
+            defining_opaque_types_and_generators: cx
+                .opaque_types_and_generators_defined_by(body_def_id),
+        }
     }
 
     /// While typechecking a body, we need to be able to define the opaque
     /// types defined by that body.
+    ///
+    /// FIXME: This will be removed because it's generally not correct to define
+    /// opaques outside of HIR typeck.
     pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
-        TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
+        TypingMode::Analysis {
+            defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
+        }
     }
 
     pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 71bfeabfda8..ab38556589e 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -56,7 +56,7 @@ pub trait Interner:
         data: PredefinedOpaquesData<Self>,
     ) -> Self::PredefinedOpaques;
 
-    type DefiningOpaqueTypes: Copy
+    type LocalDefIds: Copy
         + Debug
         + Hash
         + Default
@@ -330,10 +330,12 @@ pub trait Interner:
         binder: ty::Binder<Self, T>,
     ) -> ty::Binder<Self, T>;
 
-    fn opaque_types_defined_by(
+    fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds;
+
+    fn opaque_types_and_generators_defined_by(
         self,
         defining_anchor: Self::LocalDefId,
-    ) -> Self::DefiningOpaqueTypes;
+    ) -> Self::LocalDefIds;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/library/Cargo.lock b/library/Cargo.lock
index ba5e54db95d..f7f09a11f3a 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -67,9 +67,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.155"
+version = "0.1.156"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "341e0830ca6170a4fcf02e92e57daf4b6f10142d48da32a547023867a6c8b35e"
+checksum = "c1ffbd2789fe5bb95b96a2e22cbe3128239dc46ff0374e0d38e9f102062d7055"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index cedbd330cbd..994221de866 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -16,7 +16,7 @@ bench = false
 
 [dependencies]
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.155", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.156", features = ['rustc-dep-of-std'] }
 
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 041f80c1f2c..7ad9e59dfed 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -139,7 +139,7 @@ pub struct Iter<'a, T: 'a> {
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Iter").field(&self.iter.clone()).finish()
+        f.debug_tuple("Iter").field(&self.iter).finish()
     }
 }
 
diff --git a/library/alloctests/tests/fmt.rs b/library/alloctests/tests/fmt.rs
index c13074c53b7..a20e8c62336 100644
--- a/library/alloctests/tests/fmt.rs
+++ b/library/alloctests/tests/fmt.rs
@@ -1,6 +1,7 @@
 #![deny(warnings)]
 // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
 #![allow(static_mut_refs)]
+#![cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 
 use std::cell::RefCell;
 use std::fmt::{self, Write};
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 17231df731d..c7657350a0d 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -549,8 +549,6 @@ impl<T: Copy> Cell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(cell_update)]
-    ///
     /// use std::cell::Cell;
     ///
     /// let c = Cell::new(5);
@@ -558,7 +556,7 @@ impl<T: Copy> Cell<T> {
     /// assert_eq!(c.get(), 6);
     /// ```
     #[inline]
-    #[unstable(feature = "cell_update", issue = "50186")]
+    #[stable(feature = "cell_update", since = "CURRENT_RUSTC_VERSION")]
     pub fn update(&self, f: impl FnOnce(T) -> T) {
         let old = self.get();
         self.set(f(old));
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index ac808038f89..d820965a746 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -21,6 +21,7 @@ pub(super) const fn from_u32(i: u32) -> Option<char> {
 /// Converts a `u32` to a `char`, ignoring validity. See [`char::from_u32_unchecked`].
 #[inline]
 #[must_use]
+#[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
     // SAFETY: the caller must guarantee that `i` is a valid char value.
     unsafe {
@@ -221,6 +222,7 @@ impl FromStr for char {
 }
 
 #[inline]
+#[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
     // This is an optimized version of the check
     // (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF),
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index a700b98d068..a7563f918a2 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1497,6 +1497,7 @@ pub const fn forget<T: ?Sized>(_: T);
 /// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.:
 ///
 /// ```
+/// # #![cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
 /// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
 ///
 /// let num = unsafe {
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 3361409997e..b1119d4899b 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -145,6 +145,9 @@ impl f128 {
     pub const RADIX: u32 = 2;
 
     /// Number of significant digits in base 2.
+    ///
+    /// Note that the size of the mantissa in the bitwise representation is one
+    /// smaller than this since the leading 1 is not stored explicitly.
     #[unstable(feature = "f128", issue = "116909")]
     pub const MANTISSA_DIGITS: u32 = 113;
 
@@ -194,16 +197,22 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     pub const MAX: f128 = 1.18973149535723176508575932662800702e+4932_f128;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[unstable(feature = "f128", issue = "116909")]
     pub const MIN_EXP: i32 = -16_381;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[unstable(feature = "f128", issue = "116909")]
     pub const MAX_EXP: i32 = 16_384;
 
@@ -801,7 +810,7 @@ impl f128 {
         }
     }
 
-    /// Calculates the middle point of `self` and `rhs`.
+    /// Calculates the midpoint (average) between `self` and `rhs`.
     ///
     /// This returns NaN when *either* argument is NaN or if a combination of
     /// +inf and -inf is provided as arguments.
@@ -818,6 +827,7 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
+    #[doc(alias = "average")]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
     pub const fn midpoint(self, other: f128) -> f128 {
@@ -900,6 +910,7 @@ impl f128 {
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u128 {
         // SAFETY: `u128` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -947,6 +958,7 @@ impl f128 {
     #[inline]
     #[must_use]
     #[unstable(feature = "f128", issue = "116909")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u128) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u128` is a plain old datatype so we can always transmute from it.
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 477fb0cf27e..54e38d9e1a6 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -140,6 +140,9 @@ impl f16 {
     pub const RADIX: u32 = 2;
 
     /// Number of significant digits in base 2.
+    ///
+    /// Note that the size of the mantissa in the bitwise representation is one
+    /// smaller than this since the leading 1 is not stored explicitly.
     #[unstable(feature = "f16", issue = "116909")]
     pub const MANTISSA_DIGITS: u32 = 11;
 
@@ -189,16 +192,22 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     pub const MAX: f16 = 6.5504e+4_f16;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[unstable(feature = "f16", issue = "116909")]
     pub const MIN_EXP: i32 = -13;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[unstable(feature = "f16", issue = "116909")]
     pub const MAX_EXP: i32 = 16;
 
@@ -789,7 +798,7 @@ impl f16 {
         }
     }
 
-    /// Calculates the middle point of `self` and `rhs`.
+    /// Calculates the midpoint (average) between `self` and `rhs`.
     ///
     /// This returns NaN when *either* argument is NaN or if a combination of
     /// +inf and -inf is provided as arguments.
@@ -805,6 +814,7 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
+    #[doc(alias = "average")]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
     pub const fn midpoint(self, other: f16) -> f16 {
@@ -888,6 +898,7 @@ impl f16 {
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u16 {
         // SAFETY: `u16` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -934,6 +945,7 @@ impl f16 {
     #[inline]
     #[must_use]
     #[unstable(feature = "f16", issue = "116909")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u16) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u16` is a plain old datatype so we can always transmute from it.
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 7bada4d62c0..e66fd3bb52b 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -390,6 +390,9 @@ impl f32 {
     pub const RADIX: u32 = 2;
 
     /// Number of significant digits in base 2.
+    ///
+    /// Note that the size of the mantissa in the bitwise representation is one
+    /// smaller than this since the leading 1 is not stored explicitly.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MANTISSA_DIGITS: u32 = 24;
 
@@ -440,16 +443,22 @@ impl f32 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f32 = 3.40282347e+38_f32;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -125;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 128;
 
@@ -707,8 +716,7 @@ impl f32 {
     pub const fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
-        // SAFETY: This is just transmuting to get the sign bit, it's fine.
-        unsafe { mem::transmute::<f32, u32>(self) & 0x8000_0000 != 0 }
+        self.to_bits() & 0x8000_0000 != 0
     }
 
     /// Returns the least number greater than `self`.
@@ -983,7 +991,7 @@ impl f32 {
         }
     }
 
-    /// Calculates the middle point of `self` and `rhs`.
+    /// Calculates the midpoint (average) between `self` and `rhs`.
     ///
     /// This returns NaN when *either* argument is NaN or if a combination of
     /// +inf and -inf is provided as arguments.
@@ -995,6 +1003,7 @@ impl f32 {
     /// assert_eq!((-5.5f32).midpoint(8.0), 1.25);
     /// ```
     #[inline]
+    #[doc(alias = "average")]
     #[stable(feature = "num_midpoint", since = "1.85.0")]
     #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
     pub const fn midpoint(self, other: f32) -> f32 {
@@ -1093,6 +1102,7 @@ impl f32 {
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn to_bits(self) -> u32 {
         // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
         unsafe { mem::transmute(self) }
@@ -1138,6 +1148,7 @@ impl f32 {
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[must_use]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u32) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u32` is a plain old datatype so we can always transmute from it.
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 3b06478f7e6..2d791437b28 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -390,6 +390,9 @@ impl f64 {
     pub const RADIX: u32 = 2;
 
     /// Number of significant digits in base 2.
+    ///
+    /// Note that the size of the mantissa in the bitwise representation is one
+    /// smaller than this since the leading 1 is not stored explicitly.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MANTISSA_DIGITS: u32 = 53;
     /// Approximate number of significant digits in base 10.
@@ -439,16 +442,22 @@ impl f64 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f64 = 1.7976931348623157e+308_f64;
 
-    /// One greater than the minimum possible normal power of 2 exponent.
+    /// One greater than the minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
-    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact minimum possible *normal* power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all normal numbers representable by this type are
+    /// greater than or equal to 0.5&nbsp;×&nbsp;2<sup><i>MIN_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -1021;
-    /// Maximum possible power of 2 exponent.
+    /// One greater than the maximum possible power of 2 exponent
+    /// for a significand bounded by 1 ≤ x < 2 (i.e. the IEEE definition).
     ///
-    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
-    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
+    /// This corresponds to the exact maximum possible power of 2 exponent
+    /// for a significand bounded by 0.5 ≤ x < 1 (i.e. the C definition).
+    /// In other words, all numbers representable by this type are
+    /// strictly less than 2<sup><i>MAX_EXP</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 1024;
 
@@ -715,8 +724,7 @@ impl f64 {
     pub const fn is_sign_negative(self) -> bool {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
-        // SAFETY: This is just transmuting to get the sign bit, it's fine.
-        unsafe { mem::transmute::<f64, u64>(self) & Self::SIGN_MASK != 0 }
+        self.to_bits() & Self::SIGN_MASK != 0
     }
 
     #[must_use]
@@ -1001,7 +1009,7 @@ impl f64 {
         }
     }
 
-    /// Calculates the middle point of `self` and `rhs`.
+    /// Calculates the midpoint (average) between `self` and `rhs`.
     ///
     /// This returns NaN when *either* argument is NaN or if a combination of
     /// +inf and -inf is provided as arguments.
@@ -1013,6 +1021,7 @@ impl f64 {
     /// assert_eq!((-5.5f64).midpoint(8.0), 1.25);
     /// ```
     #[inline]
+    #[doc(alias = "average")]
     #[stable(feature = "num_midpoint", since = "1.85.0")]
     #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
     pub const fn midpoint(self, other: f64) -> f64 {
@@ -1091,6 +1100,7 @@ impl f64 {
                   without modifying the original"]
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     #[inline]
     pub const fn to_bits(self) -> u64 {
         // SAFETY: `u64` is a plain old datatype so we can always transmute to it.
@@ -1137,6 +1147,7 @@ impl f64 {
     #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")]
     #[must_use]
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
     pub const fn from_bits(v: u64) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u64` is a plain old datatype so we can always transmute from it.
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 05d8216ac27..8d31a7b697a 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -3675,6 +3675,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute them to arrays of bytes
         #[must_use = "this returns the result of the operation, \
@@ -3778,6 +3779,7 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         #[must_use]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute to them
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 348457e2c00..ecc1c7bf902 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -130,7 +130,7 @@ depending on the target pointer size.
 
 macro_rules! midpoint_impl {
     ($SelfT:ty, unsigned) => {
-        /// Calculates the middle point of `self` and `rhs`.
+        /// Calculates the midpoint (average) between `self` and `rhs`.
         ///
         /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
         /// sufficiently-large unsigned integral type. This implies that the result is
@@ -146,6 +146,8 @@ macro_rules! midpoint_impl {
         #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[doc(alias = "average_floor")]
+        #[doc(alias = "average")]
         #[inline]
         pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
             // Use the well known branchless algorithm from Hacker's Delight to compute
@@ -154,7 +156,7 @@ macro_rules! midpoint_impl {
         }
     };
     ($SelfT:ty, signed) => {
-        /// Calculates the middle point of `self` and `rhs`.
+        /// Calculates the midpoint (average) between `self` and `rhs`.
         ///
         /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
         /// sufficiently-large signed integral type. This implies that the result is
@@ -173,6 +175,9 @@ macro_rules! midpoint_impl {
         #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[doc(alias = "average_floor")]
+        #[doc(alias = "average_ceil")]
+        #[doc(alias = "average")]
         #[inline]
         pub const fn midpoint(self, rhs: Self) -> Self {
             // Use the well known branchless algorithm from Hacker's Delight to compute
@@ -184,7 +189,7 @@ macro_rules! midpoint_impl {
         }
     };
     ($SelfT:ty, $WideT:ty, unsigned) => {
-        /// Calculates the middle point of `self` and `rhs`.
+        /// Calculates the midpoint (average) between `self` and `rhs`.
         ///
         /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
         /// sufficiently-large unsigned integral type. This implies that the result is
@@ -200,13 +205,15 @@ macro_rules! midpoint_impl {
         #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[doc(alias = "average_floor")]
+        #[doc(alias = "average")]
         #[inline]
         pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
             ((self as $WideT + rhs as $WideT) / 2) as $SelfT
         }
     };
     ($SelfT:ty, $WideT:ty, signed) => {
-        /// Calculates the middle point of `self` and `rhs`.
+        /// Calculates the midpoint (average) between `self` and `rhs`.
         ///
         /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
         /// sufficiently-large signed integral type. This implies that the result is
@@ -225,6 +232,9 @@ macro_rules! midpoint_impl {
         #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[doc(alias = "average_floor")]
+        #[doc(alias = "average_ceil")]
+        #[doc(alias = "average")]
         #[inline]
         pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
             ((self as $WideT + rhs as $WideT) / 2) as $SelfT
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 1b79112aec1..8a8b2733d5e 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -1589,7 +1589,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
             super::int_log10::$Int(self.get())
         }
 
-        /// Calculates the middle point of `self` and `rhs`.
+        /// Calculates the midpoint (average) between `self` and `rhs`.
         ///
         /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
         /// sufficiently-large signed integral type. This implies that the result is
@@ -1615,6 +1615,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
         #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[doc(alias = "average_floor")]
+        #[doc(alias = "average")]
         #[inline]
         pub const fn midpoint(self, rhs: Self) -> Self {
             // SAFETY: The only way to get `0` with midpoint is to have two opposite or
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 3678bb091e7..bc6cb950816 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -3523,6 +3523,7 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute them to arrays of bytes
         #[inline]
@@ -3624,6 +3625,7 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
+        #[cfg_attr(not(bootstrap), allow(unnecessary_transmutes))]
         #[must_use]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute to them
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index ac111575938..ef548971aaf 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -12,7 +12,6 @@
 #![feature(async_iterator)]
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
-#![feature(cell_update)]
 #![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(const_eval_select)]
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index c02efd997cf..3536e84d58b 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.155" }
+compiler_builtins = { version = "=0.1.156" }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 0eef2bd225c..9ad26e5d28e 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -973,6 +973,9 @@ where
     /// Returns an array of length `N` with the results of each query. For soundness, at most one
     /// mutable reference will be returned to any value. `None` will be used if the key is missing.
     ///
+    /// This method performs a check to ensure there are no duplicate keys, which currently has a time-complexity of O(n^2),
+    /// so be careful when passing many keys.
+    ///
     /// # Panics
     ///
     /// Panics if any keys are overlapping.
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 0427feb2955..4f9259f39c1 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -1100,3 +1100,39 @@ pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io:
 pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
     sys::fs::chroot(dir.as_ref())
 }
+
+/// Create a FIFO special file at the specified path with the specified mode.
+///
+/// # Examples
+///
+/// ```no_run
+/// # #![feature(unix_mkfifo)]
+/// # #[cfg(not(unix))]
+/// # fn main() {}
+/// # #[cfg(unix)]
+/// # fn main() -> std::io::Result<()> {
+/// # use std::{
+/// #     os::unix::fs::{mkfifo, PermissionsExt},
+/// #     fs::{File, Permissions, remove_file},
+/// #     io::{Write, Read},
+/// # };
+/// # let _ = remove_file("/tmp/fifo");
+/// mkfifo("/tmp/fifo", Permissions::from_mode(0o774))?;
+///
+/// let mut wx = File::options().read(true).write(true).open("/tmp/fifo")?;
+/// let mut rx = File::open("/tmp/fifo")?;
+///
+/// wx.write_all(b"hello, world!")?;
+/// drop(wx);
+///
+/// let mut s = String::new();
+/// rx.read_to_string(&mut s)?;
+///
+/// assert_eq!(s, "hello, world!");
+/// # Ok(())
+/// # }
+/// ```
+#[unstable(feature = "unix_mkfifo", issue = "139324")]
+pub fn mkfifo<P: AsRef<Path>>(path: P, permissions: Permissions) -> io::Result<()> {
+    sys::fs::mkfifo(path.as_ref(), permissions.mode())
+}
diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs
index db9621c8c20..1840bb38c17 100644
--- a/library/std/src/os/unix/fs/tests.rs
+++ b/library/std/src/os/unix/fs/tests.rs
@@ -55,3 +55,23 @@ fn write_vectored_at() {
     let content = fs::read(&filename).unwrap();
     assert_eq!(&content, expected);
 }
+
+#[test]
+fn test_mkfifo() {
+    let tmp_dir = crate::test_helpers::tmpdir();
+
+    let fifo = tmp_dir.path().join("fifo");
+
+    mkfifo(&fifo, Permissions::from_mode(0o774)).unwrap();
+
+    let mut wx = fs::File::options().read(true).write(true).open(&fifo).unwrap();
+    let mut rx = fs::File::open(fifo).unwrap();
+
+    wx.write_all(b"hello, world!").unwrap();
+    drop(wx);
+
+    let mut s = String::new();
+    rx.read_to_string(&mut s).unwrap();
+
+    assert_eq!(s, "hello, world!");
+}
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 50f403ba411..7cd20c48d89 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -353,6 +353,15 @@ fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
     }
 }
 
+/// Checks whether the string is valid as a file extension, or panics otherwise.
+fn validate_extension(extension: &OsStr) {
+    for &b in extension.as_encoded_bytes() {
+        if is_sep_byte(b) {
+            panic!("extension cannot contain path separators: {extension:?}");
+        }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // The core iterators
 ////////////////////////////////////////////////////////////////////////////////
@@ -1507,13 +1516,7 @@ impl PathBuf {
     }
 
     fn _set_extension(&mut self, extension: &OsStr) -> bool {
-        for &b in extension.as_encoded_bytes() {
-            if b < 128 {
-                if is_separator(b as char) {
-                    panic!("extension cannot contain path separators: {:?}", extension);
-                }
-            }
-        }
+        validate_extension(extension);
 
         let file_stem = match self.file_stem() {
             None => return false,
@@ -1541,6 +1544,11 @@ impl PathBuf {
     /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
     /// returns `true` and updates the extension otherwise.
     ///
+    /// # Panics
+    ///
+    /// Panics if the passed extension contains a path separator (see
+    /// [`is_separator`]).
+    ///
     /// # Caveats
     ///
     /// The appended `extension` may contain dots and will be used in its entirety,
@@ -1582,6 +1590,8 @@ impl PathBuf {
     }
 
     fn _add_extension(&mut self, extension: &OsStr) -> bool {
+        validate_extension(extension);
+
         let file_name = match self.file_name() {
             None => return false,
             Some(f) => f.as_encoded_bytes(),
diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs
index 018d7954db2..9683fd47cf9 100644
--- a/library/std/src/sys/env_consts.rs
+++ b/library/std/src/sys/env_consts.rs
@@ -389,6 +389,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "exe";
 }
 
+#[cfg(target_os = "zkvm")]
+pub mod os {
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = ".elf";
+    pub const DLL_EXTENSION: &str = "elf";
+    pub const EXE_SUFFIX: &str = ".elf";
+    pub const EXE_EXTENSION: &str = "elf";
+}
+
 // The fallback when none of the other gates match.
 #[else]
 pub mod os {
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index 4c5e36ce67a..d55e28074fe 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -9,7 +9,7 @@ cfg_if::cfg_if! {
     if #[cfg(target_family = "unix")] {
         mod unix;
         use unix as imp;
-        pub use unix::{chown, fchown, lchown};
+        pub use unix::{chown, fchown, lchown, mkfifo};
         #[cfg(not(target_os = "fuchsia"))]
         pub use unix::chroot;
         pub(crate) use unix::debug_assert_fd_is_open;
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index bc8817bac70..351a9f9413f 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -2137,6 +2137,12 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
     Err(io::const_error!(io::ErrorKind::Unsupported, "chroot not supported by vxworks"))
 }
 
+pub fn mkfifo(path: &Path, mode: u32) -> io::Result<()> {
+    run_path_with_cstr(path, &|path| {
+        cvt(unsafe { libc::mkfifo(path.as_ptr(), mode.try_into().unwrap()) }).map(|_| ())
+    })
+}
+
 pub use remove_dir_impl::remove_dir_all;
 
 // Fallback for REDOX, ESP-ID, Horizon, Vita, Vxworks and Miri
diff --git a/library/std/src/sys/pal/zkvm/env.rs b/library/std/src/sys/pal/zkvm/env.rs
deleted file mode 100644
index b85153642b1..00000000000
--- a/library/std/src/sys/pal/zkvm/env.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod os {
-    pub const FAMILY: &str = "";
-    pub const OS: &str = "";
-    pub const DLL_PREFIX: &str = "";
-    pub const DLL_SUFFIX: &str = ".elf";
-    pub const DLL_EXTENSION: &str = "elf";
-    pub const EXE_SUFFIX: &str = ".elf";
-    pub const EXE_EXTENSION: &str = "elf";
-}
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 3b04ec50db3..92bb809d90c 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -415,6 +415,7 @@ impl Command {
         all(target_os = "linux", target_env = "musl"),
         target_os = "nto",
         target_vendor = "apple",
+        target_os = "cygwin",
     )))]
     fn posix_spawn(
         &mut self,
@@ -433,6 +434,7 @@ impl Command {
         all(target_os = "linux", target_env = "musl"),
         target_os = "nto",
         target_vendor = "apple",
+        target_os = "cygwin",
     ))]
     fn posix_spawn(
         &mut self,
@@ -584,7 +586,7 @@ impl Command {
         /// Some platforms can set a new working directory for a spawned process in the
         /// `posix_spawn` path. This function looks up the function pointer for adding
         /// such an action to a `posix_spawn_file_actions_t` struct.
-        #[cfg(not(all(target_os = "linux", target_env = "musl")))]
+        #[cfg(not(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")))]
         fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
             use crate::sys::weak::weak;
 
@@ -618,7 +620,9 @@ impl Command {
         /// Weak symbol lookup doesn't work with statically linked libcs, so in cases
         /// where static linking is possible we need to either check for the presence
         /// of the symbol at compile time or know about it upfront.
-        #[cfg(all(target_os = "linux", target_env = "musl"))]
+        ///
+        /// Cygwin doesn't support weak symbol, so just link it.
+        #[cfg(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin"))]
         fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
             // Our minimum required musl supports this function, so we can just use it.
             Some(libc::posix_spawn_file_actions_addchdir_np)
diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs
index df28e8129dd..677738bac8f 100644
--- a/library/std/tests/floats/f128.rs
+++ b/library/std/tests/floats/f128.rs
@@ -112,6 +112,8 @@ fn test_nan() {
     assert!(!nan.is_sign_negative());
     assert!(!nan.is_normal());
     assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f128::MANTISSA_DIGITS - 2)) != 0);
 }
 
 #[test]
diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs
index 1a90f00aecc..0fc4df8115a 100644
--- a/library/std/tests/floats/f16.rs
+++ b/library/std/tests/floats/f16.rs
@@ -95,6 +95,8 @@ fn test_nan() {
     assert!(!nan.is_sign_negative());
     assert!(!nan.is_normal());
     assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f16::MANTISSA_DIGITS - 2)) != 0);
 }
 
 #[test]
diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs
index d99b03cb255..9af23afc5bb 100644
--- a/library/std/tests/floats/f32.rs
+++ b/library/std/tests/floats/f32.rs
@@ -72,6 +72,8 @@ fn test_nan() {
     assert!(nan.is_sign_positive());
     assert!(!nan.is_sign_negative());
     assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f32::MANTISSA_DIGITS - 2)) != 0);
 }
 
 #[test]
diff --git a/library/std/tests/floats/f64.rs b/library/std/tests/floats/f64.rs
index 611670751bb..de9c27eb33d 100644
--- a/library/std/tests/floats/f64.rs
+++ b/library/std/tests/floats/f64.rs
@@ -60,6 +60,8 @@ fn test_nan() {
     assert!(nan.is_sign_positive());
     assert!(!nan.is_sign_negative());
     assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f64::MANTISSA_DIGITS - 2)) != 0);
 }
 
 #[test]
diff --git a/library/stdarch b/library/stdarch
-Subproject 4666c7376f25a265c74535585d622da3da6dfeb
+Subproject 1245618ccf5b2df7ab1ebb0279b9f3f72667016
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 17ee4d610f9..d415668f54a 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -56,6 +56,7 @@ dependencies = [
  "sha2",
  "sysinfo",
  "tar",
+ "tempfile",
  "termcolor",
  "toml",
  "tracing",
@@ -225,22 +226,28 @@ dependencies = [
 
 [[package]]
 name = "errno"
-version = "0.3.9"
+version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
 dependencies = [
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
+name = "fastrand"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+[[package]]
 name = "fd-lock"
 version = "4.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947"
 dependencies = [
  "cfg-if",
- "rustix",
+ "rustix 0.38.40",
  "windows-sys 0.52.0",
 ]
 
@@ -267,6 +274,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "getrandom"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi",
+]
+
+[[package]]
 name = "globset"
 version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -334,9 +353,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "libc"
-version = "0.2.167"
+version = "0.2.171"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
 
 [[package]]
 name = "libredox"
@@ -356,6 +375,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
 [[package]]
+name = "linux-raw-sys"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
+
+[[package]]
 name = "log"
 version = "0.4.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -487,6 +512,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "r-efi"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+
+[[package]]
 name = "redox_syscall"
 version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -548,11 +579,24 @@ dependencies = [
  "bitflags",
  "errno",
  "libc",
- "linux-raw-sys",
+ "linux-raw-sys 0.4.14",
  "windows-sys 0.52.0",
 ]
 
 [[package]]
+name = "rustix"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.9.3",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
 name = "ryu"
 version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -679,6 +723,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "tempfile"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600"
+dependencies = [
+ "fastrand",
+ "getrandom",
+ "once_cell",
+ "rustix 1.0.2",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
 name = "termcolor"
 version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -825,6 +882,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "wasi"
+version = "0.14.2+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -991,14 +1057,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
 name = "xattr"
 version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
 dependencies = [
  "libc",
- "linux-raw-sys",
- "rustix",
+ "linux-raw-sys 0.4.14",
+ "rustix 0.38.40",
 ]
 
 [[package]]
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 23aa87a7407..712a9b04c1a 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -83,6 +83,7 @@ features = [
 
 [dev-dependencies]
 pretty_assertions = "1.4"
+tempfile = "3.15.0"
 
 # We care a lot about bootstrap's compile times, so don't include debuginfo for
 # dependencies, only bootstrap itself.
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 68fa42ee9e6..2e5865e5096 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -111,14 +111,10 @@ impl Step for Std {
         // the `rust.download-rustc=true` option.
         let force_recompile = builder.rust_info().is_managed_git_subrepository()
             && builder.download_rustc()
-            && builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none();
+            && builder.config.has_changes_from_upstream(&["library"]);
 
         trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
         trace!("download_rustc: {}", builder.download_rustc());
-        trace!(
-            "last modified commit: {:?}",
-            builder.config.last_modified_commit(&["library"], "download-rustc", true)
-        );
         trace!(force_recompile);
 
         run.builder.ensure(Std {
diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs
index 48bb5cb8e87..ee8bd8286da 100644
--- a/src/bootstrap/src/core/build_steps/gcc.rs
+++ b/src/bootstrap/src/core/build_steps/gcc.rs
@@ -96,6 +96,8 @@ pub enum GccBuildStatus {
 /// Returns a path to the libgccjit.so file.
 #[cfg(not(test))]
 fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<PathBuf> {
+    use build_helper::git::PathFreshness;
+
     // Try to download GCC from CI if configured and available
     if !matches!(builder.config.gcc_ci_mode, crate::core::config::GccCiMode::DownloadFromCi) {
         return None;
@@ -104,18 +106,40 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<Pa
         eprintln!("GCC CI download is only available for the `x86_64-unknown-linux-gnu` target");
         return None;
     }
-    let sha =
-        detect_gcc_sha(&builder.config, builder.config.rust_info.is_managed_git_subrepository());
-    let root = ci_gcc_root(&builder.config);
-    let gcc_stamp = BuildStamp::new(&root).with_prefix("gcc").add_stamp(&sha);
-    if !gcc_stamp.is_up_to_date() && !builder.config.dry_run() {
-        builder.config.download_ci_gcc(&sha, &root);
-        t!(gcc_stamp.write());
+    let source = detect_gcc_freshness(
+        &builder.config,
+        builder.config.rust_info.is_managed_git_subrepository(),
+    );
+    builder.verbose(|| {
+        eprintln!("GCC freshness: {source:?}");
+    });
+    match source {
+        PathFreshness::LastModifiedUpstream { upstream } => {
+            // Download from upstream CI
+            let root = ci_gcc_root(&builder.config);
+            let gcc_stamp = BuildStamp::new(&root).with_prefix("gcc").add_stamp(&upstream);
+            if !gcc_stamp.is_up_to_date() && !builder.config.dry_run() {
+                builder.config.download_ci_gcc(&upstream, &root);
+                t!(gcc_stamp.write());
+            }
+
+            let libgccjit = root.join("lib").join("libgccjit.so");
+            create_lib_alias(builder, &libgccjit);
+            Some(libgccjit)
+        }
+        PathFreshness::HasLocalModifications { .. } => {
+            // We have local modifications, rebuild GCC.
+            eprintln!("Found local GCC modifications, GCC will *not* be downloaded");
+            None
+        }
+        PathFreshness::MissingUpstream => {
+            eprintln!("error: could not find commit hash for downloading GCC");
+            eprintln!("HELP: maybe your repository history is too shallow?");
+            eprintln!("HELP: consider disabling `download-ci-gcc`");
+            eprintln!("HELP: or fetch enough history to include one upstream commit");
+            None
+        }
     }
-
-    let libgccjit = root.join("lib").join("libgccjit.so");
-    create_lib_alias(builder, &libgccjit);
-    Some(libgccjit)
 }
 
 #[cfg(test)]
@@ -264,31 +288,16 @@ fn ci_gcc_root(config: &crate::Config) -> PathBuf {
     config.out.join(config.build).join("ci-gcc")
 }
 
-/// This retrieves the GCC sha we *want* to use, according to git history.
+/// Detect whether GCC sources have been modified locally or not.
 #[cfg(not(test))]
-fn detect_gcc_sha(config: &crate::Config, is_git: bool) -> String {
-    use build_helper::git::get_closest_merge_commit;
-
-    let gcc_sha = if is_git {
-        get_closest_merge_commit(
-            Some(&config.src),
-            &config.git_config(),
-            &["src/gcc", "src/bootstrap/download-ci-gcc-stamp"],
-        )
-        .unwrap()
+fn detect_gcc_freshness(config: &crate::Config, is_git: bool) -> build_helper::git::PathFreshness {
+    use build_helper::git::PathFreshness;
+
+    if is_git {
+        config.check_path_modifications(&["src/gcc", "src/bootstrap/download-ci-gcc-stamp"])
     } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) {
-        info.sha.trim().to_owned()
+        PathFreshness::LastModifiedUpstream { upstream: info.sha.trim().to_owned() }
     } else {
-        "".to_owned()
-    };
-
-    if gcc_sha.is_empty() {
-        eprintln!("error: could not find commit hash for downloading GCC");
-        eprintln!("HELP: maybe your repository history is too shallow?");
-        eprintln!("HELP: consider disabling `download-ci-gcc`");
-        eprintln!("HELP: or fetch enough history to include one upstream commit");
-        panic!();
+        PathFreshness::MissingUpstream
     }
-
-    gcc_sha
 }
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 6f6839ad15b..86af956535e 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -14,7 +14,7 @@ use std::path::{Path, PathBuf};
 use std::sync::OnceLock;
 use std::{env, fs};
 
-use build_helper::git::get_closest_merge_commit;
+use build_helper::git::PathFreshness;
 #[cfg(feature = "tracing")]
 use tracing::instrument;
 
@@ -181,26 +181,15 @@ pub const LLVM_INVALIDATION_PATHS: &[&str] = &[
     "src/version",
 ];
 
-/// This retrieves the LLVM sha we *want* to use, according to git history.
-pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String {
-    let llvm_sha = if is_git {
-        get_closest_merge_commit(Some(&config.src), &config.git_config(), LLVM_INVALIDATION_PATHS)
-            .unwrap()
+/// Detect whether LLVM sources have been modified locally or not.
+pub(crate) fn detect_llvm_freshness(config: &Config, is_git: bool) -> PathFreshness {
+    if is_git {
+        config.check_path_modifications(LLVM_INVALIDATION_PATHS)
     } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) {
-        info.sha.trim().to_owned()
+        PathFreshness::LastModifiedUpstream { upstream: info.sha.trim().to_owned() }
     } else {
-        "".to_owned()
-    };
-
-    if llvm_sha.is_empty() {
-        eprintln!("error: could not find commit hash for downloading LLVM");
-        eprintln!("HELP: maybe your repository history is too shallow?");
-        eprintln!("HELP: consider disabling `download-ci-llvm`");
-        eprintln!("HELP: or fetch enough history to include one upstream commit");
-        panic!();
+        PathFreshness::MissingUpstream
     }
-
-    llvm_sha
 }
 
 /// Returns whether the CI-found LLVM is currently usable.
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 83083e12ef1..9d07babe519 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -683,7 +683,7 @@ impl Step for Editor {
         match EditorKind::prompt_user() {
             Ok(editor_kind) => {
                 if let Some(editor_kind) = editor_kind {
-                    while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
+                    while !t!(create_editor_settings_maybe(config, &editor_kind)) {}
                 } else {
                     println!("Ok, skipping editor setup!");
                 }
@@ -695,7 +695,7 @@ impl Step for Editor {
 
 /// Create the recommended editor LSP config file for rustc development, or just print it
 /// If this method should be re-called, it returns `false`.
-fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Result<bool> {
+fn create_editor_settings_maybe(config: &Config, editor: &EditorKind) -> io::Result<bool> {
     let hashes = editor.hashes();
     let (current_hash, historical_hashes) = hashes.split_last().unwrap();
     let settings_path = editor.settings_path(config);
@@ -752,7 +752,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             // exists but user modified, back it up
             Some(false) => {
                 // exists and is not current version or outdated, so back it up
-                let backup = settings_path.clone().with_extension(editor.backup_extension());
+                let backup = settings_path.with_extension(editor.backup_extension());
                 eprintln!(
                     "WARNING: copying `{}` to `{}`",
                     settings_path.file_name().unwrap().to_str().unwrap(),
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 3426da51a80..1549d4713af 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -696,8 +696,7 @@ impl Step for Rustdoc {
             let files_to_track = &["src/librustdoc", "src/tools/rustdoc"];
 
             // Check if unchanged
-            if builder.config.last_modified_commit(files_to_track, "download-rustc", true).is_some()
-            {
+            if !builder.config.has_changes_from_upstream(files_to_track) {
                 let precompiled_rustdoc = builder
                     .config
                     .ci_rustc_dir()
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 5de824ebab2..8e2c6fc52cd 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -1,11 +1,14 @@
+use std::env::VarError;
 use std::{panic, thread};
 
+use build_helper::stage0_parser::parse_stage0_file;
 use llvm::prebuilt_llvm_config;
 
 use super::*;
 use crate::Flags;
 use crate::core::build_steps::doc::DocumentationFormat;
 use crate::core::config::Config;
+use crate::utils::tests::git::{GitCtx, git_test};
 
 static TEST_TRIPLE_1: &str = "i686-unknown-haiku";
 static TEST_TRIPLE_2: &str = "i686-unknown-hurd-gnu";
@@ -239,42 +242,80 @@ fn alias_and_path_for_library() {
 }
 
 #[test]
-fn ci_rustc_if_unchanged_logic() {
-    let config = Config::parse_inner(
-        Flags::parse(&[
-            "build".to_owned(),
-            "--dry-run".to_owned(),
-            "--set=rust.download-rustc='if-unchanged'".to_owned(),
-        ]),
-        |&_| Ok(Default::default()),
-    );
-
-    let build = Build::new(config.clone());
-    let builder = Builder::new(&build);
-
-    if config.out.exists() {
-        fs::remove_dir_all(&config.out).unwrap();
-    }
+fn ci_rustc_if_unchanged_invalidate_on_compiler_changes() {
+    git_test(|ctx| {
+        prepare_rustc_checkout(ctx);
+        ctx.create_upstream_merge(&["compiler/bar"]);
+        // This change should invalidate download-ci-rustc
+        ctx.create_nonupstream_merge(&["compiler/foo"]);
+
+        let config = parse_config_download_rustc_at(ctx.get_path(), "if-unchanged", true);
+        assert_eq!(config.download_rustc_commit, None);
+    });
+}
 
-    builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]);
+#[test]
+fn ci_rustc_if_unchanged_invalidate_on_library_changes_in_ci() {
+    git_test(|ctx| {
+        prepare_rustc_checkout(ctx);
+        ctx.create_upstream_merge(&["compiler/bar"]);
+        // This change should invalidate download-ci-rustc
+        ctx.create_nonupstream_merge(&["library/foo"]);
+
+        let config = parse_config_download_rustc_at(ctx.get_path(), "if-unchanged", true);
+        assert_eq!(config.download_rustc_commit, None);
+    });
+}
 
-    // Make sure "if-unchanged" logic doesn't try to use CI rustc while there are changes
-    // in compiler and/or library.
-    if config.download_rustc_commit.is_some() {
-        let mut paths = vec!["compiler"];
+#[test]
+fn ci_rustc_if_unchanged_do_not_invalidate_on_library_changes_outside_ci() {
+    git_test(|ctx| {
+        prepare_rustc_checkout(ctx);
+        let sha = ctx.create_upstream_merge(&["compiler/bar"]);
+        // This change should not invalidate download-ci-rustc
+        ctx.create_nonupstream_merge(&["library/foo"]);
+
+        let config = parse_config_download_rustc_at(ctx.get_path(), "if-unchanged", false);
+        assert_eq!(config.download_rustc_commit, Some(sha));
+    });
+}
 
-        // Handle library tree the same way as in `Config::download_ci_rustc_commit`.
-        if builder.config.is_running_on_ci {
-            paths.push("library");
-        }
+#[test]
+fn ci_rustc_if_unchanged_do_not_invalidate_on_tool_changes() {
+    git_test(|ctx| {
+        prepare_rustc_checkout(ctx);
+        let sha = ctx.create_upstream_merge(&["compiler/bar"]);
+        // This change should not invalidate download-ci-rustc
+        ctx.create_nonupstream_merge(&["src/tools/foo"]);
+
+        let config = parse_config_download_rustc_at(ctx.get_path(), "if-unchanged", true);
+        assert_eq!(config.download_rustc_commit, Some(sha));
+    });
+}
 
-        let has_changes = config.last_modified_commit(&paths, "download-rustc", true).is_none();
+/// Prepares the given directory so that it looks like a rustc checkout.
+/// Also configures `GitCtx` to use the correct merge bot e-mail for upstream merge commits.
+fn prepare_rustc_checkout(ctx: &mut GitCtx) {
+    ctx.merge_bot_email =
+        format!("Merge bot <{}>", parse_stage0_file().config.git_merge_commit_email);
+    ctx.write("src/ci/channel", "nightly");
+    ctx.commit();
+}
 
-        assert!(
-            !has_changes,
-            "CI-rustc can't be used with 'if-unchanged' while there are changes in compiler and/or library."
-        );
-    }
+/// Parses a Config directory from `path`, with the given value of `download_rustc`.
+fn parse_config_download_rustc_at(path: &Path, download_rustc: &str, ci: bool) -> Config {
+    Config::parse_inner(
+        Flags::parse(&[
+            "build".to_owned(),
+            "--dry-run".to_owned(),
+            "--ci".to_owned(),
+            if ci { "true" } else { "false" }.to_owned(),
+            format!("--set=rust.download-rustc='{download_rustc}'"),
+            "--src".to_owned(),
+            path.to_str().unwrap().to_owned(),
+        ]),
+        |&_| Ok(Default::default()),
+    )
 }
 
 mod defaults {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 43b62789536..419976c83b1 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -11,12 +11,12 @@ use std::io::IsTerminal;
 use std::path::{Path, PathBuf, absolute};
 use std::process::Command;
 use std::str::FromStr;
-use std::sync::OnceLock;
+use std::sync::{Arc, Mutex, OnceLock};
 use std::{cmp, env, fs};
 
 use build_helper::ci::CiEnv;
 use build_helper::exit;
-use build_helper::git::{GitConfig, get_closest_merge_commit, output_result};
+use build_helper::git::{GitConfig, PathFreshness, check_path_modifications, output_result};
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
 #[cfg(feature = "tracing")]
@@ -422,6 +422,9 @@ pub struct Config {
     pub compiletest_use_stage0_libtest: bool,
 
     pub is_running_on_ci: bool,
+
+    /// Cache for determining path modifications
+    pub path_modification_cache: Arc<Mutex<HashMap<Vec<&'static str>, PathFreshness>>>,
 }
 
 #[derive(Clone, Debug, Default)]
@@ -3193,19 +3196,30 @@ impl Config {
         let commit = if self.rust_info.is_managed_git_subrepository() {
             // Look for a version to compare to based on the current commit.
             // Only commits merged by bors will have CI artifacts.
-            match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged) {
-                Some(commit) => commit,
-                None => {
+            let freshness = self.check_path_modifications(&allowed_paths);
+            self.verbose(|| {
+                eprintln!("rustc freshness: {freshness:?}");
+            });
+            match freshness {
+                PathFreshness::LastModifiedUpstream { upstream } => upstream,
+                PathFreshness::HasLocalModifications { upstream } => {
                     if if_unchanged {
                         return None;
                     }
-                    println!("ERROR: could not find commit hash for downloading rustc");
-                    println!("HELP: maybe your repository history is too shallow?");
-                    println!(
-                        "HELP: consider setting `rust.download-rustc=false` in bootstrap.toml"
-                    );
-                    println!("HELP: or fetch enough history to include one upstream commit");
-                    crate::exit!(1);
+
+                    if self.is_running_on_ci {
+                        eprintln!("CI rustc commit matches with HEAD and we are in CI.");
+                        eprintln!(
+                            "`rustc.download-ci` functionality will be skipped as artifacts are not available."
+                        );
+                        return None;
+                    }
+
+                    upstream
+                }
+                PathFreshness::MissingUpstream => {
+                    eprintln!("No upstream commit found");
+                    return None;
                 }
             }
         } else {
@@ -3214,19 +3228,6 @@ impl Config {
                 .expect("git-commit-info is missing in the project root")
         };
 
-        if self.is_running_on_ci && {
-            let head_sha =
-                output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut());
-            let head_sha = head_sha.trim();
-            commit == head_sha
-        } {
-            eprintln!("CI rustc commit matches with HEAD and we are in CI.");
-            eprintln!(
-                "`rustc.download-ci` functionality will be skipped as artifacts are not available."
-            );
-            return None;
-        }
-
         if debug_assertions_requested {
             eprintln!(
                 "WARN: `rust.debug-assertions = true` will prevent downloading CI rustc as alt CI \
@@ -3264,9 +3265,7 @@ impl Config {
             self.update_submodule("src/llvm-project");
 
             // Check for untracked changes in `src/llvm-project` and other important places.
-            let has_changes = self
-                .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
-                .is_none();
+            let has_changes = self.has_changes_from_upstream(LLVM_INVALIDATION_PATHS);
 
             // Return false if there are untracked changes, otherwise check if CI LLVM is available.
             if has_changes { false } else { llvm::is_ci_llvm_available_for_target(self, asserts) }
@@ -3297,51 +3296,30 @@ impl Config {
         }
     }
 
-    /// Returns the last commit in which any of `modified_paths` were changed,
-    /// or `None` if there are untracked changes in the working directory and `if_unchanged` is true.
-    pub fn last_modified_commit(
-        &self,
-        modified_paths: &[&str],
-        option_name: &str,
-        if_unchanged: bool,
-    ) -> Option<String> {
-        assert!(
-            self.rust_info.is_managed_git_subrepository(),
-            "Can't run `Config::last_modified_commit` on a non-git source."
-        );
-
-        // Look for a version to compare to based on the current commit.
-        // Only commits merged by bors will have CI artifacts.
-        let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
-        if commit.is_empty() {
-            println!("error: could not find commit hash for downloading components from CI");
-            println!("help: maybe your repository history is too shallow?");
-            println!("help: consider disabling `{option_name}`");
-            println!("help: or fetch enough history to include one upstream commit");
-            crate::exit!(1);
-        }
-
-        // Warn if there were changes to the compiler or standard library since the ancestor commit.
-        let mut git = helpers::git(Some(&self.src));
-        git.args(["diff-index", "--quiet", &commit, "--"]).args(modified_paths);
-
-        let has_changes = !t!(git.as_command_mut().status()).success();
-        if has_changes {
-            if if_unchanged {
-                if self.is_verbose() {
-                    println!(
-                        "warning: saw changes to one of {modified_paths:?} since {commit}; \
-                            ignoring `{option_name}`"
-                    );
-                }
-                return None;
-            }
-            println!(
-                "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
-            );
+    /// Returns true if any of the `paths` have been modified locally.
+    pub fn has_changes_from_upstream(&self, paths: &[&'static str]) -> bool {
+        match self.check_path_modifications(paths) {
+            PathFreshness::LastModifiedUpstream { .. } => false,
+            PathFreshness::HasLocalModifications { .. } | PathFreshness::MissingUpstream => true,
         }
+    }
 
-        Some(commit.to_string())
+    /// Checks whether any of the given paths have been modified w.r.t. upstream.
+    pub fn check_path_modifications(&self, paths: &[&'static str]) -> PathFreshness {
+        // Checking path modifications through git can be relatively expensive (>100ms).
+        // We do not assume that the sources would change during bootstrap's execution,
+        // so we can cache the results here.
+        // Note that we do not use a static variable for the cache, because it would cause problems
+        // in tests that create separate `Config` instsances.
+        self.path_modification_cache
+            .lock()
+            .unwrap()
+            .entry(paths.to_vec())
+            .or_insert_with(|| {
+                check_path_modifications(&self.src, &self.git_config(), paths, CiEnv::current())
+                    .unwrap()
+            })
+            .clone()
     }
 
     /// Checks if the given target is the same as the host target.
@@ -3379,6 +3357,10 @@ impl Config {
             _ => !self.is_system_llvm(target),
         }
     }
+
+    pub fn ci_env(&self) -> CiEnv {
+        if self.is_running_on_ci { CiEnv::GitHubActions } else { CiEnv::None }
+    }
 }
 
 /// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index c8a12c9072c..96ac8a6d52f 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -5,6 +5,7 @@ use std::path::{Path, PathBuf};
 use std::{env, fs};
 
 use build_helper::ci::CiEnv;
+use build_helper::git::PathFreshness;
 use clap::CommandFactory;
 use serde::Deserialize;
 
@@ -15,6 +16,7 @@ use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
 use crate::core::build_steps::llvm;
 use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
 use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
+use crate::utils::tests::git::git_test;
 
 pub(crate) fn parse(config: &str) -> Config {
     Config::parse_inner(
@@ -51,9 +53,7 @@ fn download_ci_llvm() {
 
     let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\"");
     if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci {
-        let has_changes = if_unchanged_config
-            .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true)
-            .is_none();
+        let has_changes = if_unchanged_config.has_changes_from_upstream(LLVM_INVALIDATION_PATHS);
 
         assert!(
             !has_changes,
@@ -746,3 +746,242 @@ fn test_include_precedence_over_profile() {
     // override profile settings, so we expect this to be "dev" here.
     assert_eq!(config.channel, "dev");
 }
+
+#[test]
+fn test_pr_ci_unchanged_anywhere() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a"]);
+        ctx.create_nonupstream_merge(&["b"]);
+        let src = ctx.check_modifications(&["c"], CiEnv::GitHubActions);
+        assert_eq!(src, PathFreshness::LastModifiedUpstream { upstream: sha });
+    });
+}
+
+#[test]
+fn test_pr_ci_changed_in_pr() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a"]);
+        ctx.create_nonupstream_merge(&["b"]);
+        let src = ctx.check_modifications(&["b"], CiEnv::GitHubActions);
+        assert_eq!(src, PathFreshness::HasLocalModifications { upstream: sha });
+    });
+}
+
+#[test]
+fn test_auto_ci_unchanged_anywhere_select_parent() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a"]);
+        ctx.create_upstream_merge(&["b"]);
+        let src = ctx.check_modifications(&["c"], CiEnv::GitHubActions);
+        assert_eq!(src, PathFreshness::LastModifiedUpstream { upstream: sha });
+    });
+}
+
+#[test]
+fn test_auto_ci_changed_in_pr() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a"]);
+        ctx.create_upstream_merge(&["b", "c"]);
+        let src = ctx.check_modifications(&["c", "d"], CiEnv::GitHubActions);
+        assert_eq!(src, PathFreshness::HasLocalModifications { upstream: sha });
+    });
+}
+
+#[test]
+fn test_local_uncommitted_modifications() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a"]);
+        ctx.create_branch("feature");
+        ctx.modify("a");
+
+        assert_eq!(
+            ctx.check_modifications(&["a", "d"], CiEnv::None),
+            PathFreshness::HasLocalModifications { upstream: sha }
+        );
+    });
+}
+
+#[test]
+fn test_local_committed_modifications() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a"]);
+        ctx.create_upstream_merge(&["b", "c"]);
+        ctx.create_branch("feature");
+        ctx.modify("x");
+        ctx.commit();
+        ctx.modify("a");
+        ctx.commit();
+
+        assert_eq!(
+            ctx.check_modifications(&["a", "d"], CiEnv::None),
+            PathFreshness::HasLocalModifications { upstream: sha }
+        );
+    });
+}
+
+#[test]
+fn test_local_committed_modifications_subdirectory() {
+    git_test(|ctx| {
+        let sha = ctx.create_upstream_merge(&["a/b/c"]);
+        ctx.create_upstream_merge(&["b", "c"]);
+        ctx.create_branch("feature");
+        ctx.modify("a/b/d");
+        ctx.commit();
+
+        assert_eq!(
+            ctx.check_modifications(&["a/b"], CiEnv::None),
+            PathFreshness::HasLocalModifications { upstream: sha }
+        );
+    });
+}
+
+#[test]
+fn test_local_changes_in_head_upstream() {
+    git_test(|ctx| {
+        // We want to resolve to the upstream commit that made modifications to a,
+        // even if it is currently HEAD
+        let sha = ctx.create_upstream_merge(&["a"]);
+        assert_eq!(
+            ctx.check_modifications(&["a", "d"], CiEnv::None),
+            PathFreshness::LastModifiedUpstream { upstream: sha }
+        );
+    });
+}
+
+#[test]
+fn test_local_changes_in_previous_upstream() {
+    git_test(|ctx| {
+        // We want to resolve to this commit, which modified a
+        let sha = ctx.create_upstream_merge(&["a", "e"]);
+        // Not to this commit, which is the latest upstream commit
+        ctx.create_upstream_merge(&["b", "c"]);
+        ctx.create_branch("feature");
+        ctx.modify("d");
+        ctx.commit();
+
+        assert_eq!(
+            ctx.check_modifications(&["a"], CiEnv::None),
+            PathFreshness::LastModifiedUpstream { upstream: sha }
+        );
+    });
+}
+
+#[test]
+fn test_local_no_upstream_commit_with_changes() {
+    git_test(|ctx| {
+        ctx.create_upstream_merge(&["a", "e"]);
+        ctx.create_upstream_merge(&["a", "e"]);
+        // We want to fall back to this commit, because there are no commits
+        // that modified `x`.
+        let sha = ctx.create_upstream_merge(&["a", "e"]);
+        ctx.create_branch("feature");
+        ctx.modify("d");
+        ctx.commit();
+        assert_eq!(
+            ctx.check_modifications(&["x"], CiEnv::None),
+            PathFreshness::LastModifiedUpstream { upstream: sha }
+        );
+    });
+}
+
+#[test]
+fn test_local_no_upstream_commit() {
+    git_test(|ctx| {
+        let src = ctx.check_modifications(&["c", "d"], CiEnv::None);
+        assert_eq!(src, PathFreshness::MissingUpstream);
+    });
+}
+
+#[test]
+fn test_local_changes_negative_path() {
+    git_test(|ctx| {
+        let upstream = ctx.create_upstream_merge(&["a"]);
+        ctx.create_branch("feature");
+        ctx.modify("b");
+        ctx.modify("d");
+        ctx.commit();
+
+        assert_eq!(
+            ctx.check_modifications(&[":!b", ":!d"], CiEnv::None),
+            PathFreshness::LastModifiedUpstream { upstream: upstream.clone() }
+        );
+        assert_eq!(
+            ctx.check_modifications(&[":!c"], CiEnv::None),
+            PathFreshness::HasLocalModifications { upstream: upstream.clone() }
+        );
+        assert_eq!(
+            ctx.check_modifications(&[":!d", ":!x"], CiEnv::None),
+            PathFreshness::HasLocalModifications { upstream }
+        );
+    });
+}
+
+#[test]
+fn test_local_changes_subtree_that_used_bors() {
+    // Here we simulate a very specific situation related to subtrees.
+    // When you have merge commits locally, we should ignore them w.r.t. the artifact download
+    // logic.
+    // The upstream search code currently uses a simple heuristic:
+    // - Find commits by bors (or in general an author with the merge commit e-mail)
+    // - Find the newest such commit
+    // This should make it work even for subtrees that:
+    // - Used bors in the past (so they have bors merge commits in their history).
+    // - Use Josh to merge rustc into the subtree, in a way that the rustc history is the second
+    // parent, not the first one.
+    //
+    // In addition, when searching for modified files, we cannot simply start from HEAD, because
+    // in this situation git wouldn't find the right commit.
+    //
+    // This test checks that this specific scenario will resolve to the right rustc commit, both
+    // when finding a modified file and when finding a non-existent file (which essentially means
+    // that we just lookup the most recent upstream commit).
+    //
+    // See https://github.com/rust-lang/rust/issues/101907#issuecomment-2697671282 for more details.
+    git_test(|ctx| {
+        ctx.create_upstream_merge(&["a"]);
+
+        // Start unrelated subtree history
+        ctx.run_git(&["switch", "--orphan", "subtree"]);
+        ctx.modify("bar");
+        ctx.commit();
+        // Now we need to emulate old bors commits in the subtree.
+        // Git only has a resolution of one second, which is a problem, since our git logic orders
+        // merge commits by their date.
+        // To avoid sleeping in the test, we modify the commit date to be forcefully in the past.
+        ctx.create_upstream_merge(&["subtree/a"]);
+        ctx.run_git(&["commit", "--amend", "--date", "Wed Feb 16 14:00 2011 +0100", "--no-edit"]);
+
+        // Merge the subtree history into rustc
+        ctx.switch_to_branch("main");
+        ctx.run_git(&["merge", "subtree", "--allow-unrelated"]);
+
+        // Create a rustc commit that modifies a path that we're interested in (`x`)
+        let upstream_1 = ctx.create_upstream_merge(&["x"]);
+        // Create another bors commit
+        let upstream_2 = ctx.create_upstream_merge(&["a"]);
+
+        ctx.switch_to_branch("subtree");
+
+        // Create a subtree branch
+        ctx.create_branch("subtree-pr");
+        ctx.modify("baz");
+        ctx.commit();
+        // We merge rustc into this branch (simulating a "subtree pull")
+        ctx.merge("main", "committer <committer@foo.bar>");
+
+        // And then merge that branch into the subtree (simulating a situation right before a
+        // "subtree push")
+        ctx.switch_to_branch("subtree");
+        ctx.merge("subtree-pr", "committer <committer@foo.bar>");
+
+        // And we want to check that we resolve to the right commits.
+        assert_eq!(
+            ctx.check_modifications(&["x"], CiEnv::None),
+            PathFreshness::LastModifiedUpstream { upstream: upstream_1 }
+        );
+        assert_eq!(
+            ctx.check_modifications(&["nonexistent"], CiEnv::None),
+            PathFreshness::LastModifiedUpstream { upstream: upstream_2 }
+        );
+    });
+}
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 4e4b948a8fd..b95d07356c1 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -720,8 +720,9 @@ download-rustc = false
     #[cfg(not(test))]
     pub(crate) fn maybe_download_ci_llvm(&self) {
         use build_helper::exit;
+        use build_helper::git::PathFreshness;
 
-        use crate::core::build_steps::llvm::detect_llvm_sha;
+        use crate::core::build_steps::llvm::detect_llvm_freshness;
         use crate::core::config::check_incompatible_options_for_ci_llvm;
 
         if !self.llvm_from_ci {
@@ -729,7 +730,22 @@ download-rustc = false
         }
 
         let llvm_root = self.ci_llvm_root();
-        let llvm_sha = detect_llvm_sha(self, self.rust_info.is_managed_git_subrepository());
+        let llvm_freshness =
+            detect_llvm_freshness(self, self.rust_info.is_managed_git_subrepository());
+        self.verbose(|| {
+            eprintln!("LLVM freshness: {llvm_freshness:?}");
+        });
+        let llvm_sha = match llvm_freshness {
+            PathFreshness::LastModifiedUpstream { upstream } => upstream,
+            PathFreshness::HasLocalModifications { upstream } => upstream,
+            PathFreshness::MissingUpstream => {
+                eprintln!("error: could not find commit hash for downloading LLVM");
+                eprintln!("HELP: maybe your repository history is too shallow?");
+                eprintln!("HELP: consider disabling `download-ci-llvm`");
+                eprintln!("HELP: or fetch enough history to include one upstream commit");
+                crate::exit!(1);
+            }
+        };
         let stamp_key = format!("{}{}", llvm_sha, self.llvm_assertions);
         let llvm_stamp = BuildStamp::new(&llvm_root).with_prefix("llvm").add_stamp(stamp_key);
         if !llvm_stamp.is_up_to_date() && !self.dry_run() {
diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs
index caef8ce3088..169fcec303e 100644
--- a/src/bootstrap/src/utils/mod.rs
+++ b/src/bootstrap/src/utils/mod.rs
@@ -20,4 +20,4 @@ pub(crate) mod tracing;
 pub(crate) mod metrics;
 
 #[cfg(test)]
-mod tests;
+pub(crate) mod tests;
diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs
index 7cf1af1c3e2..b61fa3bb8d6 100644
--- a/src/bootstrap/src/utils/proc_macro_deps.rs
+++ b/src/bootstrap/src/utils/proc_macro_deps.rs
@@ -28,8 +28,6 @@ pub static CRATES: &[&str] = &[
     "libc",
     "log",
     "memchr",
-    "mime",
-    "mime_guess",
     "minimal-lexical",
     "nom",
     "once_cell",
@@ -38,7 +36,6 @@ pub static CRATES: &[&str] = &[
     "pest_meta",
     "proc-macro2",
     "quote",
-    "rinja_parser",
     "rustc-hash",
     "self_cell",
     "serde",
@@ -56,7 +53,6 @@ pub static CRATES: &[&str] = &[
     "unic-langid",
     "unic-langid-impl",
     "unic-langid-macros",
-    "unicase",
     "unicode-ident",
     "unicode-width",
     "version_check",
diff --git a/src/bootstrap/src/utils/tests/git.rs b/src/bootstrap/src/utils/tests/git.rs
new file mode 100644
index 00000000000..99e0793af46
--- /dev/null
+++ b/src/bootstrap/src/utils/tests/git.rs
@@ -0,0 +1,152 @@
+use std::ffi::OsStr;
+use std::fs::OpenOptions;
+use std::path::Path;
+use std::process::Command;
+
+use build_helper::ci::CiEnv;
+use build_helper::git::{GitConfig, PathFreshness, check_path_modifications};
+
+pub struct GitCtx {
+    dir: tempfile::TempDir,
+    pub git_repo: String,
+    pub nightly_branch: String,
+    pub merge_bot_email: String,
+}
+
+impl GitCtx {
+    fn new() -> Self {
+        let dir = tempfile::TempDir::new().unwrap();
+        let ctx = Self {
+            dir,
+            git_repo: "rust-lang/rust".to_string(),
+            nightly_branch: "nightly".to_string(),
+            merge_bot_email: "Merge bot <merge-bot@rust-lang.org>".to_string(),
+        };
+        ctx.run_git(&["init"]);
+        ctx.run_git(&["config", "user.name", "Tester"]);
+        ctx.run_git(&["config", "user.email", "tester@rust-lang.org"]);
+        ctx.modify("README.md");
+        ctx.commit();
+        ctx.run_git(&["branch", "-m", "main"]);
+        ctx
+    }
+
+    pub fn get_path(&self) -> &Path {
+        self.dir.path()
+    }
+
+    pub fn check_modifications(&self, target_paths: &[&str], ci_env: CiEnv) -> PathFreshness {
+        check_path_modifications(self.dir.path(), &self.git_config(), target_paths, ci_env).unwrap()
+    }
+
+    pub fn create_upstream_merge(&self, modified_files: &[&str]) -> String {
+        self.create_branch_and_merge("previous-pr", modified_files, &self.merge_bot_email)
+    }
+
+    pub fn create_nonupstream_merge(&self, modified_files: &[&str]) -> String {
+        self.create_branch_and_merge("pr", modified_files, "Tester <tester@rust-lang.org>")
+    }
+
+    pub fn create_branch_and_merge(
+        &self,
+        branch: &str,
+        modified_files: &[&str],
+        author: &str,
+    ) -> String {
+        let current_branch = self.get_current_branch();
+
+        self.create_branch(branch);
+        for file in modified_files {
+            self.modify(file);
+        }
+        self.commit();
+        self.switch_to_branch(&current_branch);
+        self.merge(branch, author);
+        self.run_git(&["branch", "-d", branch]);
+        self.get_current_commit()
+    }
+
+    pub fn get_current_commit(&self) -> String {
+        self.run_git(&["rev-parse", "HEAD"])
+    }
+
+    pub fn get_current_branch(&self) -> String {
+        self.run_git(&["rev-parse", "--abbrev-ref", "HEAD"])
+    }
+
+    pub fn merge(&self, branch: &str, author: &str) {
+        self.run_git(&["merge", "--no-commit", "--no-ff", branch]);
+        self.run_git(&[
+            "commit".to_string(),
+            "-m".to_string(),
+            format!("Merge of {branch} into {}", self.get_current_branch()),
+            "--author".to_string(),
+            author.to_string(),
+        ]);
+    }
+
+    pub fn modify(&self, path: &str) {
+        self.write(path, "line");
+    }
+
+    pub fn write(&self, path: &str, data: &str) {
+        use std::io::Write;
+
+        let path = self.dir.path().join(path);
+        std::fs::create_dir_all(&path.parent().unwrap()).unwrap();
+
+        let mut file = OpenOptions::new().create(true).append(true).open(path).unwrap();
+        writeln!(file, "{data}").unwrap();
+    }
+
+    pub fn commit(&self) -> String {
+        self.run_git(&["add", "."]);
+        self.run_git(&["commit", "-m", "commit message"]);
+        self.get_current_commit()
+    }
+
+    pub fn switch_to_branch(&self, name: &str) {
+        self.run_git(&["switch", name]);
+    }
+
+    /// Creates a branch and switches to it.
+    pub fn create_branch(&self, name: &str) {
+        self.run_git(&["checkout", "-b", name]);
+    }
+
+    pub fn run_git<S: AsRef<OsStr>>(&self, args: &[S]) -> String {
+        let mut cmd = self.git_cmd();
+        cmd.args(args);
+        eprintln!("Running {cmd:?}");
+        let output = cmd.output().unwrap();
+        let stdout = String::from_utf8(output.stdout).unwrap().trim().to_string();
+        let stderr = String::from_utf8(output.stderr).unwrap().trim().to_string();
+        if !output.status.success() {
+            panic!("Git command `{cmd:?}` failed\nStdout\n{stdout}\nStderr\n{stderr}");
+        }
+        stdout
+    }
+
+    fn git_cmd(&self) -> Command {
+        let mut cmd = Command::new("git");
+        cmd.current_dir(&self.dir);
+        cmd
+    }
+
+    fn git_config(&self) -> GitConfig<'_> {
+        GitConfig {
+            git_repository: &self.git_repo,
+            nightly_branch: &self.nightly_branch,
+            git_merge_commit_email: &self.merge_bot_email,
+        }
+    }
+}
+
+/// Run an end-to-end test that allows testing git logic.
+pub fn git_test<F>(test_fn: F)
+where
+    F: FnOnce(&mut GitCtx),
+{
+    let mut ctx = GitCtx::new();
+    test_fn(&mut ctx);
+}
diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs
index 0791f7a6e20..73d55db994c 100644
--- a/src/bootstrap/src/utils/tests/mod.rs
+++ b/src/bootstrap/src/utils/tests/mod.rs
@@ -1 +1,2 @@
+pub mod git;
 mod shared_helpers_tests;
diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs
index f5347c30824..8d53a83ea31 100644
--- a/src/build_helper/src/git.rs
+++ b/src/build_helper/src/git.rs
@@ -3,6 +3,7 @@ use std::process::{Command, Stdio};
 
 use crate::ci::CiEnv;
 
+#[derive(Debug)]
 pub struct GitConfig<'a> {
     pub git_repository: &'a str,
     pub nightly_branch: &'a str,
@@ -27,147 +28,234 @@ pub fn output_result(cmd: &mut Command) -> Result<String, String> {
     String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))
 }
 
-/// Finds the remote for rust-lang/rust.
-/// For example for these remotes it will return `upstream`.
-/// ```text
-/// origin  https://github.com/pietroalbani/rust.git (fetch)
-/// origin  https://github.com/pietroalbani/rust.git (push)
-/// upstream        https://github.com/rust-lang/rust (fetch)
-/// upstream        https://github.com/rust-lang/rust (push)
-/// ```
-pub fn get_rust_lang_rust_remote(
+/// Represents the result of checking whether a set of paths
+/// have been modified locally or not.
+#[derive(PartialEq, Debug, Clone)]
+pub enum PathFreshness {
+    /// Artifacts should be downloaded from this upstream commit,
+    /// there are no local modifications.
+    LastModifiedUpstream { upstream: String },
+    /// There are local modifications to a certain set of paths.
+    /// "Local" essentially means "not-upstream" here.
+    /// `upstream` is the latest upstream merge commit that made modifications to the
+    /// set of paths.
+    HasLocalModifications { upstream: String },
+    /// No upstream commit was found.
+    /// This should not happen in most reasonable circumstances, but one never knows.
+    MissingUpstream,
+}
+
+/// This function figures out if a set of paths was last modified upstream or
+/// if there are some local modifications made to them.
+/// It can be used to figure out if we should download artifacts from CI or rather
+/// build them locally.
+///
+/// The function assumes that at least a single upstream bors merge commit is in the
+/// local git history.
+///
+/// `target_paths` should be a non-empty slice of paths (git `pathspec`s) relative to `git_dir`
+/// whose modifications would invalidate the artifact.
+/// Each pathspec can also be a negative match, i.e. `:!foo`. This matches changes outside
+/// the `foo` directory.
+/// See <https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec>
+/// for how git `pathspec` works.
+///
+/// The function behaves differently in CI and outside CI.
+///
+/// - Outside CI, we want to find out if `target_paths` were modified in some local commit on
+/// top of the latest upstream commit that is available in local git history.
+/// If not, we try to find the most recent upstream commit (which we assume are commits
+/// made by bors) that modified `target_paths`.
+/// We don't want to simply take the latest master commit to avoid changing the output of
+/// this function frequently after rebasing on the latest master branch even if `target_paths`
+/// were not modified upstream in the meantime. In that case we would be redownloading CI
+/// artifacts unnecessarily.
+///
+/// - In CI, we use a shallow clone of depth 2, i.e., we fetch only a single parent commit
+/// (which will be the most recent bors merge commit) and do not have access
+/// to the full git history. Luckily, we only need to distinguish between two situations:
+/// 1) The current PR made modifications to `target_paths`.
+/// In that case, a build is typically necessary.
+/// 2) The current PR did not make modifications to `target_paths`.
+/// In that case we simply take the latest upstream commit, because on CI there is no need to avoid
+/// redownloading.
+pub fn check_path_modifications(
+    git_dir: &Path,
     config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<String, String> {
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
+    target_paths: &[&str],
+    ci_env: CiEnv,
+) -> Result<PathFreshness, String> {
+    assert!(!target_paths.is_empty());
+    for path in target_paths {
+        assert!(Path::new(path.trim_start_matches(":!")).is_relative());
     }
-    git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
-    let stdout = output_result(&mut git)?;
 
-    let rust_lang_remote = stdout
-        .lines()
-        .find(|remote| remote.contains(config.git_repository))
-        .ok_or_else(|| format!("{} remote not found", config.git_repository))?;
+    let upstream_sha = if matches!(ci_env, CiEnv::GitHubActions) {
+        // Here the situation is different for PR CI and try/auto CI.
+        // For PR CI, we have the following history:
+        // <merge commit made by GitHub>
+        // 1-N PR commits
+        // upstream merge commit made by bors
+        //
+        // For try/auto CI, we have the following history:
+        // <**non-upstream** merge commit made by bors>
+        // 1-N PR commits
+        // upstream merge commit made by bors
+        //
+        // But on both cases, HEAD should be a merge commit.
+        // So if HEAD contains modifications of `target_paths`, our PR has modified
+        // them. If not, we can use the only available upstream commit for downloading
+        // artifacts.
 
-    let remote_name =
-        rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?;
-    Ok(remote_name.into())
-}
+        // Do not include HEAD, as it is never an upstream commit
+        // If we do not find an upstream commit in CI, something is seriously wrong.
+        Some(
+            get_closest_upstream_commit(Some(git_dir), config, ci_env)?
+                .expect("No upstream commit was found on CI"),
+        )
+    } else {
+        // Outside CI, we want to find the most recent upstream commit that
+        // modified the set of paths, to have an upstream reference that does not change
+        // unnecessarily often.
+        // However, if such commit is not found, we can fall back to the latest upstream commit
+        let upstream_with_modifications =
+            get_latest_upstream_commit_that_modified_files(git_dir, config, target_paths)?;
+        match upstream_with_modifications {
+            Some(sha) => Some(sha),
+            None => get_closest_upstream_commit(Some(git_dir), config, ci_env)?,
+        }
+    };
 
-pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result<bool, String> {
-    let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
-    }
-    git.args(["rev-parse", rev]);
-    let output = git.output().map_err(|err| format!("{err:?}"))?;
-
-    match output.status.code() {
-        Some(0) => Ok(true),
-        Some(128) => Ok(false),
-        None => 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:?}"))?
-        )),
+    let Some(upstream_sha) = upstream_sha else {
+        return Ok(PathFreshness::MissingUpstream);
+    };
+
+    // For local environments, we want to find out if something has changed
+    // from the latest upstream commit.
+    // However, that should be equivalent to checking if something has changed
+    // from the latest upstream commit *that modified `target_paths`*, and
+    // with this approach we do not need to invoke git an additional time.
+    if has_changed_since(git_dir, &upstream_sha, target_paths) {
+        Ok(PathFreshness::HasLocalModifications { upstream: upstream_sha })
+    } else {
+        Ok(PathFreshness::LastModifiedUpstream { upstream: upstream_sha })
     }
 }
 
-/// Returns the master branch from which we can take diffs to see changes.
-/// This will usually be rust-lang/rust master, but sometimes this might not exist.
-/// This could be because the user is updating their forked master branch using the GitHub UI
-/// and therefore doesn't need an upstream master branch checked out.
-/// We will then fall back to origin/master in the hope that at least this exists.
-pub fn updated_master_branch(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<String, String> {
-    let upstream_remote = get_rust_lang_rust_remote(config, git_dir)?;
-    let branch = config.nightly_branch;
-    for upstream_master in [format!("{upstream_remote}/{branch}"), format!("origin/{branch}")] {
-        if rev_exists(&upstream_master, git_dir)? {
-            return Ok(upstream_master);
-        }
-    }
+/// Returns true if any of the passed `paths` have changed since the `base` commit.
+pub fn has_changed_since(git_dir: &Path, base: &str, paths: &[&str]) -> bool {
+    let mut git = Command::new("git");
+    git.current_dir(git_dir);
+
+    git.args(["diff-index", "--quiet", base, "--"]).args(paths);
 
-    Err("Cannot find any suitable upstream master branch".to_owned())
+    // Exit code 0 => no changes
+    // Exit code 1 => some changes were detected
+    !git.status().expect("cannot run git diff-index").success()
 }
 
-/// Finds the nearest merge commit by comparing the local `HEAD` with the upstream branch's state.
-/// To work correctly, the upstream remote must be properly configured using `git remote add <name> <url>`.
-/// In most cases `get_closest_merge_commit` is the function you are looking for as it doesn't require remote
-/// to be configured.
-fn git_upstream_merge_base(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<String, String> {
-    let updated_master = updated_master_branch(config, git_dir)?;
+/// Returns the latest upstream commit that modified `target_paths`, or `None` if no such commit
+/// was found.
+fn get_latest_upstream_commit_that_modified_files(
+    git_dir: &Path,
+    git_config: &GitConfig<'_>,
+    target_paths: &[&str],
+) -> Result<Option<String>, String> {
     let mut git = Command::new("git");
-    if let Some(git_dir) = git_dir {
-        git.current_dir(git_dir);
+    git.current_dir(git_dir);
+
+    // In theory, we could just use
+    // `git rev-list --first-parent HEAD --author=<merge-bot> -- <paths>`
+    // to find the latest upstream commit that modified `<paths>`.
+    // However, this does not work if you are in a subtree sync branch that contains merge commits
+    // which have the subtree history as their first parent, and the rustc history as second parent:
+    // `--first-parent` will just walk up the subtree history and never see a single rustc commit.
+    // We thus have to take a two-pronged approach. First lookup the most recent upstream commit
+    // by *date* (this should work even in a subtree sync branch), and then start the lookup for
+    // modified paths starting from that commit.
+    //
+    // See https://github.com/rust-lang/rust/pull/138591#discussion_r2037081858 for more details.
+    let upstream = get_closest_upstream_commit(Some(git_dir), git_config, CiEnv::None)?
+        .unwrap_or_else(|| "HEAD".to_string());
+
+    git.args([
+        "rev-list",
+        "--first-parent",
+        "-n1",
+        &upstream,
+        "--author",
+        git_config.git_merge_commit_email,
+    ]);
+
+    if !target_paths.is_empty() {
+        git.arg("--").args(target_paths);
     }
-    Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned())
+    let output = output_result(&mut git)?.trim().to_owned();
+    if output.is_empty() { Ok(None) } else { Ok(Some(output)) }
 }
 
-/// Searches for the nearest merge commit in the repository.
+/// Returns the most recent (ordered chronologically) commit found in the local history that
+/// should exist upstream. We identify upstream commits by the e-mail of the commit
+/// author.
 ///
-/// **In CI** finds the nearest merge commit that *also exists upstream*.
-///
-/// It looks for the most recent commit made by the merge bot by matching the author's email
-/// address with the merge bot's email.
-pub fn get_closest_merge_commit(
+/// If we are in CI, we simply return our first parent.
+fn get_closest_upstream_commit(
     git_dir: Option<&Path>,
     config: &GitConfig<'_>,
-    target_paths: &[&str],
-) -> Result<String, String> {
+    env: CiEnv,
+) -> Result<Option<String>, String> {
+    let base = match env {
+        CiEnv::None => "HEAD",
+        CiEnv::GitHubActions => {
+            // On CI, we should always have a non-upstream merge commit at the tip,
+            // and our first parent should be the most recently merged upstream commit.
+            // We thus simply return our first parent.
+            return resolve_commit_sha(git_dir, "HEAD^1").map(Some);
+        }
+    };
+
     let mut git = Command::new("git");
 
     if let Some(git_dir) = git_dir {
         git.current_dir(git_dir);
     }
 
-    let channel = include_str!("../../ci/channel").trim();
-
-    let merge_base = {
-        if CiEnv::is_ci() &&
-            // FIXME: When running on rust-lang managed CI and it's not a nightly build,
-            // `git_upstream_merge_base` fails with an error message similar to this:
-            // ```
-            //    called `Result::unwrap()` on an `Err` value: "command did not execute successfully:
-            //    cd \"/checkout\" && \"git\" \"merge-base\" \"origin/master\" \"HEAD\"\nexpected success, got: exit status: 1\n"
-            // ```
-            // Investigate and resolve this issue instead of skipping it like this.
-            (channel == "nightly" || !CiEnv::is_rust_lang_managed_ci_job())
-        {
-            git_upstream_merge_base(config, git_dir).unwrap()
-        } else {
-            // For non-CI environments, ignore rust-lang/rust upstream as it usually gets
-            // outdated very quickly.
-            "HEAD".to_string()
-        }
-    };
-
+    // We do not use `--first-parent`, because we can be in a situation (outside CI) where we have
+    // a subtree merge that actually has the main rustc history as its second parent.
+    // Using `--first-parent` would recurse into the history of the subtree, which could have some
+    // old bors commits that are not relevant to us.
+    // With `--author-date-order`, git recurses into all parent subtrees, and returns the most
+    // chronologically recent bors commit.
+    // Here we assume that none of our subtrees use bors anymore, and that all their old bors
+    // commits are way older than recent rustc bors commits!
     git.args([
         "rev-list",
+        "--author-date-order",
         &format!("--author={}", config.git_merge_commit_email),
         "-n1",
-        "--first-parent",
-        &merge_base,
+        &base,
     ]);
 
-    if !target_paths.is_empty() {
-        git.arg("--").args(target_paths);
+    let output = output_result(&mut git)?.trim().to_owned();
+    if output.is_empty() { Ok(None) } else { Ok(Some(output)) }
+}
+
+/// Resolve the commit SHA of `commit_ref`.
+fn resolve_commit_sha(git_dir: Option<&Path>, commit_ref: &str) -> Result<String, String> {
+    let mut git = Command::new("git");
+
+    if let Some(git_dir) = git_dir {
+        git.current_dir(git_dir);
     }
 
+    git.args(["rev-parse", commit_ref]);
+
     Ok(output_result(&mut git)?.trim().to_owned())
 }
 
-/// Returns the files that have been modified in the current branch compared to the last merge.
+/// Returns the files that have been modified in the current branch compared to the master branch.
+/// This includes committed changes, uncommitted changes, and changes that are not even staged.
+///
 /// The `extensions` parameter can be used to filter the files by their extension.
 /// Does not include removed files.
 /// If `extensions` is empty, all files will be returned.
@@ -176,7 +264,9 @@ pub fn get_git_modified_files(
     git_dir: Option<&Path>,
     extensions: &[&str],
 ) -> Result<Vec<String>, String> {
-    let merge_base = get_closest_merge_commit(git_dir, config, &[])?;
+    let Some(merge_base) = get_closest_upstream_commit(git_dir, config, CiEnv::None)? else {
+        return Err("No upstream commit was found".to_string());
+    };
 
     let mut git = Command::new("git");
     if let Some(git_dir) = git_dir {
@@ -204,13 +294,7 @@ pub fn get_git_modified_files(
 }
 
 /// Returns the files that haven't been added to git yet.
-pub fn get_git_untracked_files(
-    config: &GitConfig<'_>,
-    git_dir: Option<&Path>,
-) -> Result<Option<Vec<String>>, String> {
-    let Ok(_updated_master) = updated_master_branch(config, git_dir) else {
-        return Ok(None);
-    };
+pub fn get_git_untracked_files(git_dir: Option<&Path>) -> Result<Option<Vec<String>>, String> {
     let mut git = Command::new("git");
     if let Some(git_dir) = git_dir {
         git.current_dir(git_dir);
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
index be235f648b5..c09be047c6a 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
@@ -59,11 +59,10 @@ COPY scripts/shared.sh /scripts/
 
 ARG SCRIPT_ARG
 
-COPY scripts/add_dummy_commit.sh /tmp/
 COPY scripts/x86_64-gnu-llvm.sh /tmp/
 COPY scripts/x86_64-gnu-llvm2.sh /tmp/
 COPY scripts/x86_64-gnu-llvm3.sh /tmp/
 COPY scripts/stage_2_test_set1.sh /tmp/
 COPY scripts/stage_2_test_set2.sh /tmp/
 
-ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}"
+ENV SCRIPT "/tmp/${SCRIPT_ARG}"
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile
index 408b87125e0..83a3bfb37a5 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile
@@ -59,11 +59,10 @@ COPY scripts/shared.sh /scripts/
 
 ARG SCRIPT_ARG
 
-COPY scripts/add_dummy_commit.sh /tmp/
 COPY scripts/x86_64-gnu-llvm.sh /tmp/
 COPY scripts/x86_64-gnu-llvm2.sh /tmp/
 COPY scripts/x86_64-gnu-llvm3.sh /tmp/
 COPY scripts/stage_2_test_set1.sh /tmp/
 COPY scripts/stage_2_test_set2.sh /tmp/
 
-ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}"
+ENV SCRIPT "/tmp/${SCRIPT_ARG}"
diff --git a/src/ci/docker/scripts/add_dummy_commit.sh b/src/ci/docker/scripts/add_dummy_commit.sh
deleted file mode 100755
index 029e4ae141f..00000000000
--- a/src/ci/docker/scripts/add_dummy_commit.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-if [ "$READ_ONLY_SRC" = "0" ]; then
-    # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test ensures that
-    # "download-rustc=if-unchanged" logic don't use CI rustc while there are changes on
-    # compiler and/or library. Here we are adding a dummy commit on compiler and running
-    # that test to make sure we never download CI rustc with a change on the compiler tree.
-    echo "" >> ../compiler/rustc/src/main.rs
-    git config --global user.email "dummy@dummy.com"
-    git config --global user.name "dummy"
-    git add ../compiler/rustc/src/main.rs
-    git commit -m "test commit for rust.download-rustc=if-unchanged logic"
-    DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 ../x.py test bootstrap \
-        -- core::builder::tests::ci_rustc_if_unchanged_logic
-    # Revert the dummy commit
-    git reset --hard HEAD~1
-fi
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm3.sh b/src/ci/docker/scripts/x86_64-gnu-llvm3.sh
index d1bf2dab1e2..17eb2cea59a 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm3.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm3.sh
@@ -2,8 +2,6 @@
 
 set -ex
 
-/tmp/add_dummy_commit.sh
-
 ##### Test stage 1 #####
 
 ../x.py --stage 1 test --skip src/tools/tidy
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index cb2bec5a9df..950a75721c4 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -108,8 +108,6 @@ pr:
   - name: x86_64-gnu-llvm-19
     env:
       ENABLE_GCC_CODEGEN: "1"
-      # We are adding (temporarily) a dummy commit on the compiler
-      READ_ONLY_SRC: "0"
       DOCKER_SCRIPT: x86_64-gnu-llvm.sh
     <<: *job-linux-16c
   - name: x86_64-gnu-tools
diff --git a/src/ci/scripts/setup-upstream-remote.sh b/src/ci/scripts/setup-upstream-remote.sh
deleted file mode 100755
index 52b4c98a890..00000000000
--- a/src/ci/scripts/setup-upstream-remote.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-# In CI environments, bootstrap is forced to use the remote upstream based
-# on "git_repository" and "nightly_branch" values from src/stage0 file.
-# This script configures the remote as it may not exist by default.
-
-set -euo pipefail
-IFS=$'\n\t'
-
-ci_dir=$(cd $(dirname $0) && pwd)/..
-source "$ci_dir/shared.sh"
-
-git_repository=$(parse_stage0_file_by_key "git_repository")
-nightly_branch=$(parse_stage0_file_by_key "nightly_branch")
-
-# Configure "rust-lang/rust" upstream remote only when it's not origin.
-if [ -z "$(git config remote.origin.url | grep $git_repository)" ]; then
-    echo "Configuring https://github.com/$git_repository remote as upstream."
-    git remote add upstream "https://github.com/$git_repository"
-    REMOTE_NAME="upstream"
-else
-    REMOTE_NAME="origin"
-fi
-
-git fetch $REMOTE_NAME $nightly_branch
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 0c10c30cc54736c5c194ce98c50e2de84eeb6e7
+Subproject c76a20f0d987145dcedf05c5c073ce8d91f2e82
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 3340922df189bddcbaad17dc3927d51a76bcd5e
+Subproject 3bf3402aea982b876eb56c87da17b0685c6461d
diff --git a/src/doc/rustc-dev-guide/src/tests/minicore.md b/src/doc/rustc-dev-guide/src/tests/minicore.md
index e4853b6d40e..507b259e027 100644
--- a/src/doc/rustc-dev-guide/src/tests/minicore.md
+++ b/src/doc/rustc-dev-guide/src/tests/minicore.md
@@ -6,25 +6,37 @@
 ui/codegen/assembly test suites. It provides `core` stubs for tests that need to
 build for cross-compiled targets but do not need/want to run.
 
+<div class="warning">
+Please note that [`minicore`] is only intended for `core` items, and explicitly
+**not** `std` or `alloc` items because `core` items are applicable to a wider
+range of tests.
+</div>
+
 A test can use [`minicore`] by specifying the `//@ add-core-stubs` directive.
 Then, mark the test with `#![feature(no_core)]` + `#![no_std]` + `#![no_core]`.
 Due to Edition 2015 extern prelude rules, you will probably need to declare
 `minicore` as an extern crate.
 
+## Implied compiler flags
+
 Due to the `no_std` + `no_core` nature of these tests, `//@ add-core-stubs`
 implies and requires that the test will be built with `-C panic=abort`.
-Unwinding panics are not supported.
+**Unwinding panics are not supported.**
+
+Tests will also be built with `-C force-unwind-tables=yes` to preserve CFI
+directives in assembly tests.
+
+TL;DR: `//@ add-core-stubs` implies two compiler flags:
+
+1. `-C panic=abort`
+2. `-C force-unwind-tables=yes`
+
+## Adding more `core` stubs
 
 If you find a `core` item to be missing from the [`minicore`] stub, consider
 adding it to the test auxiliary if it's likely to be used or is already needed
 by more than one test.
 
-<div class="warning">
-Please note that [`minicore`] is only intended for `core` items, and explicitly
-**not** `std` or `alloc` items because `core` items are applicable to a wider
-range of tests.
-</div>
-
 ## Example codegen test that uses `minicore`
 
 ```rust,no_run
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 9870e5011eb..50c7ae3ef8d 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -34,7 +34,7 @@ target | notes
 -------|-------
 [`aarch64-apple-darwin`](platform-support/apple-darwin.md) | ARM64 macOS (11.0+, Big Sur+)
 `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+)
-`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
 `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+, Pentium 4) [^x86_32-floats-return-ABI]
 [`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+)
 [`x86_64-pc-windows-gnu`](platform-support/windows-gnu.md) | 64-bit MinGW (Windows 10+, Windows Server 2016+)
@@ -43,6 +43,8 @@ target | notes
 
 [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. Functions with the default Rust ABI are not affected. See [issue #115567][x86-32-float-return-issue].
 
+[^win32-msvc-alignment]: Due to non-standard behavior of MSVC, native C code on this target can cause types with an alignment of more than 4 bytes to be incorrectly aligned to only 4 bytes (this affects, e.g., `u64` and `i64`). Rust applies some mitigations to reduce the impact of this issue, but this can still cause unsoundness due to unsafe code that (correctly) assumes that references are always properly aligned. See [issue #112480](https://github.com/rust-lang/rust/issues/112480).
+
 [77071]: https://github.com/rust-lang/rust/issues/77071
 [x86-32-float-return-issue]: https://github.com/rust-lang/rust/issues/115567
 
@@ -95,7 +97,7 @@ target | notes
 [`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | Armv7-A OpenHarmony
 [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)
 [`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5)
-[`i686-pc-windows-gnu`](platform-support/windows-gnu.md) | 32-bit MinGW (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI]
+[`i686-pc-windows-gnu`](platform-support/windows-gnu.md) | 32-bit MinGW (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
 `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17)
 `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17)
 [`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10, glibc 2.17)
@@ -169,7 +171,7 @@ target | std | notes
 [`i686-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+, Pentium 4), LLVM ABI [^x86_32-floats-return-ABI]
 [`i686-unknown-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI]
 `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI]
-[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI (Pentium 4, softfloat)
+[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI (Pentium 4, softfloat) [^win32-msvc-alignment]
 [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI)
 [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI)
 [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
@@ -317,9 +319,9 @@ target | std | host | notes
 [`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 (Pentium 4) [^x86_32-floats-return-ABI]
 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD (Pentium 4) [^x86_32-floats-return-ABI]
 `i686-uwp-windows-gnu` | ✓ |  | [^x86_32-floats-return-ABI]
-[`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  | [^x86_32-floats-return-ABI]
+[`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  | [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
 [`i686-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ |   | 32-bit Windows 7 support [^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-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
 [`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |   | LoongArch64 OpenHarmony
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
diff --git a/src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md b/src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md
index 60aaa371bbc..e98aa996a6e 100644
--- a/src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md
+++ b/src/doc/rustc/src/platform-support/x86_64-pc-cygwin.md
@@ -20,8 +20,9 @@ The `target_os` of the target is `cygwin`, and it is `unix`.
 
 ## Building the target
 
-For cross-compilation you want LLVM with [llvm/llvm-project#121439 (merged)](https://github.com/llvm/llvm-project/pull/121439) applied to fix the LLVM codegen on importing external global variables from DLLs.
-No native builds on Cygwin now. It should be possible theoretically though, but might need a lot of patches.
+For cross-compilation you want LLVM at least 20.1.0-rc1.
+No native builds on Cygwin now.
+The tracking issue for host tools on Cygwin is [#137819](https://github.com/rust-lang/rust/issues/137819).
 
 ## Building Rust programs
 
diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md
index d0102a665b0..d0a64538e8c 100644
--- a/src/doc/unstable-book/src/language-features/deref-patterns.md
+++ b/src/doc/unstable-book/src/language-features/deref-patterns.md
@@ -54,4 +54,25 @@ if let [b] = &mut *v {
 assert_eq!(v, [Box::new(Some(2))]);
 ```
 
+Additionally, when `deref_patterns` is enabled, string literal patterns may be written where `str`
+is expected. Likewise, byte string literal patterns may be written where `[u8]` or `[u8; _]` is
+expected. This lets them be used in `deref!(_)` patterns:
+
+```rust
+# #![feature(deref_patterns)]
+# #![allow(incomplete_features)]
+match ("test".to_string(), b"test".to_vec()) {
+    (deref!("test"), deref!(b"test")) => {}
+    _ => panic!(),
+}
+
+// Matching on slices and arrays using literals is possible elsewhere as well:
+match *"test" {
+    "test" => {}
+    _ => panic!(),
+}
+```
+
+Implicit deref pattern syntax is not yet supported for string or byte string literals.
+
 [smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors
diff --git a/src/tools/clippy/.github/workflows/clippy_changelog.yml b/src/tools/clippy/.github/workflows/clippy_changelog.yml
index a2657bfea49..1e97154bf8a 100644
--- a/src/tools/clippy/.github/workflows/clippy_changelog.yml
+++ b/src/tools/clippy/.github/workflows/clippy_changelog.yml
@@ -24,7 +24,7 @@ jobs:
     - name: Check Changelog
       if: ${{ github.event_name == 'pull_request' }}
       run: |
-        body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR_NUMBER" | \
+        body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" | \
           python -c "import sys, json; print(json.load(sys.stdin)['body'])")
         output=$(awk '/^changelog:\s*\S/ && !/changelog: \[.*\]: your change/' <<< "$body" | sed "s/changelog:\s*//g")
         if [ -z "$output" ]; then
diff --git a/src/tools/clippy/.github/workflows/clippy_mq.yml b/src/tools/clippy/.github/workflows/clippy_mq.yml
index 741e7457331..07d5a08304e 100644
--- a/src/tools/clippy/.github/workflows/clippy_mq.yml
+++ b/src/tools/clippy/.github/workflows/clippy_mq.yml
@@ -66,7 +66,7 @@ jobs:
       run: cargo test --features internal -- --skip dogfood
 
     - name: Test clippy_lints
-      run: cargo test --features internal
+      run: cargo test
       working-directory: clippy_lints
 
     - name: Test clippy_utils
diff --git a/src/tools/clippy/.github/workflows/clippy_pr.yml b/src/tools/clippy/.github/workflows/clippy_pr.yml
index 80523d91f4f..880ebd6e5d5 100644
--- a/src/tools/clippy/.github/workflows/clippy_pr.yml
+++ b/src/tools/clippy/.github/workflows/clippy_pr.yml
@@ -42,7 +42,7 @@ jobs:
       run: cargo test --features internal
 
     - name: Test clippy_lints
-      run: cargo test --features internal
+      run: cargo test
       working-directory: clippy_lints
 
     - name: Test clippy_utils
diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml
index b42f3e7712f..ede19c11257 100644
--- a/src/tools/clippy/.github/workflows/deploy.yml
+++ b/src/tools/clippy/.github/workflows/deploy.yml
@@ -8,6 +8,10 @@ on:
     tags:
       - rust-1.**
 
+concurrency:
+  group: ${{ github.workflow }}
+  cancel-in-progress: false
+
 env:
   TARGET_BRANCH: 'gh-pages'
   SHA: '${{ github.sha }}'
diff --git a/src/tools/clippy/.github/workflows/lintcheck.yml b/src/tools/clippy/.github/workflows/lintcheck.yml
index d487c7d9498..70c805903d3 100644
--- a/src/tools/clippy/.github/workflows/lintcheck.yml
+++ b/src/tools/clippy/.github/workflows/lintcheck.yml
@@ -66,7 +66,7 @@ jobs:
 
     - name: Run lintcheck
       if: steps.cache-json.outputs.cache-hit != 'true'
-      run: ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml
+      run: env CLIPPY_CONF_DIR="$PWD/lintcheck/ci-config" ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml
 
     - name: Upload base JSON
       uses: actions/upload-artifact@v4
@@ -97,7 +97,7 @@ jobs:
       run: cargo build --manifest-path=lintcheck/Cargo.toml
 
     - name: Run lintcheck
-      run: ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml
+      run: env CLIPPY_CONF_DIR="$PWD/lintcheck/ci-config" ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml
 
     - name: Upload head JSON
       uses: actions/upload-artifact@v4
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 1bf4b51ff0f..2b62c9a59aa 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,68 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[609cd310...master](https://github.com/rust-lang/rust-clippy/compare/609cd310...master)
+[3e3715c3...master](https://github.com/rust-lang/rust-clippy/compare/3e3715c3...master)
+
+## Rust 1.86
+
+Current stable, released 2025-04-03
+
+[View all 108 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-12-27T15%3A11%3A38Z..2025-02-06T13%3A57%3A58Z+base%3Amaster)
+
+### New Lints
+
+* Added [`unneeded_struct_pattern`] to `style` [#13465](https://github.com/rust-lang/rust-clippy/pull/13465)
+* Added [`doc_overindented_list_items`] to `style` [#13711](https://github.com/rust-lang/rust-clippy/pull/13711)
+* Added [`manual_ok_err`] to `complexity` [#13740](https://github.com/rust-lang/rust-clippy/pull/13740)
+* Added [`non_std_lazy_statics`] to `pedantic` [#13770](https://github.com/rust-lang/rust-clippy/pull/13770)
+* Added [`manual_repeat_n`] to `style` [#13858](https://github.com/rust-lang/rust-clippy/pull/13858)
+* Added [`manual_option_as_slice`] to `complexity` [#13901](https://github.com/rust-lang/rust-clippy/pull/13901)
+* Added [`double_ended_iterator_last`] to `perf` [#13922](https://github.com/rust-lang/rust-clippy/pull/13922)
+* Added [`useless_nonzero_new_unchecked`] to `complexity` [#13993](https://github.com/rust-lang/rust-clippy/pull/13993)
+* Added [`sliced_string_as_bytes`] to `perf` [#14002](https://github.com/rust-lang/rust-clippy/pull/14002)
+* Added [`unnecessary_semicolon`] to `pedantic` [#14032](https://github.com/rust-lang/rust-clippy/pull/14032)
+* Added [`return_and_then`] to `restriction` [#14051](https://github.com/rust-lang/rust-clippy/pull/14051)
+* Added [`manual_slice_fill`] to `style` [#14082](https://github.com/rust-lang/rust-clippy/pull/14082)
+* Added [`precedence_bits`] to `restriction` [#14115](https://github.com/rust-lang/rust-clippy/pull/14115)
+
+### Moves and Deprecations
+
+* Moved [`redundant_locals`] to `suspicious` (from `correctness`, now warn-by-default)
+  [#13747](https://github.com/rust-lang/rust-clippy/pull/13747)
+* Moved [`format_push_string`] to `pedantic` (from `restriction`)
+  [#13894](https://github.com/rust-lang/rust-clippy/pull/13894)
+* Moved [`format_collect`] to `pedantic` (from `perf`, now allow-by-default)
+  [#13894](https://github.com/rust-lang/rust-clippy/pull/13894)
+* Moved [`mutex_integer`] to `restriction` (from `nursery`) [#14110](https://github.com/rust-lang/rust-clippy/pull/14110)
+
+### Enhancements
+
+* Add `lint-inconsistent-struct-field-initializers` configuration option to [`inconsistent_struct_constructor`]
+  [#13737](https://github.com/rust-lang/rust-clippy/pull/13737)
+* [`len_zero`] now also triggers if deref target implements `is_empty()`
+  [#13871](https://github.com/rust-lang/rust-clippy/pull/13871)
+* [`obfuscated_if_else`] now also triggers for the `.then(..).unwrap_or(..)` pattern
+  [#14021](https://github.com/rust-lang/rust-clippy/pull/14021)
+
+### False Positive Fixes
+
+* [`trailing_empty_array`] no longer triggers in tests [#13844](https://github.com/rust-lang/rust-clippy/pull/13844)
+* [`missing_const_for_fn`] no longer triggers in tests [#13945](https://github.com/rust-lang/rust-clippy/pull/13945)
+* [`significant_drop_in_scrutinee`]: do not falsely warn for temporaries created by `.await` expansion
+  [#13985](https://github.com/rust-lang/rust-clippy/pull/13985)
+
+### ICE Fixes
+
+* [`borrow_interior_mutable_const`] Fix an ICE that can occur when taking a reference to a tuple/`struct` field of an
+  interior mutable `const` [#13877](https://github.com/rust-lang/rust-clippy/pull/13877)
+
+### Others
+
+* Clippy now uses Rust edition 2024 [#13751](https://github.com/rust-lang/rust-clippy/pull/13751)
 
 ## Rust 1.85
 
-Current stable, released 2025-02-20
+Released 2025-02-20
 
 [View all 72 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-11-15T19%3A31%3A08Z..2024-12-26T13%3A59%3A48Z+base%3Amaster)
 
@@ -5516,6 +5573,7 @@ Released 2018-09-13
 [`cast_slice_different_sizes`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_different_sizes
 [`cast_slice_from_raw_parts`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_from_raw_parts
 [`cfg_not_test`]: https://rust-lang.github.io/rust-clippy/master/index.html#cfg_not_test
+[`char_indices_as_byte_indices`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_indices_as_byte_indices
 [`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8
 [`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp
 [`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp
@@ -5681,6 +5739,7 @@ Released 2018-09-13
 [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
 [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
+[`ignore_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignore_without_reason
 [`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns
 [`impl_hash_borrow_with_str_and_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_hash_borrow_with_str_and_bytes
 [`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
@@ -5783,12 +5842,14 @@ Released 2018-09-13
 [`macro_metavars_in_unsafe`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe
 [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
 [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
+[`manual_abs_diff`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_abs_diff
 [`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
 [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
 [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits
 [`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals
 [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp
 [`manual_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_contains
+[`manual_dangling_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_dangling_ptr
 [`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil
 [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter
 [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
@@ -6055,6 +6116,7 @@ Released 2018-09-13
 [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
 [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
 [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
+[`redundant_test_prefix`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_test_prefix
 [`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations
 [`ref_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_as_ptr
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
@@ -6156,6 +6218,7 @@ Released 2018-09-13
 [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
 [`suspicious_xor_used_as_pow`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_xor_used_as_pow
 [`swap_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#swap_ptr_to_ref
+[`swap_with_temporary`]: https://rust-lang.github.io/rust-clippy/master/index.html#swap_with_temporary
 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
 [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr
@@ -6346,6 +6409,7 @@ Released 2018-09-13
 [`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types
 [`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish
 [`check-incompatible-msrv-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-incompatible-msrv-in-tests
+[`check-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-inconsistent-struct-field-initializers
 [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items
 [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold
 [`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros
@@ -6362,7 +6426,7 @@ Released 2018-09-13
 [`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
 [`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
 [`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
-[`lint-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inconsistent-struct-field-initializers
+[`lint-commented-code`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-commented-code
 [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
 [`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
 [`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index f5a8e3dc387..1cfc1c196c0 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy"
 # begin autogenerated version
-version = "0.1.87"
+version = "0.1.88"
 # end autogenerated version
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
@@ -27,6 +27,7 @@ clippy_config = { path = "clippy_config" }
 clippy_lints = { path = "clippy_lints" }
 clippy_utils = { path = "clippy_utils" }
 rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }
+clippy_lints_internal = { path = "clippy_lints_internal", optional = true }
 tempfile = { version = "3.3", optional = true }
 termize = "0.1"
 color-print = "0.3.4"
@@ -43,7 +44,7 @@ walkdir = "2.3"
 filetime = "0.2.9"
 itertools = "0.12"
 pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] }
-rinja = { version = "0.3", default-features = false, features = ["config"] }
+askama = { version = "0.13", default-features = false, features = ["alloc", "config", "derive"] }
 
 # UI test dependencies
 clippy_utils = { path = "clippy_utils" }
@@ -58,8 +59,8 @@ tokio = { version = "1", features = ["io-util"] }
 rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }
 
 [features]
-integration = ["tempfile"]
-internal = ["clippy_lints/internal", "tempfile"]
+integration = ["dep:tempfile"]
+internal = ["dep:clippy_lints_internal", "dep:tempfile"]
 
 [package.metadata.rust-analyzer]
 # This package uses #[feature(rustc_private)]
diff --git a/src/tools/clippy/rinja.toml b/src/tools/clippy/askama.toml
index a10da6e1f28..a10da6e1f28 100644
--- a/src/tools/clippy/rinja.toml
+++ b/src/tools/clippy/askama.toml
diff --git a/src/tools/clippy/book/src/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md
index 19328fdd3cd..39fe7358ed8 100644
--- a/src/tools/clippy/book/src/SUMMARY.md
+++ b/src/tools/clippy/book/src/SUMMARY.md
@@ -30,6 +30,7 @@
         - [Updating the Changelog](development/infrastructure/changelog_update.md)
         - [Release a New Version](development/infrastructure/release.md)
         - [The Clippy Book](development/infrastructure/book.md)
+        - [Benchmarking Clippy](development/infrastructure/benchmarking.md)
     - [Proposals](development/proposals/README.md)
         - [Roadmap 2021](development/proposals/roadmap-2021.md)
         - [Syntax Tree Patterns](development/proposals/syntax-tree-patterns.md)
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index 0b9010f0107..e5e82ede4fd 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -99,6 +99,7 @@ struct A;
 impl A {
     pub fn fo(&self) {}
     pub fn foo(&self) {}
+    //~^ foo_functions
     pub fn food(&self) {}
 }
 
@@ -106,12 +107,14 @@ impl A {
 trait B {
     fn fo(&self) {}
     fn foo(&self) {}
+    //~^ foo_functions
     fn food(&self) {}
 }
 
 // Plain functions
 fn fo() {}
 fn foo() {}
+//~^ foo_functions
 fn food() {}
 
 fn main() {
@@ -122,17 +125,24 @@ fn main() {
 }
 ```
 
-Now we can run the test with `TESTNAME=foo_functions cargo uibless`, currently
-this test is meaningless though.
+Note that we are adding comment annotations with the name of our lint to mark
+lines where we expect an error. Except for very specific situations
+(`//@check-pass`), at least one error marker must be present in a test file for
+it to be accepted.
+
+Once we have implemented our lint we can run `TESTNAME=foo_functions cargo
+uibless` to generate the `.stderr` file. If our lint makes use of structured
+suggestions then this command will also generate the corresponding `.fixed`
+file.
 
 While we are working on implementing our lint, we can keep running the UI test.
 That allows us to check if the output is turning into what we want by checking the
 `.stderr` file that gets updated on every test run.
 
-Running `TESTNAME=foo_functions cargo uitest` should pass on its own. When we
-commit our lint, we need to commit the generated `.stderr` files, too. In
-general, you should only commit files changed by `cargo bless` for the
-specific lint you are creating/editing.
+Once we have implemented our lint running `TESTNAME=foo_functions cargo uitest`
+should pass on its own. When we commit our lint, we need to commit the generated
+ `.stderr` and if applicable `.fixed` files, too. In general, you should only
+ commit files changed by `cargo bless` for the specific lint you are creating/editing.
 
 > _Note:_ you can run multiple test files by specifying a comma separated list:
 > `TESTNAME=foo_functions,test2,test3`.
diff --git a/src/tools/clippy/book/src/development/basics.md b/src/tools/clippy/book/src/development/basics.md
index 931e5c3a294..4219724ed5d 100644
--- a/src/tools/clippy/book/src/development/basics.md
+++ b/src/tools/clippy/book/src/development/basics.md
@@ -147,7 +147,7 @@ following:
 
 First, take note of the toolchain
 [override](https://rust-lang.github.io/rustup/overrides.html) in
-`/rust-toolchain`. We will use this override to install Clippy into the right
+`/rust-toolchain.toml`. We will use this override to install Clippy into the right
 toolchain.
 
 > Tip: You can view the active toolchain for the current directory with `rustup
diff --git a/src/tools/clippy/book/src/development/common_tools_writing_lints.md b/src/tools/clippy/book/src/development/common_tools_writing_lints.md
index 051febc2ca5..2e39f279eae 100644
--- a/src/tools/clippy/book/src/development/common_tools_writing_lints.md
+++ b/src/tools/clippy/book/src/development/common_tools_writing_lints.md
@@ -159,19 +159,21 @@ paths for Clippy can be found in [paths.rs][paths]
 To check if our type defines a method called `some_method`:
 
 ```rust
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::return_ty;
+use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{sym, return_ty};
 
 impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
         // Check if item is a method/function
         if let ImplItemKind::Fn(ref signature, _) = impl_item.kind
             // Check the method is named `some_method`
-            && impl_item.ident.name.as_str() == "some_method"
+            //
+            // Add `some_method` to `clippy_utils::sym` if it's not already there
+            && impl_item.ident.name == sym::some_method
             // We can also check it has a parameter `self`
             && signature.decl.implicit_self.has_implicit_self()
             // We can go further and even check if its return type is `String`
-            && is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type))
+            && is_type_lang_item(cx, return_ty(cx, impl_item.hir_id), LangItem::String)
         {
             // ...
         }
diff --git a/src/tools/clippy/book/src/development/defining_lints.md b/src/tools/clippy/book/src/development/defining_lints.md
index 169cecd7d11..cb6d7b740db 100644
--- a/src/tools/clippy/book/src/development/defining_lints.md
+++ b/src/tools/clippy/book/src/development/defining_lints.md
@@ -9,7 +9,7 @@ lint involves some boilerplate code.
 
 A lint type is the category of items and expressions in which your lint focuses on.
 
-As of the writing of this documentation update, there are 12 _types_ of lints
+As of the writing of this documentation update, there are 11 _types_ of lints
 besides the numerous standalone lints living under `clippy_lints/src/`:
 
 - `cargo`
@@ -23,7 +23,6 @@ besides the numerous standalone lints living under `clippy_lints/src/`:
 - `transmute`
 - `types`
 - `unit_types`
-- `utils / internal` (Clippy internal lints)
 
 These types group together lints that share some common behaviors. For instance,
 `functions` groups together lints that deal with some aspects of functions in
diff --git a/src/tools/clippy/book/src/development/infrastructure/benchmarking.md b/src/tools/clippy/book/src/development/infrastructure/benchmarking.md
new file mode 100644
index 00000000000..a3ebce922f6
--- /dev/null
+++ b/src/tools/clippy/book/src/development/infrastructure/benchmarking.md
@@ -0,0 +1,55 @@
+# Benchmarking Clippy
+
+Benchmarking Clippy is similar to using our Lintcheck tool, in fact, it even
+uses the same tool! Just by adding a `--perf` flag it will transform Lintcheck
+into a very simple but powerful benchmarking tool!
+
+It requires having the [`perf` tool][perf] installed, as `perf` is what's actually
+profiling Clippy under the hood.
+
+The lintcheck `--perf` tool generates a series of `perf.data` in the
+`target/lintcheck/sources/<package>-<version>` directories. Each `perf.data`
+corresponds to the package which is contained.
+
+Lintcheck uses the `-g` flag, meaning that you can get stack traces for richer
+analysis, including with tools such as [flamegraph][flamegraph-perf]
+(or [`flamegraph-rs`][flamegraph-rs]).
+
+Currently, we only measure instruction count, as it's the most reproducible metric
+and [rustc-perf][rustc-perf] also considers it the main number to focus on.
+
+## Benchmarking a PR
+
+Having a benchmarking tool directly implemented into lintcheck gives us the
+ability to benchmark any given PR just by making a before and after 
+
+Here's the way you can get into any PR, benchmark it, and then benchmark
+`master`.
+
+The first `perf.data` will not have any numbers appended, but any subsequent
+benchmark will be written to `perf.data.number` with a number growing for 0.
+All benchmarks are compressed so that you can
+
+```bash
+git fetch upstream pull/<PR_NUMBER>/head:<BRANCH_NAME>
+git switch BRANCHNAME
+
+# Bench
+cargo lintcheck --perf
+
+# Get last common commit, checkout that
+LAST_COMMIT=$(git log BRANCHNAME..master --oneline | tail -1 | cut -c 1-11)
+git switch -c temporary $LAST_COMMIT
+
+# We're now on master
+
+# Bench
+cargo lintcheck --perf
+perf diff ./target/lintcheck/sources/CRATE/perf.data ./target/lintcheck/sources/CRATE/perf.data.0
+```
+
+
+[perf]: https://perfwiki.github.io/main/
+[flamegraph-perf]: https://github.com/brendangregg/FlameGraph
+[flamegraph-rs]: https://github.com/flamegraph-rs/flamegraph
+[rustc-perf]: https://github.com/rust-lang/rustc-perf
diff --git a/src/tools/clippy/book/src/development/infrastructure/release.md b/src/tools/clippy/book/src/development/infrastructure/release.md
index 8b080c099b8..a429e0d953c 100644
--- a/src/tools/clippy/book/src/development/infrastructure/release.md
+++ b/src/tools/clippy/book/src/development/infrastructure/release.md
@@ -88,9 +88,6 @@ git push upstream stable
 After updating the `stable` branch, tag the HEAD commit and push it to the
 Clippy repo.
 
-> Note: Only push the tag once the Deploy GitHub action of the `beta` branch is
-> finished. Otherwise the deploy for the tag might fail.
-
 ```bash
 git tag rust-1.XX.0               # XX should be exchanged with the corresponding version
 git push upstream rust-1.XX.0     # `upstream` is the `rust-lang/rust-clippy` remote
diff --git a/src/tools/clippy/book/src/development/infrastructure/sync.md b/src/tools/clippy/book/src/development/infrastructure/sync.md
index da1ad586607..2bbdf47a835 100644
--- a/src/tools/clippy/book/src/development/infrastructure/sync.md
+++ b/src/tools/clippy/book/src/development/infrastructure/sync.md
@@ -86,7 +86,7 @@ to be run inside the `rust` directory):
 4. Bump the nightly version in the Clippy repository by running these commands:
    ```bash
    cargo dev sync update_nightly
-   git commit -m "Bump nightly version -> YYYY-MM-DD" rust-toolchain clippy_utils/README.md
+   git commit -m "Bump nightly version -> YYYY-MM-DD" rust-toolchain.toml clippy_utils/README.md
    ```
 5. Open a PR to `rust-lang/rust-clippy` and wait for it to get merged (to
    accelerate the process ping the `@rust-lang/clippy` team in your PR and/or
diff --git a/src/tools/clippy/book/src/development/writing_tests.md b/src/tools/clippy/book/src/development/writing_tests.md
index d4cca2a72f0..1da54322fcf 100644
--- a/src/tools/clippy/book/src/development/writing_tests.md
+++ b/src/tools/clippy/book/src/development/writing_tests.md
@@ -41,20 +41,23 @@ Update the file with some examples to get started:
 struct A;
 impl A {
     pub fn fo(&self) {}
-    pub fn foo(&self) {} //~ ERROR: function called "foo"
+    pub fn foo(&self) {}
+    //~^ foo_functions
     pub fn food(&self) {}
 }
 
 // Default trait methods
 trait B {
     fn fo(&self) {}
-    fn foo(&self) {} //~ ERROR: function called "foo"
+    fn foo(&self) {}
+    //~^ foo_functions
     fn food(&self) {}
 }
 
 // Plain functions
 fn fo() {}
-fn foo() {} //~ ERROR: function called "foo"
+fn foo() {}
+//~^ foo_functions
 fn food() {}
 
 fn main() {
@@ -66,19 +69,38 @@ fn main() {
 ```
 
 Without actual lint logic to emit the lint when we see a `foo` function name,
-this test will just pass, because no lint will be emitted. However, we can now
-run the test with the following command:
+this test will fail, because we expect errors at lines marked with
+`//~^ foo_functions`. However, we can now run the test with the following command:
 
 ```sh
 $ TESTNAME=foo_functions cargo uitest
 ```
 
-Clippy will compile and it will conclude with an `ok` for the tests:
+Clippy will compile and it will fail complaining it didn't receive any errors:
 
 ```
 ...Clippy warnings and test outputs...
-test compile_test ... ok
-test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.48s
+error: diagnostic code `clippy::foo_functions` not found on line 8
+ --> tests/ui/foo_functions.rs:9:10
+  |
+9 |     //~^ foo_functions
+  |          ^^^^^^^^^^^^^ expected because of this pattern
+  |
+
+error: diagnostic code `clippy::foo_functions` not found on line 16
+  --> tests/ui/foo_functions.rs:17:10
+   |
+17 |     //~^ foo_functions
+   |          ^^^^^^^^^^^^^ expected because of this pattern
+   |
+
+error: diagnostic code `clippy::foo_functions` not found on line 23
+  --> tests/ui/foo_functions.rs:24:6
+   |
+24 | //~^ foo_functions
+   |      ^^^^^^^^^^^^^ expected because of this pattern
+   |
+
 ```
 
 This is normal. After all, we wrote a bunch of Rust code but we haven't really
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 3726d6e8a86..2314d1beac7 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -425,6 +425,33 @@ Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code.
 * [`incompatible_msrv`](https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv)
 
 
+## `check-inconsistent-struct-field-initializers`
+Whether to suggest reordering constructor fields when initializers are present.
+
+Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
+suggested code would compile, it can change semantics if the initializer expressions have side effects. The
+following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors:
+
+```rust
+struct MyStruct {
+    vector: Vec<u32>,
+    length: usize
+}
+fn main() {
+    let vector = vec![1,2,3];
+    MyStruct { length: vector.len(), vector};
+}
+```
+
+[from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor)
+
+
 ## `check-private-items`
 Whether to also run the listed lints on private items.
 
@@ -613,31 +640,15 @@ The maximum size of the `Err`-variant in a `Result` returned from a function
 * [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
 
 
-## `lint-inconsistent-struct-field-initializers`
-Whether to suggest reordering constructor fields when initializers are present.
-
-Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
-suggested code would compile, it can change semantics if the initializer expressions have side effects. The
-following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors:
-
-```rust
-struct MyStruct {
-    vector: Vec<u32>,
-    length: usize
-}
-fn main() {
-    let vector = vec![1,2,3];
-    MyStruct { length: vector.len(), vector};
-}
-```
-
-[from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924
+## `lint-commented-code`
+Whether collapsible `if` chains are linted if they contain comments inside the parts
+that would be collapsed.
 
 **Default Value:** `false`
 
 ---
 **Affected lints:**
-* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor)
+* [`collapsible_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if)
 
 
 ## `literal-representation-threshold`
@@ -786,6 +797,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 * [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
 * [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants)
 * [`lines_filter_map_ok`](https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok)
+* [`manual_abs_diff`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_abs_diff)
 * [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
 * [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals)
 * [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
@@ -793,6 +805,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 * [`manual_flatten`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten)
 * [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one)
 * [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
+* [`manual_is_power_of_two`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two)
 * [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
 * [`manual_midpoint`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint)
 * [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
@@ -1059,7 +1072,8 @@ The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
 
 
 ## `warn-on-all-wildcard-imports`
-Whether to allow certain wildcard imports (prelude, super in tests).
+Whether to emit warnings on all wildcard imports, including those from `prelude`, from `super` in tests,
+or for `pub use` reexports.
 
 **Default Value:** `false`
 
diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml
index f4789c9d030..0a7724bbe4e 100644
--- a/src/tools/clippy/clippy.toml
+++ b/src/tools/clippy/clippy.toml
@@ -1,15 +1,20 @@
 avoid-breaking-exported-api = false
 
-lint-inconsistent-struct-field-initializers = true
+check-inconsistent-struct-field-initializers = true
+
+lint-commented-code = true
 
 [[disallowed-methods]]
 path = "rustc_lint::context::LintContext::lint"
 reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
+allow-invalid = true
 
 [[disallowed-methods]]
 path = "rustc_lint::context::LintContext::span_lint"
 reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
+allow-invalid = true
 
 [[disallowed-methods]]
 path = "rustc_middle::ty::context::TyCtxt::node_span_lint"
 reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead"
+allow-invalid = true
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index 934725fccb8..93fd2e35d1b 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_config"
 # begin autogenerated version
-version = "0.1.87"
+version = "0.1.88"
 # end autogenerated version
 edition = "2024"
 publish = false
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 798f8b3aa5a..511cb84527d 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -120,12 +120,7 @@ impl ConfError {
         Self {
             message: message.into(),
             suggestion,
-            span: Span::new(
-                file.start_pos + BytePos::from_usize(span.start),
-                file.start_pos + BytePos::from_usize(span.end),
-                SyntaxContext::root(),
-                None,
-            ),
+            span: span_from_toml_range(file, span),
         }
     }
 }
@@ -176,11 +171,61 @@ macro_rules! default_text {
     };
 }
 
+macro_rules! deserialize {
+    ($map:expr, $ty:ty, $errors:expr, $file:expr) => {{
+        let raw_value = $map.next_value::<toml::Spanned<toml::Value>>()?;
+        let value_span = raw_value.span();
+        let value = match <$ty>::deserialize(raw_value.into_inner()) {
+            Err(e) => {
+                $errors.push(ConfError::spanned(
+                    $file,
+                    e.to_string().replace('\n', " ").trim(),
+                    None,
+                    value_span,
+                ));
+                continue;
+            },
+            Ok(value) => value,
+        };
+        (value, value_span)
+    }};
+
+    ($map:expr, $ty:ty, $errors:expr, $file:expr, $replacements_allowed:expr) => {{
+        let array = $map.next_value::<Vec<toml::Spanned<toml::Value>>>()?;
+        let mut disallowed_paths_span = Range {
+            start: usize::MAX,
+            end: usize::MIN,
+        };
+        let mut disallowed_paths = Vec::new();
+        for raw_value in array {
+            let value_span = raw_value.span();
+            let mut disallowed_path = match DisallowedPath::<$replacements_allowed>::deserialize(raw_value.into_inner())
+            {
+                Err(e) => {
+                    $errors.push(ConfError::spanned(
+                        $file,
+                        e.to_string().replace('\n', " ").trim(),
+                        None,
+                        value_span,
+                    ));
+                    continue;
+                },
+                Ok(disallowed_path) => disallowed_path,
+            };
+            disallowed_paths_span = union(&disallowed_paths_span, &value_span);
+            disallowed_path.set_span(span_from_toml_range($file, value_span));
+            disallowed_paths.push(disallowed_path);
+        }
+        (disallowed_paths, disallowed_paths_span)
+    }};
+}
+
 macro_rules! define_Conf {
     ($(
         $(#[doc = $doc:literal])+
         $(#[conf_deprecated($dep:literal, $new_conf:ident)])?
         $(#[default_text = $default_text:expr])?
+        $(#[disallowed_paths_allow_replacements = $replacements_allowed:expr])?
         $(#[lints($($for_lints:ident),* $(,)?)])?
         $name:ident: $ty:ty = $default:expr,
     )*) => {
@@ -218,42 +263,46 @@ macro_rules! define_Conf {
                 let mut value_spans = HashMap::new();
                 let mut errors = Vec::new();
                 let mut warnings = Vec::new();
+
+                // Declare a local variable for each field available to a configuration file.
                 $(let mut $name = None;)*
+
                 // could get `Field` here directly, but get `String` first for diagnostics
                 while let Some(name) = map.next_key::<toml::Spanned<String>>()? {
-                    match Field::deserialize(name.get_ref().as_str().into_deserializer()) {
+                    let field = match Field::deserialize(name.get_ref().as_str().into_deserializer()) {
                         Err(e) => {
                             let e: FieldError = e;
                             errors.push(ConfError::spanned(self.0, e.error, e.suggestion, name.span()));
+                            continue;
                         }
-                        $(Ok(Field::$name) => {
+                        Ok(field) => field
+                    };
+
+                    match field {
+                        $(Field::$name => {
+                            // Is this a deprecated field, i.e., is `$dep` set? If so, push a warning.
                             $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), None, name.span()));)?
-                            let raw_value = map.next_value::<toml::Spanned<toml::Value>>()?;
-                            let value_span = raw_value.span();
-                            match <$ty>::deserialize(raw_value.into_inner()) {
-                                Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), None, value_span)),
-                                Ok(value) => match $name {
-                                    Some(_) => {
-                                        errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span()));
-                                    }
-                                    None => {
-                                        $name = Some(value);
-                                        value_spans.insert(name.get_ref().as_str().to_string(), value_span);
-                                        // $new_conf is the same as one of the defined `$name`s, so
-                                        // this variable is defined in line 2 of this function.
-                                        $(match $new_conf {
-                                            Some(_) => errors.push(ConfError::spanned(self.0, concat!(
-                                                "duplicate field `", stringify!($new_conf),
-                                                "` (provided as `", stringify!($name), "`)"
-                                            ), None, name.span())),
-                                            None => $new_conf = $name.clone(),
-                                        })?
-                                    },
-                                }
+                            let (value, value_span) =
+                                deserialize!(map, $ty, errors, self.0 $(, $replacements_allowed)?);
+                            // Was this field set previously?
+                            if $name.is_some() {
+                                errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span()));
+                                continue;
                             }
+                            $name = Some(value);
+                            value_spans.insert(name.get_ref().as_str().to_string(), value_span);
+                            // If this is a deprecated field, was the new field (`$new_conf`) set previously?
+                            // Note that `$new_conf` is one of the defined `$name`s.
+                            $(match $new_conf {
+                                Some(_) => errors.push(ConfError::spanned(self.0, concat!(
+                                    "duplicate field `", stringify!($new_conf),
+                                    "` (provided as `", stringify!($name), "`)"
+                                ), None, name.span())),
+                                None => $new_conf = $name.clone(),
+                            })?
                         })*
                         // ignore contents of the third_party key
-                        Ok(Field::third_party) => drop(map.next_value::<IgnoredAny>())
+                        Field::third_party => drop(map.next_value::<IgnoredAny>())
                     }
                 }
                 let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* };
@@ -275,6 +324,22 @@ macro_rules! define_Conf {
     };
 }
 
+fn union(x: &Range<usize>, y: &Range<usize>) -> Range<usize> {
+    Range {
+        start: cmp::min(x.start, y.start),
+        end: cmp::max(x.end, y.end),
+    }
+}
+
+fn span_from_toml_range(file: &SourceFile, span: Range<usize>) -> Span {
+    Span::new(
+        file.start_pos + BytePos::from_usize(span.start),
+        file.start_pos + BytePos::from_usize(span.end),
+        SyntaxContext::root(),
+        None,
+    )
+}
+
 define_Conf! {
     /// Which crates to allow absolute paths from
     #[lints(absolute_paths)]
@@ -461,6 +526,7 @@ define_Conf! {
     )]
     avoid_breaking_exported_api: bool = true,
     /// The list of types which may not be held across an await point.
+    #[disallowed_paths_allow_replacements = false]
     #[lints(await_holding_invalid_type)]
     await_holding_invalid_types: Vec<DisallowedPathWithoutReplacement> = Vec::new(),
     /// DEPRECATED LINT: BLACKLISTED_NAME.
@@ -474,6 +540,26 @@ define_Conf! {
     /// Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code.
     #[lints(incompatible_msrv)]
     check_incompatible_msrv_in_tests: bool = false,
+    /// Whether to suggest reordering constructor fields when initializers are present.
+    ///
+    /// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
+    /// suggested code would compile, it can change semantics if the initializer expressions have side effects. The
+    /// following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors:
+    ///
+    /// ```rust
+    /// struct MyStruct {
+    ///     vector: Vec<u32>,
+    ///     length: usize
+    /// }
+    /// fn main() {
+    ///     let vector = vec![1,2,3];
+    ///     MyStruct { length: vector.len(), vector};
+    /// }
+    /// ```
+    ///
+    /// [from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924
+    #[lints(inconsistent_struct_constructor)]
+    check_inconsistent_struct_field_initializers: bool = false,
     /// Whether to also run the listed lints on private items.
     #[lints(missing_errors_doc, missing_panics_doc, missing_safety_doc, unnecessary_safety_doc)]
     check_private_items: bool = false,
@@ -486,9 +572,11 @@ define_Conf! {
     #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)]
     cyclomatic_complexity_threshold: u64 = 25,
     /// The list of disallowed macros, written as fully qualified paths.
+    #[disallowed_paths_allow_replacements = true]
     #[lints(disallowed_macros)]
     disallowed_macros: Vec<DisallowedPath> = Vec::new(),
     /// The list of disallowed methods, written as fully qualified paths.
+    #[disallowed_paths_allow_replacements = true]
     #[lints(disallowed_methods)]
     disallowed_methods: Vec<DisallowedPath> = Vec::new(),
     /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
@@ -497,6 +585,7 @@ define_Conf! {
     #[lints(disallowed_names)]
     disallowed_names: Vec<String> = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect(),
     /// The list of disallowed types, written as fully qualified paths.
+    #[disallowed_paths_allow_replacements = true]
     #[lints(disallowed_types)]
     disallowed_types: Vec<DisallowedPath> = Vec::new(),
     /// The list of words this lint should not consider as identifiers needing ticks. The value
@@ -549,25 +638,15 @@ define_Conf! {
     /// The maximum size of the `Err`-variant in a `Result` returned from a function
     #[lints(result_large_err)]
     large_error_threshold: u64 = 128,
+    /// Whether collapsible `if` chains are linted if they contain comments inside the parts
+    /// that would be collapsed.
+    #[lints(collapsible_if)]
+    lint_commented_code: bool = false,
     /// Whether to suggest reordering constructor fields when initializers are present.
+    /// DEPRECATED CONFIGURATION: lint-inconsistent-struct-field-initializers
     ///
-    /// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
-    /// suggested code would compile, it can change semantics if the initializer expressions have side effects. The
-    /// following example [from rust-clippy#11846] shows how the suggestion can run into borrow check errors:
-    ///
-    /// ```rust
-    /// struct MyStruct {
-    ///     vector: Vec<u32>,
-    ///     length: usize
-    /// }
-    /// fn main() {
-    ///     let vector = vec![1,2,3];
-    ///     MyStruct { length: vector.len(), vector};
-    /// }
-    /// ```
-    ///
-    /// [from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924
-    #[lints(inconsistent_struct_constructor)]
+    /// Use the `check-inconsistent-struct-field-initializers` configuration instead.
+    #[conf_deprecated("Please use `check-inconsistent-struct-field-initializers` instead", check_inconsistent_struct_field_initializers)]
     lint_inconsistent_struct_field_initializers: bool = false,
     /// The lower bound for linting decimal literals
     #[lints(decimal_literal_representation)]
@@ -635,6 +714,7 @@ define_Conf! {
         iter_kv_map,
         legacy_numeric_constants,
         lines_filter_map_ok,
+        manual_abs_diff,
         manual_bits,
         manual_c_str_literals,
         manual_clamp,
@@ -642,6 +722,7 @@ define_Conf! {
         manual_flatten,
         manual_hash_one,
         manual_is_ascii_check,
+        manual_is_power_of_two,
         manual_let_else,
         manual_midpoint,
         manual_non_exhaustive,
@@ -760,7 +841,8 @@ define_Conf! {
     /// The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
     #[lints(verbose_bit_mask)]
     verbose_bit_mask_threshold: u64 = 1,
-    /// Whether to allow certain wildcard imports (prelude, super in tests).
+    /// Whether to emit warnings on all wildcard imports, including those from `prelude`, from `super` in tests,
+    /// or for `pub use` reexports.
     #[lints(wildcard_imports)]
     warn_on_all_wildcard_imports: bool = false,
     /// Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros.
@@ -981,7 +1063,23 @@ impl serde::de::Error for FieldError {
         // set and allows it.
         use fmt::Write;
 
-        let mut expected = expected.to_vec();
+        let metadata = get_configuration_metadata();
+        let deprecated = metadata
+            .iter()
+            .filter_map(|conf| {
+                if conf.deprecation_reason.is_some() {
+                    Some(conf.name.as_str())
+                } else {
+                    None
+                }
+            })
+            .collect::<Vec<_>>();
+
+        let mut expected = expected
+            .iter()
+            .copied()
+            .filter(|name| !deprecated.contains(name))
+            .collect::<Vec<_>>();
         expected.sort_unstable();
 
         let (rows, column_widths) = calculate_dimensions(&expected);
@@ -1064,7 +1162,13 @@ mod tests {
     fn configs_are_tested() {
         let mut names: HashSet<String> = crate::get_configuration_metadata()
             .into_iter()
-            .map(|meta| meta.name.replace('_', "-"))
+            .filter_map(|meta| {
+                if meta.deprecation_reason.is_none() {
+                    Some(meta.name.replace('_', "-"))
+                } else {
+                    None
+                }
+            })
             .collect();
 
         let toml_files = WalkDir::new("../tests")
diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs
index 5d6e8b87516..c227b8900b7 100644
--- a/src/tools/clippy/clippy_config/src/lib.rs
+++ b/src/tools/clippy/clippy_config/src/lib.rs
@@ -13,6 +13,7 @@
     rustc::untranslatable_diagnostic
 )]
 
+extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_middle;
diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs
index 8faac9ecffe..5949eaca7bc 100644
--- a/src/tools/clippy/clippy_config/src/types.rs
+++ b/src/tools/clippy/clippy_config/src/types.rs
@@ -1,5 +1,7 @@
-use clippy_utils::def_path_def_ids;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, Diag};
+use rustc_hir::PrimTy;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
@@ -21,6 +23,17 @@ pub struct DisallowedPath<const REPLACEMENT_ALLOWED: bool = true> {
     path: String,
     reason: Option<String>,
     replacement: Option<String>,
+    /// Setting `allow_invalid` to true suppresses a warning if `path` does not refer to an existing
+    /// definition.
+    ///
+    /// This could be useful when conditional compilation is used, or when a clippy.toml file is
+    /// shared among multiple projects.
+    allow_invalid: bool,
+    /// The span of the `DisallowedPath`.
+    ///
+    /// Used for diagnostics.
+    #[serde(skip_serializing)]
+    span: Span,
 }
 
 impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath<REPLACEMENT_ALLOWED> {
@@ -36,6 +49,8 @@ impl<'de, const REPLACEMENT_ALLOWED: bool> Deserialize<'de> for DisallowedPath<R
             path: enum_.path().to_owned(),
             reason: enum_.reason().map(ToOwned::to_owned),
             replacement: enum_.replacement().map(ToOwned::to_owned),
+            allow_invalid: enum_.allow_invalid(),
+            span: Span::default(),
         })
     }
 }
@@ -50,6 +65,8 @@ enum DisallowedPathEnum {
         path: String,
         reason: Option<String>,
         replacement: Option<String>,
+        #[serde(rename = "allow-invalid")]
+        allow_invalid: Option<bool>,
     },
 }
 
@@ -58,7 +75,7 @@ impl<const REPLACEMENT_ALLOWED: bool> DisallowedPath<REPLACEMENT_ALLOWED> {
         &self.path
     }
 
-    pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) + use<'_, REPLACEMENT_ALLOWED> {
+    pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) {
         move |diag| {
             if let Some(replacement) = &self.replacement {
                 diag.span_suggestion(
@@ -72,6 +89,14 @@ impl<const REPLACEMENT_ALLOWED: bool> DisallowedPath<REPLACEMENT_ALLOWED> {
             }
         }
     }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
 }
 
 impl DisallowedPathEnum {
@@ -94,20 +119,87 @@ impl DisallowedPathEnum {
             Self::Simple(_) => None,
         }
     }
+
+    fn allow_invalid(&self) -> bool {
+        match &self {
+            Self::WithReason { allow_invalid, .. } => allow_invalid.unwrap_or_default(),
+            Self::Simple(_) => false,
+        }
+    }
 }
 
 /// Creates a map of disallowed items to the reason they were disallowed.
+#[allow(clippy::type_complexity)]
 pub fn create_disallowed_map<const REPLACEMENT_ALLOWED: bool>(
     tcx: TyCtxt<'_>,
-    disallowed: &'static [DisallowedPath<REPLACEMENT_ALLOWED>],
-) -> DefIdMap<(&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)> {
-    disallowed
-        .iter()
-        .map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x))
-        .flat_map(|(name, path, disallowed_path)| {
-            def_path_def_ids(tcx, &path).map(move |id| (id, (name, disallowed_path)))
-        })
-        .collect()
+    disallowed_paths: &'static [DisallowedPath<REPLACEMENT_ALLOWED>],
+    def_kind_predicate: impl Fn(DefKind) -> bool,
+    predicate_description: &str,
+    allow_prim_tys: bool,
+) -> (
+    DefIdMap<(&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)>,
+    FxHashMap<PrimTy, (&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)>,
+) {
+    let mut def_ids: DefIdMap<(&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)> = DefIdMap::default();
+    let mut prim_tys: FxHashMap<PrimTy, (&'static str, &'static DisallowedPath<REPLACEMENT_ALLOWED>)> =
+        FxHashMap::default();
+    for disallowed_path in disallowed_paths {
+        let path = disallowed_path.path();
+        let mut resolutions = clippy_utils::def_path_res(tcx, &path.split("::").collect::<Vec<_>>());
+
+        let mut found_def_id = None;
+        let mut found_prim_ty = false;
+        resolutions.retain(|res| match res {
+            Res::Def(def_kind, def_id) => {
+                found_def_id = Some(*def_id);
+                def_kind_predicate(*def_kind)
+            },
+            Res::PrimTy(_) => {
+                found_prim_ty = true;
+                allow_prim_tys
+            },
+            _ => false,
+        });
+
+        if resolutions.is_empty() {
+            let span = disallowed_path.span();
+
+            if let Some(def_id) = found_def_id {
+                tcx.sess.dcx().span_warn(
+                    span,
+                    format!(
+                        "expected a {predicate_description}, found {} {}",
+                        tcx.def_descr_article(def_id),
+                        tcx.def_descr(def_id)
+                    ),
+                );
+            } else if found_prim_ty {
+                tcx.sess.dcx().span_warn(
+                    span,
+                    format!("expected a {predicate_description}, found a primitive type",),
+                );
+            } else if !disallowed_path.allow_invalid {
+                tcx.sess.dcx().span_warn(
+                    span,
+                    format!("`{path}` does not refer to an existing {predicate_description}"),
+                );
+            }
+        }
+
+        for res in resolutions {
+            match res {
+                Res::Def(_, def_id) => {
+                    def_ids.insert(def_id, (path, disallowed_path));
+                },
+                Res::PrimTy(ty) => {
+                    prim_tys.insert(ty, (path, disallowed_path));
+                },
+                _ => unreachable!(),
+            }
+        }
+    }
+
+    (def_ids, prim_tys)
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 9280369c23b..c1ffaf269c6 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -13,6 +13,7 @@
 #[allow(unused_extern_crates)]
 extern crate rustc_driver;
 extern crate rustc_lexer;
+extern crate rustc_literal_escaper;
 
 pub mod dogfood;
 pub mod fmt;
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index 074dea4ab77..83f8e66b334 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -170,7 +170,6 @@ enum DevCommand {
                 "restriction",
                 "cargo",
                 "nursery",
-                "internal",
             ],
             default_value = "nursery",
         )]
@@ -334,7 +333,7 @@ struct SyncCommand {
 #[derive(Subcommand)]
 enum SyncSubcommand {
     #[command(name = "update_nightly")]
-    /// Update nightly version in rust-toolchain and `clippy_utils`
+    /// Update nightly version in `rust-toolchain.toml` and `clippy_utils`
     UpdateNightly,
 }
 
diff --git a/src/tools/clippy/clippy_dev/src/setup/toolchain.rs b/src/tools/clippy/clippy_dev/src/setup/toolchain.rs
index 2966629cf70..ecd80215f7e 100644
--- a/src/tools/clippy/clippy_dev/src/setup/toolchain.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/toolchain.rs
@@ -62,7 +62,7 @@ pub fn create(standalone: bool, force: bool, release: bool, name: &str) {
 
     println!("Created toolchain {name}, use it in other projects with e.g. `cargo +{name} clippy`");
     if !standalone {
-        println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes");
+        println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain.toml` changes");
     }
 }
 
diff --git a/src/tools/clippy/clippy_dev/src/sync.rs b/src/tools/clippy/clippy_dev/src/sync.rs
index 3522d182e90..a6b65e561c2 100644
--- a/src/tools/clippy/clippy_dev/src/sync.rs
+++ b/src/tools/clippy/clippy_dev/src/sync.rs
@@ -10,7 +10,7 @@ pub fn update_nightly() {
     let date = Utc::now().format("%Y-%m-%d").to_string();
     replace_region_in_file(
         UpdateMode::Change,
-        Path::new("rust-toolchain"),
+        Path::new("rust-toolchain.toml"),
         "# begin autogenerated nightly\n",
         "# end autogenerated nightly",
         |res| {
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index b80ee5aac7e..d848a97f86d 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -1,7 +1,8 @@
 use crate::utils::{UpdateMode, clippy_project_root, exit_with_failure, replace_region_in_file};
 use aho_corasick::AhoCorasickBuilder;
 use itertools::Itertools;
-use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape};
+use rustc_lexer::{LiteralKind, TokenKind, tokenize};
+use rustc_literal_escaper::{Mode, unescape_unicode};
 use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
 use std::fmt::{self, Write};
@@ -37,9 +38,8 @@ fn generate_lint_files(
     deprecated_lints: &[DeprecatedLint],
     renamed_lints: &[RenamedLint],
 ) {
-    let internal_lints = Lint::internal_lints(lints);
-    let mut usable_lints = Lint::usable_lints(lints);
-    usable_lints.sort_by_key(|lint| lint.name.clone());
+    let mut lints = lints.to_owned();
+    lints.sort_by_key(|lint| lint.name.clone());
 
     replace_region_in_file(
         update_mode,
@@ -47,7 +47,7 @@ fn generate_lint_files(
         "[There are over ",
         " lints included in this crate!]",
         |res| {
-            write!(res, "{}", round_to_fifty(usable_lints.len())).unwrap();
+            write!(res, "{}", round_to_fifty(lints.len())).unwrap();
         },
     );
 
@@ -57,7 +57,7 @@ fn generate_lint_files(
         "[There are over ",
         " lints included in this crate!]",
         |res| {
-            write!(res, "{}", round_to_fifty(usable_lints.len())).unwrap();
+            write!(res, "{}", round_to_fifty(lints.len())).unwrap();
         },
     );
 
@@ -67,7 +67,7 @@ fn generate_lint_files(
         "<!-- begin autogenerated links to lint list -->\n",
         "<!-- end autogenerated links to lint list -->",
         |res| {
-            for lint in usable_lints
+            for lint in lints
                 .iter()
                 .map(|l| &*l.name)
                 .chain(deprecated_lints.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
@@ -86,7 +86,7 @@ fn generate_lint_files(
         "// begin lints modules, do not remove this comment, it’s used in `update_lints`\n",
         "// end lints modules, do not remove this comment, it’s used in `update_lints`",
         |res| {
-            for lint_mod in usable_lints.iter().map(|l| &l.module).unique().sorted() {
+            for lint_mod in lints.iter().map(|l| &l.module).unique().sorted() {
                 writeln!(res, "mod {lint_mod};").unwrap();
             }
         },
@@ -95,7 +95,7 @@ fn generate_lint_files(
     process_file(
         "clippy_lints/src/declared_lints.rs",
         update_mode,
-        &gen_declared_lints(internal_lints.iter(), usable_lints.iter()),
+        &gen_declared_lints(lints.iter()),
     );
 
     let content = gen_deprecated_lints_test(deprecated_lints);
@@ -106,10 +106,9 @@ fn generate_lint_files(
 }
 
 pub fn print_lints() {
-    let (lint_list, _, _) = gather_all();
-    let usable_lints = Lint::usable_lints(&lint_list);
-    let usable_lint_count = usable_lints.len();
-    let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter());
+    let (lints, _, _) = gather_all();
+    let lint_count = lints.len();
+    let grouped_by_lint_group = Lint::by_lint_group(lints.into_iter());
 
     for (lint_group, mut lints) in grouped_by_lint_group {
         println!("\n## {lint_group}");
@@ -121,7 +120,7 @@ pub fn print_lints() {
         }
     }
 
-    println!("there are {usable_lint_count} lints");
+    println!("there are {lint_count} lints");
 }
 
 /// Runs the `rename_lint` command.
@@ -402,53 +401,53 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
         }
     }
 
-    if path.exists() {
-        if let Some(lint) = lints.iter().find(|l| l.name == name) {
-            if lint.module == name {
-                // The lint name is the same as the file, we can just delete the entire file
-                fs::remove_file(path)?;
-            } else {
-                // We can't delete the entire file, just remove the declaration
-
-                if let Some(Some("mod.rs")) = path.file_name().map(OsStr::to_str) {
-                    // Remove clippy_lints/src/some_mod/some_lint.rs
-                    let mut lint_mod_path = path.to_path_buf();
-                    lint_mod_path.set_file_name(name);
-                    lint_mod_path.set_extension("rs");
+    if path.exists()
+        && let Some(lint) = lints.iter().find(|l| l.name == name)
+    {
+        if lint.module == name {
+            // The lint name is the same as the file, we can just delete the entire file
+            fs::remove_file(path)?;
+        } else {
+            // We can't delete the entire file, just remove the declaration
 
-                    let _ = fs::remove_file(lint_mod_path);
-                }
+            if let Some(Some("mod.rs")) = path.file_name().map(OsStr::to_str) {
+                // Remove clippy_lints/src/some_mod/some_lint.rs
+                let mut lint_mod_path = path.to_path_buf();
+                lint_mod_path.set_file_name(name);
+                lint_mod_path.set_extension("rs");
 
-                let mut content =
-                    fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy()));
+                let _ = fs::remove_file(lint_mod_path);
+            }
 
-                eprintln!(
-                    "warn: you will have to manually remove any code related to `{name}` from `{}`",
-                    path.display()
-                );
+            let mut content =
+                fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy()));
 
-                assert!(
-                    content[lint.declaration_range.clone()].contains(&name.to_uppercase()),
-                    "error: `{}` does not contain lint `{}`'s declaration",
-                    path.display(),
-                    lint.name
-                );
+            eprintln!(
+                "warn: you will have to manually remove any code related to `{name}` from `{}`",
+                path.display()
+            );
 
-                // Remove lint declaration (declare_clippy_lint!)
-                content.replace_range(lint.declaration_range.clone(), "");
+            assert!(
+                content[lint.declaration_range.clone()].contains(&name.to_uppercase()),
+                "error: `{}` does not contain lint `{}`'s declaration",
+                path.display(),
+                lint.name
+            );
 
-                // Remove the module declaration (mod xyz;)
-                let mod_decl = format!("\nmod {name};");
-                content = content.replacen(&mod_decl, "", 1);
+            // Remove lint declaration (declare_clippy_lint!)
+            content.replace_range(lint.declaration_range.clone(), "");
 
-                remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content);
-                fs::write(path, content).unwrap_or_else(|_| panic!("failed to write to `{}`", path.to_string_lossy()));
-            }
+            // Remove the module declaration (mod xyz;)
+            let mod_decl = format!("\nmod {name};");
+            content = content.replacen(&mod_decl, "", 1);
 
-            remove_test_assets(name);
-            remove_lint(name, lints);
-            return Ok(true);
+            remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content);
+            fs::write(path, content).unwrap_or_else(|_| panic!("failed to write to `{}`", path.to_string_lossy()));
         }
+
+        remove_test_assets(name);
+        remove_lint(name, lints);
+        return Ok(true);
     }
 
     Ok(false)
@@ -527,22 +526,6 @@ impl Lint {
         }
     }
 
-    /// Returns all non-deprecated lints and non-internal lints
-    #[must_use]
-    fn usable_lints(lints: &[Self]) -> Vec<Self> {
-        lints
-            .iter()
-            .filter(|l| !l.group.starts_with("internal"))
-            .cloned()
-            .collect()
-    }
-
-    /// Returns all internal lints
-    #[must_use]
-    fn internal_lints(lints: &[Self]) -> Vec<Self> {
-        lints.iter().filter(|l| l.group == "internal").cloned().collect()
-    }
-
     /// Returns the lints in a `HashMap`, grouped by the different lint groups
     #[must_use]
     fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> {
@@ -579,23 +562,14 @@ impl RenamedLint {
 
 /// Generates the code for registering lints
 #[must_use]
-fn gen_declared_lints<'a>(
-    internal_lints: impl Iterator<Item = &'a Lint>,
-    usable_lints: impl Iterator<Item = &'a Lint>,
-) -> String {
-    let mut details: Vec<_> = internal_lints
-        .map(|l| (false, &l.module, l.name.to_uppercase()))
-        .chain(usable_lints.map(|l| (true, &l.module, l.name.to_uppercase())))
-        .collect();
+fn gen_declared_lints<'a>(lints: impl Iterator<Item = &'a Lint>) -> String {
+    let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect();
     details.sort_unstable();
 
     let mut output = GENERATED_FILE_COMMENT.to_string();
     output.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
 
-    for (is_public, module_name, lint_name) in details {
-        if !is_public {
-            output.push_str("    #[cfg(feature = \"internal\")]\n");
-        }
+    for (module_name, lint_name) in details {
         let _: fmt::Result = writeln!(output, "    crate::{module_name}::{lint_name}_INFO,");
     }
     output.push_str("];\n");
@@ -830,7 +804,7 @@ fn remove_line_splices(s: &str) -> String {
         .and_then(|s| s.strip_suffix('"'))
         .unwrap_or_else(|| panic!("expected quoted string, found `{s}`"));
     let mut res = String::with_capacity(s.len());
-    unescape::unescape_unicode(s, unescape::Mode::Str, &mut |range, ch| {
+    unescape_unicode(s, Mode::Str, &mut |range, ch| {
         if ch.is_ok() {
             res.push_str(&s[range]);
         }
@@ -937,41 +911,6 @@ mod tests {
     }
 
     #[test]
-    fn test_usable_lints() {
-        let lints = vec![
-            Lint::new(
-                "should_assert_eq2",
-                "Not Deprecated",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-            ),
-            Lint::new(
-                "should_assert_eq2",
-                "internal",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-            ),
-            Lint::new(
-                "should_assert_eq2",
-                "internal_style",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-            ),
-        ];
-        let expected = vec![Lint::new(
-            "should_assert_eq2",
-            "Not Deprecated",
-            "\"abc\"",
-            "module_name",
-            Range::default(),
-        )];
-        assert_eq!(expected, Lint::usable_lints(&lints));
-    }
-
-    #[test]
     fn test_by_lint_group() {
         let lints = vec![
             Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
diff --git a/src/tools/clippy/clippy_dev/src/utils.rs b/src/tools/clippy/clippy_dev/src/utils.rs
index b87fcca13b1..206816398f5 100644
--- a/src/tools/clippy/clippy_dev/src/utils.rs
+++ b/src/tools/clippy/clippy_dev/src/utils.rs
@@ -30,10 +30,10 @@ pub fn clippy_project_root() -> PathBuf {
     let current_dir = std::env::current_dir().unwrap();
     for path in current_dir.ancestors() {
         let result = fs::read_to_string(path.join("Cargo.toml"));
-        if let Err(err) = &result {
-            if err.kind() == io::ErrorKind::NotFound {
-                continue;
-            }
+        if let Err(err) = &result
+            && err.kind() == io::ErrorKind::NotFound
+        {
+            continue;
         }
 
         let content = result.unwrap();
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 54347043a13..20951afccbb 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_lints"
 # begin autogenerated version
-version = "0.1.87"
+version = "0.1.88"
 # end autogenerated version
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
@@ -19,10 +19,7 @@ itertools = "0.12"
 quine-mc_cluskey = "0.2"
 regex-syntax = "0.8"
 serde = { version = "1.0", features = ["derive"] }
-serde_json = { version = "1.0", optional = true }
-tempfile = { version = "3.3.0", optional = true }
 toml = "0.7.3"
-regex = { version = "1.5", optional = true }
 unicode-normalization = "0.1"
 unicode-script = { version = "0.5", default-features = false }
 semver = "1.0"
@@ -31,10 +28,6 @@ url = "2.2"
 [dev-dependencies]
 walkdir = "2.3"
 
-[features]
-# build clippy with internal lints enabled, off by default
-internal = ["serde_json", "tempfile", "regex"]
-
 [package.metadata.rust-analyzer]
 # This crate uses #[feature(rustc_private)]
 rustc_private = true
diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
index 57cabe43703..272444475c0 100644
--- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
+++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
@@ -5,6 +5,7 @@ use clippy_config::types::{
     SourceItemOrderingWithinModuleItemGroupings,
 };
 use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::is_cfg_test;
 use rustc_hir::{
     AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant,
     VariantData,
@@ -263,10 +264,11 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
                         continue;
                     }
 
-                    if let Some(cur_v) = cur_v {
-                        if cur_v.ident.name.as_str() > variant.ident.name.as_str() && cur_v.span != variant.span {
-                            Self::lint_member_name(cx, &variant.ident, &cur_v.ident);
-                        }
+                    if let Some(cur_v) = cur_v
+                        && cur_v.ident.name.as_str() > variant.ident.name.as_str()
+                        && cur_v.span != variant.span
+                    {
+                        Self::lint_member_name(cx, &variant.ident, &cur_v.ident);
                     }
                     cur_v = Some(variant);
                 }
@@ -278,10 +280,11 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
                         continue;
                     }
 
-                    if let Some(cur_f) = cur_f {
-                        if cur_f.ident.name.as_str() > field.ident.name.as_str() && cur_f.span != field.span {
-                            Self::lint_member_name(cx, &field.ident, &cur_f.ident);
-                        }
+                    if let Some(cur_f) = cur_f
+                        && cur_f.ident.name.as_str() > field.ident.name.as_str()
+                        && cur_f.span != field.span
+                    {
+                        Self::lint_member_name(cx, &field.ident, &cur_f.ident);
                     }
                     cur_f = Some(field);
                 }
@@ -342,7 +345,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
         struct CurItem<'a> {
             item: &'a Item<'a>,
             order: usize,
-            name: String,
+            name: Option<String>,
         }
         let mut cur_t: Option<CurItem<'_>> = None;
 
@@ -359,32 +362,36 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
         // as no sorting by source map/line of code has to be applied.
         //
         for item in items {
-            if item.span.in_external_macro(cx.sess().source_map()) {
+            if is_cfg_test(cx.tcx, item.hir_id()) {
                 continue;
             }
 
-            let ident = if let Some(ident) = item.kind.ident() {
-                ident
-            } else if let ItemKind::Impl(_) = item.kind
-                && !get_item_name(item).is_empty()
-            {
-                rustc_span::Ident::empty() // FIXME: a bit strange, is there a better way to do it?
-            } else {
-                continue;
-            };
-
-            if ident.name.as_str().starts_with('_') {
-                // Filters out unnamed macro-like impls for various derives,
-                // e.g. serde::Serialize or num_derive::FromPrimitive.
+            if item.span.in_external_macro(cx.sess().source_map()) {
                 continue;
             }
 
-            if ident.name == rustc_span::sym::std && item.span.is_dummy() {
-                if let ItemKind::ExternCrate(None, _) = item.kind {
-                    // Filters the auto-included Rust standard library.
+            if let Some(ident) = item.kind.ident() {
+                if ident.name.as_str().starts_with('_') {
+                    // Filters out unnamed macro-like impls for various derives,
+                    // e.g. serde::Serialize or num_derive::FromPrimitive.
                     continue;
                 }
-                println!("Unknown item: {item:?}");
+
+                if ident.name == rustc_span::sym::std && item.span.is_dummy() {
+                    if let ItemKind::ExternCrate(None, _) = item.kind {
+                        // Filters the auto-included Rust standard library.
+                        continue;
+                    }
+                    if cfg!(debug_assertions) {
+                        rustc_middle::bug!("unknown item: {item:?}");
+                    }
+                }
+            } else if let ItemKind::Impl(_) = item.kind
+                && get_item_name(item).is_some()
+            {
+                // keep going below
+            } else {
+                continue;
             }
 
             let item_kind = convert_module_item_kind(&item.kind);
@@ -493,7 +500,7 @@ fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleIte
 /// further in the [Rust Reference, Paths Chapter][rust_ref].
 ///
 /// [rust_ref]: https://doc.rust-lang.org/reference/paths.html#crate-1
-fn get_item_name(item: &Item<'_>) -> String {
+fn get_item_name(item: &Item<'_>) -> Option<String> {
     match item.kind {
         ItemKind::Impl(im) => {
             if let TyKind::Path(path) = im.self_ty.kind {
@@ -513,27 +520,19 @@ fn get_item_name(item: &Item<'_>) -> String {
                         }
 
                         segs.push(String::new());
-                        segs.join("!!")
+                        Some(segs.join("!!"))
                     },
                     QPath::TypeRelative(_, _path_seg) => {
                         // This case doesn't exist in the clippy tests codebase.
-                        String::new()
+                        None
                     },
-                    QPath::LangItem(_, _) => String::new(),
+                    QPath::LangItem(_, _) => None,
                 }
             } else {
                 // Impls for anything that isn't a named type can be skipped.
-                String::new()
+                None
             }
         },
-        // FIXME: `Ident::empty` for anonymous items is a bit strange, is there
-        // a better way to do it?
-        _ => item
-            .kind
-            .ident()
-            .unwrap_or(rustc_span::Ident::empty())
-            .name
-            .as_str()
-            .to_owned(),
+        _ => item.kind.ident().map(|name| name.as_str().to_owned()),
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs
index 78102772927..27e304a848e 100644
--- a/src/tools/clippy/clippy_lints/src/as_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs
@@ -12,17 +12,17 @@ declare_clippy_lint! {
     /// regardless of whether good alternatives exist or not. If you want more
     /// precise lints for `as`, please consider using these separate lints:
     ///
-    /// - clippy::cast_lossless
-    /// - clippy::cast_possible_truncation
-    /// - clippy::cast_possible_wrap
-    /// - clippy::cast_precision_loss
-    /// - clippy::cast_sign_loss
-    /// - clippy::char_lit_as_u8
-    /// - clippy::fn_to_numeric_cast
-    /// - clippy::fn_to_numeric_cast_with_truncation
-    /// - clippy::ptr_as_ptr
-    /// - clippy::unnecessary_cast
-    /// - invalid_reference_casting
+    /// - `clippy::cast_lossless`
+    /// - `clippy::cast_possible_truncation`
+    /// - `clippy::cast_possible_wrap`
+    /// - `clippy::cast_precision_loss`
+    /// - `clippy::cast_sign_loss`
+    /// - `clippy::char_lit_as_u8`
+    /// - `clippy::fn_to_numeric_cast`
+    /// - `clippy::fn_to_numeric_cast_with_truncation`
+    /// - `clippy::ptr_as_ptr`
+    /// - `clippy::unnecessary_cast`
+    /// - `invalid_reference_casting`
     ///
     /// There is a good explanation the reason why this lint should work in this
     /// way and how it is useful [in this
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index e5439a6d401..9acff676d4f 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -243,7 +243,7 @@ fn build_sugg<'tcx>(
                         // `lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)`
                         Sugg::hir_with_applicability(cx, lhs, "_", app)
                     }
-                    .maybe_par();
+                    .maybe_paren();
 
                     // Determine whether we need to reference the argument to clone_from().
                     let clone_receiver_type = cx.typeck_results().expr_ty(fn_arg);
@@ -284,7 +284,7 @@ fn build_sugg<'tcx>(
             let rhs_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind {
                 // `*lhs = rhs.to_owned()` -> `rhs.clone_into(lhs)`
                 // `*lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, lhs)`
-                let sugg = Sugg::hir_with_applicability(cx, ref_expr, "_", app).maybe_par();
+                let sugg = Sugg::hir_with_applicability(cx, ref_expr, "_", app).maybe_paren();
                 let inner_type = cx.typeck_results().expr_ty(ref_expr);
                 // If after unwrapping the dereference, the type is not a mutable reference, we add &mut to make it
                 // deref to a mutable reference.
@@ -296,7 +296,7 @@ fn build_sugg<'tcx>(
             } else {
                 // `lhs = rhs.to_owned()` -> `rhs.clone_into(&mut lhs)`
                 // `lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, &mut lhs)`
-                Sugg::hir_with_applicability(cx, lhs, "_", app).maybe_par().mut_addr()
+                Sugg::hir_with_applicability(cx, lhs, "_", app).maybe_paren().mut_addr()
             };
 
             match call_kind {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
index fecf3166406..457692ed5dc 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
@@ -8,17 +8,18 @@ use rustc_span::{DUMMY_SP, sym};
 
 pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
     for lint in items {
-        if let Some(lint_name) = extract_clippy_lint(lint) {
-            if lint_name.as_str() == "restriction" && name != sym::allow {
-                span_lint_and_help(
-                    cx,
-                    BLANKET_CLIPPY_RESTRICTION_LINTS,
-                    lint.span(),
-                    "`clippy::restriction` is not meant to be enabled as a group",
-                    None,
-                    "enable the restriction lints you need individually",
-                );
-            }
+        if let Some(lint_name) = extract_clippy_lint(lint)
+            && lint_name.as_str() == "restriction"
+            && name != sym::allow
+        {
+            span_lint_and_help(
+                cx,
+                BLANKET_CLIPPY_RESTRICTION_LINTS,
+                lint.span(),
+                "`clippy::restriction` is not meant to be enabled as a group",
+                None,
+                "enable the restriction lints you need individually",
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
index d3153ec6613..50943b36809 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
@@ -6,10 +6,10 @@ use rustc_span::Span;
 use semver::Version;
 
 pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
-    if let LitKind::Str(is, _) = lit.kind {
-        if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
-            return;
-        }
+    if let LitKind::Str(is, _) = lit.kind
+        && (is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok())
+    {
+        return;
     }
     span_lint(
         cx,
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index 4c84e61b1f2..a851daaede7 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -36,10 +36,7 @@ fn check_duplicated_attr(
     }
     let Some(ident) = attr.ident() else { return };
     let name = ident.name;
-    if name == sym::doc
-        || name == sym::cfg_attr_trace
-        || name == sym::rustc_on_unimplemented
-        || name == sym::reason {
+    if name == sym::doc || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason {
         // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
         // conditions are the same.
         // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index e04d2ad5d13..f7f168cb267 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -14,8 +14,9 @@ mod useless_attribute;
 mod utils;
 
 use clippy_config::Conf;
+use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::msrvs::{self, Msrv, MsrvStack};
-use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind};
+use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind};
 use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
@@ -448,6 +449,31 @@ declare_clippy_lint! {
     "duplicated attribute"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for ignored tests without messages.
+    ///
+    /// ### Why is this bad?
+    /// The reason for ignoring the test may not be obvious.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[test]
+    /// #[ignore]
+    /// fn test() {}
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// #[test]
+    /// #[ignore = "Some good reason"]
+    /// fn test() {}
+    /// ```
+    #[clippy::version = "1.85.0"]
+    pub IGNORE_WITHOUT_REASON,
+    pedantic,
+    "ignored tests without messages"
+}
+
 pub struct Attributes {
     msrv: Msrv,
 }
@@ -532,6 +558,7 @@ impl_lint_pass!(PostExpansionEarlyAttributes => [
     ALLOW_ATTRIBUTES,
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     DEPRECATED_SEMVER,
+    IGNORE_WITHOUT_REASON,
     USELESS_ATTRIBUTE,
     BLANKET_CLIPPY_RESTRICTION_LINTS,
     SHOULD_PANIC_WITHOUT_EXPECT,
@@ -546,28 +573,27 @@ impl EarlyLintPass for PostExpansionEarlyAttributes {
     }
 
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
-        if let Some(items) = &attr.meta_item_list() {
-            if let Some(ident) = attr.ident() {
-                if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
-                    allow_attributes::check(cx, attr);
-                }
-                if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
+        if let Some(items) = &attr.meta_item_list()
+            && let Some(ident) = attr.ident()
+        {
+            if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
+                allow_attributes::check(cx, attr);
+            }
+            if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
+                allow_attributes_without_reason::check(cx, ident.name, items, attr);
+            }
+            if is_lint_level(ident.name, attr.id) {
+                blanket_clippy_restriction_lints::check(cx, ident.name, items);
+            }
+            if items.is_empty() || !attr.has_name(sym::deprecated) {
+                return;
+            }
+            for item in items {
+                if let MetaItemInner::MetaItem(mi) = &item
+                    && let MetaItemKind::NameValue(lit) = &mi.kind
+                    && mi.has_name(sym::since)
                 {
-                    allow_attributes_without_reason::check(cx, ident.name, items, attr);
-                }
-                if is_lint_level(ident.name, attr.id) {
-                    blanket_clippy_restriction_lints::check(cx, ident.name, items);
-                }
-                if items.is_empty() || !attr.has_name(sym::deprecated) {
-                    return;
-                }
-                for item in items {
-                    if let MetaItemInner::MetaItem(mi) = &item
-                        && let MetaItemKind::NameValue(lit) = &mi.kind
-                        && mi.has_name(sym::since)
-                    {
-                        deprecated_semver::check(cx, item.span(), lit);
-                    }
+                    deprecated_semver::check(cx, item.span(), lit);
                 }
             }
         }
@@ -575,6 +601,22 @@ impl EarlyLintPass for PostExpansionEarlyAttributes {
         if attr.has_name(sym::should_panic) {
             should_panic_without_expect::check(cx, attr);
         }
+
+        if attr.has_name(sym::ignore)
+            && match &attr.kind {
+                AttrKind::Normal(normal_attr) => !matches!(normal_attr.item.args, AttrArgs::Eq { .. }),
+                AttrKind::DocComment(..) => true,
+            }
+        {
+            span_lint_and_help(
+                cx,
+                IGNORE_WITHOUT_REASON,
+                attr.span,
+                "`#[ignore]` without reason",
+                None,
+                "add a reason with `= \"..\"`",
+            );
+        }
     }
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
index e5cfbaf952a..df01c7fde18 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
@@ -30,7 +30,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute],
                     diag.warn(
                         "unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI",
                     )
-                    .help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`")
+                    .help("qualify the desired ABI explicitly via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`")
                     .span_label(packed_span, "`packed` representation set here");
                 },
             );
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index 1cb43ab02a3..d75b73280e6 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -14,75 +14,75 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
         if attr.span.in_external_macro(cx.sess().source_map()) {
             return;
         }
-        if let Some(lint_list) = &attr.meta_item_list() {
-            if attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) {
-                for lint in lint_list {
-                    match item.kind {
-                        ItemKind::Use(..) => {
-                            let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else {
-                                return;
-                            };
+        if let Some(lint_list) = &attr.meta_item_list()
+            && attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id))
+        {
+            for lint in lint_list {
+                match item.kind {
+                    ItemKind::Use(..) => {
+                        let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else {
+                            return;
+                        };
 
-                            if namespace.is_none()
-                                && matches!(
-                                    name.as_str(),
-                                    "ambiguous_glob_reexports"
-                                        | "dead_code"
-                                        | "deprecated"
-                                        | "hidden_glob_reexports"
-                                        | "unreachable_pub"
-                                        | "unused"
-                                        | "unused_braces"
-                                        | "unused_import_braces"
-                                        | "unused_imports"
-                                )
-                            {
-                                return;
-                            }
+                        if namespace.is_none()
+                            && matches!(
+                                name.as_str(),
+                                "ambiguous_glob_reexports"
+                                    | "dead_code"
+                                    | "deprecated"
+                                    | "hidden_glob_reexports"
+                                    | "unreachable_pub"
+                                    | "unused"
+                                    | "unused_braces"
+                                    | "unused_import_braces"
+                                    | "unused_imports"
+                            )
+                        {
+                            return;
+                        }
 
-                            if namespace == Some(sym::clippy)
-                                && matches!(
-                                    name.as_str(),
-                                    "wildcard_imports"
-                                        | "enum_glob_use"
-                                        | "redundant_pub_crate"
-                                        | "macro_use_imports"
-                                        | "unsafe_removed_from_name"
-                                        | "module_name_repetitions"
-                                        | "single_component_path_imports"
-                                        | "disallowed_types"
-                                        | "unused_trait_names"
-                                )
-                            {
-                                return;
-                            }
-                        },
-                        ItemKind::ExternCrate(..) => {
-                            if is_word(lint, sym::unused_imports) && skip_unused_imports {
-                                return;
-                            }
-                            if is_word(lint, sym::unused_extern_crates) {
-                                return;
-                            }
-                        },
-                        _ => {},
-                    }
+                        if namespace == Some(sym::clippy)
+                            && matches!(
+                                name.as_str(),
+                                "wildcard_imports"
+                                    | "enum_glob_use"
+                                    | "redundant_pub_crate"
+                                    | "macro_use_imports"
+                                    | "unsafe_removed_from_name"
+                                    | "module_name_repetitions"
+                                    | "single_component_path_imports"
+                                    | "disallowed_types"
+                                    | "unused_trait_names"
+                            )
+                        {
+                            return;
+                        }
+                    },
+                    ItemKind::ExternCrate(..) => {
+                        if is_word(lint, sym::unused_imports) && skip_unused_imports {
+                            return;
+                        }
+                        if is_word(lint, sym::unused_extern_crates) {
+                            return;
+                        }
+                    },
+                    _ => {},
                 }
-                let line_span = first_line_of_span(cx, attr.span);
+            }
+            let line_span = first_line_of_span(cx, attr.span);
 
-                if let Some(src) = line_span.get_source_text(cx) {
-                    if src.contains("#[") {
-                        #[expect(clippy::collapsible_span_lint_calls)]
-                        span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
-                            diag.span_suggestion(
-                                line_span,
-                                "if you just forgot a `!`, use",
-                                src.replacen("#[", "#![", 1),
-                                Applicability::MaybeIncorrect,
-                            );
-                        });
-                    }
-                }
+            if let Some(src) = line_span.get_source_text(cx)
+                && src.contains("#[")
+            {
+                #[expect(clippy::collapsible_span_lint_calls)]
+                span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
+                    diag.span_suggestion(
+                        line_span,
+                        "if you just forgot a `!`, use",
+                        src.replacen("#[", "#![", 1),
+                        Applicability::MaybeIncorrect,
+                    );
+                });
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index 92a0c7f9acb..52d1d5b4c67 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -179,9 +179,14 @@ pub struct AwaitHolding {
 
 impl AwaitHolding {
     pub(crate) fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
-        Self {
-            def_ids: create_disallowed_map(tcx, &conf.await_holding_invalid_types),
-        }
+        let (def_ids, _) = create_disallowed_map(
+            tcx,
+            &conf.await_holding_invalid_types,
+            crate::disallowed_types::def_kind_predicate,
+            "type",
+            false,
+        );
+        Self { def_ids }
     }
 }
 
@@ -192,10 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for AwaitHolding {
             def_id,
             ..
         }) = expr.kind
+            && let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(*def_id)
         {
-            if let Some(coroutine_layout) = cx.tcx.mir_coroutine_witnesses(*def_id) {
-                self.check_interior_types(cx, coroutine_layout);
-            }
+            self.check_interior_types(cx, coroutine_layout);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
index 612712d1684..129e7747840 100644
--- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::HasSession;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{is_else_clause, is_in_const_context};
+use clippy_utils::{higher, is_else_clause, is_in_const_context, span_contains_comment};
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -46,18 +47,25 @@ declare_lint_pass!(BoolToIntWithIf => [BOOL_TO_INT_WITH_IF]);
 
 impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::If(cond, then, Some(else_)) = expr.kind
-            && matches!(cond.kind, ExprKind::DropTemps(_))
+        if !expr.span.from_expansion()
+            && let Some(higher::If {
+                cond,
+                then,
+                r#else: Some(r#else),
+            }) = higher::If::hir(expr)
             && let Some(then_lit) = as_int_bool_lit(then)
-            && let Some(else_lit) = as_int_bool_lit(else_)
+            && let Some(else_lit) = as_int_bool_lit(r#else)
             && then_lit != else_lit
-            && !expr.span.from_expansion()
             && !is_in_const_context(cx)
         {
             let ty = cx.typeck_results().expr_ty(then);
-            let mut applicability = Applicability::MachineApplicable;
+            let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+                Applicability::MaybeIncorrect
+            } else {
+                Applicability::MachineApplicable
+            };
             let snippet = {
-                let mut sugg = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
+                let mut sugg = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "..", &mut applicability);
                 if !then_lit {
                     sugg = !sugg;
                 }
@@ -72,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
                 s
             };
 
-            let into_snippet = snippet.clone().maybe_par();
+            let into_snippet = snippet.clone().maybe_paren();
             let as_snippet = snippet.as_ty(ty);
 
             span_lint_and_then(
@@ -91,10 +99,11 @@ impl<'tcx> LateLintPass<'tcx> for BoolToIntWithIf {
     }
 }
 
-fn as_int_bool_lit(e: &Expr<'_>) -> Option<bool> {
-    if let ExprKind::Block(b, _) = e.kind
+fn as_int_bool_lit(expr: &Expr<'_>) -> Option<bool> {
+    if let ExprKind::Block(b, _) = expr.kind
         && b.stmts.is_empty()
         && let Some(e) = b.expr
+        && !e.span.from_expansion()
         && let ExprKind::Lit(lit) = e.kind
         && let LitKind::Int(x, _) = lit.node
     {
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 7bb5dbee126..bc6ba84772b 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -13,7 +13,7 @@ use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
 use rustc_lint::{LateContext, LateLintPass, Level};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{Span, sym};
+use rustc_span::{Span, SyntaxContext, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -242,11 +242,11 @@ struct Hir2Qmm<'a, 'tcx, 'v> {
 impl<'v> Hir2Qmm<'_, '_, 'v> {
     fn extract(&mut self, op: BinOpKind, a: &[&'v Expr<'_>], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
         for a in a {
-            if let ExprKind::Binary(binop, lhs, rhs) = &a.kind {
-                if binop.node == op {
-                    v = self.extract(op, &[lhs, rhs], v)?;
-                    continue;
-                }
+            if let ExprKind::Binary(binop, lhs, rhs) = &a.kind
+                && binop.node == op
+            {
+                v = self.extract(op, &[lhs, rhs], v)?;
+                continue;
             }
             v.push(self.run(a)?);
         }
@@ -349,9 +349,13 @@ impl SuggestContext<'_, '_, '_> {
                     if let Some(str) = simplify_not(self.cx, self.msrv, terminal) {
                         self.output.push_str(&str);
                     } else {
-                        self.output.push('!');
-                        self.output
-                            .push_str(&Sugg::hir_opt(self.cx, terminal)?.maybe_par().to_string());
+                        let mut app = Applicability::MachineApplicable;
+                        let snip = Sugg::hir_with_context(self.cx, terminal, SyntaxContext::root(), "", &mut app);
+                        // Ignore the case If the expression is inside a macro expansion, or the default snippet is used
+                        if app != Applicability::MachineApplicable {
+                            return None;
+                        }
+                        self.output.push_str(&(!snip).to_string());
                     }
                 },
                 True | False | Not(_) => {
@@ -414,12 +418,12 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: Msrv, expr: &Expr<'_>) -> Optio
                 let lhs_snippet = lhs.span.get_source_text(cx)?;
                 let rhs_snippet = rhs.span.get_source_text(cx)?;
 
-                if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) {
-                    if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) {
-                        // e.g. `(a as u64) < b`. Without the parens the `<` is
-                        // interpreted as a start of generic arguments for `u64`
-                        return Some(format!("({lhs_snippet}){op}{rhs_snippet}"));
-                    }
+                if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')'))
+                    && let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node)
+                {
+                    // e.g. `(a as u64) < b`. Without the parens the `<` is
+                    // interpreted as a start of generic arguments for `u64`
+                    return Some(format!("({lhs_snippet}){op}{rhs_snippet}"));
                 }
 
                 Some(format!("{lhs_snippet}{op}{rhs_snippet}"))
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index 8892a9e6b6b..7cde007a9b6 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -2,7 +2,7 @@ use crate::reference::DEREF_ADDROF;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed};
+use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed, is_mutable};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -73,6 +73,9 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
                 }
             })
             && !is_from_proc_macro(cx, e)
+            && let e_ty = cx.typeck_results().expr_ty_adjusted(e)
+            // check if the reference is coercing to a mutable reference
+            && (!matches!(e_ty.kind(), ty::Ref(_, _, Mutability::Mut)) || is_mutable(cx, deref_target))
             && let Some(deref_text) = deref_target.span.get_source_text(cx)
         {
             span_lint_and_then(
@@ -90,10 +93,10 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
 
                     // has deref trait -> give 2 help
                     // doesn't have deref trait -> give 1 help
-                    if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait() {
-                        if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) {
-                            return;
-                        }
+                    if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait()
+                        && !implements_trait(cx, *inner_ty, deref_trait_id, &[])
+                    {
+                        return;
                     }
 
                     diag.span_suggestion(
diff --git a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
index 64345c81a24..ad0a4f8cdf3 100644
--- a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -1,11 +1,12 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::{is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core};
+use clippy_utils::{get_parent_expr, is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::adjustment::{Adjust, AutoBorrow};
 use rustc_span::BytePos;
 
 use super::BORROW_AS_PTR;
@@ -29,10 +30,6 @@ pub(super) fn check<'tcx>(
         }
 
         let (suggestion, span) = if msrv.meets(cx, msrvs::RAW_REF_OP) {
-            let operator_kind = match mutability {
-                Mutability::Not => "const",
-                Mutability::Mut => "mut",
-            };
             // Make sure that the span to be replaced doesn't include parentheses, that could break the
             // suggestion.
             let span = if has_enclosing_paren(snippet_with_applicability(cx, expr.span, "", &mut app)) {
@@ -42,7 +39,7 @@ pub(super) fn check<'tcx>(
             } else {
                 expr.span
             };
-            (format!("&raw {operator_kind} {snip}"), span)
+            (format!("&raw {} {snip}", mutability.ptr_str()), span)
         } else {
             let Some(std_or_core) = std_or_core(cx) else {
                 return false;
@@ -59,3 +56,25 @@ pub(super) fn check<'tcx>(
     }
     false
 }
+
+/// Check for an implicit cast from reference to raw pointer outside an explicit `as`.
+pub(super) fn check_implicit_cast(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if !expr.span.from_expansion()
+        && let ExprKind::AddrOf(BorrowKind::Ref, _, pointee) = expr.kind
+        && !matches!(get_parent_expr(cx, expr).map(|e| e.kind), Some(ExprKind::Cast(..)))
+        && let [deref, borrow] = cx.typeck_results().expr_adjustments(expr)
+        && matches!(deref.kind, Adjust::Deref(..))
+        && let Adjust::Borrow(AutoBorrow::RawPtr(mutability)) = borrow.kind
+        // Do not suggest taking a raw pointer to a temporary value
+        && !is_expr_temporary_value(cx, pointee)
+    {
+        span_lint_and_then(cx, BORROW_AS_PTR, expr.span, "implicit borrow as raw pointer", |diag| {
+            diag.span_suggestion_verbose(
+                expr.span.until(pointee.span),
+                "use a raw pointer instead",
+                format!("&raw {} ", mutability.ptr_str()),
+                Applicability::MachineApplicable,
+            );
+        });
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
index 8b3529e84fc..164d3540253 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
@@ -36,7 +36,7 @@ pub(super) fn check(
             span,
             format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
             "replace with",
-            format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()),
+            format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_paren()),
             Applicability::MachineApplicable,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index 3ae43732dc0..0f066fae118 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -42,7 +42,7 @@ pub(super) fn check(
                     diag.span_suggestion_verbose(
                         expr.span,
                         "use `Into::into` instead",
-                        format!("{}.into()", from_sugg.maybe_par()),
+                        format!("{}.into()", from_sugg.maybe_paren()),
                         applicability,
                     );
                 },
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index ca973f4bb1a..8742f5f1a0e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -64,11 +64,11 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::MAX))
         },
         ExprKind::MethodCall(method, _, [lo, hi], _) => {
-            if method.ident.as_str() == "clamp" {
+            if method.ident.as_str() == "clamp"
                 //FIXME: make this a diagnostic item
-                if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
-                    return lo_bits.max(hi_bits);
-                }
+                && let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi))
+            {
+                return lo_bits.max(hi_bits);
             }
             nbits
         },
@@ -185,7 +185,7 @@ fn offer_suggestion(
 ) {
     let cast_to_snip = snippet(cx, cast_to_span, "..");
     let suggestion = if cast_to_snip == "_" {
-        format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_par())
+        format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_paren())
     } else {
         format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
     };
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
index 57a135abc2e..3fca0f89707 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -19,16 +19,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
             cx.typeck_results().expr_ty(expr),
         );
         lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
-    } else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind {
-        if method_path.ident.name.as_str() == "cast"
-            && let Some(generic_args) = method_path.args
-            && let [GenericArg::Type(cast_to)] = generic_args.args
-            // There probably is no obvious reason to do this, just to be consistent with `as` cases.
-            && !is_hir_ty_cfg_dependant(cx, cast_to.as_unambig_ty())
-        {
-            let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
-            lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
-        }
+    } else if let ExprKind::MethodCall(method_path, self_arg, [], _) = &expr.kind
+        && method_path.ident.name.as_str() == "cast"
+        && let Some(generic_args) = method_path.args
+        && let [GenericArg::Type(cast_to)] = generic_args.args
+        // There probably is no obvious reason to do this, just to be consistent with `as` cases.
+        && !is_hir_ty_cfg_dependant(cx, cast_to.as_unambig_ty())
+    {
+        let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
+        lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
index c48f253606d..a5b295c88b1 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -21,42 +21,41 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Msrv)
         start_ty,
         end_ty,
     }) = expr_cast_chain_tys(cx, expr)
+        && let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(start_ty.ty), cx.layout_of(end_ty.ty))
     {
-        if let (Ok(from_layout), Ok(to_layout)) = (cx.layout_of(start_ty.ty), cx.layout_of(end_ty.ty)) {
-            let from_size = from_layout.size.bytes();
-            let to_size = to_layout.size.bytes();
-            if from_size != to_size && from_size != 0 && to_size != 0 && msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) {
-                span_lint_and_then(
-                    cx,
-                    CAST_SLICE_DIFFERENT_SIZES,
-                    expr.span,
-                    format!(
-                        "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count",
-                        start_ty.ty, end_ty.ty,
-                    ),
-                    |diag| {
-                        let ptr_snippet = source::snippet(cx, left_cast.span, "..");
+        let from_size = from_layout.size.bytes();
+        let to_size = to_layout.size.bytes();
+        if from_size != to_size && from_size != 0 && to_size != 0 && msrv.meets(cx, msrvs::PTR_SLICE_RAW_PARTS) {
+            span_lint_and_then(
+                cx,
+                CAST_SLICE_DIFFERENT_SIZES,
+                expr.span,
+                format!(
+                    "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count",
+                    start_ty.ty, end_ty.ty,
+                ),
+                |diag| {
+                    let ptr_snippet = source::snippet(cx, left_cast.span, "..");
 
-                        let (mutbl_fn_str, mutbl_ptr_str) = match end_ty.mutbl {
-                            Mutability::Mut => ("_mut", "mut"),
-                            Mutability::Not => ("", "const"),
-                        };
-                        let sugg = format!(
-                            "core::ptr::slice_from_raw_parts{mutbl_fn_str}({ptr_snippet} as *{mutbl_ptr_str} {}, ..)",
-                            // get just the ty from the TypeAndMut so that the printed type isn't something like `mut
-                            // T`, extract just the `T`
-                            end_ty.ty
-                        );
+                    let (mutbl_fn_str, mutbl_ptr_str) = match end_ty.mutbl {
+                        Mutability::Mut => ("_mut", "mut"),
+                        Mutability::Not => ("", "const"),
+                    };
+                    let sugg = format!(
+                        "core::ptr::slice_from_raw_parts{mutbl_fn_str}({ptr_snippet} as *{mutbl_ptr_str} {}, ..)",
+                        // get just the ty from the TypeAndMut so that the printed type isn't something like `mut
+                        // T`, extract just the `T`
+                        end_ty.ty
+                    );
 
-                        diag.span_suggestion(
-                            expr.span,
-                            format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
-                            sugg,
-                            rustc_errors::Applicability::HasPlaceholders,
-                        );
-                    },
-                );
-            }
+                    diag.span_suggestion(
+                        expr.span,
+                        format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
+                        sugg,
+                        rustc_errors::Applicability::HasPlaceholders,
+                    );
+                },
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs
new file mode 100644
index 00000000000..8ace27eca89
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs
@@ -0,0 +1,82 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::SpanRangeExt;
+use clippy_utils::ty::is_normalizable;
+use clippy_utils::{expr_or_init, match_def_path, path_def_id, paths, std_or_core};
+use rustc_ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, Ty, TyKind};
+use rustc_lint::LateContext;
+use rustc_span::source_map::Spanned;
+
+use super::MANUAL_DANGLING_PTR;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) {
+    if let TyKind::Ptr(ref ptr_ty) = to.kind {
+        let init_expr = expr_or_init(cx, from);
+        if is_expr_const_aligned(cx, init_expr, ptr_ty.ty)
+            && let Some(std_or_core) = std_or_core(cx)
+        {
+            let sugg_fn = match ptr_ty.mutbl {
+                Mutability::Not => "ptr::dangling",
+                Mutability::Mut => "ptr::dangling_mut",
+            };
+
+            let sugg = if let TyKind::Infer(()) = ptr_ty.ty.kind {
+                format!("{std_or_core}::{sugg_fn}()")
+            } else if let Some(mut_ty_snip) = ptr_ty.ty.span.get_source_text(cx) {
+                format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
+            } else {
+                return;
+            };
+
+            span_lint_and_sugg(
+                cx,
+                MANUAL_DANGLING_PTR,
+                expr.span,
+                "manual creation of a dangling pointer",
+                "use",
+                sugg,
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
+
+// Checks if the given expression is a call to `align_of` whose generic argument matches the target
+// type, or a positive constant literal that matches the target type's alignment.
+fn is_expr_const_aligned(cx: &LateContext<'_>, expr: &Expr<'_>, to: &Ty<'_>) -> bool {
+    match expr.kind {
+        ExprKind::Call(fun, _) => is_align_of_call(cx, fun, to),
+        ExprKind::Lit(lit) => is_literal_aligned(cx, lit, to),
+        _ => false,
+    }
+}
+
+fn is_align_of_call(cx: &LateContext<'_>, fun: &Expr<'_>, to: &Ty<'_>) -> bool {
+    if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind
+        && let Some(fun_id) = path_def_id(cx, fun)
+        && match_def_path(cx, fun_id, &paths::ALIGN_OF)
+        && let Some(args) = path.segments.last().and_then(|seg| seg.args)
+        && let [GenericArg::Type(generic_ty)] = args.args
+    {
+        let typeck = cx.typeck_results();
+        return typeck.node_type(generic_ty.hir_id) == typeck.node_type(to.hir_id);
+    }
+    false
+}
+
+fn is_literal_aligned(cx: &LateContext<'_>, lit: &Spanned<LitKind>, to: &Ty<'_>) -> bool {
+    let LitKind::Int(val, _) = lit.node else { return false };
+    if val == 0 {
+        return false;
+    }
+    let to_mid_ty = cx.typeck_results().node_type(to.hir_id);
+    is_normalizable(cx, cx.param_env, to_mid_ty)
+        && cx
+            .tcx
+            .layout_of(cx.typing_env().as_query_input(to_mid_ty))
+            .is_ok_and(|layout| {
+                let align = u128::from(layout.align.abi.bytes());
+                u128::from(val) <= align
+            })
+}
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index dc2a1fa85bf..76931fce209 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -17,6 +17,7 @@ mod char_lit_as_u8;
 mod fn_to_numeric_cast;
 mod fn_to_numeric_cast_any;
 mod fn_to_numeric_cast_with_truncation;
+mod manual_dangling_ptr;
 mod ptr_as_ptr;
 mod ptr_cast_constness;
 mod ref_as_ptr;
@@ -71,7 +72,7 @@ declare_clippy_lint! {
     /// ### Example
     /// ```no_run
     /// let y: i8 = -1;
-    /// y as u128; // will return 18446744073709551615
+    /// y as u64; // will return 18446744073709551615
     /// ```
     #[clippy::version = "pre 1.29.0"]
     pub CAST_SIGN_LOSS,
@@ -759,6 +760,32 @@ declare_clippy_lint! {
     "detects `as *mut _` and `as *const _` conversion"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for casts of small constant literals or `mem::align_of` results to raw pointers.
+    ///
+    /// ### Why is this bad?
+    /// This creates a dangling pointer and is better expressed as
+    /// {`std`, `core`}`::ptr::`{`dangling`, `dangling_mut`}.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let ptr = 4 as *const u32;
+    /// let aligned = std::mem::align_of::<u32>() as *const u32;
+    /// let mut_ptr: *mut i64 = 8 as *mut _;
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let ptr = std::ptr::dangling::<u32>();
+    /// let aligned = std::ptr::dangling::<u32>();
+    /// let mut_ptr: *mut i64 = std::ptr::dangling_mut();
+    /// ```
+    #[clippy::version = "1.87.0"]
+    pub MANUAL_DANGLING_PTR,
+    style,
+    "casting small constant literals to pointers to create dangling pointers"
+}
+
 pub struct Casts {
     msrv: Msrv,
 }
@@ -795,6 +822,7 @@ impl_lint_pass!(Casts => [
     ZERO_PTR,
     REF_AS_PTR,
     AS_POINTER_UNDERSCORE,
+    MANUAL_DANGLING_PTR,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Casts {
@@ -823,6 +851,10 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to);
             zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
 
+            if self.msrv.meets(cx, msrvs::MANUAL_DANGLING_PTR) {
+                manual_dangling_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
+            }
+
             if cast_to.is_numeric() {
                 cast_possible_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir.span);
                 if cast_from.is_numeric() {
@@ -846,6 +878,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             }
         }
 
+        if self.msrv.meets(cx, msrvs::RAW_REF_OP) {
+            borrow_as_ptr::check_implicit_cast(cx, expr);
+        }
         cast_ptr_alignment::check(cx, expr);
         char_lit_as_u8::check(cx, expr);
         ptr_as_ptr::check(cx, expr, self.msrv);
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index d57e391b55d..6f944914b8f 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -81,7 +81,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) {
 
             (
                 "try `pointer::cast`, a safer alternative",
-                format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
+                format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_paren()),
             )
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
index cad9c1df273..2471c735551 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -53,7 +53,8 @@ pub(super) fn check<'tcx>(
         }
 
         if msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS) {
-            let sugg = Sugg::hir(cx, cast_expr, "_");
+            let mut app = Applicability::MachineApplicable;
+            let sugg = Sugg::hir_with_context(cx, cast_expr, expr.span.ctxt(), "_", &mut app);
             let constness = match *to_mutbl {
                 Mutability::Not => "const",
                 Mutability::Mut => "mut",
@@ -65,8 +66,8 @@ pub(super) fn check<'tcx>(
                 expr.span,
                 "`as` casting between raw pointers while changing only its constness",
                 format!("try `pointer::cast_{constness}`, a safer alternative"),
-                format!("{}.cast_{constness}()", sugg.maybe_par()),
-                Applicability::MachineApplicable,
+                format!("{}.cast_{constness}()", sugg.maybe_paren()),
+                app,
             );
         }
     }
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 72953818a70..ae994e94a32 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -130,11 +130,11 @@ pub(super) fn check<'tcx>(
             | LitKind::Float(_, LitFloatType::Suffixed(_))
                 if cast_from.kind() == cast_to.kind() =>
             {
-                if let Some(src) = cast_expr.span.get_source_text(cx) {
-                    if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
-                        lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
-                        return true;
-                    }
+                if let Some(src) = cast_expr.span.get_source_text(cx)
+                    && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
+                {
+                    lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
+                    return true;
                 }
             },
             _ => {},
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index b36c8662289..8ada608049c 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -253,11 +253,11 @@ fn get_types_from_cast<'a>(
         match limit.kind {
             // `from_type::from(_)`
             ExprKind::Call(path, _) => {
-                if let ExprKind::Path(ref path) = path.kind {
+                if let ExprKind::Path(ref path) = path.kind
                     // `to_type`
-                    if let Some(to_type) = get_implementing_type(path, types, func) {
-                        return Some((from_type, to_type));
-                    }
+                    && let Some(to_type) = get_implementing_type(path, types, func)
+                {
+                    return Some((from_type, to_type));
                 }
             },
             // `to_type::MAX`
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index a1ff20dee72..1d44c7e9c88 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -62,6 +62,7 @@ impl CognitiveComplexity {
 
         let mut cc = 1u64;
         let mut returns = 0u64;
+        let mut prev_expr: Option<&ExprKind<'tcx>> = None;
         let _: Option<!> = for_each_expr_without_closures(expr, |e| {
             match e.kind {
                 ExprKind::If(_, _, _) => {
@@ -73,9 +74,14 @@ impl CognitiveComplexity {
                     }
                     cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64;
                 },
-                ExprKind::Ret(_) => returns += 1,
+                ExprKind::Ret(_) => {
+                    if !matches!(prev_expr, Some(ExprKind::Ret(_))) {
+                        returns += 1;
+                    }
+                },
                 _ => {},
             }
+            prev_expr = Some(&e.kind);
             ControlFlow::Continue(())
         });
 
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
index e73bfc6ebf7..20fae8a6775 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
@@ -1,10 +1,12 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability};
-use clippy_utils::sugg::Sugg;
-use rustc_ast::ast;
+use clippy_utils::source::{IntoSpan as _, SpanRangeExt, snippet, snippet_block, snippet_block_with_applicability};
+use rustc_ast::BinOpKind;
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_hir::{Block, Expr, ExprKind, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
+use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
 declare_clippy_lint! {
@@ -75,105 +77,152 @@ declare_clippy_lint! {
     "nested `else`-`if` expressions that can be collapsed (e.g., `else { if x { ... } }`)"
 }
 
-declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
+pub struct CollapsibleIf {
+    let_chains_enabled: bool,
+    lint_commented_code: bool,
+}
+
+impl CollapsibleIf {
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
+        Self {
+            let_chains_enabled: tcx.features().let_chains(),
+            lint_commented_code: conf.lint_commented_code,
+        }
+    }
 
-impl EarlyLintPass for CollapsibleIf {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        if let ast::ExprKind::If(cond, then, else_) = &expr.kind
+    fn check_collapsible_else_if(cx: &LateContext<'_>, then_span: Span, else_block: &Block<'_>) {
+        if !block_starts_with_comment(cx, else_block)
+            && let Some(else_) = expr_block(else_block)
+            && cx.tcx.hir_attrs(else_.hir_id).is_empty()
+            && !else_.span.from_expansion()
+            && let ExprKind::If(..) = else_.kind
+        {
+            // Prevent "elseif"
+            // Check that the "else" is followed by whitespace
+            let up_to_else = then_span.between(else_block.span);
+            let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() {
+                !c.is_whitespace()
+            } else {
+                false
+            };
+
+            let mut applicability = Applicability::MachineApplicable;
+            span_lint_and_sugg(
+                cx,
+                COLLAPSIBLE_ELSE_IF,
+                else_block.span,
+                "this `else { if .. }` block can be collapsed",
+                "collapse nested if block",
+                format!(
+                    "{}{}",
+                    if requires_space { " " } else { "" },
+                    snippet_block_with_applicability(cx, else_.span, "..", Some(else_block.span), &mut applicability)
+                ),
+                applicability,
+            );
+        }
+    }
+
+    fn check_collapsible_if_if(&self, cx: &LateContext<'_>, expr: &Expr<'_>, check: &Expr<'_>, then: &Block<'_>) {
+        if let Some(inner) = expr_block(then)
+            && cx.tcx.hir_attrs(inner.hir_id).is_empty()
+            && let ExprKind::If(check_inner, _, None) = &inner.kind
+            && self.eligible_condition(check_inner)
+            && let ctxt = expr.span.ctxt()
+            && inner.span.ctxt() == ctxt
+            && (self.lint_commented_code || !block_starts_with_comment(cx, then))
+        {
+            span_lint_and_then(
+                cx,
+                COLLAPSIBLE_IF,
+                expr.span,
+                "this `if` statement can be collapsed",
+                |diag| {
+                    let then_open_bracket = then.span.split_at(1).0.with_leading_whitespace(cx).into_span();
+                    let then_closing_bracket = {
+                        let end = then.span.shrink_to_hi();
+                        end.with_lo(end.lo() - rustc_span::BytePos(1))
+                            .with_leading_whitespace(cx)
+                            .into_span()
+                    };
+                    let inner_if = inner.span.split_at(2).0;
+                    let mut sugg = vec![
+                        // Remove the outer then block `{`
+                        (then_open_bracket, String::new()),
+                        // Remove the outer then block '}'
+                        (then_closing_bracket, String::new()),
+                        // Replace inner `if` by `&&`
+                        (inner_if, String::from("&&")),
+                    ];
+                    sugg.extend(parens_around(check));
+                    sugg.extend(parens_around(check_inner));
+
+                    diag.multipart_suggestion("collapse nested if block", sugg, Applicability::MachineApplicable);
+                },
+            );
+        }
+    }
+
+    pub fn eligible_condition(&self, cond: &Expr<'_>) -> bool {
+        self.let_chains_enabled || !matches!(cond.kind, ExprKind::Let(..))
+    }
+}
+
+impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
+
+impl LateLintPass<'_> for CollapsibleIf {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let ExprKind::If(cond, then, else_) = &expr.kind
             && !expr.span.from_expansion()
         {
-            if let Some(else_) = else_ {
-                check_collapsible_maybe_if_let(cx, then.span, else_);
-            } else if !matches!(cond.kind, ast::ExprKind::Let(..)) {
-                check_collapsible_no_if_let(cx, expr, cond, then);
+            if let Some(else_) = else_
+                && let ExprKind::Block(else_, None) = else_.kind
+            {
+                Self::check_collapsible_else_if(cx, then.span, else_);
+            } else if else_.is_none()
+                && self.eligible_condition(cond)
+                && let ExprKind::Block(then, None) = then.kind
+            {
+                self.check_collapsible_if_if(cx, expr, cond, then);
             }
         }
     }
 }
 
-fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
+fn block_starts_with_comment(cx: &LateContext<'_>, block: &Block<'_>) -> bool {
     // We trim all opening braces and whitespaces and then check if the next string is a comment.
-    let trimmed_block_text = snippet_block(cx, expr.span, "..", None)
+    let trimmed_block_text = snippet_block(cx, block.span, "..", None)
         .trim_start_matches(|c: char| c.is_whitespace() || c == '{')
         .to_owned();
     trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*")
 }
 
-fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) {
-    if let ast::ExprKind::Block(ref block, _) = else_.kind
-        && !block_starts_with_comment(cx, block)
-        && let Some(else_) = expr_block(block)
-        && else_.attrs.is_empty()
-        && !else_.span.from_expansion()
-        && let ast::ExprKind::If(..) = else_.kind
-    {
-        // Prevent "elseif"
-        // Check that the "else" is followed by whitespace
-        let up_to_else = then_span.between(block.span);
-        let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() {
-            !c.is_whitespace()
-        } else {
-            false
-        };
-
-        let mut applicability = Applicability::MachineApplicable;
-        span_lint_and_sugg(
-            cx,
-            COLLAPSIBLE_ELSE_IF,
-            block.span,
-            "this `else { if .. }` block can be collapsed",
-            "collapse nested if block",
-            format!(
-                "{}{}",
-                if requires_space { " " } else { "" },
-                snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability)
-            ),
-            applicability,
-        );
-    }
-}
-
-fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) {
-    if !block_starts_with_comment(cx, then)
-        && let Some(inner) = expr_block(then)
-        && inner.attrs.is_empty()
-        && let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind
-        // Prevent triggering on `if c { if let a = b { .. } }`.
-        && !matches!(check_inner.kind, ast::ExprKind::Let(..))
-        && let ctxt = expr.span.ctxt()
-        && inner.span.ctxt() == ctxt
-    {
-        span_lint_and_then(
-            cx,
-            COLLAPSIBLE_IF,
-            expr.span,
-            "this `if` statement can be collapsed",
-            |diag| {
-                let mut app = Applicability::MachineApplicable;
-                let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app);
-                let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app);
-                diag.span_suggestion(
-                    expr.span,
-                    "collapse nested if block",
-                    format!(
-                        "if {} {}",
-                        lhs.and(&rhs),
-                        snippet_block(cx, content.span, "..", Some(expr.span)),
-                    ),
-                    app, // snippet
-                );
-            },
-        );
+/// If `block` is a block with either one expression or a statement containing an expression,
+/// return the expression. We don't peel blocks recursively, as extra blocks might be intentional.
+fn expr_block<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    match block.stmts {
+        [] => block.expr,
+        [stmt] => {
+            if let StmtKind::Semi(expr) = stmt.kind {
+                Some(expr)
+            } else {
+                None
+            }
+        },
+        _ => None,
     }
 }
 
-/// If the block contains only one expression, return it.
-fn expr_block(block: &ast::Block) -> Option<&ast::Expr> {
-    if let [stmt] = &*block.stmts
-        && let ast::StmtKind::Expr(expr) | ast::StmtKind::Semi(expr) = &stmt.kind
+/// If the expression is a `||`, suggest parentheses around it.
+fn parens_around(expr: &Expr<'_>) -> Vec<(Span, String)> {
+    if let ExprKind::Binary(op, _, _) = expr.peel_drop_temps().kind
+        && op.node == BinOpKind::Or
     {
-        Some(expr)
+        vec![
+            (expr.span.shrink_to_lo(), String::from("(")),
+            (expr.span.shrink_to_hi(), String::from(")")),
+        ]
     } else {
-        None
+        vec![]
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index 0e7f01e44b0..9c3009a86cd 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -125,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
         let ExprKind::Binary(_, lhs, rhs) = conds[0].kind else {
             unreachable!();
         };
-        let lhs = Sugg::hir(cx, lhs, "..").maybe_par();
+        let lhs = Sugg::hir(cx, lhs, "..").maybe_paren();
         let rhs = Sugg::hir(cx, rhs, "..").addr();
         span_lint_and_sugg(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 03ed9c657b3..42fbe6438d4 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -256,7 +256,7 @@ fn lint_branches_sharing_code<'tcx>(
         let suggestion = reindent_multiline(&suggestion, true, indent);
 
         let span = span.with_hi(last_block.span.hi());
-        // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
+        // Improve formatting if the inner block has indentation (i.e. normal Rust formatting)
         let span = span
             .map_range(cx, |src, range| {
                 (range.start > 4 && src.get(range.start - 4..range.start)? == "    ")
@@ -539,10 +539,10 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
                     .filter(|stmt| !ignore_span.overlaps(stmt.span))
                     .try_for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt));
 
-                if let Some(expr) = block.expr {
-                    if res.is_continue() {
-                        res = intravisit::walk_expr(&mut walker, expr);
-                    }
+                if let Some(expr) = block.expr
+                    && res.is_continue()
+                {
+                    res = intravisit::walk_expr(&mut walker, expr);
                 }
 
                 res.is_break()
diff --git a/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs b/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs
index 4d908af4084..9f82f876727 100644
--- a/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs
+++ b/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs
@@ -165,17 +165,4 @@ macro_rules! declare_clippy_lint {
             $(, $eval_always)?
         }
     };
-
-    (
-        $(#[doc = $lit:literal])*
-        pub $lint_name:ident,
-        internal,
-        $desc:literal
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Allow, crate::LintCategory::Internal, $desc,
-            None, "0.0.0"
-        }
-    };
 }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 39e45163707..2cccd6ba270 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -3,36 +3,6 @@
 // Manual edits will be overwritten.
 
 pub static LINTS: &[&crate::LintInfo] = &[
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::invalid_paths::INVALID_PATHS_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::slow_symbol_comparisons::SLOW_SYMBOL_COMPARISONS_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
-    #[cfg(feature = "internal")]
-    crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO,
     crate::absolute_paths::ABSOLUTE_PATHS_INFO,
     crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
     crate::approx_const::APPROX_CONSTANT_INFO,
@@ -52,6 +22,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
     crate::attrs::DUPLICATED_ATTRIBUTES_INFO,
+    crate::attrs::IGNORE_WITHOUT_REASON_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO,
     crate::attrs::NON_MINIMAL_CFG_INFO,
@@ -96,6 +67,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::casts::FN_TO_NUMERIC_CAST_INFO,
     crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO,
     crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
+    crate::casts::MANUAL_DANGLING_PTR_INFO,
     crate::casts::PTR_AS_PTR_INFO,
     crate::casts::PTR_CAST_CONSTNESS_INFO,
     crate::casts::REF_AS_PTR_INFO,
@@ -286,6 +258,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::literal_representation::UNREADABLE_LITERAL_INFO,
     crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO,
     crate::literal_string_with_formatting_args::LITERAL_STRING_WITH_FORMATTING_ARGS_INFO,
+    crate::loops::CHAR_INDICES_AS_BYTE_INDICES_INFO,
     crate::loops::EMPTY_LOOP_INFO,
     crate::loops::EXPLICIT_COUNTER_LOOP_INFO,
     crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO,
@@ -312,6 +285,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::macro_metavars_in_unsafe::MACRO_METAVARS_IN_UNSAFE_INFO,
     crate::macro_use::MACRO_USE_IMPORTS_INFO,
     crate::main_recursion::MAIN_RECURSION_INFO,
+    crate::manual_abs_diff::MANUAL_ABS_DIFF_INFO,
     crate::manual_assert::MANUAL_ASSERT_INFO,
     crate::manual_async_fn::MANUAL_ASYNC_FN_INFO,
     crate::manual_bits::MANUAL_BITS_INFO,
@@ -334,7 +308,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO,
     crate::manual_string_new::MANUAL_STRING_NEW_INFO,
     crate::manual_strip::MANUAL_STRIP_INFO,
-    crate::manual_unwrap_or_default::MANUAL_UNWRAP_OR_DEFAULT_INFO,
     crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO,
     crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO,
     crate::match_result_ok::MATCH_RESULT_OK_INFO,
@@ -344,10 +317,10 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::matches::MANUAL_MAP_INFO,
     crate::matches::MANUAL_OK_ERR_INFO,
     crate::matches::MANUAL_UNWRAP_OR_INFO,
+    crate::matches::MANUAL_UNWRAP_OR_DEFAULT_INFO,
     crate::matches::MATCH_AS_REF_INFO,
     crate::matches::MATCH_BOOL_INFO,
     crate::matches::MATCH_LIKE_MATCHES_MACRO_INFO,
-    crate::matches::MATCH_ON_VEC_ITEMS_INFO,
     crate::matches::MATCH_OVERLAPPING_ARM_INFO,
     crate::matches::MATCH_REF_PATS_INFO,
     crate::matches::MATCH_SAME_ARMS_INFO,
@@ -488,6 +461,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::methods::SUSPICIOUS_OPEN_OPTIONS_INFO,
     crate::methods::SUSPICIOUS_SPLITN_INFO,
     crate::methods::SUSPICIOUS_TO_OWNED_INFO,
+    crate::methods::SWAP_WITH_TEMPORARY_INFO,
     crate::methods::TYPE_ID_ON_BOX_INFO,
     crate::methods::UNBUFFERED_BYTES_INFO,
     crate::methods::UNINIT_ASSUMED_INIT_INFO,
@@ -664,6 +638,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::redundant_slicing::DEREF_BY_SLICING_INFO,
     crate::redundant_slicing::REDUNDANT_SLICING_INFO,
     crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
+    crate::redundant_test_prefix::REDUNDANT_TEST_PREFIX_INFO,
     crate::redundant_type_annotations::REDUNDANT_TYPE_ANNOTATIONS_INFO,
     crate::ref_option_ref::REF_OPTION_REF_INFO,
     crate::ref_patterns::REF_PATTERNS_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index bbd5dc15542..f8a9037fc80 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,5 +1,6 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_ty_alias;
+use clippy_utils::source::SpanRangeExt as _;
 use hir::ExprKind;
 use hir::def::Res;
 use rustc_errors::Applicability;
@@ -70,15 +71,26 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
             && let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant()
             && !var.is_field_list_non_exhaustive()
             && !expr.span.from_expansion() && !qpath.span().from_expansion()
+            // do not suggest replacing an expression by a type name with placeholders
+            && !base.is_suggestable_infer_ty()
         {
-            span_lint_and_sugg(
+            let mut removals = vec![(expr.span.with_lo(qpath.qself_span().hi()), String::new())];
+            if expr.span.with_source_text(cx, |s| s.starts_with('<')) == Some(true) {
+                // Remove `<`, '>` has already been removed by the existing removal expression.
+                removals.push((expr.span.with_hi(qpath.qself_span().lo()), String::new()));
+            }
+            span_lint_and_then(
                 cx,
                 DEFAULT_CONSTRUCTED_UNIT_STRUCTS,
-                expr.span.with_lo(qpath.qself_span().hi()),
+                expr.span,
                 "use of `default` to create a unit struct",
-                "remove this call to `default`",
-                String::new(),
-                Applicability::MachineApplicable,
+                |diag| {
+                    diag.multipart_suggestion(
+                        "remove this call to `default`",
+                        removals,
+                        Applicability::MachineApplicable,
+                    );
+                },
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index de66ead4f42..b60c11d79d4 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -42,6 +42,8 @@ declare_with_version! { DEPRECATED(DEPRECATED_VERSION): &[(&str, &str)] = &[
     ("clippy::wrong_pub_self_convention", "`clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config"),
     #[clippy::version = "1.86.0"]
     ("clippy::option_map_or_err_ok", "`clippy::manual_ok_or` covers this case"),
+    #[clippy::version = "1.86.0"]
+    ("clippy::match_on_vec_items", "`clippy::indexing_slicing` covers indexing and slicing on `Vec<_>`"),
     // end deprecated lints. used by `cargo dev deprecate_lint`
 ]}
 
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 849c60b89b9..7da5a530eaa 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1133,61 +1133,60 @@ fn report<'tcx>(
 
 impl<'tcx> Dereferencing<'tcx> {
     fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &Expr<'tcx>, local: HirId) {
-        if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
-            if let Some(pat) = outer_pat {
-                // Check for auto-deref
-                if !matches!(
-                    cx.typeck_results().expr_adjustments(e),
-                    [
-                        Adjustment {
-                            kind: Adjust::Deref(_),
-                            ..
-                        },
-                        Adjustment {
-                            kind: Adjust::Deref(_),
-                            ..
-                        },
+        if let Some(outer_pat) = self.ref_locals.get_mut(&local)
+            && let Some(pat) = outer_pat
+            // Check for auto-deref
+            && !matches!(
+                cx.typeck_results().expr_adjustments(e),
+                [
+                    Adjustment {
+                        kind: Adjust::Deref(_),
                         ..
-                    ]
-                ) {
-                    match get_parent_expr(cx, e) {
-                        // Field accesses are the same no matter the number of references.
-                        Some(Expr {
-                            kind: ExprKind::Field(..),
-                            ..
-                        }) => (),
-                        Some(&Expr {
-                            span,
-                            kind: ExprKind::Unary(UnOp::Deref, _),
-                            ..
-                        }) if !span.from_expansion() => {
-                            // Remove explicit deref.
-                            let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
-                            pat.replacements.push((span, snip.into()));
-                        },
-                        Some(parent) if !parent.span.from_expansion() => {
-                            // Double reference might be needed at this point.
-                            if parent.precedence() == ExprPrecedence::Unambiguous {
-                                // Parentheses would be needed here, don't lint.
-                                *outer_pat = None;
-                            } else {
-                                pat.always_deref = false;
-                                let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
-                                pat.replacements.push((e.span, format!("&{snip}")));
-                            }
-                        },
-                        _ if !e.span.from_expansion() => {
-                            // Double reference might be needed at this point.
-                            pat.always_deref = false;
-                            let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
-                            pat.replacements.push((e.span, format!("&{snip}")));
-                        },
-                        // Edge case for macros. The span of the identifier will usually match the context of the
-                        // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
-                        // macros
-                        _ => *outer_pat = None,
+                    },
+                    Adjustment {
+                        kind: Adjust::Deref(_),
+                        ..
+                    },
+                    ..
+                ]
+            )
+        {
+            match get_parent_expr(cx, e) {
+                // Field accesses are the same no matter the number of references.
+                Some(Expr {
+                    kind: ExprKind::Field(..),
+                    ..
+                }) => (),
+                Some(&Expr {
+                    span,
+                    kind: ExprKind::Unary(UnOp::Deref, _),
+                    ..
+                }) if !span.from_expansion() => {
+                    // Remove explicit deref.
+                    let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
+                    pat.replacements.push((span, snip.into()));
+                },
+                Some(parent) if !parent.span.from_expansion() => {
+                    // Double reference might be needed at this point.
+                    if parent.precedence() == ExprPrecedence::Unambiguous {
+                        // Parentheses would be needed here, don't lint.
+                        *outer_pat = None;
+                    } else {
+                        pat.always_deref = false;
+                        let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
+                        pat.replacements.push((e.span, format!("&{snip}")));
                     }
-                }
+                },
+                _ if !e.span.from_expansion() => {
+                    // Double reference might be needed at this point.
+                    pat.always_deref = false;
+                    let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
+                    pat.replacements.push((e.span, format!("&{snip}")));
+                },
+                // Edge case for macros. The span of the identifier will usually match the context of the
+                // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
+                // macros
+                _ => *outer_pat = None,
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 8d9222e4bf6..10331b3855b 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -94,18 +94,18 @@ fn check_struct<'tcx>(
     ty_args: GenericArgsRef<'_>,
     typeck_results: &'tcx TypeckResults<'tcx>,
 ) {
-    if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
-        if let Some(PathSegment { args, .. }) = p.segments.last() {
-            let args = args.map(|a| a.args).unwrap_or(&[]);
-
-            // ty_args contains the generic parameters of the type declaration, while args contains the
-            // arguments used at instantiation time. If both len are not equal, it means that some
-            // parameters were not provided (which means that the default values were used); in this
-            // case we will not risk suggesting too broad a rewrite. We won't either if any argument
-            // is a type or a const.
-            if ty_args.len() != args.len() || args.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_))) {
-                return;
-            }
+    if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind
+        && let Some(PathSegment { args, .. }) = p.segments.last()
+    {
+        let args = args.map(|a| a.args).unwrap_or(&[]);
+
+        // ty_args contains the generic parameters of the type declaration, while args contains the
+        // arguments used at instantiation time. If both len are not equal, it means that some
+        // parameters were not provided (which means that the default values were used); in this
+        // case we will not risk suggesting too broad a rewrite. We won't either if any argument
+        // is a type or a const.
+        if ty_args.len() != args.len() || args.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_))) {
+            return;
         }
     }
 
@@ -188,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             self_ty,
             ..
         }) = item.kind
-            && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
+            && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
             && !item.span.from_expansion()
             && let Some(def_id) = trait_ref.trait_def_id()
             && cx.tcx.is_diagnostic_item(sym::Default, def_id)
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index c85aca8d04e..06528f875a2 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
         }) = item.kind
         {
             let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            let is_automatically_derived = cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
+            let is_automatically_derived = cx.tcx.is_automatically_derived(item.owner_id.to_def_id());
 
             check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
             check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
@@ -235,7 +235,7 @@ fn check_hash_peq<'tcx>(
     {
         // Look for the PartialEq implementations for `ty`
         cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
-            let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
+            let peq_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id);
 
             if !hash_is_automatically_derived || peq_is_automatically_derived {
                 return;
@@ -278,7 +278,7 @@ fn check_ord_partial_ord<'tcx>(
     {
         // Look for the PartialOrd implementations for `ty`
         cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| {
-            let partial_ord_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
+            let partial_ord_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id);
 
             if partial_ord_is_automatically_derived == ord_is_automatically_derived {
                 return;
@@ -349,6 +349,10 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
     {
         return;
     }
+    // The presence of `unsafe` fields prevents deriving `Clone` automatically
+    if ty_adt.all_fields().any(|f| f.safety.is_unsafe()) {
+        return;
+    }
 
     span_lint_and_note(
         cx,
@@ -426,10 +430,10 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> Self::Result {
-        if let ExprKind::Block(block, _) = expr.kind {
-            if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) {
-                return ControlFlow::Break(());
-            }
+        if let ExprKind::Block(block, _) = expr.kind
+            && block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
+        {
+            return ControlFlow::Break(());
         }
 
         walk_expr(self, expr)
@@ -479,7 +483,7 @@ fn ty_implements_eq_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, eq_trait_id: De
     tcx.non_blanket_impls_for_ty(eq_trait_id, ty).next().is_some()
 }
 
-/// Creates the `ParamEnv` used for the give type's derived `Eq` impl.
+/// Creates the `ParamEnv` used for the given type's derived `Eq` impl.
 fn typing_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ty::TypingEnv<'_> {
     // Initial map from generic index to param def.
     // Vec<(param_def, needs_eq)>
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
index 4b8a689e994..fc6af204a74 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -4,6 +4,7 @@ use clippy_config::types::{DisallowedPath, create_disallowed_map};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::macros::macro_backtrace;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{
     AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
@@ -72,8 +73,15 @@ pub struct DisallowedMacros {
 
 impl DisallowedMacros {
     pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf, earlies: AttrStorage) -> Self {
+        let (disallowed, _) = create_disallowed_map(
+            tcx,
+            &conf.disallowed_macros,
+            |def_kind| matches!(def_kind, DefKind::Macro(_)),
+            "macro",
+            false,
+        );
         Self {
-            disallowed: create_disallowed_map(tcx, &conf.disallowed_macros),
+            disallowed,
             seen: FxHashSet::default(),
             derive_src: None,
             earlies,
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
index 149cf1cf2de..1382dafa931 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
@@ -63,9 +63,19 @@ pub struct DisallowedMethods {
 
 impl DisallowedMethods {
     pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
-        Self {
-            disallowed: create_disallowed_map(tcx, &conf.disallowed_methods),
-        }
+        let (disallowed, _) = create_disallowed_map(
+            tcx,
+            &conf.disallowed_methods,
+            |def_kind| {
+                matches!(
+                    def_kind,
+                    DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn
+                )
+            },
+            "function",
+            false,
+        );
+        Self { disallowed }
     }
 }
 
@@ -74,12 +84,7 @@ impl_lint_pass!(DisallowedMethods => [DISALLOWED_METHODS]);
 impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let (id, span) = match &expr.kind {
-            ExprKind::Path(path)
-                if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) =
-                    cx.qpath_res(path, expr.hir_id) =>
-            {
-                (id, expr.span)
-            },
+            ExprKind::Path(path) if let Res::Def(_, id) = cx.qpath_res(path, expr.hir_id) => (id, expr.span),
             ExprKind::MethodCall(name, ..) if let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) => {
                 (id, name.ident.span)
             },
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
index 38903596414..2bae82648ac 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
@@ -1,8 +1,8 @@
 use clippy_config::Conf;
-use clippy_config::types::DisallowedPath;
+use clippy_config::types::{DisallowedPath, create_disallowed_map};
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def::Res;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -60,22 +60,7 @@ pub struct DisallowedTypes {
 
 impl DisallowedTypes {
     pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
-        let mut def_ids = DefIdMap::default();
-        let mut prim_tys = FxHashMap::default();
-        for disallowed_path in &conf.disallowed_types {
-            let path: Vec<_> = disallowed_path.path().split("::").collect::<Vec<_>>();
-            for res in clippy_utils::def_path_res(tcx, &path) {
-                match res {
-                    Res::Def(_, id) => {
-                        def_ids.insert(id, (disallowed_path.path(), disallowed_path));
-                    },
-                    Res::PrimTy(ty) => {
-                        prim_tys.insert(ty, (disallowed_path.path(), disallowed_path));
-                    },
-                    _ => {},
-                }
-            }
-        }
+        let (def_ids, prim_tys) = create_disallowed_map(tcx, &conf.disallowed_types, def_kind_predicate, "type", true);
         Self { def_ids, prim_tys }
     }
 
@@ -95,6 +80,19 @@ impl DisallowedTypes {
     }
 }
 
+pub fn def_kind_predicate(def_kind: DefKind) -> bool {
+    matches!(
+        def_kind,
+        DefKind::Struct
+            | DefKind::Union
+            | DefKind::Enum
+            | DefKind::Trait
+            | DefKind::TyAlias
+            | DefKind::ForeignTy
+            | DefKind::AssocTy
+    )
+}
+
 impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
 
 impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
index 8cdaba88e50..7a1c7c675d2 100644
--- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
@@ -113,20 +113,20 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
         s != "-" && s.contains('-')
     }
 
-    if let Ok(url) = Url::parse(word) {
+    if let Ok(url) = Url::parse(word)
         // try to get around the fact that `foo::bar` parses as a valid URL
-        if !url.cannot_be_a_base() {
-            span_lint_and_sugg(
-                cx,
-                DOC_MARKDOWN,
-                span,
-                "you should put bare URLs between `<`/`>` or make a proper Markdown link",
-                "try",
-                format!("<{word}>"),
-                Applicability::MachineApplicable,
-            );
-            return;
-        }
+        && !url.cannot_be_a_base()
+    {
+        span_lint_and_sugg(
+            cx,
+            DOC_MARKDOWN,
+            span,
+            "you should put bare URLs between `<`/`>` or make a proper Markdown link",
+            "try",
+            format!("<{word}>"),
+            Applicability::MachineApplicable,
+        );
+        return;
     }
 
     // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
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 e75abf28bac..039937e0207 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -1,11 +1,14 @@
 use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
-use clippy_utils::ty::{implements_trait_with_env, is_type_diagnostic_item};
-use clippy_utils::{is_doc_hidden, return_ty};
+use clippy_utils::macros::{is_panic, root_macro_call_first_node};
+use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item};
+use clippy_utils::visitors::for_each_expr;
+use clippy_utils::{fulfill_or_allowed, is_doc_hidden, method_chain_args, return_ty};
 use rustc_hir::{BodyId, FnSig, OwnerId, Safety};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::{Span, sym};
+use std::ops::ControlFlow;
 
 pub fn check(
     cx: &LateContext<'_>,
@@ -13,7 +16,6 @@ pub fn check(
     sig: FnSig<'_>,
     headers: DocHeaders,
     body_id: Option<BodyId>,
-    panic_info: Option<(Span, bool)>,
     check_private_items: bool,
 ) {
     if !check_private_items && !cx.effective_visibilities.is_exported(owner_id.def_id) {
@@ -46,13 +48,16 @@ pub fn check(
         ),
         _ => (),
     }
-    if !headers.panics && panic_info.is_some_and(|el| !el.1) {
+    if !headers.panics
+        && let Some(body_id) = body_id
+        && let Some(panic_span) = find_panic(cx, body_id)
+    {
         span_lint_and_note(
             cx,
             MISSING_PANICS_DOC,
             span,
             "docs for function which may panic missing `# Panics` section",
-            panic_info.map(|el| el.0),
+            Some(panic_span),
             "first possible panic found here",
         );
     }
@@ -89,3 +94,39 @@ pub fn check(
         }
     }
 }
+
+fn find_panic(cx: &LateContext<'_>, body_id: BodyId) -> Option<Span> {
+    let mut panic_span = None;
+    let typeck = cx.tcx.typeck_body(body_id);
+    for_each_expr(cx, cx.tcx.hir_body(body_id), |expr| {
+        if let Some(macro_call) = root_macro_call_first_node(cx, expr)
+            && (is_panic(cx, macro_call.def_id)
+                || matches!(
+                    cx.tcx.get_diagnostic_name(macro_call.def_id),
+                    Some(sym::assert_macro | sym::assert_eq_macro | sym::assert_ne_macro)
+                ))
+            && !cx.tcx.hir_is_inside_const_context(expr.hir_id)
+            && !fulfill_or_allowed(cx, MISSING_PANICS_DOC, [expr.hir_id])
+            && panic_span.is_none()
+        {
+            panic_span = Some(macro_call.span);
+        }
+
+        // check for `unwrap` and `expect` for both `Option` and `Result`
+        if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or_else(|| method_chain_args(expr, &["expect"]))
+            && let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs()
+            && matches!(
+                get_type_diagnostic_name(cx, receiver_ty),
+                Some(sym::Option | sym::Result)
+            )
+            && !fulfill_or_allowed(cx, MISSING_PANICS_DOC, [expr.hir_id])
+            && panic_span.is_none()
+        {
+            panic_span = Some(expr.span);
+        }
+
+        // Visit all nodes to fulfill any `#[expect]`s after the first linted panic
+        ControlFlow::<!>::Continue(())
+    });
+    panic_span
+}
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 36fd396cc1d..ab77edf1147 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -3,11 +3,8 @@
 use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
-use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::Visitable;
-use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
+use clippy_utils::{is_entrypoint_fn, is_trait_impl_item};
 use pulldown_cmark::Event::{
     Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start,
     TaskListMarker, Text,
@@ -16,18 +13,15 @@ use pulldown_cmark::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, It
 use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options, TagEnd};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind};
+use rustc_hir::{Attribute, ImplItemKind, ItemKind, Node, Safety, TraitItemKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::nested_filter;
-use rustc_middle::ty;
 use rustc_resolve::rustdoc::{
     DocFragment, add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range,
     span_of_fragments,
 };
 use rustc_session::impl_lint_pass;
+use rustc_span::Span;
 use rustc_span::edition::Edition;
-use rustc_span::{Span, sym};
 use std::ops::Range;
 use url::Url;
 
@@ -194,6 +188,19 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
+    ///
+    /// Individual panics within a function can be ignored with `#[expect]` or
+    /// `#[allow]`:
+    ///
+    /// ```no_run
+    /// # use std::num::NonZeroUsize;
+    /// pub fn will_not_panic(x: usize) {
+    ///     #[expect(clippy::missing_panics_doc, reason = "infallible")]
+    ///     let y = NonZeroUsize::new(1).unwrap();
+    ///
+    ///     // If any panics are added in the future the lint will still catch them
+    /// }
+    /// ```
     #[clippy::version = "1.51.0"]
     pub MISSING_PANICS_DOC,
     pedantic,
@@ -657,20 +664,16 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                     self.check_private_items,
                 );
                 match item.kind {
-                    ItemKind::Fn { sig, body: body_id, .. } => {
+                    ItemKind::Fn { sig, body, .. } => {
                         if !(is_entrypoint_fn(cx, item.owner_id.to_def_id())
                             || item.span.in_external_macro(cx.tcx.sess.source_map()))
                         {
-                            let body = cx.tcx.hir_body(body_id);
-
-                            let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
                             missing_headers::check(
                                 cx,
                                 item.owner_id,
                                 sig,
                                 headers,
-                                Some(body_id),
-                                panic_info,
+                                Some(body),
                                 self.check_private_items,
                             );
                         }
@@ -697,15 +700,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                 if let TraitItemKind::Fn(sig, ..) = trait_item.kind
                     && !trait_item.span.in_external_macro(cx.tcx.sess.source_map())
                 {
-                    missing_headers::check(
-                        cx,
-                        trait_item.owner_id,
-                        sig,
-                        headers,
-                        None,
-                        None,
-                        self.check_private_items,
-                    );
+                    missing_headers::check(cx, trait_item.owner_id, sig, headers, None, self.check_private_items);
                 }
             },
             Node::ImplItem(impl_item) => {
@@ -713,16 +708,12 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                     && !impl_item.span.in_external_macro(cx.tcx.sess.source_map())
                     && !is_trait_impl_item(cx, impl_item.hir_id())
                 {
-                    let body = cx.tcx.hir_body(body_id);
-
-                    let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(impl_item.owner_id), body.value);
                     missing_headers::check(
                         cx,
                         impl_item.owner_id,
                         sig,
                         headers,
                         Some(body_id),
-                        panic_span,
                         self.check_private_items,
                     );
                 }
@@ -880,19 +871,18 @@ fn check_for_code_clusters<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a
                 if let Some(start) = code_starts_at
                     && let Some(end) = code_ends_at
                     && code_includes_link
+                    && let Some(span) = fragments.span(cx, start..end)
                 {
-                    if let Some(span) = fragments.span(cx, start..end) {
-                        span_lint_and_then(cx, DOC_LINK_CODE, span, "code link adjacent to code text", |diag| {
-                            let sugg = format!("<code>{}</code>", doc[start..end].replace('`', ""));
-                            diag.span_suggestion_verbose(
-                                span,
-                                "wrap the entire group in `<code>` tags",
-                                sugg,
-                                Applicability::MaybeIncorrect,
-                            );
-                            diag.help("separate code snippets will be shown with a gap");
-                        });
-                    }
+                    span_lint_and_then(cx, DOC_LINK_CODE, span, "code link adjacent to code text", |diag| {
+                        let sugg = format!("<code>{}</code>", doc[start..end].replace('`', ""));
+                        diag.span_suggestion_verbose(
+                            span,
+                            "wrap the entire group in `<code>` tags",
+                            sugg,
+                            Applicability::MaybeIncorrect,
+                        );
+                        diag.help("separate code snippets will be shown with a gap");
+                    });
                 }
                 code_includes_link = false;
                 code_starts_at = None;
@@ -1169,72 +1159,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     headers
 }
 
-struct FindPanicUnwrap<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    is_const: bool,
-    panic_span: Option<Span>,
-    typeck_results: &'tcx ty::TypeckResults<'tcx>,
-}
-
-impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> {
-    pub fn find_span(
-        cx: &'a LateContext<'tcx>,
-        typeck_results: &'tcx ty::TypeckResults<'tcx>,
-        body: impl Visitable<'tcx>,
-    ) -> Option<(Span, bool)> {
-        let mut vis = Self {
-            cx,
-            is_const: false,
-            panic_span: None,
-            typeck_results,
-        };
-        body.visit(&mut vis);
-        vis.panic_span.map(|el| (el, vis.is_const))
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if self.panic_span.is_some() {
-            return;
-        }
-
-        if let Some(macro_call) = root_macro_call_first_node(self.cx, expr) {
-            if is_panic(self.cx, macro_call.def_id)
-                || matches!(
-                    self.cx.tcx.item_name(macro_call.def_id).as_str(),
-                    "assert" | "assert_eq" | "assert_ne"
-                )
-            {
-                self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id);
-                self.panic_span = Some(macro_call.span);
-            }
-        }
-
-        // check for `unwrap` and `expect` for both `Option` and `Result`
-        if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) {
-            let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
-            if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
-                || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
-            {
-                self.panic_span = Some(expr.span);
-            }
-        }
-
-        // and check sub-expressions
-        intravisit::walk_expr(self, expr);
-    }
-
-    // Panics in const blocks will cause compilation to fail.
-    fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
-
-    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
-        self.cx.tcx
-    }
-}
-
 #[expect(clippy::range_plus_one)] // inclusive ranges aren't the same type
 fn looks_like_refdef(doc: &str, range: Range<usize>) -> Option<Range<usize>> {
     if range.end < range.start {
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index bf549dcdb50..ec4538039a9 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -64,7 +64,10 @@ pub fn check(
                     match parser.parse_item(ForceCollect::No) {
                         Ok(Some(item)) => match &item.kind {
                             ItemKind::Fn(box Fn {
-                                ident, sig, body: Some(block), ..
+                                ident,
+                                sig,
+                                body: Some(block),
+                                ..
                             }) if ident.name == sym::main => {
                                 if !ignore {
                                     get_test_spans(&item, *ident, &mut test_attr_spans);
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 617982f4da3..5c360ce6a5f 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -144,10 +144,10 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
 //     ..
 // }
 fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool {
-    if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
-        if let Node::Arm(Arm { body, .. }) = cx.tcx.parent_hir_node(drop_expr.hir_id) {
-            return body.hir_id == drop_expr.hir_id;
-        }
+    if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))
+        && let Node::Arm(Arm { body, .. }) = cx.tcx.parent_hir_node(drop_expr.hir_id)
+    {
+        return body.hir_id == drop_expr.hir_id;
     }
     false
 }
diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
index c67dcd3c82b..0c5f8bbf4ca 100644
--- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{SpanRangeExt, snippet_indent};
 use clippy_utils::tokenize_with_text;
@@ -89,7 +91,7 @@ declare_clippy_lint! {
 #[derive(Debug)]
 struct ItemInfo {
     kind: &'static str,
-    name: Symbol,
+    name: Option<Symbol>,
     span: Span,
     mod_items: Option<NodeId>,
 }
@@ -315,8 +317,12 @@ impl EmptyLineAfter {
                     for stop in gaps.iter().flat_map(|gap| gap.prev_chunk) {
                         stop.comment_out(cx, &mut suggestions);
                     }
+                    let name = match info.name {
+                        Some(name) => format!("{} `{name}`", info.kind).into(),
+                        None => Cow::from("the following item"),
+                    };
                     diag.multipart_suggestion_verbose(
-                        format!("if the doc comment should not document `{}` comment it out", info.name),
+                        format!("if the doc comment should not document {name} then comment it out"),
                         suggestions,
                         Applicability::MaybeIncorrect,
                     );
@@ -381,13 +387,10 @@ impl EmptyLineAfter {
     ) {
         self.items.push(ItemInfo {
             kind: kind.descr(),
-            // FIXME: this `sym::empty` can be leaked, see
-            // https://github.com/rust-lang/rust/pull/138740#discussion_r2021979899
-            name: if let Some(ident) = ident { ident.name } else { kw::Empty },
-            span: if let Some(ident) = ident {
-                span.with_hi(ident.span.hi())
-            } else {
-                span.with_hi(span.lo())
+            name: ident.map(|ident| ident.name),
+            span: match ident {
+                Some(ident) => span.with_hi(ident.span.hi()),
+                None => span.shrink_to_lo(),
             },
             mod_items: match kind {
                 ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items
@@ -447,7 +450,7 @@ impl EarlyLintPass for EmptyLineAfter {
     fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) {
         self.items.push(ItemInfo {
             kind: "crate",
-            name: kw::Crate,
+            name: Some(kw::Crate),
             span: krate.spans.inner_span.with_hi(krate.spans.inner_span.lo()),
             mod_items: krate
                 .items
diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index 7d87f04fef9..a38d6df89f2 100644
--- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -1,10 +1,15 @@
-use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{Item, ItemKind, Variant, VariantData};
+use clippy_utils::attrs::span_contains_cfg;
+use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
-use rustc_lexer::TokenKind;
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_hir::def::CtorOf;
+use rustc_hir::def::DefKind::Ctor;
+use rustc_hir::def::Res::Def;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node, Path, QPath, Variant, VariantData};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
+use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
 declare_clippy_lint! {
@@ -70,10 +75,23 @@ declare_clippy_lint! {
     "finds enum variants with empty brackets"
 }
 
-declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VARIANTS_WITH_BRACKETS]);
+#[derive(Debug)]
+enum Usage {
+    Unused { redundant_use_sites: Vec<Span> },
+    Used,
+    NoDefinition { redundant_use_sites: Vec<Span> },
+}
+
+#[derive(Default)]
+pub struct EmptyWithBrackets {
+    // Value holds `Usage::Used` if the empty tuple variant was used as a function
+    empty_tuple_enum_variants: FxIndexMap<LocalDefId, Usage>,
+}
+
+impl_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VARIANTS_WITH_BRACKETS]);
 
-impl EarlyLintPass for EmptyWithBrackets {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+impl LateLintPass<'_> for EmptyWithBrackets {
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         if let ItemKind::Struct(ident, var_data, _) = &item.kind
             && has_brackets(var_data)
             && let span_after_ident = item.span.with_lo(ident.span.hi())
@@ -96,70 +114,175 @@ impl EarlyLintPass for EmptyWithBrackets {
         }
     }
 
-    fn check_variant(&mut self, cx: &EarlyContext<'_>, variant: &Variant) {
+    fn check_variant(&mut self, cx: &LateContext<'_>, variant: &Variant<'_>) {
+        // the span of the parentheses/braces
         let span_after_ident = variant.span.with_lo(variant.ident.span.hi());
 
-        if has_brackets(&variant.data) && has_no_fields(cx, &variant.data, span_after_ident) {
-            span_lint_and_then(
+        if has_no_fields(cx, &variant.data, span_after_ident) {
+            match variant.data {
+                VariantData::Struct { .. } => {
+                    // Empty struct variants can be linted immediately
+                    span_lint_and_then(
+                        cx,
+                        EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
+                        span_after_ident,
+                        "enum variant has empty brackets",
+                        |diagnostic| {
+                            diagnostic.span_suggestion_hidden(
+                                span_after_ident,
+                                "remove the brackets",
+                                "",
+                                Applicability::MaybeIncorrect,
+                            );
+                        },
+                    );
+                },
+                VariantData::Tuple(.., local_def_id) => {
+                    // Don't lint reachable tuple enums
+                    if cx.effective_visibilities.is_reachable(variant.def_id) {
+                        return;
+                    }
+                    if let Some(entry) = self.empty_tuple_enum_variants.get_mut(&local_def_id) {
+                        // empty_tuple_enum_variants contains Usage::NoDefinition if the variant was called before the
+                        // definition was encountered. Now that there's a definition, convert it
+                        // to Usage::Unused.
+                        if let Usage::NoDefinition { redundant_use_sites } = entry {
+                            *entry = Usage::Unused {
+                                redundant_use_sites: redundant_use_sites.clone(),
+                            };
+                        }
+                    } else {
+                        self.empty_tuple_enum_variants.insert(
+                            local_def_id,
+                            Usage::Unused {
+                                redundant_use_sites: vec![],
+                            },
+                        );
+                    }
+                },
+                VariantData::Unit(..) => {},
+            }
+        }
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let Some(def_id) = check_expr_for_enum_as_function(expr) {
+            if let Some(parentheses_span) = call_parentheses_span(cx.tcx, expr) {
+                // Do not count expressions from macro expansion as a redundant use site.
+                if expr.span.from_expansion() {
+                    return;
+                }
+                match self.empty_tuple_enum_variants.get_mut(&def_id) {
+                    Some(
+                        &mut (Usage::Unused {
+                            ref mut redundant_use_sites,
+                        }
+                        | Usage::NoDefinition {
+                            ref mut redundant_use_sites,
+                        }),
+                    ) => {
+                        redundant_use_sites.push(parentheses_span);
+                    },
+                    None => {
+                        // The variant isn't in the IndexMap which means its definition wasn't encountered yet.
+                        self.empty_tuple_enum_variants.insert(
+                            def_id,
+                            Usage::NoDefinition {
+                                redundant_use_sites: vec![parentheses_span],
+                            },
+                        );
+                    },
+                    _ => {},
+                }
+            } else {
+                // The parentheses are not redundant.
+                self.empty_tuple_enum_variants.insert(def_id, Usage::Used);
+            }
+        }
+    }
+
+    fn check_crate_post(&mut self, cx: &LateContext<'_>) {
+        for (local_def_id, usage) in &self.empty_tuple_enum_variants {
+            // Ignore all variants with Usage::Used or Usage::NoDefinition
+            let Usage::Unused { redundant_use_sites } = usage else {
+                continue;
+            };
+            // Attempt to fetch the Variant from LocalDefId.
+            let Node::Variant(variant) = cx.tcx.hir_node(
+                cx.tcx
+                    .local_def_id_to_hir_id(cx.tcx.parent(local_def_id.to_def_id()).expect_local()),
+            ) else {
+                continue;
+            };
+            // Span of the parentheses in variant definition
+            let span = variant.span.with_lo(variant.ident.span.hi());
+            span_lint_hir_and_then(
                 cx,
                 EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
-                span_after_ident,
+                variant.hir_id,
+                span,
                 "enum variant has empty brackets",
                 |diagnostic| {
-                    diagnostic.span_suggestion_hidden(
-                        span_after_ident,
-                        "remove the brackets",
-                        "",
-                        Applicability::MaybeIncorrect,
-                    );
+                    if redundant_use_sites.is_empty() {
+                        // If there's no redundant use sites, the definition is the only place to modify.
+                        diagnostic.span_suggestion_hidden(
+                            span,
+                            "remove the brackets",
+                            "",
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let mut parentheses_spans: Vec<_> =
+                            redundant_use_sites.iter().map(|span| (*span, String::new())).collect();
+                        parentheses_spans.push((span, String::new()));
+                        diagnostic.multipart_suggestion(
+                            "remove the brackets",
+                            parentheses_spans,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 },
             );
         }
     }
 }
 
-fn has_no_ident_token(braces_span_str: &str) -> bool {
-    !rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident)
+fn has_brackets(var_data: &VariantData<'_>) -> bool {
+    !matches!(var_data, VariantData::Unit(..))
 }
 
-fn has_brackets(var_data: &VariantData) -> bool {
-    !matches!(var_data, VariantData::Unit(_))
-}
-
-fn has_no_fields(cx: &EarlyContext<'_>, var_data: &VariantData, braces_span: Span) -> bool {
-    if !var_data.fields().is_empty() {
-        return false;
-    }
-
+fn has_no_fields(cx: &LateContext<'_>, var_data: &VariantData<'_>, braces_span: Span) -> bool {
+    var_data.fields().is_empty() &&
     // there might still be field declarations hidden from the AST
     // (conditionally compiled code using #[cfg(..)])
-
-    let Some(braces_span_str) = snippet_opt(cx, braces_span) else {
-        return false;
-    };
-
-    has_no_ident_token(braces_span_str.as_ref())
+    !span_contains_cfg(cx, braces_span)
 }
 
-#[cfg(test)]
-mod unit_test {
-    use super::*;
-
-    #[test]
-    fn test_has_no_ident_token() {
-        let input = "{ field: u8 }";
-        assert!(!has_no_ident_token(input));
-
-        let input = "(u8, String);";
-        assert!(!has_no_ident_token(input));
-
-        let input = " {
-                // test = 5
-        }
-        ";
-        assert!(has_no_ident_token(input));
+// If expression HIR ID and callee HIR ID are same, returns the span of the parentheses, else,
+// returns None.
+fn call_parentheses_span(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> Option<Span> {
+    if let Node::Expr(parent) = tcx.parent_hir_node(expr.hir_id)
+        && let ExprKind::Call(callee, ..) = parent.kind
+        && callee.hir_id == expr.hir_id
+    {
+        Some(parent.span.with_lo(expr.span.hi()))
+    } else {
+        None
+    }
+}
 
-        let input = " ();";
-        assert!(has_no_ident_token(input));
+// Returns the LocalDefId of the variant being called as a function if it exists.
+fn check_expr_for_enum_as_function(expr: &Expr<'_>) -> Option<LocalDefId> {
+    if let ExprKind::Path(QPath::Resolved(
+        _,
+        Path {
+            res: Def(Ctor(CtorOf::Variant, _), def_id),
+            ..
+        },
+    )) = expr.kind
+    {
+        def_id.as_local()
+    } else {
+        None
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index dcfee0b6d3c..182cb4e46d2 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -95,14 +95,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 return;
             };
 
-            if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
-                span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
-                return;
-            }
-
             if then_search.edits.is_empty() && else_search.edits.is_empty() {
                 // No insertions
                 return;
+            } else if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
+                // If there are other uses of the key, and the key is not copy,
+                // we cannot perform a fix automatically, but continue to emit a lint.
+                None
             } else if then_search.edits.is_empty() || else_search.edits.is_empty() {
                 // if .. { insert } else { .. } or if .. { .. } else { insert }
                 let ((then_str, entry_kind), else_str) = match (else_search.edits.is_empty(), contains_expr.negated) {
@@ -123,10 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                         snippet_with_applicability(cx, then_expr.span, "{ .. }", &mut app),
                     ),
                 };
-                format!(
+                Some(format!(
                     "if let {}::{entry_kind} = {map_str}.entry({key_str}) {then_str} else {else_str}",
                     map_ty.entry_path(),
-                )
+                ))
             } else {
                 // if .. { insert } else { insert }
                 let ((then_str, then_entry), (else_str, else_entry)) = if contains_expr.negated {
@@ -142,13 +141,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 };
                 let indent_str = snippet_indent(cx, expr.span);
                 let indent_str = indent_str.as_deref().unwrap_or("");
-                format!(
+                Some(format!(
                     "match {map_str}.entry({key_str}) {{\n{indent_str}    {entry}::{then_entry} => {}\n\
                         {indent_str}    {entry}::{else_entry} => {}\n{indent_str}}}",
                     reindent_multiline(&then_str, true, Some(4 + indent_str.len())),
                     reindent_multiline(&else_str, true, Some(4 + indent_str.len())),
                     entry = map_ty.entry_path(),
-                )
+                ))
             }
         } else {
             if then_search.edits.is_empty() {
@@ -163,17 +162,17 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 } else {
                     then_search.snippet_occupied(cx, then_expr.span, &mut app)
                 };
-                format!(
+                Some(format!(
                     "if let {}::{entry_kind} = {map_str}.entry({key_str}) {body_str}",
                     map_ty.entry_path(),
-                )
+                ))
             } else if let Some(insertion) = then_search.as_single_insertion() {
                 let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0;
                 if contains_expr.negated {
                     if insertion.value.can_have_side_effects() {
-                        format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});")
+                        Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});"))
                     } else {
-                        format!("{map_str}.entry({key_str}).or_insert({value_str});")
+                        Some(format!("{map_str}.entry({key_str}).or_insert({value_str});"))
                     }
                 } else {
                     // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
@@ -183,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
             } else {
                 let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app);
                 if contains_expr.negated {
-                    format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});")
+                    Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});"))
                 } else {
                     // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
                     // This would need to be a different lint.
@@ -192,7 +191,11 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
             }
         };
 
-        span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
+        if let Some(sugg) = sugg {
+            span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
+        } else {
+            span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index f01b5c840d2..ec81294624e 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -49,10 +49,10 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
                         .ok()
                         .map(|val| rustc_middle::mir::Const::from_value(val, ty));
                     if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx.tcx, c)) {
-                        if let ty::Adt(adt, _) = ty.kind() {
-                            if adt.is_enum() {
-                                ty = adt.repr().discr_type().to_ty(cx.tcx);
-                            }
+                        if let ty::Adt(adt, _) = ty.kind()
+                            && adt.is_enum()
+                        {
+                            ty = adt.repr().discr_type().to_ty(cx.tcx);
                         }
                         match ty.kind() {
                             ty::Int(IntTy::Isize) => {
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index e248f08789b..2cb3b32babe 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -72,10 +72,10 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
         _: Span,
         fn_def_id: LocalDefId,
     ) {
-        if let Some(header) = fn_kind.header() {
-            if header.abi != ExternAbi::Rust {
-                return;
-            }
+        if let Some(header) = fn_kind.header()
+            && header.abi != ExternAbi::Rust
+        {
+            return;
         }
 
         let parent_id = cx
@@ -93,12 +93,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
             // find `self` ty for this trait if relevant
             if let ItemKind::Trait(_, _, _, _, _, items) = item.kind {
                 for trait_item in items {
-                    if trait_item.id.owner_id.def_id == fn_def_id {
+                    if trait_item.id.owner_id.def_id == fn_def_id
                         // be sure we have `self` parameter in this function
-                        if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
-                            trait_self_ty =
-                                Some(TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()).self_ty());
-                        }
+                        && trait_item.kind == (AssocItemKind::Fn { has_self: true })
+                    {
+                        trait_self_ty = Some(TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()).self_ty());
                     }
                 }
             }
@@ -142,22 +141,22 @@ fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool {
 
 impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
     fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
-        if cmt.place.projections.is_empty() {
-            if let PlaceBase::Local(lid) = cmt.place.base {
-                // FIXME(rust/#120456) - is `swap_remove` correct?
-                self.set.swap_remove(&lid);
-            }
+        if cmt.place.projections.is_empty()
+            && let PlaceBase::Local(lid) = cmt.place.base
+        {
+            // FIXME(rust/#120456) - is `swap_remove` correct?
+            self.set.swap_remove(&lid);
         }
     }
 
     fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
-        if cmt.place.projections.is_empty() {
-            if let PlaceBase::Local(lid) = cmt.place.base {
-                // FIXME(rust/#120456) - is `swap_remove` correct?
-                self.set.swap_remove(&lid);
-            }
+        if cmt.place.projections.is_empty()
+            && let PlaceBase::Local(lid) = cmt.place.base
+        {
+            // FIXME(rust/#120456) - is `swap_remove` correct?
+            self.set.swap_remove(&lid);
         }
     }
 
@@ -171,10 +170,11 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
 
             // skip if there is a `self` parameter binding to a type
             // that contains `Self` (i.e.: `self: Box<Self>`), see #4804
-            if let Some(trait_self_ty) = self.trait_self_ty {
-                if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
-                    return;
-                }
+            if let Some(trait_self_ty) = self.trait_self_ty
+                && self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower
+                && cmt.place.ty().contains(trait_self_ty)
+            {
+                return;
             }
 
             if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
index f67d38d932b..c868b782f43 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -75,10 +75,10 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
 
     impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> {
         fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-            if let Some(macro_call) = root_macro_call_first_node(self.lcx, expr) {
-                if is_panic(self.lcx, macro_call.def_id) {
-                    self.result.push(expr.span);
-                }
+            if let Some(macro_call) = root_macro_call_first_node(self.lcx, expr)
+                && is_panic(self.lcx, macro_call.def_id)
+            {
+                self.result.push(expr.span);
             }
 
             // check for `unwrap`
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 daa199779e3..d5f0659f842 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -154,7 +154,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
         };
     }
 
-    suggestion.maybe_par()
+    suggestion.maybe_paren()
 }
 
 fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
@@ -165,7 +165,7 @@ fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, ar
             expr.span,
             "logarithm for bases 2, 10 and e can be computed more accurately",
             "consider using",
-            format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_par()),
+            format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_paren()),
             Applicability::MachineApplicable,
         );
     }
@@ -228,24 +228,24 @@ fn get_integer_from_float_constant(value: &Constant<'_>) -> Option<i32> {
 
 fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
     // Check receiver
-    if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) {
-        if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
+    if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver)
+        && let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
             Some("exp")
         } else if F32(2.0) == value || F64(2.0) == value {
             Some("exp2")
         } else {
             None
-        } {
-            span_lint_and_sugg(
-                cx,
-                SUBOPTIMAL_FLOPS,
-                expr.span,
-                "exponent for bases 2 and e can be computed more accurately",
-                "consider using",
-                format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])),
-                Applicability::MachineApplicable,
-            );
         }
+    {
+        span_lint_and_sugg(
+            cx,
+            SUBOPTIMAL_FLOPS,
+            expr.span,
+            "exponent for bases 2 and e can be computed more accurately",
+            "consider using",
+            format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])),
+            Applicability::MachineApplicable,
+        );
     }
 
     // Check argument
@@ -254,13 +254,13 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
             (
                 SUBOPTIMAL_FLOPS,
                 "square-root of a number can be computed more efficiently and accurately",
-                format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_par()),
+                format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_paren()),
             )
         } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
             (
                 IMPRECISE_FLOPS,
                 "cube-root of a number can be computed more accurately",
-                format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_par()),
+                format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_paren()),
             )
         } else if let Some(exponent) = get_integer_from_float_constant(&value) {
             (
@@ -268,7 +268,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
                 "exponentiation with integer powers can be computed more efficiently",
                 format!(
                     "{}.powi({})",
-                    Sugg::hir(cx, receiver, "..").maybe_par(),
+                    Sugg::hir(cx, receiver, "..").maybe_paren(),
                     numeric_literal::format(&exponent.to_string(), None, false)
                 ),
             )
@@ -289,55 +289,53 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
 }
 
 fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) {
-        if value == Int(2) {
-            if let Some(parent) = get_parent_expr(cx, expr) {
-                if let Some(grandparent) = get_parent_expr(cx, parent) {
-                    if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind
-                    {
-                        if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() {
-                            return;
-                        }
-                    }
-                }
+    if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0])
+        && value == Int(2)
+        && let Some(parent) = get_parent_expr(cx, expr)
+    {
+        if let Some(grandparent) = get_parent_expr(cx, parent)
+            && let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = grandparent.kind
+            && method_name.as_str() == "sqrt"
+            && detect_hypot(cx, receiver).is_some()
+        {
+            return;
+        }
 
-                if let ExprKind::Binary(
-                    Spanned {
-                        node: op @ (BinOpKind::Add | BinOpKind::Sub),
-                        ..
-                    },
-                    lhs,
-                    rhs,
-                ) = parent.kind
-                {
-                    let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
-
-                    // Negate expr if original code has subtraction and expr is on the right side
-                    let maybe_neg_sugg = |expr, hir_id| {
-                        let sugg = Sugg::hir(cx, expr, "..");
-                        if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
-                            -sugg
-                        } else {
-                            sugg
-                        }
-                    };
-
-                    span_lint_and_sugg(
-                        cx,
-                        SUBOPTIMAL_FLOPS,
-                        parent.span,
-                        "multiply and add expressions can be calculated more efficiently and accurately",
-                        "consider using",
-                        format!(
-                            "{}.mul_add({}, {})",
-                            Sugg::hir(cx, receiver, "..").maybe_par(),
-                            maybe_neg_sugg(receiver, expr.hir_id),
-                            maybe_neg_sugg(other_addend, other_addend.hir_id),
-                        ),
-                        Applicability::MachineApplicable,
-                    );
+        if let ExprKind::Binary(
+            Spanned {
+                node: op @ (BinOpKind::Add | BinOpKind::Sub),
+                ..
+            },
+            lhs,
+            rhs,
+        ) = parent.kind
+        {
+            let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
+
+            // Negate expr if original code has subtraction and expr is on the right side
+            let maybe_neg_sugg = |expr, hir_id| {
+                let sugg = Sugg::hir(cx, expr, "..");
+                if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
+                    -sugg
+                } else {
+                    sugg
                 }
-            }
+            };
+
+            span_lint_and_sugg(
+                cx,
+                SUBOPTIMAL_FLOPS,
+                parent.span,
+                "multiply and add expressions can be calculated more efficiently and accurately",
+                "consider using",
+                format!(
+                    "{}.mul_add({}, {})",
+                    Sugg::hir(cx, receiver, "..").maybe_paren(),
+                    maybe_neg_sugg(receiver, expr.hir_id),
+                    maybe_neg_sugg(other_addend, other_addend.hir_id),
+                ),
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
@@ -371,7 +369,7 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
         {
             return Some(format!(
                 "{}.hypot({})",
-                Sugg::hir(cx, lmul_lhs, "..").maybe_par(),
+                Sugg::hir(cx, lmul_lhs, "..").maybe_paren(),
                 Sugg::hir(cx, rmul_lhs, "..")
             ));
         }
@@ -403,7 +401,7 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
         {
             return Some(format!(
                 "{}.hypot({})",
-                Sugg::hir(cx, largs_0, "..").maybe_par(),
+                Sugg::hir(cx, largs_0, "..").maybe_paren(),
                 Sugg::hir(cx, rargs_0, "..")
             ));
         }
@@ -449,7 +447,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
             expr.span,
             "(e.pow(x) - 1) can be computed more accurately",
             "consider using",
-            format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_par()),
+            format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_paren()),
             Applicability::MachineApplicable,
         );
     }
@@ -483,12 +481,12 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
         rhs,
     ) = &expr.kind
     {
-        if let Some(parent) = get_parent_expr(cx, expr) {
-            if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind {
-                if method_name.as_str() == "sqrt" && detect_hypot(cx, receiver).is_some() {
-                    return;
-                }
-            }
+        if let Some(parent) = get_parent_expr(cx, expr)
+            && let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, receiver, ..) = parent.kind
+            && method_name.as_str() == "sqrt"
+            && detect_hypot(cx, receiver).is_some()
+        {
+            return;
         }
 
         let maybe_neg_sugg = |expr| {
@@ -566,15 +564,15 @@ fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 /// If the two expressions are not negations of each other, then it
 /// returns None.
 fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> {
-    if let ExprKind::Unary(UnOp::Neg, expr1_negated) = &expr1.kind {
-        if eq_expr_value(cx, expr1_negated, expr2) {
-            return Some((false, expr2));
-        }
+    if let ExprKind::Unary(UnOp::Neg, expr1_negated) = &expr1.kind
+        && eq_expr_value(cx, expr1_negated, expr2)
+    {
+        return Some((false, expr2));
     }
-    if let ExprKind::Unary(UnOp::Neg, expr2_negated) = &expr2.kind {
-        if eq_expr_value(cx, expr1, expr2_negated) {
-            return Some((true, expr1));
-        }
+    if let ExprKind::Unary(UnOp::Neg, expr2_negated) = &expr2.kind
+        && eq_expr_value(cx, expr1, expr2_negated)
+    {
+        return Some((true, expr1));
     }
     None
 }
@@ -591,11 +589,11 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
     {
         let positive_abs_sugg = (
             "manual implementation of `abs` method",
-            format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_par()),
+            format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()),
         );
         let negative_abs_sugg = (
             "manual implementation of negation of `abs` method",
-            format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_par()),
+            format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()),
         );
         let sugg = if is_testing_positive(cx, cond, body) {
             if if_expr_positive {
@@ -672,7 +670,7 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
             "consider using",
             format!(
                 "{}.log({})",
-                Sugg::hir(cx, largs_self, "..").maybe_par(),
+                Sugg::hir(cx, largs_self, "..").maybe_paren(),
                 Sugg::hir(cx, rargs_self, ".."),
             ),
             Applicability::MachineApplicable,
@@ -703,7 +701,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue)
             && (F32(180_f32) == lvalue || F64(180_f64) == lvalue)
         {
-            let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
+            let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_paren());
             if let ExprKind::Lit(literal) = mul_lhs.kind
                 && let ast::LitKind::Float(ref value, float_type) = literal.node
                 && float_type == ast::LitFloatType::Unsuffixed
@@ -726,7 +724,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
         } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue)
             && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue)
         {
-            let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
+            let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_paren());
             if let ExprKind::Lit(literal) = mul_lhs.kind
                 && let ast::LitKind::Float(ref value, float_type) = literal.node
                 && float_type == ast::LitFloatType::Unsuffixed
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index 5e3f6b6a137..94e66769eb2 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
                                 .into_owned()
                         } else {
                             let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
-                            format!("{}.to_string()", sugg.maybe_par())
+                            format!("{}.to_string()", sugg.maybe_paren())
                         };
                         span_useless_format(cx, call_site, sugg, applicability);
                     }
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 06224f57c5c..8a3f8e1c587 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -141,7 +141,7 @@ declare_clippy_lint! {
     /// format!("{var:.prec$}");
     /// ```
     ///
-    /// If allow-mixed-uninlined-format-args is set to false in clippy.toml,
+    /// If `allow-mixed-uninlined-format-args` is set to `false` in clippy.toml,
     /// the following code will also trigger the lint:
     /// ```no_run
     /// # let var = 42;
@@ -159,7 +159,7 @@ declare_clippy_lint! {
     /// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
     #[clippy::version = "1.66.0"]
     pub UNINLINED_FORMAT_ARGS,
-    pedantic,
+    style,
     "using non-inlined variables in `format!` calls"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index 5b42a40d850..0535ecf5240 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, is_format_macro, root_macro_call_first_node};
-use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
+use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators, sym};
 use rustc_ast::{FormatArgsPiece, FormatTrait};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
+use rustc_span::Symbol;
 use rustc_span::symbol::kw;
-use rustc_span::{Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -185,13 +185,13 @@ impl FormatImplExpr<'_, '_> {
                     && let trait_name = match placeholder.format_trait {
                         FormatTrait::Display => sym::Display,
                         FormatTrait::Debug => sym::Debug,
-                        FormatTrait::LowerExp => sym!(LowerExp),
-                        FormatTrait::UpperExp => sym!(UpperExp),
-                        FormatTrait::Octal => sym!(Octal),
+                        FormatTrait::LowerExp => sym::LowerExp,
+                        FormatTrait::UpperExp => sym::UpperExp,
+                        FormatTrait::Octal => sym::Octal,
                         FormatTrait::Pointer => sym::Pointer,
-                        FormatTrait::Binary => sym!(Binary),
-                        FormatTrait::LowerHex => sym!(LowerHex),
-                        FormatTrait::UpperHex => sym!(UpperHex),
+                        FormatTrait::Binary => sym::Binary,
+                        FormatTrait::LowerHex => sym::LowerHex,
+                        FormatTrait::UpperHex => sym::UpperHex,
                     }
                     && trait_name == self.format_trait_impl.name
                     && let Ok(index) = placeholder.argument.index
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index c8fe7ac73cb..4b482f7b233 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -138,27 +138,28 @@ impl EarlyLintPass for Formatting {
 
 /// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint.
 fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
-    if let ExprKind::Assign(ref lhs, ref rhs, _) = expr.kind {
-        if !lhs.span.from_expansion() && !rhs.span.from_expansion() {
-            let eq_span = lhs.span.between(rhs.span);
-            if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind {
-                if let Some(eq_snippet) = snippet_opt(cx, eq_span) {
-                    let op = op.as_str();
-                    let eqop_span = lhs.span.between(sub_rhs.span);
-                    if eq_snippet.ends_with('=') {
-                        span_lint_and_note(
-                            cx,
-                            SUSPICIOUS_ASSIGNMENT_FORMATTING,
-                            eqop_span,
-                            format!(
-                                "this looks like you are trying to use `.. {op}= ..`, but you \
+    if let ExprKind::Assign(ref lhs, ref rhs, _) = expr.kind
+        && !lhs.span.from_expansion()
+        && !rhs.span.from_expansion()
+    {
+        let eq_span = lhs.span.between(rhs.span);
+        if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind
+            && let Some(eq_snippet) = snippet_opt(cx, eq_span)
+        {
+            let op = op.as_str();
+            let eqop_span = lhs.span.between(sub_rhs.span);
+            if eq_snippet.ends_with('=') {
+                span_lint_and_note(
+                    cx,
+                    SUSPICIOUS_ASSIGNMENT_FORMATTING,
+                    eqop_span,
+                    format!(
+                        "this looks like you are trying to use `.. {op}= ..`, but you \
                                  really are doing `.. = ({op} ..)`"
-                            ),
-                            None,
-                            format!("to remove this lint, use either `{op}=` or `= {op}`"),
-                        );
-                    }
-                }
+                    ),
+                    None,
+                    format!("to remove this lint, use either `{op}=` or `= {op}`"),
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
index 7361546153c..25b087e8484 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
             };
 
             let sugg =
-                Sugg::hir_with_applicability(cx, expr, "<string>", &mut Applicability::MachineApplicable).maybe_par();
+                Sugg::hir_with_applicability(cx, expr, "<string>", &mut Applicability::MachineApplicable).maybe_paren();
 
             span_lint_and_sugg(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
index 854fe144c29..fa63876410f 100644
--- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind};
+use rustc_hir::{BlockCheckMode, Body, ExprKind, FnDecl, ImplicitSelfKind, UnsafeSource};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Span;
@@ -40,14 +40,25 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
         name
     };
 
-    // Body must be &(mut) <self_data>.name
+    // Body must be `&(mut) <self_data>.name`, potentially in an `unsafe` block
     // self_data is not necessarily self, to also lint sub-getters, etc…
 
     let block_expr = if let ExprKind::Block(block, _) = body.value.kind
         && block.stmts.is_empty()
         && let Some(block_expr) = block.expr
     {
-        block_expr
+        if let ExprKind::Block(unsafe_block, _) = block_expr.kind
+            && unsafe_block.stmts.is_empty()
+            && matches!(
+                unsafe_block.rules,
+                BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
+            )
+            && let Some(unsafe_block_expr) = unsafe_block.expr
+        {
+            unsafe_block_expr
+        } else {
+            block_expr
+        }
     } else {
         return;
     };
diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
index 4495aeb5953..2d22bb157a9 100644
--- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
@@ -59,9 +59,7 @@ impl RenamedFnArgs {
         let mut renamed: Vec<(Span, String)> = vec![];
 
         debug_assert!(default_idents.size_hint() == current_idents.size_hint());
-        while let (Some(default_ident), Some(current_ident)) =
-            (default_idents.next(), current_idents.next())
-        {
+        while let (Some(default_ident), Some(current_ident)) = (default_idents.next(), current_idents.next()) {
             let has_name_to_check = |ident: Option<Ident>| {
                 if let Some(ident) = ident
                     && ident.name != kw::Underscore
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
index 05dc47f6fe5..48d050aa36a 100644
--- a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
@@ -47,16 +47,16 @@ pub(super) fn check_fn(
 }
 
 pub(super) fn check_trait_item(cx: &LateContext<'_>, item: &hir::TraitItem<'_>, too_many_arguments_threshold: u64) {
-    if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
+    if let hir::TraitItemKind::Fn(ref sig, _) = item.kind
         // don't lint extern functions decls, it's not their fault
-        if sig.header.abi == ExternAbi::Rust {
-            check_arg_number(
-                cx,
-                sig.decl,
-                item.span.with_hi(sig.decl.output.span().hi()),
-                too_many_arguments_threshold,
-            );
-        }
+        && sig.header.abi == ExternAbi::Rust
+    {
+        check_arg_number(
+            cx,
+            sig.decl,
+            item.span.with_hi(sig.decl.output.span().hi()),
+            too_many_arguments_threshold,
+        );
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index fbbd33efd02..9e94280fc07 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
                 |diag| {
                     let mut app = Applicability::MachineApplicable;
                     let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
-                        .maybe_par()
+                        .maybe_paren()
                         .to_string();
                     let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
                     let method_body = if let Some(first_stmt) = then_block.stmts.first() {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index 5f95464e4d4..076017a247b 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -1,7 +1,7 @@
 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_without_closures;
-use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
+use clippy_utils::{desugar_await, get_async_closure_expr, get_async_fn_body, is_async_fn, is_from_proc_macro};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
@@ -134,6 +134,10 @@ fn lint_implicit_returns(
         },
 
         ExprKind::Match(_, arms, _) => {
+            if let Some(await_expr) = desugar_await(expr) {
+                lint_return(cx, await_expr.hir_id, await_expr.span);
+                return LintLocation::Inner;
+            }
             for arm in arms {
                 let res = lint_implicit_returns(
                     cx,
@@ -153,18 +157,18 @@ fn lint_implicit_returns(
         ExprKind::Loop(block, ..) => {
             let mut add_return = false;
             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 {
-                            // At this point sub_expr can be `None` in async functions which either diverge, or return
-                            // the unit type.
-                            if let Some(sub_expr) = sub_expr {
-                                lint_break(cx, e.hir_id, e.span, sub_expr.span);
-                            }
-                        } else {
-                            // the break expression is from a macro call, add a return to the loop
-                            add_return = true;
+                if let ExprKind::Break(dest, sub_expr) = e.kind
+                    && dest.target_id.ok() == Some(expr.hir_id)
+                {
+                    if call_site_span.is_none() && e.span.ctxt() == ctxt {
+                        // At this point sub_expr can be `None` in async functions which either diverge, or return
+                        // the unit type.
+                        if let Some(sub_expr) = sub_expr {
+                            lint_break(cx, e.hir_id, e.span, sub_expr.span);
                         }
+                    } else {
+                        // the break expression is from a macro call, add a return to the loop
+                        add_return = true;
                     }
                 }
                 ControlFlow::Continue(())
@@ -241,6 +245,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn {
                 Some(e) => e,
                 None => return,
             }
+        } else if let Some(expr) = get_async_closure_expr(cx.tcx, body.value) {
+            expr
         } else {
             body.value
         };
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 5d7d3ae3f24..514e72a4868 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -239,7 +239,7 @@ fn check_subtraction(
             // This part of the condition is voluntarily split from the one before to ensure that
             // if `snippet_opt` fails, it won't try the next conditions.
             if (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST))
-                && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr).map(Sugg::maybe_par)
+                && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr).map(Sugg::maybe_paren)
                 && let Some(little_expr_sugg) = Sugg::hir_opt(cx, little_expr)
             {
                 let sugg = format!(
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 430f2411183..6b89abdb036 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
@@ -8,7 +8,7 @@ use rustc_hir::{
 };
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, ClauseKind, Generics, Ty, TyCtxt};
+use rustc_middle::ty::{self, AssocItem, ClauseKind, Generics, Ty, TyCtxt};
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
@@ -315,7 +315,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) {
                 assocs
                     .filter_by_name_unhygienic(constraint.ident.name)
                     .next()
-                    .is_some_and(|assoc| assoc.is_type())
+                    .is_some_and(AssocItem::is_type)
                 })
         {
             emit_lint(cx, poly_trait, bounds, index, implied_constraints, bound);
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index e1dd7872b9d..e6129757e56 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -65,13 +65,13 @@ declare_clippy_lint! {
 }
 
 pub struct InconsistentStructConstructor {
-    lint_inconsistent_struct_field_initializers: bool,
+    check_inconsistent_struct_field_initializers: bool,
 }
 
 impl InconsistentStructConstructor {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
-            lint_inconsistent_struct_field_initializers: conf.lint_inconsistent_struct_field_initializers,
+            check_inconsistent_struct_field_initializers: conf.check_inconsistent_struct_field_initializers,
         }
     }
 }
@@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
         let all_fields_are_shorthand = fields.iter().all(|f| f.is_shorthand);
         let applicability = if all_fields_are_shorthand {
             Applicability::MachineApplicable
-        } else if self.lint_inconsistent_struct_field_initializers {
+        } else if self.check_inconsistent_struct_field_initializers {
             Applicability::MaybeIncorrect
         } else {
             return;
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 33431385c7d..99a393b4d53 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -2,13 +2,12 @@ use clippy_config::Conf;
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::ty::{deref_chain, get_adt_inherent_method};
-use clippy_utils::{higher, is_from_proc_macro, is_in_test};
+use clippy_utils::{higher, is_from_proc_macro, is_in_test, sym};
 use rustc_ast::ast::RangeLimits;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
-use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -136,28 +135,28 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
 
                     let const_range = to_const_range(cx, range, size);
 
-                    if let (Some(start), _) = const_range {
-                        if start > size {
-                            span_lint(
-                                cx,
-                                OUT_OF_BOUNDS_INDEXING,
-                                range.start.map_or(expr.span, |start| start.span),
-                                "range is out of bounds",
-                            );
-                            return;
-                        }
+                    if let (Some(start), _) = const_range
+                        && start > size
+                    {
+                        span_lint(
+                            cx,
+                            OUT_OF_BOUNDS_INDEXING,
+                            range.start.map_or(expr.span, |start| start.span),
+                            "range is out of bounds",
+                        );
+                        return;
                     }
 
-                    if let (_, Some(end)) = const_range {
-                        if end > size {
-                            span_lint(
-                                cx,
-                                OUT_OF_BOUNDS_INDEXING,
-                                range.end.map_or(expr.span, |end| end.span),
-                                "range is out of bounds",
-                            );
-                            return;
-                        }
+                    if let (_, Some(end)) = const_range
+                        && end > size
+                    {
+                        span_lint(
+                            cx,
+                            OUT_OF_BOUNDS_INDEXING,
+                            range.end.map_or(expr.span, |end| end.span),
+                            "range is out of bounds",
+                        );
+                        return;
                     }
 
                     if let (Some(_), Some(_)) = const_range {
@@ -268,7 +267,7 @@ fn ty_has_applicable_get_function<'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| {
+        && let Some(get_output_ty) = get_adt_inherent_method(cx, ty, sym::get).map(|m| {
             cx.tcx
                 .fn_sig(m.def_id)
                 .skip_binder()
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 960b9aa032b..427a1f82555 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -156,11 +156,12 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                     .and(cap);
                 }
             }
-            if method.ident.name.as_str() == "flat_map" && args.len() == 1 {
-                if let ExprKind::Closure(&Closure { body, .. }) = args[0].kind {
-                    let body = cx.tcx.hir_body(body);
-                    return is_infinite(cx, body.value);
-                }
+            if method.ident.name.as_str() == "flat_map"
+                && args.len() == 1
+                && let ExprKind::Closure(&Closure { body, .. }) = args[0].kind
+            {
+                let body = cx.tcx.hir_body(body);
+                return is_infinite(cx, body.value);
             }
             Finite
         },
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 4ae1119ab3a..91f65d0b79c 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -123,7 +123,7 @@ fn print_manual_instant_elapsed_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, sugg
         expr.span,
         "manual implementation of `Instant::elapsed`",
         "try",
-        format!("{}.elapsed()", sugg.maybe_par()),
+        format!("{}.elapsed()", sugg.maybe_paren()),
         Applicability::MachineApplicable,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
index fc575bff7e6..67ce57de254 100644
--- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs
+++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
@@ -130,14 +130,14 @@ impl IntPlusOne {
             BinOpKind::Le => "<",
             _ => return None,
         };
-        if let Some(snippet) = node.span.get_source_text(cx) {
-            if let Some(other_side_snippet) = other_side.span.get_source_text(cx) {
-                let rec = match side {
-                    Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
-                    Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
-                };
-                return rec;
-            }
+        if let Some(snippet) = node.span.get_source_text(cx)
+            && let Some(other_side_snippet) = other_side.span.get_source_text(cx)
+        {
+            let rec = match side {
+                Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
+                Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
+            };
+            return rec;
         }
         None
     }
@@ -157,10 +157,10 @@ impl IntPlusOne {
 
 impl EarlyLintPass for IntPlusOne {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
-        if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind {
-            if let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs) {
-                Self::emit_warning(cx, item, rec);
-            }
+        if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind
+            && let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs)
+        {
+            Self::emit_warning(cx, item, rec);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
index b42664340d1..b0ecc5d52dd 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -91,49 +91,49 @@ fn upcast_comparison_bounds_err<'tcx>(
     rhs: &'tcx Expr<'_>,
     invert: bool,
 ) {
-    if let Some((lb, ub)) = lhs_bounds {
-        if let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(rhs) {
-            if rel == Rel::Eq || rel == Rel::Ne {
-                if norm_rhs_val < lb || norm_rhs_val > ub {
-                    err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
-                }
-            } else if match rel {
-                Rel::Lt => {
-                    if invert {
-                        norm_rhs_val < lb
-                    } else {
-                        ub < norm_rhs_val
-                    }
-                },
-                Rel::Le => {
-                    if invert {
-                        norm_rhs_val <= lb
-                    } else {
-                        ub <= norm_rhs_val
-                    }
-                },
-                Rel::Eq | Rel::Ne => unreachable!(),
-            } {
-                err_upcast_comparison(cx, span, lhs, true);
-            } else if match rel {
-                Rel::Lt => {
-                    if invert {
-                        norm_rhs_val >= ub
-                    } else {
-                        lb >= norm_rhs_val
-                    }
-                },
-                Rel::Le => {
-                    if invert {
-                        norm_rhs_val > ub
-                    } else {
-                        lb > norm_rhs_val
-                    }
-                },
-                Rel::Eq | Rel::Ne => unreachable!(),
-            } {
-                err_upcast_comparison(cx, span, lhs, false);
+    if let Some((lb, ub)) = lhs_bounds
+        && let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(rhs)
+    {
+        if rel == Rel::Eq || rel == Rel::Ne {
+            if norm_rhs_val < lb || norm_rhs_val > ub {
+                err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
             }
+        } else if match rel {
+            Rel::Lt => {
+                if invert {
+                    norm_rhs_val < lb
+                } else {
+                    ub < norm_rhs_val
+                }
+            },
+            Rel::Le => {
+                if invert {
+                    norm_rhs_val <= lb
+                } else {
+                    ub <= norm_rhs_val
+                }
+            },
+            Rel::Eq | Rel::Ne => unreachable!(),
+        } {
+            err_upcast_comparison(cx, span, lhs, true);
+        } else if match rel {
+            Rel::Lt => {
+                if invert {
+                    norm_rhs_val >= ub
+                } else {
+                    lb >= norm_rhs_val
+                }
+            },
+            Rel::Le => {
+                if invert {
+                    norm_rhs_val > ub
+                } else {
+                    lb > norm_rhs_val
+                }
+            },
+            Rel::Eq | Rel::Ne => unreachable!(),
+        } {
+            err_upcast_comparison(cx, span, lhs, false);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index 977fd5fce15..b1271a264b5 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -377,22 +377,21 @@ impl ItemNameRepetitions {
                         "field name starts with the struct's name",
                     );
                 }
-                if field_words.len() > item_name_words.len() {
+                if field_words.len() > item_name_words.len()
                     // lint only if the end is not covered by the start
-                    if field_words
+                    && field_words
                         .iter()
                         .rev()
                         .zip(item_name_words.iter().rev())
                         .all(|(a, b)| a == b)
-                    {
-                        span_lint_hir(
-                            cx,
-                            STRUCT_FIELD_NAMES,
-                            field.hir_id,
-                            field.span,
-                            "field name ends with the struct's name",
-                        );
-                    }
+                {
+                    span_lint_hir(
+                        cx,
+                        STRUCT_FIELD_NAMES,
+                        field.hir_id,
+                        field.span,
+                        "field name ends with the struct's name",
+                    );
                 }
             }
         }
@@ -445,57 +444,56 @@ impl LateLintPass<'_> for ItemNameRepetitions {
 
         let item_name = ident.name.as_str();
         let item_camel = to_camel_case(item_name);
-        if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
-            if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules {
-                // constants don't have surrounding modules
-                if !mod_camel.is_empty() {
-                    if mod_name == &ident.name
-                        && let ItemKind::Mod(..) = item.kind
-                        && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public())
-                    {
-                        span_lint(
-                            cx,
-                            MODULE_INCEPTION,
-                            item.span,
-                            "module has the same name as its containing module",
-                        );
-                    }
+        if !item.span.from_expansion() && is_present_in_source(cx, item.span)
+            && let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules
+            // constants don't have surrounding modules
+            && !mod_camel.is_empty()
+        {
+            if mod_name == &ident.name
+                && let ItemKind::Mod(..) = item.kind
+                && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public())
+            {
+                span_lint(
+                    cx,
+                    MODULE_INCEPTION,
+                    item.span,
+                    "module has the same name as its containing module",
+                );
+            }
 
-                    // The `module_name_repetitions` lint should only trigger if the item has the module in its
-                    // name. Having the same name is accepted.
-                    if cx.tcx.visibility(item.owner_id).is_public()
-                        && cx.tcx.visibility(mod_owner_id.def_id).is_public()
-                        && item_camel.len() > mod_camel.len()
-                    {
-                        let matching = count_match_start(mod_camel, &item_camel);
-                        let rmatching = count_match_end(mod_camel, &item_camel);
-                        let nchars = mod_camel.chars().count();
-
-                        let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric();
-
-                        if matching.char_count == nchars {
-                            match item_camel.chars().nth(nchars) {
-                                Some(c) if is_word_beginning(c) => span_lint(
-                                    cx,
-                                    MODULE_NAME_REPETITIONS,
-                                    ident.span,
-                                    "item name starts with its containing module's name",
-                                ),
-                                _ => (),
-                            }
-                        }
-                        if rmatching.char_count == nchars
-                            && !self.is_allowed_prefix(&item_camel[..item_camel.len() - rmatching.byte_count])
-                        {
-                            span_lint(
-                                cx,
-                                MODULE_NAME_REPETITIONS,
-                                ident.span,
-                                "item name ends with its containing module's name",
-                            );
-                        }
+            // The `module_name_repetitions` lint should only trigger if the item has the module in its
+            // name. Having the same name is accepted.
+            if cx.tcx.visibility(item.owner_id).is_public()
+                && cx.tcx.visibility(mod_owner_id.def_id).is_public()
+                && item_camel.len() > mod_camel.len()
+            {
+                let matching = count_match_start(mod_camel, &item_camel);
+                let rmatching = count_match_end(mod_camel, &item_camel);
+                let nchars = mod_camel.chars().count();
+
+                let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric();
+
+                if matching.char_count == nchars {
+                    match item_camel.chars().nth(nchars) {
+                        Some(c) if is_word_beginning(c) => span_lint(
+                            cx,
+                            MODULE_NAME_REPETITIONS,
+                            ident.span,
+                            "item name starts with its containing module's name",
+                        ),
+                        _ => (),
                     }
                 }
+                if rmatching.char_count == nchars
+                    && !self.is_allowed_prefix(&item_camel[..item_camel.len() - rmatching.byte_count])
+                {
+                    span_lint(
+                        cx,
+                        MODULE_NAME_REPETITIONS,
+                        ident.span,
+                        "item name ends with its containing module's name",
+                    );
+                }
             }
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 77085d52a32..8c71d34c95f 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -2,13 +2,13 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
 use clippy_utils::source::{SpanRangeExt, snippet_with_context};
 use clippy_utils::sugg::{Sugg, has_enclosing_paren};
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, is_trait_method, peel_ref_operators};
+use clippy_utils::{fulfill_or_allowed, get_item_name, get_parent_as_impl, is_trait_method, peel_ref_operators, sym};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::{
-    AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
+    AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, HirId, ImplItem, ImplItemKind,
     ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatExprKind, PatKind, PathSegment, PrimTy,
     QPath, TraitItemRef, TyKind,
 };
@@ -16,7 +16,6 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, FnSig, Ty};
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::sym;
 use rustc_span::{Ident, Span, Symbol};
 use rustc_trait_selection::traits::supertrait_def_ids;
 
@@ -143,7 +142,6 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             && let Some(ty_id) = cx.qpath_res(ty_path, imp.self_ty.hir_id).opt_def_id()
             && let Some(local_id) = ty_id.as_local()
             && let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_id)
-            && !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id)
             && let Some(output) =
                 parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder())
         {
@@ -157,7 +155,17 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
                 },
                 _ => return,
             };
-            check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind);
+            check_for_is_empty(
+                cx,
+                sig.span,
+                sig.decl.implicit_self,
+                output,
+                ty_id,
+                name,
+                kind,
+                item.hir_id(),
+                ty_hir_id,
+            );
         }
     }
 
@@ -180,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             let mut applicability = Applicability::MachineApplicable;
 
             let lit1 = peel_ref_operators(cx, lt.init);
-            let lit_str = Sugg::hir_with_context(cx, lit1, lt.span.ctxt(), "_", &mut applicability).maybe_par();
+            let lit_str = Sugg::hir_with_context(cx, lit1, lt.span.ctxt(), "_", &mut applicability).maybe_paren();
 
             span_lint_and_sugg(
                 cx,
@@ -202,7 +210,11 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
                 expr.span,
                 lhs_expr,
                 peel_ref_operators(cx, rhs_expr),
-                (method.ident.name == sym::ne).then_some("!").unwrap_or_default(),
+                if method.ident.name == sym::ne {
+                    "!"
+                } else {
+                    Default::default()
+                },
             );
         }
 
@@ -282,15 +294,10 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Iden
     {
         let mut current_and_super_traits = DefIdSet::default();
         fill_trait_set(visited_trait.owner_id.to_def_id(), &mut current_and_super_traits, cx);
-        let is_empty = sym!(is_empty);
-
         let is_empty_method_found = current_and_super_traits
             .items()
-            .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty))
-            .any(|i| {
-                i.is_method()
-                    && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1
-            });
+            .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(sym::is_empty))
+            .any(|i| i.is_method() && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1);
 
         if !is_empty_method_found {
             span_lint(
@@ -442,6 +449,7 @@ fn check_is_empty_sig<'tcx>(
 }
 
 /// Checks if the given type has an `is_empty` method with the appropriate signature.
+#[expect(clippy::too_many_arguments)]
 fn check_for_is_empty(
     cx: &LateContext<'_>,
     span: Span,
@@ -450,6 +458,8 @@ fn check_for_is_empty(
     impl_ty: DefId,
     item_name: Symbol,
     item_kind: &str,
+    len_method_hir_id: HirId,
+    ty_decl_hir_id: HirId,
 ) {
     // Implementor may be a type alias, in which case we need to get the `DefId` of the aliased type to
     // find the correct inherent impls.
@@ -459,12 +469,11 @@ fn check_for_is_empty(
         return;
     };
 
-    let is_empty = Symbol::intern("is_empty");
     let is_empty = cx
         .tcx
         .inherent_impls(impl_ty)
         .iter()
-        .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty))
+        .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(sym::is_empty))
         .find(|item| item.is_fn());
 
     let (msg, is_empty_span, self_kind) = match is_empty {
@@ -505,14 +514,16 @@ fn check_for_is_empty(
         Some(_) => return,
     };
 
-    span_lint_and_then(cx, LEN_WITHOUT_IS_EMPTY, span, msg, |db| {
-        if let Some(span) = is_empty_span {
-            db.span_note(span, "`is_empty` defined here");
-        }
-        if let Some(self_kind) = self_kind {
-            db.note(output.expected_sig(self_kind));
-        }
-    });
+    if !fulfill_or_allowed(cx, LEN_WITHOUT_IS_EMPTY, [len_method_hir_id, ty_decl_hir_id]) {
+        span_lint_and_then(cx, LEN_WITHOUT_IS_EMPTY, span, msg, |db| {
+            if let Some(span) = is_empty_span {
+                db.span_note(span, "`is_empty` defined here");
+            }
+            if let Some(self_kind) = self_kind {
+                db.note(output.expected_sig(self_kind));
+            }
+        });
+    }
 }
 
 fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
@@ -522,10 +533,10 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
 
     if let (&ExprKind::MethodCall(method_path, receiver, [], _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
         // check if we are in an is_empty() method
-        if let Some(name) = get_item_name(cx, method) {
-            if name.as_str() == "is_empty" {
-                return;
-            }
+        if let Some(name) = get_item_name(cx, method)
+            && name.as_str() == "is_empty"
+        {
+            return;
         }
 
         check_len(cx, span, method_path.ident.name, receiver, &lit.node, op, compare_to);
@@ -572,7 +583,7 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex
         let mut applicability = Applicability::MachineApplicable;
 
         let lit1 = peel_ref_operators(cx, lit1);
-        let lit_str = Sugg::hir_with_context(cx, lit1, span.ctxt(), "_", &mut applicability).maybe_par();
+        let lit_str = Sugg::hir_with_context(cx, lit1, span.ctxt(), "_", &mut applicability).maybe_paren();
 
         span_lint_and_sugg(
             cx,
@@ -587,11 +598,11 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex
 }
 
 fn is_empty_string(expr: &Expr<'_>) -> bool {
-    if let ExprKind::Lit(lit) = expr.kind {
-        if let LitKind::Str(lit, _) = lit.node {
-            let lit = lit.as_str();
-            return lit.is_empty();
-        }
+    if let ExprKind::Lit(lit) = expr.kind
+        && let LitKind::Str(lit, _) = lit.node
+    {
+        let lit = lit.as_str();
+        return lit.is_empty();
     }
     false
 }
@@ -618,11 +629,10 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 
     /// Checks the inherent impl's items for an `is_empty(self)` method.
     fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
-        let is_empty = sym!(is_empty);
         cx.tcx.inherent_impls(id).iter().any(|imp| {
             cx.tcx
                 .associated_items(*imp)
-                .filter_by_name_unhygienic(is_empty)
+                .filter_by_name_unhygienic(sym::is_empty)
                 .any(|item| is_is_empty(cx, item))
         })
     }
@@ -630,10 +640,9 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     fn ty_has_is_empty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, depth: usize) -> bool {
         match ty.kind() {
             ty::Dynamic(tt, ..) => tt.principal().is_some_and(|principal| {
-                let is_empty = sym!(is_empty);
                 cx.tcx
                     .associated_items(principal.def_id())
-                    .filter_by_name_unhygienic(is_empty)
+                    .filter_by_name_unhygienic(sym::is_empty)
                     .any(|item| is_is_empty(cx, item))
             }),
             ty::Alias(ty::Projection, proj) => has_is_empty_impl(cx, proj.def_id),
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 3fe3cd67e16..5fa8f6f4bf3 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -65,7 +65,6 @@ mod declare_clippy_lint;
 #[macro_use]
 extern crate clippy_utils;
 
-#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
 mod utils;
 
 pub mod ctfe; // Very important lint, do not remove (rust#125116)
@@ -205,6 +204,7 @@ mod loops;
 mod macro_metavars_in_unsafe;
 mod macro_use;
 mod main_recursion;
+mod manual_abs_diff;
 mod manual_assert;
 mod manual_async_fn;
 mod manual_bits;
@@ -226,7 +226,6 @@ mod manual_rotate;
 mod manual_slice_size_calculation;
 mod manual_string_new;
 mod manual_strip;
-mod manual_unwrap_or_default;
 mod map_unit_fn;
 mod match_result_ok;
 mod matches;
@@ -320,6 +319,7 @@ mod redundant_locals;
 mod redundant_pub_crate;
 mod redundant_slicing;
 mod redundant_static_lifetimes;
+mod redundant_test_prefix;
 mod redundant_type_annotations;
 mod ref_option_ref;
 mod ref_patterns;
@@ -412,21 +412,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::{Lint, LintId};
 use utils::attr_collector::{AttrCollector, AttrStorage};
 
-/// Register all pre expansion lints
-///
-/// Pre-expansion lints run before any macro expansion has happened.
-///
-/// Note that due to the architecture of the compiler, currently `cfg_attr` attributes on crate
-/// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
-///
-/// Used in `./src/driver.rs`.
-pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
-    // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
-    store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
-
-    store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
-}
-
 #[derive(Default)]
 struct RegistrationGroups {
     all: Vec<LintId>,
@@ -439,8 +424,6 @@ struct RegistrationGroups {
     restriction: Vec<LintId>,
     style: Vec<LintId>,
     suspicious: Vec<LintId>,
-    #[cfg(feature = "internal")]
-    internal: Vec<LintId>,
 }
 
 impl RegistrationGroups {
@@ -456,8 +439,6 @@ impl RegistrationGroups {
         store.register_group(true, "clippy::restriction", Some("clippy_restriction"), self.restriction);
         store.register_group(true, "clippy::style", Some("clippy_style"), self.style);
         store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), self.suspicious);
-        #[cfg(feature = "internal")]
-        store.register_group(true, "clippy::internal", Some("clippy_internal"), self.internal);
     }
 }
 
@@ -472,8 +453,6 @@ pub(crate) enum LintCategory {
     Restriction,
     Style,
     Suspicious,
-    #[cfg(feature = "internal")]
-    Internal,
 }
 
 #[allow(clippy::enum_glob_use)]
@@ -495,8 +474,6 @@ impl LintCategory {
             Restriction => &mut groups.restriction,
             Style => &mut groups.style,
             Suspicious => &mut groups.suspicious,
-            #[cfg(feature = "internal")]
-            Internal => &mut groups.internal,
         }
     }
 }
@@ -530,8 +507,6 @@ impl LintInfo {
             Restriction => "restriction",
             Style => "style",
             Suspicious => "suspicious",
-            #[cfg(feature = "internal")]
-            Internal => "internal",
         }
     }
 }
@@ -589,6 +564,13 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         store.register_removed(name, reason);
     }
 
+    // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
+    // Due to the architecture of the compiler, currently `cfg_attr` attributes on crate
+    // level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
+    store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
+
+    store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
+
     let format_args_storage = FormatArgsStorage::default();
     let format_args = format_args_storage.clone();
     store.register_early_pass(move || {
@@ -601,30 +583,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     let attrs = attr_storage.clone();
     store.register_early_pass(move || Box::new(AttrCollector::new(attrs.clone())));
 
-    // all the internal lints
-    #[cfg(feature = "internal")]
-    {
-        store.register_early_pass(|| {
-            Box::new(utils::internal_lints::unsorted_clippy_utils_paths::UnsortedClippyUtilsPaths)
-        });
-        store.register_early_pass(|| Box::new(utils::internal_lints::produce_ice::ProduceIce));
-        store.register_late_pass(|_| Box::new(utils::internal_lints::collapsible_calls::CollapsibleCalls));
-        store.register_late_pass(|_| Box::new(utils::internal_lints::invalid_paths::InvalidPaths));
-        store.register_late_pass(|_| {
-            Box::<utils::internal_lints::interning_defined_symbol::InterningDefinedSymbol>::default()
-        });
-        store.register_late_pass(|_| {
-            Box::<utils::internal_lints::lint_without_lint_pass::LintWithoutLintPass>::default()
-        });
-        store.register_late_pass(|_| Box::<utils::internal_lints::unnecessary_def_path::UnnecessaryDefPath>::default());
-        store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass));
-        store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl));
-        store.register_late_pass(|_| {
-            Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new())
-        });
-        store.register_late_pass(|_| Box::new(utils::internal_lints::slow_symbol_comparisons::SlowSymbolComparisons));
-    }
-
     store.register_late_pass(|_| Box::new(ctfe::ClippyCtfe));
 
     store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));
@@ -772,7 +730,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
     store.register_late_pass(|_| Box::new(returns::Return));
-    store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
+    store.register_late_pass(move |tcx| Box::new(collapsible_if::CollapsibleIf::new(tcx, conf)));
     store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements));
     store.register_early_pass(|| Box::new(precedence::Precedence));
     store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
@@ -857,7 +815,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(write::Write::new(conf, format_args.clone())));
     store.register_late_pass(move |_| Box::new(cargo::Cargo::new(conf)));
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
-    store.register_early_pass(|| Box::new(empty_with_brackets::EmptyWithBrackets));
+    store.register_late_pass(|_| Box::new(empty_with_brackets::EmptyWithBrackets::default()));
     store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
     store.register_early_pass(|| Box::new(pub_use::PubUse));
     store.register_late_pass(|_| Box::new(format_push_string::FormatPushString));
@@ -879,6 +837,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(std_instead_of_core::StdReexports::new(conf)));
     store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(conf)));
     store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
+    store.register_late_pass(move |_| Box::new(manual_abs_diff::ManualAbsDiff::new(conf)));
     store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(conf)));
     store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
     store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
@@ -960,7 +919,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations));
     store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(conf)));
     store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects));
-    store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault));
     store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed));
     store.register_late_pass(move |_| Box::new(macro_metavars_in_unsafe::ExprMetavarsInUnsafe::new(conf)));
     store.register_late_pass(move |_| Box::new(string_patterns::StringPatterns::new(conf)));
@@ -971,7 +929,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses));
     store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock));
     store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
-    store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo));
+    store.register_late_pass(move |_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo::new(conf)));
     store.register_late_pass(|_| Box::new(non_zero_suggestions::NonZeroSuggestions));
     store.register_late_pass(|_| Box::new(literal_string_with_formatting_args::LiteralStringWithFormattingArg));
     store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf)));
@@ -984,5 +942,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(non_std_lazy_statics::NonStdLazyStatic::new(conf)));
     store.register_late_pass(|_| Box::new(manual_option_as_slice::ManualOptionAsSlice::new(conf)));
     store.register_late_pass(|_| Box::new(single_option_map::SingleOptionMap));
+    store.register_late_pass(move |_| Box::new(redundant_test_prefix::RedundantTestPrefix));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index dabef18b98a..5ef5e3a44f8 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -150,10 +150,10 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
         } = item.kind
         {
             check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv);
-        } else if let ItemKind::Impl(impl_) = item.kind {
-            if !item.span.from_expansion() {
-                report_extra_impl_lifetimes(cx, impl_);
-            }
+        } else if let ItemKind::Impl(impl_) = item.kind
+            && !item.span.from_expansion()
+        {
+            report_extra_impl_lifetimes(cx, impl_);
         }
     }
 
@@ -300,8 +300,8 @@ fn could_use_elision<'tcx>(
     let input_lts = input_visitor.lts;
     let output_lts = output_visitor.lts;
 
-    if let Some(trait_sig) = trait_sig
-        && non_elidable_self_type(cx, func, trait_sig.first().copied(), msrv)
+    if let Some(&[trait_sig]) = trait_sig
+        && non_elidable_self_type(cx, func, trait_sig, msrv)
     {
         return None;
     }
@@ -310,11 +310,11 @@ fn could_use_elision<'tcx>(
         let body = cx.tcx.hir_body(body_id);
 
         let first_ident = body.params.first().and_then(|param| param.pat.simple_ident());
-        if non_elidable_self_type(cx, func, Some(first_ident), msrv) {
+        if non_elidable_self_type(cx, func, first_ident, msrv) {
             return None;
         }
 
-        let mut checker = BodyLifetimeChecker;
+        let mut checker = BodyLifetimeChecker::new(cx);
         if checker.visit_expr(body.value).is_break() {
             return None;
         }
@@ -384,8 +384,8 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet<LocalDefI
 }
 
 // elision doesn't work for explicit self types before Rust 1.81, see rust-lang/rust#69064
-fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Option<Ident>>, msrv: Msrv) -> bool {
-    if let Some(Some(ident)) = ident
+fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>, msrv: Msrv) -> bool {
+    if let Some(ident) = ident
         && ident.name == kw::SelfLower
         && !func.implicit_self.has_implicit_self()
         && let Some(self_ty) = func.inputs.first()
@@ -911,10 +911,23 @@ fn elision_suggestions(
     Some(suggestions)
 }
 
-struct BodyLifetimeChecker;
+struct BodyLifetimeChecker<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
 
-impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
+impl<'tcx> BodyLifetimeChecker<'tcx> {
+    fn new(cx: &LateContext<'tcx>) -> Self {
+        Self { tcx: cx.tcx }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker<'tcx> {
     type Result = ControlFlow<()>;
+    type NestedFilter = middle_nested_filter::OnlyBodies;
+
+    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
+        self.tcx
+    }
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) -> ControlFlow<()> {
         if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index 805de23408b..7cbfa2d097a 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -387,12 +387,11 @@ impl LiteralDigitGrouping {
 
         let first = groups.next().expect("At least one group");
 
-        if radix == Radix::Binary || radix == Radix::Octal || radix == Radix::Hexadecimal {
-            if let Some(second_size) = groups.next() {
-                if !groups.all(|i| i == second_size) || first > second_size {
-                    return Err(WarningType::UnusualByteGroupings);
-                }
-            }
+        if (radix == Radix::Binary || radix == Radix::Octal || radix == Radix::Hexadecimal)
+            && let Some(second_size) = groups.next()
+            && (!groups.all(|i| i == second_size) || first > second_size)
+        {
+            return Err(WarningType::UnusualByteGroupings);
         }
 
         if let Some(second) = groups.next() {
diff --git a/src/tools/clippy/clippy_lints/src/literal_string_with_formatting_args.rs b/src/tools/clippy/clippy_lints/src/literal_string_with_formatting_args.rs
index 975e6833a35..244e7c95122 100644
--- a/src/tools/clippy/clippy_lints/src/literal_string_with_formatting_args.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_string_with_formatting_args.rs
@@ -45,15 +45,14 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, spans: &[(Span, Option<Strin
         let spans = spans
             .iter()
             .filter_map(|(span, name)| {
-                if let Some(name) = name {
+                if let Some(name) = name
                     // We need to check that the name is a local.
-                    if !mir
+                    && !mir
                         .var_debug_info
                         .iter()
                         .any(|local| !local.source_info.span.from_expansion() && local.name.as_str() == name)
-                    {
-                        return None;
-                    }
+                {
+                    return None;
                 }
                 Some(*span)
             })
diff --git a/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs b/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs
new file mode 100644
index 00000000000..8916454ada1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/loops/char_indices_as_byte_indices.rs
@@ -0,0 +1,141 @@
+use std::ops::ControlFlow;
+
+use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::visitors::for_each_expr;
+use clippy_utils::{eq_expr_value, higher, path_to_local_id};
+use rustc_errors::{Applicability, MultiSpan};
+use rustc_hir::{Expr, ExprKind, LangItem, Node, Pat, PatKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
+use rustc_span::{Span, sym};
+
+use super::CHAR_INDICES_AS_BYTE_INDICES;
+
+// The list of `str` methods we want to lint that have a `usize` argument representing a byte index.
+// Note: `String` also has methods that work with byte indices,
+// but they all take `&mut self` and aren't worth considering since the user couldn't have called
+// them while the chars iterator is live anyway.
+const BYTE_INDEX_METHODS: &[&str] = &[
+    "is_char_boundary",
+    "floor_char_boundary",
+    "ceil_char_boundary",
+    "get",
+    "index",
+    "index_mut",
+    "get_mut",
+    "get_unchecked",
+    "get_unchecked_mut",
+    "slice_unchecked",
+    "slice_mut_unchecked",
+    "split_at",
+    "split_at_mut",
+    "split_at_checked",
+    "split_at_mut_checked",
+];
+
+const CONTINUE: ControlFlow<!, ()> = ControlFlow::Continue(());
+
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'_>, iterable: &Expr<'_>, body: &'tcx Expr<'tcx>) {
+    if let ExprKind::MethodCall(_, enumerate_recv, _, enumerate_span) = iterable.kind
+        && let Some(method_id) = cx.typeck_results().type_dependent_def_id(iterable.hir_id)
+        && cx.tcx.is_diagnostic_item(sym::enumerate_method, method_id)
+        && let ExprKind::MethodCall(_, chars_recv, _, chars_span) = enumerate_recv.kind
+        && let Some(method_id) = cx.typeck_results().type_dependent_def_id(enumerate_recv.hir_id)
+        && cx.tcx.is_diagnostic_item(sym::str_chars, method_id)
+    {
+        if let PatKind::Tuple([pat, _], _) = pat.kind
+            && let PatKind::Binding(_, binding_id, ..) = pat.kind
+        {
+            // Destructured iterator element `(idx, _)`, look for uses of the binding
+            for_each_expr(cx, body, |expr| {
+                if path_to_local_id(expr, binding_id) {
+                    check_index_usage(cx, expr, pat, enumerate_span, chars_span, chars_recv);
+                }
+                CONTINUE
+            });
+        } else if let PatKind::Binding(_, binding_id, ..) = pat.kind {
+            // Bound as a tuple, look for `tup.0`
+            for_each_expr(cx, body, |expr| {
+                if let ExprKind::Field(e, field) = expr.kind
+                    && path_to_local_id(e, binding_id)
+                    && field.name == sym::integer(0)
+                {
+                    check_index_usage(cx, expr, pat, enumerate_span, chars_span, chars_recv);
+                }
+                CONTINUE
+            });
+        }
+    }
+}
+
+fn check_index_usage<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    pat: &Pat<'_>,
+    enumerate_span: Span,
+    chars_span: Span,
+    chars_recv: &Expr<'_>,
+) {
+    let Some(parent_expr) = index_consumed_at(cx, expr) else {
+        return;
+    };
+
+    let is_string_like = |ty: Ty<'_>| ty.is_str() || is_type_lang_item(cx, ty, LangItem::String);
+    let message = match parent_expr.kind {
+        ExprKind::MethodCall(segment, recv, ..)
+            // We currently only lint `str` methods (which `String` can deref to), so a `.is_str()` check is sufficient here
+            // (contrary to the `ExprKind::Index` case which needs to handle both with `is_string_like` because `String` implements
+            // `Index` directly and no deref to `str` would happen in that case).
+            if cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_str()
+                && BYTE_INDEX_METHODS.contains(&segment.ident.name.as_str())
+                && eq_expr_value(cx, chars_recv, recv) =>
+        {
+            "passing a character position to a method that expects a byte index"
+        },
+        ExprKind::Index(target, ..)
+            if is_string_like(cx.typeck_results().expr_ty_adjusted(target).peel_refs())
+                && eq_expr_value(cx, chars_recv, target) =>
+        {
+            "indexing into a string with a character position where a byte index is expected"
+        },
+        _ => return,
+    };
+
+    span_lint_hir_and_then(
+        cx,
+        CHAR_INDICES_AS_BYTE_INDICES,
+        expr.hir_id,
+        expr.span,
+        message,
+        |diag| {
+            diag.note("a character can take up more than one byte, so they are not interchangeable")
+                .span_note(
+                    MultiSpan::from_spans(vec![pat.span, enumerate_span]),
+                    "position comes from the enumerate iterator",
+                )
+                .span_suggestion_verbose(
+                    chars_span.to(enumerate_span),
+                    "consider using `.char_indices()` instead",
+                    "char_indices()",
+                    Applicability::MaybeIncorrect,
+                );
+        },
+    );
+}
+
+/// Returns the expression which ultimately consumes the index.
+/// This is usually the parent expression, i.e. `.split_at(idx)` for `idx`,
+/// but for `.get(..idx)` we want to consider the method call the consuming expression,
+/// which requires skipping past the range expression.
+fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) {
+        match node {
+            Node::Expr(expr) if higher::Range::hir(expr).is_some() => {},
+            Node::ExprField(_) => {},
+            Node::Expr(expr) => return Some(expr),
+            _ => break,
+        }
+    }
+    None
+}
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 412c78cc804..d0b26c91ffa 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -2,6 +2,7 @@ use super::EXPLICIT_ITER_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sym;
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection,
     make_normalized_projection_with_regions, normalize_with_regions,
@@ -11,7 +12,6 @@ use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{self, EarlyBinder, Ty};
-use rustc_span::sym;
 
 pub(super) fn check(
     cx: &LateContext<'_>,
@@ -119,7 +119,7 @@ fn is_ref_iterable<'tcx>(
         && let typing_env = ty::TypingEnv::non_body_analysis(cx.tcx, fn_id)
         && implements_trait_with_env(cx.tcx, typing_env, req_self_ty, trait_id, Some(fn_id), &[])
         && let Some(into_iter_ty) =
-            make_normalized_projection_with_regions(cx.tcx, typing_env, trait_id, sym!(IntoIter), [req_self_ty])
+            make_normalized_projection_with_regions(cx.tcx, typing_env, trait_id, sym::IntoIter, [req_self_ty])
         && let req_res_ty = normalize_with_regions(cx.tcx, typing_env, req_res_ty)
         && into_iter_ty == req_res_ty
     {
@@ -152,7 +152,7 @@ fn is_ref_iterable<'tcx>(
                 // Using by value won't consume anything
                 if implements_trait(cx, self_ty, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym::IntoIter, [self_ty])
                     && ty == res_ty
                 {
                     return Some((AdjustKind::None, self_ty));
@@ -169,7 +169,7 @@ fn is_ref_iterable<'tcx>(
                 };
                 if implements_trait(cx, self_ty, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym::IntoIter, [self_ty])
                     && ty == res_ty
                 {
                     return Some((AdjustKind::reborrow(mutbl), self_ty));
@@ -183,7 +183,7 @@ fn is_ref_iterable<'tcx>(
             let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl);
             if implements_trait(cx, self_ty, trait_id, &[])
                 && let Some(ty) =
-                    make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
+                    make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym::IntoIter, [self_ty])
                 && ty == res_ty
             {
                 return Some((AdjustKind::borrow(mutbl), self_ty));
@@ -206,7 +206,7 @@ fn is_ref_iterable<'tcx>(
                     && target != self_ty
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym::IntoIter, [target])
                     && ty == res_ty
                 {
                     Some((AdjustKind::auto_reborrow(mutbl), target))
@@ -224,7 +224,7 @@ fn is_ref_iterable<'tcx>(
                 if is_copy(cx, target)
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym::IntoIter, [target])
                     && ty == res_ty
                 {
                     Some((AdjustKind::Deref, target))
@@ -242,7 +242,7 @@ fn is_ref_iterable<'tcx>(
                 if self_ty.is_ref()
                     && implements_trait(cx, target, trait_id, &[])
                     && let Some(ty) =
-                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
+                        make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym::IntoIter, [target])
                     && ty == res_ty
                 {
                     Some((AdjustKind::auto_borrow(mutbl), target))
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
index 185d834beca..e314bc2068b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
@@ -13,45 +13,45 @@ use rustc_span::sym;
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
     let pat_span = pat.span;
 
-    if let PatKind::Tuple(pat, _) = pat.kind {
-        if pat.len() == 2 {
-            let arg_span = arg.span;
-            let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() {
-                ty::Ref(_, ty, mutbl) => match (&pat[0].kind, &pat[1].kind) {
-                    (key, _) if pat_is_wild(cx, key, body) => (pat[1].span, "value", ty, mutbl),
-                    (_, value) if pat_is_wild(cx, value, body) => (pat[0].span, "key", ty, Mutability::Not),
-                    _ => return,
-                },
+    if let PatKind::Tuple(pat, _) = pat.kind
+        && pat.len() == 2
+    {
+        let arg_span = arg.span;
+        let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() {
+            ty::Ref(_, ty, mutbl) => match (&pat[0].kind, &pat[1].kind) {
+                (key, _) if pat_is_wild(cx, key, body) => (pat[1].span, "value", ty, mutbl),
+                (_, value) if pat_is_wild(cx, value, body) => (pat[0].span, "key", ty, Mutability::Not),
                 _ => return,
-            };
-            let mutbl = match mutbl {
-                Mutability::Not => "",
-                Mutability::Mut => "_mut",
-            };
-            let arg = match arg.kind {
-                ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr,
-                _ => arg,
-            };
+            },
+            _ => return,
+        };
+        let mutbl = match mutbl {
+            Mutability::Not => "",
+            Mutability::Mut => "_mut",
+        };
+        let arg = match arg.kind {
+            ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr,
+            _ => arg,
+        };
 
-            if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) {
-                span_lint_and_then(
-                    cx,
-                    FOR_KV_MAP,
-                    arg_span,
-                    format!("you seem to want to iterate on a map's {kind}s"),
-                    |diag| {
-                        let map = sugg::Sugg::hir(cx, arg, "map");
-                        diag.multipart_suggestion(
-                            "use the corresponding method",
-                            vec![
-                                (pat_span, snippet(cx, new_pat_span, kind).into_owned()),
-                                (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_par())),
-                            ],
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                );
-            }
+        if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) {
+            span_lint_and_then(
+                cx,
+                FOR_KV_MAP,
+                arg_span,
+                format!("you seem to want to iterate on a map's {kind}s"),
+                |diag| {
+                    let map = sugg::Sugg::hir(cx, arg, "map");
+                    diag.multipart_suggestion(
+                        "use the corresponding method",
+                        vec![
+                            (pat_span, snippet(cx, new_pat_span, kind).into_owned()),
+                            (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_paren())),
+                        ],
+                        Applicability::MachineApplicable,
+                    );
+                },
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index aa8a2934f89..35737f3eafe 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -3,6 +3,7 @@ use super::utils::make_iterator_snippet;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::usage::contains_return_break_continue_macro;
 use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt};
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -35,6 +36,7 @@ pub(super) fn check<'tcx>(
         && let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind
         && is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome)
         && path_res(cx, inner_ret) == Res::Local(binding_id)
+        && !contains_return_break_continue_macro(cond)
         && let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr)
     {
         let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 701567a7d84..d9c4b526da9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -28,37 +28,37 @@ pub(super) fn check<'tcx>(
         end: Some(end),
         limits,
     }) = higher::Range::hir(arg)
-    {
         // the var must be a single name
-        if let PatKind::Binding(_, canonical_id, _, _) = pat.kind {
-            let mut starts = vec![Start {
-                id: canonical_id,
-                kind: StartKind::Range,
-            }];
-
-            // This is one of few ways to return different iterators
-            // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434
-            let mut iter_a = None;
-            let mut iter_b = None;
-
-            if let ExprKind::Block(block, _) = body.kind {
-                if let Some(loop_counters) = get_loop_counters(cx, block, expr) {
-                    starts.extend(loop_counters);
-                }
-                iter_a = Some(get_assignments(block, &starts));
-            } else {
-                iter_b = Some(get_assignment(body));
+        && let PatKind::Binding(_, canonical_id, _, _) = pat.kind
+    {
+        let mut starts = vec![Start {
+            id: canonical_id,
+            kind: StartKind::Range,
+        }];
+
+        // This is one of few ways to return different iterators
+        // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434
+        let mut iter_a = None;
+        let mut iter_b = None;
+
+        if let ExprKind::Block(block, _) = body.kind {
+            if let Some(loop_counters) = get_loop_counters(cx, block, expr) {
+                starts.extend(loop_counters);
             }
+            iter_a = Some(get_assignments(block, &starts));
+        } else {
+            iter_b = Some(get_assignment(body));
+        }
 
-            let assignments = iter_a.into_iter().flatten().chain(iter_b);
+        let assignments = iter_a.into_iter().flatten().chain(iter_b);
 
-            let big_sugg = assignments
-                // The only statements in the for loops can be indexed assignments from
-                // indexed retrievals (except increments of loop counters).
-                .map(|o| {
-                    o.and_then(|(lhs, rhs)| {
-                        let rhs = fetch_cloned_expr(rhs);
-                        if let ExprKind::Index(base_left, idx_left, _) = lhs.kind
+        let big_sugg = assignments
+            // The only statements in the for loops can be indexed assignments from
+            // indexed retrievals (except increments of loop counters).
+            .map(|o| {
+                o.and_then(|(lhs, rhs)| {
+                    let rhs = fetch_cloned_expr(rhs);
+                    if let ExprKind::Index(base_left, idx_left, _) = lhs.kind
                             && let ExprKind::Index(base_right, idx_right, _) = rhs.kind
                             && let Some(ty) = get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_left))
                             && get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some()
@@ -68,42 +68,41 @@ pub(super) fn check<'tcx>(
                             && !local_used_in(cx, canonical_id, base_right)
 							// Source and destination must be different
                             && path_to_local(base_left) != path_to_local(base_right)
-                        {
-                            Some((
-                                ty,
-                                IndexExpr {
-                                    base: base_left,
-                                    idx: start_left,
-                                    idx_offset: offset_left,
-                                },
-                                IndexExpr {
-                                    base: base_right,
-                                    idx: start_right,
-                                    idx_offset: offset_right,
-                                },
-                            ))
-                        } else {
-                            None
-                        }
-                    })
+                    {
+                        Some((
+                            ty,
+                            IndexExpr {
+                                base: base_left,
+                                idx: start_left,
+                                idx_offset: offset_left,
+                            },
+                            IndexExpr {
+                                base: base_right,
+                                idx: start_right,
+                                idx_offset: offset_right,
+                            },
+                        ))
+                    } else {
+                        None
+                    }
                 })
-                .map(|o| o.map(|(ty, dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, ty, &dst, &src)))
-                .collect::<Option<Vec<_>>>()
-                .filter(|v| !v.is_empty())
-                .map(|v| v.join("\n    "));
-
-            if let Some(big_sugg) = big_sugg {
-                span_lint_and_sugg(
-                    cx,
-                    MANUAL_MEMCPY,
-                    expr.span,
-                    "it looks like you're manually copying between slices",
-                    "try replacing the loop by",
-                    big_sugg,
-                    Applicability::Unspecified,
-                );
-                return true;
-            }
+            })
+            .map(|o| o.map(|(ty, dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, ty, &dst, &src)))
+            .collect::<Option<Vec<_>>>()
+            .filter(|v| !v.is_empty())
+            .map(|v| v.join("\n    "));
+
+        if let Some(big_sugg) = big_sugg {
+            span_lint_and_sugg(
+                cx,
+                MANUAL_MEMCPY,
+                expr.span,
+                "it looks like you're manually copying between slices",
+                "try replacing the loop by",
+                big_sugg,
+                Applicability::Unspecified,
+            );
+            return true;
         }
     }
     false
@@ -184,7 +183,12 @@ fn build_manual_memcpy_suggestion<'tcx>(
     {
         dst_base_str
     } else {
-        format!("{dst_base_str}[{}..{}]", dst_offset.maybe_par(), dst_limit.maybe_par()).into()
+        format!(
+            "{dst_base_str}[{}..{}]",
+            dst_offset.maybe_paren(),
+            dst_limit.maybe_paren()
+        )
+        .into()
     };
 
     let method_str = if is_copy(cx, elem_ty) {
@@ -196,7 +200,12 @@ fn build_manual_memcpy_suggestion<'tcx>(
     let src = if is_array_length_equal_to_range(cx, start, end, src.base) {
         src_base_str
     } else {
-        format!("{src_base_str}[{}..{}]", src_offset.maybe_par(), src_limit.maybe_par()).into()
+        format!(
+            "{src_base_str}[{}..{}]",
+            src_offset.maybe_paren(),
+            src_limit.maybe_paren()
+        )
+        .into()
     };
 
     format!("{dst}.{method_str}(&{src});")
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
index 4473a3343c7..9527e258db8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
@@ -81,15 +81,15 @@ fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>,
 }
 
 fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) {
-    if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind {
-        if let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind {
-            let offending_arg = args
-                .iter()
-                .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span));
+    if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind
+        && let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind
+    {
+        let offending_arg = args
+            .iter()
+            .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span));
 
-            if let Some(offending_arg) = offending_arg {
-                report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span);
-            }
+        if let Some(offending_arg) = offending_arg {
+            report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 4b0bf5a4b3c..2b66827e82e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -1,3 +1,4 @@
+mod char_indices_as_byte_indices;
 mod empty_loop;
 mod explicit_counter_loop;
 mod explicit_into_iter_loop;
@@ -740,6 +741,49 @@ declare_clippy_lint! {
     "manually filling a slice with a value"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of a character position yielded by `.chars().enumerate()` in a context where a **byte index** is expected,
+    /// such as an argument to a specific `str` method or indexing into a `str` or `String`.
+    ///
+    /// ### Why is this bad?
+    /// A character (more specifically, a Unicode scalar value) that is yielded by `str::chars` can take up multiple bytes,
+    /// so a character position does not necessarily have the same byte index at which the character is stored.
+    /// Thus, using the character position where a byte index is expected can unexpectedly return wrong values
+    /// or panic when the string consists of multibyte characters.
+    ///
+    /// For example, the character `a` in `äa` is stored at byte index 2 but has the character position 1.
+    /// Using the character position 1 to index into the string will lead to a panic as it is in the middle of the first character.
+    ///
+    /// Instead of `.chars().enumerate()`, the correct iterator to use is `.char_indices()`, which yields byte indices.
+    ///
+    /// This pattern is technically fine if the strings are known to only use the ASCII subset,
+    /// though in those cases it would be better to use `bytes()` directly to make the intent clearer,
+    /// but there is also no downside to just using `.char_indices()` directly and supporting non-ASCII strings.
+    ///
+    /// You may also want to read the [chapter on strings in the Rust Book](https://doc.rust-lang.org/book/ch08-02-strings.html)
+    /// which goes into this in more detail.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// # let s = "...";
+    /// for (idx, c) in s.chars().enumerate() {
+    ///     let _ = s[idx..]; // ⚠️ Panics for strings consisting of multibyte characters
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// # let s = "...";
+    /// for (idx, c) in s.char_indices() {
+    ///     let _ = s[idx..];
+    /// }
+    /// ```
+    #[clippy::version = "1.83.0"]
+    pub CHAR_INDICES_AS_BYTE_INDICES,
+    correctness,
+    "using the character position yielded by `.chars().enumerate()` in a context where a byte index is expected"
+}
+
 pub struct Loops {
     msrv: Msrv,
     enforce_iter_loop_reborrow: bool,
@@ -777,6 +821,7 @@ impl_lint_pass!(Loops => [
     UNUSED_ENUMERATE_INDEX,
     INFINITE_LOOP,
     MANUAL_SLICE_FILL,
+    CHAR_INDICES_AS_BYTE_INDICES,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Loops {
@@ -860,6 +905,7 @@ impl Loops {
         manual_flatten::check(cx, pat, arg, body, span, self.msrv);
         manual_find::check(cx, pat, arg, body, span, expr);
         unused_enumerate_index::check(cx, pat, arg, body);
+        char_indices_as_byte_indices::check(cx, pat, arg, body);
     }
 
     fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index a24dd44790e..70ca452013f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -82,14 +82,14 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
     fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
-        if bk == ty::BorrowKind::Mutable {
-            if let PlaceBase::Local(id) = cmt.place.base {
-                if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
-                    self.span_low = Some(self.cx.tcx.hir_span(diag_expr_id));
-                }
-                if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
-                    self.span_high = Some(self.cx.tcx.hir_span(diag_expr_id));
-                }
+        if bk == ty::BorrowKind::Mutable
+            && let PlaceBase::Local(id) = cmt.place.base
+        {
+            if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
+                self.span_low = Some(self.cx.tcx.hir_span(diag_expr_id));
+            }
+            if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
+                self.span_high = Some(self.cx.tcx.hir_span(diag_expr_id));
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 0f62183eb33..7837b18bcd3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -31,155 +31,154 @@ pub(super) fn check<'tcx>(
         ref end,
         limits,
     }) = higher::Range::hir(arg)
-    {
         // the var must be a single name
-        if let PatKind::Binding(_, canonical_id, ident, _) = pat.kind {
-            let mut visitor = VarVisitor {
-                cx,
-                var: canonical_id,
-                indexed_mut: FxHashSet::default(),
-                indexed_indirectly: FxHashMap::default(),
-                indexed_directly: FxIndexMap::default(),
-                referenced: FxHashSet::default(),
-                nonindex: false,
-                prefer_mutable: false,
-            };
-            walk_expr(&mut visitor, body);
-
-            // linting condition: we only indexed one variable, and indexed it directly
-            if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 {
-                let (indexed, (indexed_extent, indexed_ty)) = visitor
-                    .indexed_directly
-                    .into_iter()
-                    .next()
-                    .expect("already checked that we have exactly 1 element");
+        && let PatKind::Binding(_, canonical_id, ident, _) = pat.kind
+    {
+        let mut visitor = VarVisitor {
+            cx,
+            var: canonical_id,
+            indexed_mut: FxHashSet::default(),
+            indexed_indirectly: FxHashMap::default(),
+            indexed_directly: FxIndexMap::default(),
+            referenced: FxHashSet::default(),
+            nonindex: false,
+            prefer_mutable: false,
+        };
+        walk_expr(&mut visitor, body);
 
-                // ensure that the indexed variable was declared before the loop, see #601
-                if let Some(indexed_extent) = indexed_extent {
-                    let parent_def_id = cx.tcx.hir_get_parent_item(expr.hir_id);
-                    let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
-                    let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
-                    if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
-                        return;
-                    }
-                }
+        // linting condition: we only indexed one variable, and indexed it directly
+        if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 {
+            let (indexed, (indexed_extent, indexed_ty)) = visitor
+                .indexed_directly
+                .into_iter()
+                .next()
+                .expect("already checked that we have exactly 1 element");
 
-                // don't lint if the container that is indexed does not have .iter() method
-                let has_iter = has_iter_method(cx, indexed_ty);
-                if has_iter.is_none() {
+            // ensure that the indexed variable was declared before the loop, see #601
+            if let Some(indexed_extent) = indexed_extent {
+                let parent_def_id = cx.tcx.hir_get_parent_item(expr.hir_id);
+                let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
+                let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
+                if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
                     return;
                 }
+            }
 
-                // don't lint if the container that is indexed into is also used without
-                // indexing
-                if visitor.referenced.contains(&indexed) {
-                    return;
-                }
+            // don't lint if the container that is indexed does not have .iter() method
+            let has_iter = has_iter_method(cx, indexed_ty);
+            if has_iter.is_none() {
+                return;
+            }
 
-                let starts_at_zero = is_integer_const(cx, start, 0);
+            // don't lint if the container that is indexed into is also used without
+            // indexing
+            if visitor.referenced.contains(&indexed) {
+                return;
+            }
 
-                let skip = if starts_at_zero {
-                    String::new()
-                } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
-                    return;
-                } else {
-                    format!(".skip({})", snippet(cx, start.span, ".."))
-                };
+            let starts_at_zero = is_integer_const(cx, start, 0);
 
-                let mut end_is_start_plus_val = false;
+            let skip = if starts_at_zero {
+                String::new()
+            } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
+                return;
+            } else {
+                format!(".skip({})", snippet(cx, start.span, ".."))
+            };
 
-                let take = if let Some(end) = *end {
-                    let mut take_expr = end;
+            let mut end_is_start_plus_val = false;
 
-                    if let ExprKind::Binary(ref op, left, right) = end.kind {
-                        if op.node == BinOpKind::Add {
-                            let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
-                            let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
+            let take = if let Some(end) = *end {
+                let mut take_expr = end;
 
-                            if start_equal_left {
-                                take_expr = right;
-                            } else if start_equal_right {
-                                take_expr = left;
-                            }
+                if let ExprKind::Binary(ref op, left, right) = end.kind
+                    && op.node == BinOpKind::Add
+                {
+                    let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
+                    let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
 
-                            end_is_start_plus_val = start_equal_left | start_equal_right;
-                        }
+                    if start_equal_left {
+                        take_expr = right;
+                    } else if start_equal_right {
+                        take_expr = left;
                     }
 
-                    if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
-                        String::new()
-                    } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
-                        return;
-                    } else {
-                        match limits {
-                            ast::RangeLimits::Closed => {
-                                let take_expr = sugg::Sugg::hir(cx, take_expr, "<count>");
-                                format!(".take({})", take_expr + sugg::ONE)
-                            },
-                            ast::RangeLimits::HalfOpen => {
-                                format!(".take({})", snippet(cx, take_expr.span, ".."))
-                            },
-                        }
-                    }
-                } else {
-                    String::new()
-                };
+                    end_is_start_plus_val = start_equal_left | start_equal_right;
+                }
 
-                let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) {
-                    ("mut ", "iter_mut")
+                if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
+                    String::new()
+                } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
+                    return;
                 } else {
-                    ("", "iter")
-                };
+                    match limits {
+                        ast::RangeLimits::Closed => {
+                            let take_expr = sugg::Sugg::hir(cx, take_expr, "<count>");
+                            format!(".take({})", take_expr + sugg::ONE)
+                        },
+                        ast::RangeLimits::HalfOpen => {
+                            format!(".take({})", snippet(cx, take_expr.span, ".."))
+                        },
+                    }
+                }
+            } else {
+                String::new()
+            };
 
-                let take_is_empty = take.is_empty();
-                let mut method_1 = take;
-                let mut method_2 = skip;
+            let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) {
+                ("mut ", "iter_mut")
+            } else {
+                ("", "iter")
+            };
 
-                if end_is_start_plus_val {
-                    mem::swap(&mut method_1, &mut method_2);
-                }
+            let take_is_empty = take.is_empty();
+            let mut method_1 = take;
+            let mut method_2 = skip;
 
-                if visitor.nonindex {
-                    span_lint_and_then(
-                        cx,
-                        NEEDLESS_RANGE_LOOP,
-                        arg.span,
-                        format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
-                        |diag| {
-                            diag.multipart_suggestion(
-                                "consider using an iterator and enumerate()",
-                                vec![
-                                    (pat.span, format!("({}, <item>)", ident.name)),
-                                    (
-                                        arg.span,
-                                        format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
-                                    ),
-                                ],
-                                Applicability::HasPlaceholders,
-                            );
-                        },
-                    );
+            if end_is_start_plus_val {
+                mem::swap(&mut method_1, &mut method_2);
+            }
+
+            if visitor.nonindex {
+                span_lint_and_then(
+                    cx,
+                    NEEDLESS_RANGE_LOOP,
+                    arg.span,
+                    format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
+                    |diag| {
+                        diag.multipart_suggestion(
+                            "consider using an iterator and enumerate()",
+                            vec![
+                                (pat.span, format!("({}, <item>)", ident.name)),
+                                (
+                                    arg.span,
+                                    format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
+                                ),
+                            ],
+                            Applicability::HasPlaceholders,
+                        );
+                    },
+                );
+            } else {
+                let repl = if starts_at_zero && take_is_empty {
+                    format!("&{ref_mut}{indexed}")
                 } else {
-                    let repl = if starts_at_zero && take_is_empty {
-                        format!("&{ref_mut}{indexed}")
-                    } else {
-                        format!("{indexed}.{method}(){method_1}{method_2}")
-                    };
+                    format!("{indexed}.{method}(){method_1}{method_2}")
+                };
 
-                    span_lint_and_then(
-                        cx,
-                        NEEDLESS_RANGE_LOOP,
-                        arg.span,
-                        format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
-                        |diag| {
-                            diag.multipart_suggestion(
-                                "consider using an iterator",
-                                vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
-                                Applicability::HasPlaceholders,
-                            );
-                        },
-                    );
-                }
+                span_lint_and_then(
+                    cx,
+                    NEEDLESS_RANGE_LOOP,
+                    arg.span,
+                    format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
+                    |diag| {
+                        diag.multipart_suggestion(
+                            "consider using an iterator",
+                            vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
+                            Applicability::HasPlaceholders,
+                        );
+                    },
+                );
             }
         }
     }
@@ -346,10 +345,10 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> {
                 for expr in args {
                     let ty = self.cx.typeck_results().expr_ty_adjusted(expr);
                     self.prefer_mutable = false;
-                    if let ty::Ref(_, _, mutbl) = *ty.kind() {
-                        if mutbl == Mutability::Mut {
-                            self.prefer_mutable = true;
-                        }
+                    if let ty::Ref(_, _, mutbl) = *ty.kind()
+                        && mutbl == Mutability::Mut
+                    {
+                        self.prefer_mutable = true;
                     }
                     self.visit_expr(expr);
                 }
@@ -361,10 +360,10 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> {
                     iter::once(receiver).chain(args.iter()),
                 ) {
                     self.prefer_mutable = false;
-                    if let ty::Ref(_, _, mutbl) = *ty.kind() {
-                        if mutbl == Mutability::Mut {
-                            self.prefer_mutable = true;
-                        }
+                    if let ty::Ref(_, _, mutbl) = *ty.kind()
+                        && mutbl == Mutability::Mut
+                    {
+                        self.prefer_mutable = true;
                     }
                     self.visit_expr(expr);
                 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index c3a2a38b5ec..69c84bc7038 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -244,10 +244,10 @@ fn never_loop_expr<'tcx>(
             });
             combine_seq(first, || {
                 // checks if break targets a block instead of a loop
-                if let ExprKind::Break(Destination { target_id: Ok(t), .. }, _) = expr.kind {
-                    if let Some((_, reachable)) = local_labels.iter_mut().find(|(label, _)| *label == t) {
-                        *reachable = true;
-                    }
+                if let ExprKind::Break(Destination { target_id: Ok(t), .. }, _) = expr.kind
+                    && let Some((_, reachable)) = local_labels.iter_mut().find(|(label, _)| *label == t)
+                {
+                    *reachable = true;
                 }
                 NeverLoopResult::Diverging
             })
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 3c6fbef2bda..2f6950b4380 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -3,9 +3,7 @@ use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_loc
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{Visitor, walk_expr, walk_local};
-use rustc_hir::{
-    AssignOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind
-};
+use rustc_hir::{AssignOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
@@ -265,7 +263,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
     if impls_iterator {
         format!(
             "{}",
-            sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
+            sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_paren()
         )
     } else {
         // (&x).into_iter() ==> x.iter()
@@ -283,12 +281,12 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
                 };
                 format!(
                     "{}.{method_name}()",
-                    sugg::Sugg::hir_with_applicability(cx, caller, "_", applic_ref).maybe_par(),
+                    sugg::Sugg::hir_with_applicability(cx, caller, "_", applic_ref).maybe_paren(),
                 )
             },
             _ => format!(
                 "{}.into_iter()",
-                sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
+                sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_paren()
             ),
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
index df6e85611fb..9071c9c95f9 100644
--- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -5,7 +5,8 @@ use itertools::Itertools;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
 use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, Level, LintContext};
+use rustc_middle::lint::LevelAndSource;
 use rustc_session::impl_lint_pass;
 use rustc_span::{Span, SyntaxContext, sym};
 use std::collections::BTreeMap;
@@ -249,6 +250,20 @@ impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe {
             })
             .flatten()
             .copied()
+            .inspect(|&unsafe_block| {
+                if let LevelAndSource {
+                    level: Level::Expect,
+                    lint_id: Some(id),
+                    ..
+                } = cx.tcx.lint_level_at_node(MACRO_METAVARS_IN_UNSAFE, unsafe_block)
+                {
+                    // Since we're going to deduplicate expanded unsafe blocks by its enclosing macro definition soon,
+                    // which would lead to unfulfilled `#[expect()]`s in all other unsafe blocks that are filtered out
+                    // except for the one we emit the warning at, we must manually fulfill the lint
+                    // for all unsafe blocks here.
+                    cx.fulfill_expectation(id);
+                }
+            })
             .map(|id| {
                 // Remove the syntax context to hide "in this macro invocation" in the diagnostic.
                 // The invocation doesn't matter. Also we want to dedupe by the unsafe block and not by anything
diff --git a/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs b/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs
new file mode 100644
index 00000000000..c515e41f242
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs
@@ -0,0 +1,152 @@
+use clippy_config::Conf;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::higher::If;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::HasSession as _;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{eq_expr_value, peel_blocks, span_contains_comment};
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty};
+use rustc_session::impl_lint_pass;
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects patterns like `if a > b { a - b } else { b - a }` and suggests using `a.abs_diff(b)`.
+    ///
+    /// ### Why is this bad?
+    /// Using `abs_diff` is shorter, more readable, and avoids control flow.
+    ///
+    /// ### Examples
+    /// ```no_run
+    /// # let (a, b) = (5_usize, 3_usize);
+    /// if a > b {
+    ///     a - b
+    /// } else {
+    ///     b - a
+    /// }
+    /// # ;
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// # let (a, b) = (5_usize, 3_usize);
+    /// a.abs_diff(b)
+    /// # ;
+    /// ```
+    #[clippy::version = "1.86.0"]
+    pub MANUAL_ABS_DIFF,
+    complexity,
+    "using an if-else pattern instead of `abs_diff`"
+}
+
+impl_lint_pass!(ManualAbsDiff => [MANUAL_ABS_DIFF]);
+
+pub struct ManualAbsDiff {
+    msrv: Msrv,
+}
+
+impl ManualAbsDiff {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self { msrv: conf.msrv }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for ManualAbsDiff {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if !expr.span.from_expansion()
+            && let Some(if_expr) = If::hir(expr)
+            && let Some(r#else) = if_expr.r#else
+            && let ExprKind::Binary(op, rhs, lhs) = if_expr.cond.kind
+            && let (BinOpKind::Gt | BinOpKind::Ge, mut a, mut b) | (BinOpKind::Lt | BinOpKind::Le, mut b, mut a) =
+                (op.node, rhs, lhs)
+            && let Some(ty) = self.are_ty_eligible(cx, a, b)
+            && is_sub_expr(cx, if_expr.then, a, b, ty)
+            && is_sub_expr(cx, r#else, b, a, ty)
+        {
+            span_lint_and_then(
+                cx,
+                MANUAL_ABS_DIFF,
+                expr.span,
+                "manual absolute difference pattern without using `abs_diff`",
+                |diag| {
+                    if is_unsuffixed_numeral_lit(a) && !is_unsuffixed_numeral_lit(b) {
+                        (a, b) = (b, a);
+                    }
+                    let applicability = {
+                        let source_map = cx.sess().source_map();
+                        if span_contains_comment(source_map, if_expr.then.span)
+                            || span_contains_comment(source_map, r#else.span)
+                        {
+                            Applicability::MaybeIncorrect
+                        } else {
+                            Applicability::MachineApplicable
+                        }
+                    };
+                    let sugg = format!(
+                        "{}.abs_diff({})",
+                        Sugg::hir(cx, a, "..").maybe_paren(),
+                        Sugg::hir(cx, b, "..")
+                    );
+                    diag.span_suggestion(expr.span, "replace with `abs_diff`", sugg, applicability);
+                },
+            );
+        }
+    }
+}
+
+impl ManualAbsDiff {
+    /// Returns a type if `a` and `b` are both of it, and this lint can be applied to that
+    /// type (currently, any primitive int, or a `Duration`)
+    fn are_ty_eligible<'tcx>(&self, cx: &LateContext<'tcx>, a: &Expr<'_>, b: &Expr<'_>) -> Option<Ty<'tcx>> {
+        let is_int = |ty: Ty<'_>| matches!(ty.kind(), ty::Uint(_) | ty::Int(_)) && self.msrv.meets(cx, msrvs::ABS_DIFF);
+        let is_duration =
+            |ty| is_type_diagnostic_item(cx, ty, sym::Duration) && self.msrv.meets(cx, msrvs::DURATION_ABS_DIFF);
+
+        let a_ty = cx.typeck_results().expr_ty(a).peel_refs();
+        (a_ty == cx.typeck_results().expr_ty(b).peel_refs() && (is_int(a_ty) || is_duration(a_ty))).then_some(a_ty)
+    }
+}
+
+/// Checks if the given expression is a subtraction operation between two expected expressions,
+/// i.e. if `expr` is `{expected_a} - {expected_b}`.
+///
+/// If `expected_ty` is a signed primitive integer, this function will only return `Some` if the
+/// subtraction expr is wrapped in a cast to the equivalent unsigned int.
+fn is_sub_expr(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    expected_a: &Expr<'_>,
+    expected_b: &Expr<'_>,
+    expected_ty: Ty<'_>,
+) -> bool {
+    let expr = peel_blocks(expr).kind;
+
+    if let ty::Int(ty) = expected_ty.kind() {
+        let unsigned = Ty::new_uint(cx.tcx, ty.to_unsigned());
+
+        return if let ExprKind::Cast(expr, cast_ty) = expr
+            && cx.typeck_results().node_type(cast_ty.hir_id) == unsigned
+        {
+            is_sub_expr(cx, expr, expected_a, expected_b, unsigned)
+        } else {
+            false
+        };
+    }
+
+    if let ExprKind::Binary(op, a, b) = expr
+        && let BinOpKind::Sub = op.node
+        && eq_expr_value(cx, a, expected_a)
+        && eq_expr_value(cx, b, expected_b)
+    {
+        true
+    } else {
+        false
+    }
+}
+
+fn is_unsuffixed_numeral_lit(expr: &Expr<'_>) -> bool {
+    matches!(expr.kind, ExprKind::Lit(lit) if lit.node.is_numeric() && lit.node.is_unsuffixed())
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index 83c16d4466d..8378e15c581 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
                 ExprKind::Unary(UnOp::Not, e) => (e, ""),
                 _ => (cond, "!"),
             };
-            let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
+            let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_paren();
             let semicolon = if is_parent_stmt(cx, expr.hir_id) { ";" } else { "" };
             let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip}){semicolon}");
             // we show to the user the suggestion without the comments, but when applying the fix, include the
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index 50c8331eeba..02afe9f0997 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -181,7 +181,7 @@ fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggest
         make_assignment,
         hir_with_ignore_attr,
     } = suggestion;
-    let input = Sugg::hir(cx, input, "..").maybe_par();
+    let input = Sugg::hir(cx, input, "..").maybe_paren();
     let min = Sugg::hir(cx, min, "..");
     let max = Sugg::hir(cx, max, "..");
     let semicolon = if make_assignment.is_some() { ";" } else { "" };
diff --git a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
index 9944c4f8804..444ecd5d2bb 100644
--- a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
@@ -1,8 +1,9 @@
-use clippy_utils::SpanlessEq;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::{Sugg, has_enclosing_paren};
+use clippy_utils::{SpanlessEq, sym};
 use rustc_ast::{BinOpKind, LitIntType, LitKind, UnOp};
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
@@ -11,9 +12,6 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self};
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::Symbol;
-
-use clippy_config::Conf;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -141,8 +139,7 @@ fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let expr_ty = cx.typeck_results().expr_ty(expr);
     match expr_ty.peel_refs().kind() {
         ty::Uint(_) => true,
-        ty::Int(_) => cx.tcx.features().enabled(Symbol::intern("int_roundings")),
-
+        ty::Int(_) => cx.tcx.features().enabled(sym::int_roundings),
         _ => false,
     }
 }
@@ -167,7 +164,7 @@ fn build_suggestion(
     rhs: &Expr<'_>,
     applicability: &mut Applicability,
 ) {
-    let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_par();
+    let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_paren();
     let type_suffix = if cx.typeck_results().expr_ty(lhs).is_numeric()
         && matches!(
             lhs.kind,
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index faf01a276a1..8ab49bd2ea8 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -148,7 +148,7 @@ fn check_is_ascii(
     };
     let default_snip = "..";
     let mut app = Applicability::MachineApplicable;
-    let recv = Sugg::hir_with_context(cx, recv, span.ctxt(), default_snip, &mut app).maybe_par();
+    let recv = Sugg::hir_with_context(cx, recv, span.ctxt(), default_snip, &mut app).maybe_paren();
     let mut suggestion = vec![(span, format!("{recv}.{sugg}()"))];
     if let Some((ty_span, ty)) = ty_sugg {
         suggestion.push((ty_span, format!("{recv}: {ty}")));
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
index 841adfec462..b4cd988329d 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
@@ -1,13 +1,14 @@
-use clippy_utils::SpanlessEq;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
-use rustc_ast::LitKind;
-use rustc_data_structures::packed::Pu128;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::ty_from_hir_ty;
+use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal};
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Uint;
-use rustc_session::declare_lint_pass;
+use rustc_middle::ty;
+use rustc_session::impl_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -33,112 +34,111 @@ declare_clippy_lint! {
     "manually reimplementing `is_power_of_two`"
 }
 
-declare_lint_pass!(ManualIsPowerOfTwo => [MANUAL_IS_POWER_OF_TWO]);
+pub struct ManualIsPowerOfTwo {
+    msrv: Msrv,
+}
 
-impl LateLintPass<'_> for ManualIsPowerOfTwo {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let mut applicability = Applicability::MachineApplicable;
+impl_lint_pass!(ManualIsPowerOfTwo => [MANUAL_IS_POWER_OF_TWO]);
 
-        if let ExprKind::Binary(bin_op, left, right) = expr.kind
-            && bin_op.node == BinOpKind::Eq
-        {
-            // a.count_ones() == 1
-            if let ExprKind::MethodCall(method_name, receiver, [], _) = left.kind
-                && method_name.ident.as_str() == "count_ones"
-                && let &Uint(_) = cx.typeck_results().expr_ty(receiver).kind()
-                && check_lit(right, 1)
-            {
-                build_sugg(cx, expr, receiver, &mut applicability);
-            }
+impl ManualIsPowerOfTwo {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self { msrv: conf.msrv }
+    }
 
-            // 1 == a.count_ones()
-            if let ExprKind::MethodCall(method_name, receiver, [], _) = right.kind
-                && method_name.ident.as_str() == "count_ones"
-                && let &Uint(_) = cx.typeck_results().expr_ty(receiver).kind()
-                && check_lit(left, 1)
-            {
-                build_sugg(cx, expr, receiver, &mut applicability);
-            }
+    fn build_sugg(&self, cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
+        if is_in_const_context(cx) && !self.msrv.meets(cx, msrvs::CONST_IS_POWER_OF_TWO) {
+            return;
+        }
 
-            // a & (a - 1) == 0
-            if let ExprKind::Binary(op1, left1, right1) = left.kind
-                && op1.node == BinOpKind::BitAnd
-                && let ExprKind::Binary(op2, left2, right2) = right1.kind
-                && op2.node == BinOpKind::Sub
-                && check_eq_expr(cx, left1, left2)
-                && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
-                && check_lit(right2, 1)
-                && check_lit(right, 0)
-            {
-                build_sugg(cx, expr, left1, &mut applicability);
-            }
+        let mut applicability = Applicability::MachineApplicable;
+        let snippet = Sugg::hir_with_applicability(cx, receiver, "_", &mut applicability);
 
-            // (a - 1) & a == 0;
-            if let ExprKind::Binary(op1, left1, right1) = left.kind
-                && op1.node == BinOpKind::BitAnd
-                && let ExprKind::Binary(op2, left2, right2) = left1.kind
-                && op2.node == BinOpKind::Sub
-                && check_eq_expr(cx, right1, left2)
-                && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind()
-                && check_lit(right2, 1)
-                && check_lit(right, 0)
-            {
-                build_sugg(cx, expr, right1, &mut applicability);
-            }
+        span_lint_and_sugg(
+            cx,
+            MANUAL_IS_POWER_OF_TWO,
+            expr.span,
+            "manually reimplementing `is_power_of_two`",
+            "consider using `.is_power_of_two()`",
+            format!("{}.is_power_of_two()", snippet.maybe_paren()),
+            applicability,
+        );
+    }
+}
 
-            // 0 == a & (a - 1);
-            if let ExprKind::Binary(op1, left1, right1) = right.kind
-                && op1.node == BinOpKind::BitAnd
-                && let ExprKind::Binary(op2, left2, right2) = right1.kind
-                && op2.node == BinOpKind::Sub
-                && check_eq_expr(cx, left1, left2)
-                && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
-                && check_lit(right2, 1)
-                && check_lit(left, 0)
+impl<'tcx> LateLintPass<'tcx> for ManualIsPowerOfTwo {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if !expr.span.from_expansion()
+            && let Some((lhs, rhs)) = unexpanded_binop_operands(expr, BinOpKind::Eq)
+        {
+            if let Some(a) = count_ones_receiver(cx, lhs)
+                && is_integer_literal(rhs, 1)
             {
-                build_sugg(cx, expr, left1, &mut applicability);
-            }
-
-            // 0 == (a - 1) & a
-            if let ExprKind::Binary(op1, left1, right1) = right.kind
-                && op1.node == BinOpKind::BitAnd
-                && let ExprKind::Binary(op2, left2, right2) = left1.kind
-                && op2.node == BinOpKind::Sub
-                && check_eq_expr(cx, right1, left2)
-                && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind()
-                && check_lit(right2, 1)
-                && check_lit(left, 0)
+                self.build_sugg(cx, expr, a);
+            } else if let Some(a) = count_ones_receiver(cx, rhs)
+                && is_integer_literal(lhs, 1)
+            {
+                self.build_sugg(cx, expr, a);
+            } else if is_integer_literal(rhs, 0)
+                && let Some(a) = is_and_minus_one(cx, lhs)
+            {
+                self.build_sugg(cx, expr, a);
+            } else if is_integer_literal(lhs, 0)
+                && let Some(a) = is_and_minus_one(cx, rhs)
             {
-                build_sugg(cx, expr, right1, &mut applicability);
+                self.build_sugg(cx, expr, a);
             }
         }
     }
 }
 
-fn build_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, applicability: &mut Applicability) {
-    let snippet = snippet_with_applicability(cx, receiver.span, "..", applicability);
-
-    span_lint_and_sugg(
-        cx,
-        MANUAL_IS_POWER_OF_TWO,
-        expr.span,
-        "manually reimplementing `is_power_of_two`",
-        "consider using `.is_power_of_two()`",
-        format!("{snippet}.is_power_of_two()"),
-        *applicability,
-    );
+/// Return the unsigned integer receiver of `.count_ones()` or the argument of
+/// `<int-type>::count_ones(…)`.
+fn count_ones_receiver<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    let (method, ty, receiver) = if let ExprKind::MethodCall(method_name, receiver, [], _) = expr.kind {
+        (method_name, cx.typeck_results().expr_ty_adjusted(receiver), receiver)
+    } else if let ExprKind::Call(func, [arg]) = expr.kind
+        && let ExprKind::Path(QPath::TypeRelative(ty, func_name)) = func.kind
+    {
+        (func_name, ty_from_hir_ty(cx, ty), arg)
+    } else {
+        return None;
+    };
+    (method.ident.as_str() == "count_ones" && matches!(ty.kind(), ty::Uint(_))).then_some(receiver)
 }
 
-fn check_lit(expr: &Expr<'_>, expected_num: u128) -> bool {
-    if let ExprKind::Lit(lit) = expr.kind
-        && let LitKind::Int(Pu128(num), _) = lit.node
-        && num == expected_num
+/// Return `greater` if `smaller == greater - 1`
+fn is_one_less<'tcx>(
+    cx: &LateContext<'tcx>,
+    greater: &'tcx Expr<'tcx>,
+    smaller: &Expr<'tcx>,
+) -> Option<&'tcx Expr<'tcx>> {
+    if let Some((lhs, rhs)) = unexpanded_binop_operands(smaller, BinOpKind::Sub)
+        && SpanlessEq::new(cx).eq_expr(greater, lhs)
+        && is_integer_literal(rhs, 1)
+        && matches!(cx.typeck_results().expr_ty_adjusted(greater).kind(), ty::Uint(_))
     {
-        return true;
+        Some(greater)
+    } else {
+        None
     }
-    false
 }
 
-fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
-    SpanlessEq::new(cx).eq_expr(lhs, rhs)
+/// Return `v` if `expr` is `v & (v - 1)` or `(v - 1) & v`
+fn is_and_minus_one<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    let (lhs, rhs) = unexpanded_binop_operands(expr, BinOpKind::BitAnd)?;
+    is_one_less(cx, lhs, rhs).or_else(|| is_one_less(cx, rhs, lhs))
+}
+
+/// Return the operands of the `expr` binary operation if the operator is `op` and none of the
+/// operands come from expansion.
+fn unexpanded_binop_operands<'hir>(expr: &Expr<'hir>, op: BinOpKind) -> Option<(&'hir Expr<'hir>, &'hir Expr<'hir>)> {
+    if let ExprKind::Binary(binop, lhs, rhs) = expr.kind
+        && binop.node == op
+        && !lhs.span.from_expansion()
+        && !rhs.span.from_expansion()
+    {
+        Some((lhs, rhs))
+    } else {
+        None
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
index 8dee29b2a0b..e4ad3953b67 100644
--- a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
@@ -34,7 +34,7 @@ declare_clippy_lint! {
     /// _ = opt.as_slice();
     /// _ = opt.as_slice();
     /// ```
-    #[clippy::version = "1.85.0"]
+    #[clippy::version = "1.86.0"]
     pub MANUAL_OPTION_AS_SLICE,
     complexity,
     "manual `Option::as_slice`"
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 16dd1ad4e47..98e8b1f5cf9 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -92,10 +92,10 @@ fn check_into_iter(
         && let [filter_params] = filter_body.params
     {
         if match_map_type(cx, left_expr) {
-            if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind {
-                if let Some(sugg) = make_sugg(cx, key_pat, value_pat, left_expr, filter_body) {
-                    make_span_lint_and_sugg(cx, parent_expr_span, sugg);
-                }
+            if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind
+                && let Some(sugg) = make_sugg(cx, key_pat, value_pat, left_expr, filter_body)
+            {
+                make_span_lint_and_sugg(cx, parent_expr_span, sugg);
             }
             // Cannot lint other cases because `retain` requires two parameters
         } else {
@@ -196,22 +196,21 @@ fn check_to_owned(
         && let filter_body = cx.tcx.hir_body(closure.body)
         && let [filter_params] = filter_body.params
         && msrv.meets(cx, msrvs::STRING_RETAIN)
+        && let hir::PatKind::Ref(pat, _) = filter_params.pat.kind
     {
-        if let hir::PatKind::Ref(pat, _) = filter_params.pat.kind {
-            make_span_lint_and_sugg(
-                cx,
-                parent_expr_span,
-                format!(
-                    "{}.retain(|{}| {})",
-                    snippet(cx, left_expr.span, ".."),
-                    snippet(cx, pat.span, ".."),
-                    snippet(cx, filter_body.value.span, "..")
-                ),
-            );
-        }
-        // Be conservative now. Do nothing for the `Binding` case.
-        // TODO: Ideally, we can rewrite the lambda by stripping one level of reference
+        make_span_lint_and_sugg(
+            cx,
+            parent_expr_span,
+            format!(
+                "{}.retain(|{}| {})",
+                snippet(cx, left_expr.span, ".."),
+                snippet(cx, pat.span, ".."),
+                snippet(cx, filter_body.value.span, "..")
+            ),
+        );
     }
+    // Be conservative now. Do nothing for the `Binding` case.
+    // TODO: Ideally, we can rewrite the lambda by stripping one level of reference
 }
 
 fn make_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/manual_rotate.rs b/src/tools/clippy/clippy_lints/src/manual_rotate.rs
index 07537fc65c0..06ee00c2cef 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rotate.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rotate.rs
@@ -101,7 +101,7 @@ impl LateLintPass<'_> for ManualRotate {
                     (r_shift_dir, r_amount)
                 };
                 let mut applicability = Applicability::MachineApplicable;
-                let expr_sugg = sugg::Sugg::hir_with_applicability(cx, l_expr, "_", &mut applicability).maybe_par();
+                let expr_sugg = sugg::Sugg::hir_with_applicability(cx, l_expr, "_", &mut applicability).maybe_paren();
                 span_lint_and_sugg(
                     cx,
                     MANUAL_ROTATE,
diff --git a/src/tools/clippy/clippy_lints/src/manual_string_new.rs b/src/tools/clippy/clippy_lints/src/manual_string_new.rs
index 5c2a711b5cb..7ca3b712066 100644
--- a/src/tools/clippy/clippy_lints/src/manual_string_new.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_string_new.rs
@@ -113,15 +113,14 @@ fn parse_call(cx: &LateContext<'_>, span: Span, func: &Expr<'_>, arg: &Expr<'_>)
             && is_expr_kind_empty_str(&arg.kind)
         {
             warn_then_suggest(cx, span);
-        } else if let QPath::Resolved(_, path) = qpath {
+        } else if let QPath::Resolved(_, path) = qpath
             // From::from(...) or TryFrom::try_from(...)
-            if let [path_seg1, path_seg2] = path.segments
-                && is_expr_kind_empty_str(&arg.kind)
-                && ((path_seg1.ident.name == sym::From && path_seg2.ident.name == sym::from)
-                    || (path_seg1.ident.name == sym::TryFrom && path_seg2.ident.name == sym::try_from))
-            {
-                warn_then_suggest(cx, span);
-            }
+            && let [path_seg1, path_seg2] = path.segments
+            && is_expr_kind_empty_str(&arg.kind)
+            && ((path_seg1.ident.name == sym::From && path_seg2.ident.name == sym::from)
+                || (path_seg1.ident.name == sym::TryFrom && path_seg2.ident.name == sym::try_from))
+        {
+            warn_then_suggest(cx, span);
         }
     }
 }
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
deleted file mode 100644
index 87d2faa225c..00000000000
--- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
+++ /dev/null
@@ -1,212 +0,0 @@
-use rustc_errors::Applicability;
-use rustc_hir::def::Res;
-use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::GenericArgKind;
-use rustc_session::declare_lint_pass;
-use rustc_span::sym;
-
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::IfLetOrMatch;
-use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::{expr_type_is_certain, implements_trait};
-use clippy_utils::{is_default_equivalent, is_in_const_context, path_res, peel_blocks, span_contains_comment};
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks if a `match` or `if let` expression can be simplified using
-    /// `.unwrap_or_default()`.
-    ///
-    /// ### Why is this bad?
-    /// It can be done in one call with `.unwrap_or_default()`.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// let x: Option<String> = Some(String::new());
-    /// let y: String = match x {
-    ///     Some(v) => v,
-    ///     None => String::new(),
-    /// };
-    ///
-    /// let x: Option<Vec<String>> = Some(Vec::new());
-    /// let y: Vec<String> = if let Some(v) = x {
-    ///     v
-    /// } else {
-    ///     Vec::new()
-    /// };
-    /// ```
-    /// Use instead:
-    /// ```no_run
-    /// let x: Option<String> = Some(String::new());
-    /// let y: String = x.unwrap_or_default();
-    ///
-    /// let x: Option<Vec<String>> = Some(Vec::new());
-    /// let y: Vec<String> = x.unwrap_or_default();
-    /// ```
-    #[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`"
-}
-
-declare_lint_pass!(ManualUnwrapOrDefault => [MANUAL_UNWRAP_OR_DEFAULT]);
-
-fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<HirId> {
-    if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind
-        && let PatKind::Binding(_, pat_id, _, _) = 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::OptionSome) == Some(def_id)
-        || cx.tcx.lang_items().get(LangItem::ResultOk) == Some(def_id))
-    {
-        Some(pat_id)
-    } else {
-        None
-    }
-}
-
-fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    if let PatKind::Expr(PatExpr { kind: PatExprKind::Path(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::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)
-    } else {
-        None
-    }
-}
-
-fn get_some_and_none_bodies<'tcx>(
-    cx: &LateContext<'tcx>,
-    arm1: &'tcx Arm<'tcx>,
-    arm2: &'tcx Arm<'tcx>,
-) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> {
-    if let Some(binding_id) = get_some(cx, arm1.pat)
-        && let Some(body_none) = get_none(cx, arm2)
-    {
-        Some(((arm1.body, binding_id), body_none))
-    } else if let Some(binding_id) = get_some(cx, arm2.pat)
-        && let Some(body_none) = get_none(cx, arm1)
-    {
-        Some(((arm2.body, binding_id), body_none))
-    } else {
-        None
-    }
-}
-
-#[allow(clippy::needless_pass_by_value)]
-fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, expr: &'tcx Expr<'tcx>) {
-    // Get expr_name ("if let" or "match" depending on kind of expression),  the condition, the body for
-    // the some arm, the body for the none arm and the binding id of the some arm
-    let (expr_name, condition, body_some, body_none, binding_id) = match if_let_or_match {
-        IfLetOrMatch::Match(condition, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar)
-            // Make sure there are no guards to keep things simple
-            if arm1.guard.is_none()
-                && arm2.guard.is_none()
-                // Get the some and none bodies and the binding id of the some arm
-                && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) =>
-        {
-            ("match", condition, body_some, body_none, binding_id)
-        },
-        IfLetOrMatch::IfLet(condition, pat, if_expr, Some(else_expr), _)
-            if let Some(binding_id) = get_some(cx, pat) =>
-        {
-            ("if let", condition, if_expr, else_expr, binding_id)
-        },
-        _ => {
-            // All other cases (match with number of arms != 2, if let without else, etc.)
-            return;
-        },
-    };
-
-    // We check if the return type of the expression implements Default.
-    let expr_type = cx.typeck_results().expr_ty(expr);
-    if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
-        && implements_trait(cx, expr_type, default_trait_id, &[])
-        // We check if the initial condition implements Default.
-        && let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1)
-        && let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
-        && implements_trait(cx, condition_ty, default_trait_id, &[])
-        // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
-        && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
-        && let Res::Local(local_id) = path.res
-        && local_id == binding_id
-        // We now check the `None` arm is calling a method equivalent to `Default::default`.
-        && let body_none = peel_blocks(body_none)
-        && is_default_equivalent(cx, body_none)
-        && let Some(receiver) = Sugg::hir_opt(cx, condition).map(Sugg::maybe_par)
-    {
-        // Machine applicable only if there are no comments present
-        let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
-            Applicability::MaybeIncorrect
-        } else {
-            Applicability::MachineApplicable
-        };
-
-        // We now check if the condition is a None variant, in which case we need to specify the type
-        if path_res(cx, condition)
-            .opt_def_id()
-            .is_some_and(|id| Some(cx.tcx.parent(id)) == cx.tcx.lang_items().option_none_variant())
-        {
-            return span_lint_and_sugg(
-                cx,
-                MANUAL_UNWRAP_OR_DEFAULT,
-                expr.span,
-                format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
-                "replace it with",
-                format!("{receiver}::<{expr_type}>.unwrap_or_default()"),
-                applicability,
-            );
-        }
-
-        // We check if the expression type is still uncertain, in which case we ask the user to specify it
-        if !expr_type_is_certain(cx, condition) {
-            return span_lint_and_sugg(
-                cx,
-                MANUAL_UNWRAP_OR_DEFAULT,
-                expr.span,
-                format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
-                format!("ascribe the type {expr_type} and replace your expression with"),
-                format!("{receiver}.unwrap_or_default()"),
-                Applicability::Unspecified,
-            );
-        }
-
-        span_lint_and_sugg(
-            cx,
-            MANUAL_UNWRAP_OR_DEFAULT,
-            expr.span,
-            format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
-            "replace it with",
-            format!("{receiver}.unwrap_or_default()"),
-            applicability,
-        );
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, expr)
-            && !expr.span.from_expansion()
-            && !is_in_const_context(cx)
-        {
-            handle(cx, if_let_or_match, expr);
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index 56aead85e7c..b607f8117eb 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -101,10 +101,10 @@ fn is_unit_type(ty: Ty<'_>) -> bool {
 fn is_unit_function(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
 
-    if let ty::FnDef(id, _) = *ty.kind() {
-        if let Some(fn_type) = cx.tcx.fn_sig(id).instantiate_identity().no_bound_vars() {
-            return is_unit_type(fn_type.output());
-        }
+    if let ty::FnDef(id, _) = *ty.kind()
+        && let Some(fn_type) = cx.tcx.fn_sig(id).instantiate_identity().no_bound_vars()
+    {
+        return is_unit_type(fn_type.output());
     }
     false
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
index 6f446bf9565..5b50efad3e4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::snippet;
@@ -99,7 +99,7 @@ fn check_arm<'tcx>(
         } else {
             String::new()
         };
-        span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, msg, |diag| {
+        span_lint_hir_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.hir_id, inner_expr.span, msg, |diag| {
             let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]);
             help_span.push_span_label(binding_span, "replace this binding");
             help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}"));
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
index 4cc43e427ec..abf723fa6f4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
@@ -41,10 +41,10 @@ fn get_cond_expr<'tcx>(
 fn peels_blocks_incl_unsafe_opt<'a>(expr: &'a Expr<'a>) -> Option<&'a Expr<'a>> {
     // we don't want to use `peel_blocks` here because we don't care if the block is unsafe, it's
     // checked by `contains_unsafe_block`
-    if let ExprKind::Block(block, None) = expr.kind {
-        if block.stmts.is_empty() {
-            return block.expr;
-        }
+    if let ExprKind::Block(block, None) = expr.kind
+        && block.stmts.is_empty()
+    {
+        return block.expr;
     }
     None
 }
@@ -61,13 +61,13 @@ fn peels_blocks_incl_unsafe<'a>(expr: &'a Expr<'a>) -> &'a Expr<'a> {
 // }
 // Returns true if <expr> resolves to `Some(x)`, `false` otherwise
 fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: &Expr<'_>) -> bool {
-    if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) {
+    if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr)
         // there can be not statements in the block as they would be removed when switching to `.filter`
-        if let ExprKind::Call(callee, [arg]) = inner_expr.kind {
-            return ctxt == expr.span.ctxt()
-                && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome)
-                && path_to_local_id(arg, target);
-        }
+        && let ExprKind::Call(callee, [arg]) = inner_expr.kind
+    {
+        return ctxt == expr.span.ctxt()
+            && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome)
+            && path_to_local_id(arg, target);
     }
     false
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
index 576e42a564c..4959908dad6 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
@@ -85,7 +85,7 @@ fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool
 /// contains `Err(IDENT)`, `None` otherwise.
 fn is_ok_or_err<'hir>(cx: &LateContext<'_>, pat: &Pat<'hir>) -> Option<(bool, &'hir Ident)> {
     if let PatKind::TupleStruct(qpath, [arg], _) = &pat.kind
-        && let PatKind::Binding(BindingMode::NONE, _, ident, _) = &arg.kind
+        && let PatKind::Binding(BindingMode::NONE, _, ident, None) = &arg.kind
         && let res = cx.qpath_res(qpath, pat.hir_id)
         && let Res::Def(DefKind::Ctor(..), id) = res
         && let id @ Some(_) = cx.tcx.opt_parent(id)
@@ -132,7 +132,7 @@ fn apply_lint(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Expr<'_>, is_ok
     } else {
         Applicability::MachineApplicable
     };
-    let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_par();
+    let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_paren();
     let sugg = format!("{scrut}.{method}()");
     // If the expression being expanded is the `if …` part of an `else if …`, it must be blockified.
     let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index 2bf7ec8ab7d..b64ae0b24d8 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -1,133 +1,219 @@
 use clippy_utils::consts::ConstEvalCtxt;
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::usage::contains_return_break_continue_macro;
-use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
+use clippy_utils::source::{SpanRangeExt as _, indent_of, reindent_multiline};
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionNone, ResultErr};
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Arm, Expr, Pat, PatExpr, PatExprKind, PatKind};
-use rustc_lint::LateContext;
-use rustc_middle::ty::Ty;
+use rustc_hir::def::Res;
+use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, Pat, PatExpr, PatExprKind, PatKind, QPath};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::ty::{GenericArgKind, Ty};
 use rustc_span::sym;
 
-use super::MANUAL_UNWRAP_OR;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::{expr_type_is_certain, get_type_diagnostic_name, implements_trait};
+use clippy_utils::{is_default_equivalent, is_lint_allowed, path_res, peel_blocks, span_contains_comment};
 
-pub(super) fn check_match<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'tcx>,
-    scrutinee: &'tcx Expr<'_>,
-    arms: &'tcx [Arm<'_>],
-) {
-    let ty = cx.typeck_results().expr_ty(scrutinee);
-    if let Some((or_arm, unwrap_arm)) = applicable_or_arm(cx, arms) {
-        check_and_lint(cx, expr, unwrap_arm.pat, scrutinee, unwrap_arm.body, or_arm.body, ty);
+use super::{MANUAL_UNWRAP_OR, MANUAL_UNWRAP_OR_DEFAULT};
+
+fn get_some(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<HirId> {
+    if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind
+        && let PatKind::Binding(_, pat_id, _, _) = 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)
+        && let Some(lang_item) = cx.tcx.lang_items().from_def_id(def_id)
+        && matches!(lang_item, LangItem::OptionSome | LangItem::ResultOk)
+    {
+        Some(pat_id)
+    } else {
+        None
     }
 }
 
-pub(super) fn check_if_let<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'_>,
-    let_pat: &'tcx Pat<'_>,
-    let_expr: &'tcx Expr<'_>,
-    then_expr: &'tcx Expr<'_>,
-    else_expr: &'tcx Expr<'_>,
-) {
-    let ty = cx.typeck_results().expr_ty(let_expr);
-    let then_ty = cx.typeck_results().expr_ty(then_expr);
-    // The signature is `fn unwrap_or<T>(self: Option<T>, default: T) -> T`.
-    // When `expr_adjustments(then_expr).is_empty()`, `T` should equate to `default`'s type.
-    // Otherwise, type error will occur.
-    if cx.typeck_results().expr_adjustments(then_expr).is_empty()
-        && let rustc_middle::ty::Adt(_did, args) = ty.kind()
-        && let Some(some_ty) = args.first().and_then(|arg| arg.as_type())
-        && some_ty != then_ty
+fn get_none<'tcx>(cx: &LateContext<'_>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    if let PatKind::Expr(PatExpr { kind: PatExprKind::Path(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::OptionNone) == Some(def_id)
     {
-        return;
+        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)
+    } else {
+        None
     }
-    check_and_lint(cx, expr, let_pat, let_expr, then_expr, peel_blocks(else_expr), ty);
 }
 
-fn check_and_lint<'tcx>(
+fn get_some_and_none_bodies<'tcx>(
     cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'_>,
-    let_pat: &'tcx Pat<'_>,
-    let_expr: &'tcx Expr<'_>,
-    then_expr: &'tcx Expr<'_>,
-    else_expr: &'tcx Expr<'_>,
-    ty: Ty<'tcx>,
+    arm1: &'tcx Arm<'tcx>,
+    arm2: &'tcx Arm<'tcx>,
+) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> {
+    if let Some(binding_id) = get_some(cx, arm1.pat)
+        && let Some(body_none) = get_none(cx, arm2)
+    {
+        Some(((arm1.body, binding_id), body_none))
+    } else if let Some(binding_id) = get_some(cx, arm2.pat)
+        && let Some(body_none) = get_none(cx, arm1)
+    {
+        Some(((arm2.body, binding_id), body_none))
+    } else {
+        None
+    }
+}
+
+fn handle(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    expr_name: &'static str,
+    condition: &Expr<'_>,
+    body_some: &Expr<'_>,
+    body_none: &Expr<'_>,
+    binding_id: HirId,
 ) {
-    if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = let_pat.kind
-        && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id)
-        && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
-        && (cx.tcx.lang_items().option_some_variant() == Some(variant_id)
-            || cx.tcx.lang_items().result_ok_variant() == Some(variant_id))
-        && let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind
-        && path_to_local_id(peel_blocks(then_expr), binding_hir_id)
-        && cx.typeck_results().expr_adjustments(then_expr).is_empty()
-        && let Some(ty_name) = find_type_name(cx, ty)
-        && let Some(or_body_snippet) = else_expr.span.get_source_text(cx)
-        && let Some(indent) = indent_of(cx, expr.span)
-        && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
+    // Only deal with situations where both alternatives return the same non-adjusted type.
+    if cx.typeck_results().expr_ty(body_some) != cx.typeck_results().expr_ty(body_none) {
+        return;
+    }
+
+    let expr_type = cx.typeck_results().expr_ty(expr);
+    // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
+    if let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
+        && let Res::Local(local_id) = path.res
+        && local_id == binding_id
     {
-        lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent);
+        // Machine applicable only if there are no comments present
+        let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+            Applicability::MaybeIncorrect
+        } else {
+            Applicability::MachineApplicable
+        };
+        let receiver = Sugg::hir_with_applicability(cx, condition, "_", &mut applicability).maybe_paren();
+
+        // We now check the `None` arm is calling a method equivalent to `Default::default`.
+        if !is_lint_allowed(cx, MANUAL_UNWRAP_OR_DEFAULT, expr.hir_id)
+            // We check if the return type of the expression implements Default.
+            && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
+            && implements_trait(cx, expr_type, default_trait_id, &[])
+            // We check if the initial condition implements Default.
+            && let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1)
+            && let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
+            && implements_trait(cx, condition_ty, default_trait_id, &[])
+            && is_default_equivalent(cx, peel_blocks(body_none))
+        {
+            // We now check if the condition is a None variant, in which case we need to specify the type
+            if path_res(cx, condition)
+                .opt_def_id()
+                .is_some_and(|id| Some(cx.tcx.parent(id)) == cx.tcx.lang_items().option_none_variant())
+            {
+                return span_lint_and_sugg(
+                    cx,
+                    MANUAL_UNWRAP_OR_DEFAULT,
+                    expr.span,
+                    format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
+                    "replace it with",
+                    format!("{receiver}::<{expr_type}>.unwrap_or_default()"),
+                    applicability,
+                );
+            }
+
+            // We check if the expression type is still uncertain, in which case we ask the user to specify it
+            if !expr_type_is_certain(cx, condition) {
+                return span_lint_and_sugg(
+                    cx,
+                    MANUAL_UNWRAP_OR_DEFAULT,
+                    expr.span,
+                    format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
+                    format!("ascribe the type {expr_type} and replace your expression with"),
+                    format!("{receiver}.unwrap_or_default()"),
+                    Applicability::Unspecified,
+                );
+            }
+
+            span_lint_and_sugg(
+                cx,
+                MANUAL_UNWRAP_OR_DEFAULT,
+                expr.span,
+                format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
+                "replace it with",
+                format!("{receiver}.unwrap_or_default()"),
+                applicability,
+            );
+        } else if let Some(ty_name) = find_type_name(cx, cx.typeck_results().expr_ty(condition))
+            && cx.typeck_results().expr_adjustments(body_some).is_empty()
+            && let Some(or_body_snippet) = peel_blocks(body_none).span.get_source_text(cx)
+            && let Some(indent) = indent_of(cx, expr.span)
+            && ConstEvalCtxt::new(cx).eval_simple(body_none).is_some()
+        {
+            let reindented_or_body = reindent_multiline(&or_body_snippet, true, Some(indent));
+            let mut app = Applicability::MachineApplicable;
+            let suggestion = Sugg::hir_with_context(cx, condition, expr.span.ctxt(), "..", &mut app).maybe_paren();
+            span_lint_and_sugg(
+                cx,
+                MANUAL_UNWRAP_OR,
+                expr.span,
+                format!("this pattern reimplements `{ty_name}::unwrap_or`"),
+                "replace with",
+                format!("{suggestion}.unwrap_or({reindented_or_body})",),
+                app,
+            );
+        }
     }
 }
 
 fn find_type_name<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'static str> {
-    if is_type_diagnostic_item(cx, ty, sym::Option) {
-        Some("Option")
-    } else if is_type_diagnostic_item(cx, ty, sym::Result) {
-        Some("Result")
-    } else {
-        None
+    match get_type_diagnostic_name(cx, ty)? {
+        sym::Option => Some("Option"),
+        sym::Result => Some("Result"),
+        _ => None,
     }
 }
 
-fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<(&'a Arm<'a>, &'a Arm<'a>)> {
-    if arms.len() == 2
-        && arms.iter().all(|arm| arm.guard.is_none())
-        && let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| match arm.pat.kind {
-            PatKind::Expr(PatExpr {
-                hir_id,
-                kind: PatExprKind::Path(qpath),
-                ..
-            }) => is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone),
-            PatKind::TupleStruct(ref qpath, [pat], _) => {
-                matches!(pat.kind, PatKind::Wild)
-                    && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
-            },
-            _ => false,
-        })
-        && let unwrap_arm = &arms[1 - idx]
-        && !contains_return_break_continue_macro(or_arm.body)
+pub fn check_match<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    scrutinee: &'tcx Expr<'tcx>,
+    arms: &'tcx [Arm<'tcx>],
+) {
+    if let [arm1, arm2] = arms
+        // Make sure there are no guards to keep things simple
+        && arm1.guard.is_none()
+        && arm2.guard.is_none()
+        // Get the some and none bodies and the binding id of the some arm
+        && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
     {
-        Some((or_arm, unwrap_arm))
-    } else {
-        None
+        handle(cx, expr, "match", scrutinee, body_some, body_none, binding_id);
     }
 }
 
-fn lint<'tcx>(
+pub fn check_if_let<'tcx>(
     cx: &LateContext<'tcx>,
-    expr: &Expr<'tcx>,
-    scrutinee: &'tcx Expr<'_>,
-    ty_name: &str,
-    or_body_snippet: &str,
-    indent: usize,
+    expr: &'tcx Expr<'tcx>,
+    pat: &'tcx Pat<'tcx>,
+    scrutinee: &'tcx Expr<'tcx>,
+    then_expr: &'tcx Expr<'tcx>,
+    else_expr: &'tcx Expr<'tcx>,
 ) {
-    let reindented_or_body = reindent_multiline(or_body_snippet, true, Some(indent));
-
-    let mut app = Applicability::MachineApplicable;
-    let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par();
-    span_lint_and_sugg(
-        cx,
-        MANUAL_UNWRAP_OR,
-        expr.span,
-        format!("this pattern reimplements `{ty_name}::unwrap_or`"),
-        "replace with",
-        format!("{suggestion}.unwrap_or({reindented_or_body})",),
-        app,
-    );
+    if let Some(binding_id) = get_some(cx, pat) {
+        handle(
+            cx,
+            expr,
+            "if let",
+            scrutinee,
+            peel_blocks(then_expr),
+            peel_blocks(else_expr),
+            binding_id,
+        );
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index d29d1ea3e96..f14b69d91ce 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -76,17 +76,18 @@ where
         && first_attrs.is_empty()
         && iter.all(|arm| find_bool_lit(&arm.2.kind).is_some_and(|b| b == b0) && arm.3.is_none() && arm.0.is_empty())
     {
-        if let Some(last_pat) = last_pat_opt {
-            if !is_wild(last_pat) {
-                return false;
-            }
+        if let Some(last_pat) = last_pat_opt
+            && !is_wild(last_pat)
+        {
+            return false;
         }
 
         for arm in iter_without_last.clone() {
-            if let Some(pat) = arm.1 {
-                if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) {
-                    return false;
-                }
+            if let Some(pat) = arm.1
+                && !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id)
+                && is_some(pat.kind)
+            {
+                return false;
             }
         }
 
@@ -113,10 +114,10 @@ where
 
         // strip potential borrows (#6503), but only if the type is a reference
         let mut ex_new = ex;
-        if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind {
-            if let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() {
-                ex_new = ex_inner;
-            }
+        if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind
+            && let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind()
+        {
+            ex_new = ex_inner;
         }
         span_lint_and_sugg(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs
deleted file mode 100644
index dd71560e169..00000000000
--- a/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
-use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, LangItem};
-use rustc_lint::LateContext;
-use rustc_span::sym;
-
-use super::MATCH_ON_VEC_ITEMS;
-
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) {
-    if let Some(idx_expr) = is_vec_indexing(cx, scrutinee)
-        && let ExprKind::Index(vec, idx, _) = idx_expr.kind
-    {
-        // FIXME: could be improved to suggest surrounding every pattern with Some(_),
-        // but only when `or_patterns` are stabilized.
-        span_lint_and_sugg(
-            cx,
-            MATCH_ON_VEC_ITEMS,
-            scrutinee.span,
-            "indexing into a vector may panic",
-            "try",
-            format!("{}.get({})", snippet(cx, vec.span, ".."), snippet(cx, idx.span, "..")),
-            Applicability::MaybeIncorrect,
-        );
-    }
-}
-
-fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    if let ExprKind::Index(array, index, _) = expr.kind
-        && is_vector(cx, array)
-        && !is_full_range(cx, index)
-    {
-        return Some(expr);
-    }
-
-    None
-}
-
-fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    let ty = cx.typeck_results().expr_ty(expr);
-    let ty = ty.peel_refs();
-    is_type_diagnostic_item(cx, ty, sym::Vec)
-}
-
-fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    let ty = cx.typeck_results().expr_ty(expr);
-    let ty = ty.peel_refs();
-    is_type_lang_item(cx, ty, LangItem::RangeFull)
-}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index 864923b2773..adda3586990 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::HirNode;
-use clippy_utils::source::{indent_of, snippet, snippet_block_with_context, snippet_with_applicability};
+use clippy_utils::source::{indent_of, snippet, snippet_block_with_context, snippet_with_context};
 use clippy_utils::{get_parent_expr, is_refutable, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, Expr, ExprKind, Node, PatKind, StmtKind};
@@ -24,16 +24,10 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
     let bind_names = arms[0].pat.span;
     let match_body = peel_blocks(arms[0].body);
     let mut app = Applicability::MaybeIncorrect;
-    let mut snippet_body = snippet_block_with_context(
-        cx,
-        match_body.span,
-        arms[0].span.ctxt(),
-        "..",
-        Some(expr.span),
-        &mut app,
-    )
-    .0
-    .to_string();
+    let ctxt = expr.span.ctxt();
+    let mut snippet_body = snippet_block_with_context(cx, match_body.span, ctxt, "..", Some(expr.span), &mut app)
+        .0
+        .to_string();
 
     // Do we need to add ';' to suggestion ?
     if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
@@ -77,10 +71,10 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
                     span,
                     format!(
                         "let {} = {};\n{}let {} = {snippet_body};",
-                        snippet_with_applicability(cx, bind_names, "..", &mut app),
-                        snippet_with_applicability(cx, matched_vars, "..", &mut app),
+                        snippet_with_context(cx, bind_names, ctxt, "..", &mut app).0,
+                        snippet_with_context(cx, matched_vars, ctxt, "..", &mut app).0,
                         " ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
-                        snippet_with_applicability(cx, pat_span, "..", &mut app)
+                        snippet_with_context(cx, pat_span, ctxt, "..", &mut app).0
                     ),
                 ),
                 None => {
@@ -178,24 +172,24 @@ fn sugg_with_curlies<'a>(
     let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0));
 
     let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
-    if let Some(parent_expr) = get_parent_expr(cx, match_expr) {
-        if let ExprKind::Closure { .. } = parent_expr.kind {
-            cbrace_end = format!("\n{indent}}}");
-            // Fix body indent due to the closure
-            indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
-            cbrace_start = format!("{{\n{indent}");
-        }
+    if let Some(parent_expr) = get_parent_expr(cx, match_expr)
+        && let ExprKind::Closure { .. } = parent_expr.kind
+    {
+        cbrace_end = format!("\n{indent}}}");
+        // Fix body indent due to the closure
+        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
+        cbrace_start = format!("{{\n{indent}");
     }
 
     // If the parent is already an arm, and the body is another match statement,
     // we need curly braces around suggestion
-    if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id) {
-        if let ExprKind::Match(..) = arm.body.kind {
-            cbrace_end = format!("\n{indent}}}");
-            // Fix body indent due to the match
-            indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
-            cbrace_start = format!("{{\n{indent}");
-        }
+    if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id)
+        && let ExprKind::Match(..) = arm.body.kind
+    {
+        cbrace_end = format!("\n{indent}}}");
+        // Fix body indent due to the match
+        indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
+        cbrace_start = format!("{{\n{indent}");
     }
 
     let assignment_str = assignment.map_or_else(String::new, |span| {
@@ -204,14 +198,17 @@ fn sugg_with_curlies<'a>(
         s
     });
 
+    let ctxt = match_expr.span.ctxt();
     let scrutinee = if needs_var_binding {
         format!(
             "let {} = {}",
-            snippet_with_applicability(cx, bind_names, "..", applicability),
-            snippet_with_applicability(cx, matched_vars, "..", applicability)
+            snippet_with_context(cx, bind_names, ctxt, "..", applicability).0,
+            snippet_with_context(cx, matched_vars, ctxt, "..", applicability).0
         )
     } else {
-        snippet_with_applicability(cx, matched_vars, "..", applicability).to_string()
+        snippet_with_context(cx, matched_vars, ctxt, "..", applicability)
+            .0
+            .to_string()
     };
 
     format!("{cbrace_start}{scrutinee};\n{indent}{assignment_str}{snippet_body}{cbrace_end}")
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
index df1b83cbb51..65b93a095b9 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -26,10 +26,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arm
         && let ty::Str = ty.kind()
     {
         let mut visitor = MatchExprVisitor { cx };
-        if let ControlFlow::Break(case_method) = visitor.visit_expr(scrutinee) {
-            if let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) {
-                lint(cx, &case_method, bad_case_span, bad_case_sym.as_str());
-            }
+        if let ControlFlow::Break(case_method) = visitor.visit_expr(scrutinee)
+            && let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms)
+        {
+            lint(cx, &case_method, bad_case_span, bad_case_sym.as_str());
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
index 11b588b3355..24b4a675800 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
@@ -80,18 +80,20 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
                     path
                 },
                 PatKind::TupleStruct(path, patterns, ..) => {
-                    if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
-                        if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
-                            missing_variants.retain(|e| e.ctor_def_id() != Some(id));
-                        }
+                    if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id()
+                        && arm.guard.is_none()
+                        && patterns.iter().all(|p| !is_refutable(cx, p))
+                    {
+                        missing_variants.retain(|e| e.ctor_def_id() != Some(id));
                     }
                     path
                 },
                 PatKind::Struct(path, patterns, ..) => {
-                    if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
-                        if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p.pat)) {
-                            missing_variants.retain(|e| e.def_id != id);
-                        }
+                    if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id()
+                        && arm.guard.is_none()
+                        && patterns.iter().all(|p| !is_refutable(cx, p.pat))
+                    {
+                        missing_variants.retain(|e| e.def_id != id);
                     }
                     path
                 },
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index d0d2025878e..8ce8453360f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -26,11 +26,12 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
                     if !matching_wild {
                         // Looking for unused bindings (i.e.: `_e`)
                         for pat in inner {
-                            if let PatKind::Binding(_, id, ident, None) = pat.kind {
-                                if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) {
-                                    ident_bind_name = ident.name;
-                                    matching_wild = true;
-                                }
+                            if let PatKind::Binding(_, id, ident, None) = pat.kind
+                                && ident.as_str().starts_with('_')
+                                && !is_local_used(cx, arm.body, id)
+                            {
+                                ident_bind_name = ident.name;
+                                matching_wild = true;
                             }
                         }
                     }
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 2b9173e6f41..c6ebd6144c7 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -8,7 +8,6 @@ mod manual_utils;
 mod match_as_ref;
 mod match_bool;
 mod match_like_matches;
-mod match_on_vec_items;
 mod match_ref_pats;
 mod match_same_arms;
 mod match_single_binding;
@@ -724,38 +723,39 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for `match vec[idx]` or `match vec[n..m]`.
+    /// Checks if a `match` or `if let` expression can be simplified using
+    /// `.unwrap_or_default()`.
     ///
     /// ### Why is this bad?
-    /// This can panic at runtime.
+    /// It can be done in one call with `.unwrap_or_default()`.
     ///
     /// ### Example
-    /// ```rust, no_run
-    /// let arr = vec![0, 1, 2, 3];
-    /// let idx = 1;
+    /// ```no_run
+    /// let x: Option<String> = Some(String::new());
+    /// let y: String = match x {
+    ///     Some(v) => v,
+    ///     None => String::new(),
+    /// };
     ///
-    /// match arr[idx] {
-    ///     0 => println!("{}", 0),
-    ///     1 => println!("{}", 3),
-    ///     _ => {},
-    /// }
+    /// let x: Option<Vec<String>> = Some(Vec::new());
+    /// let y: Vec<String> = if let Some(v) = x {
+    ///     v
+    /// } else {
+    ///     Vec::new()
+    /// };
     /// ```
-    ///
     /// Use instead:
-    /// ```rust, no_run
-    /// let arr = vec![0, 1, 2, 3];
-    /// let idx = 1;
+    /// ```no_run
+    /// let x: Option<String> = Some(String::new());
+    /// let y: String = x.unwrap_or_default();
     ///
-    /// match arr.get(idx) {
-    ///     Some(0) => println!("{}", 0),
-    ///     Some(1) => println!("{}", 3),
-    ///     _ => {},
-    /// }
+    /// let x: Option<Vec<String>> = Some(Vec::new());
+    /// let y: Vec<String> = x.unwrap_or_default();
     /// ```
-    #[clippy::version = "1.45.0"]
-    pub MATCH_ON_VEC_ITEMS,
-    pedantic,
-    "matching on vector elements can panic"
+    #[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`"
 }
 
 declare_clippy_lint! {
@@ -1040,7 +1040,7 @@ impl_lint_pass!(Matches => [
     NEEDLESS_MATCH,
     COLLAPSIBLE_MATCH,
     MANUAL_UNWRAP_OR,
-    MATCH_ON_VEC_ITEMS,
+    MANUAL_UNWRAP_OR_DEFAULT,
     MATCH_STR_CASE_MISMATCH,
     SIGNIFICANT_DROP_IN_SCRUTINEE,
     TRY_ERR,
@@ -1118,7 +1118,6 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
                     match_wild_enum::check(cx, ex, arms);
                     match_as_ref::check(cx, ex, arms, expr);
                     needless_match::check_match(cx, ex, arms, expr);
-                    match_on_vec_items::check(cx, ex);
                     match_str_case_mismatch::check(cx, ex, arms);
                     redundant_guards::check(cx, arms, self.msrv);
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
index 7e65d586110..6c5d7cab203 100644
--- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
@@ -67,10 +67,10 @@ fn check_all_arms(cx: &LateContext<'_>, match_expr: &Expr<'_>, arms: &[Arm<'_>])
     for arm in arms {
         let arm_expr = peel_blocks_with_stmt(arm.body);
 
-        if let Some(guard_expr) = &arm.guard {
-            if guard_expr.can_have_side_effects() {
-                return false;
-            }
+        if let Some(guard_expr) = &arm.guard
+            && guard_expr.can_have_side_effects()
+        {
+            return false;
         }
 
         if let PatKind::Wild = arm.pat.kind {
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 4184f8b9e6e..d3136c89178 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -11,17 +11,17 @@ use super::MATCH_OVERLAPPING_ARM;
 pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
     if arms.len() >= 2 && cx.typeck_results().expr_ty(ex).is_integral() {
         let ranges = all_ranges(cx, arms, cx.typeck_results().expr_ty(ex));
-        if !ranges.is_empty() {
-            if let Some((start, end)) = overlapping(&ranges) {
-                span_lint_and_note(
-                    cx,
-                    MATCH_OVERLAPPING_ARM,
-                    start.span,
-                    "some ranges overlap",
-                    Some(end.span),
-                    "overlaps with this",
-                );
-            }
+        if !ranges.is_empty()
+            && let Some((start, end)) = overlapping(&ranges)
+        {
+            span_lint_and_note(
+                cx,
+                MATCH_OVERLAPPING_ARM,
+                start.span,
+                "some ranges overlap",
+                Some(end.span),
+                "overlaps with this",
+            );
         }
     }
 }
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 722ea7042dd..db20be40f27 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
@@ -4,7 +4,7 @@ use clippy_utils::source::walk_span_to_context;
 use clippy_utils::sugg::{Sugg, make_unop};
 use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
 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 clippy_utils::{higher, is_expn_of, is_trait_method, sym};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
@@ -12,7 +12,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
-use rustc_span::{Span, Symbol, sym};
+use rustc_span::{Span, Symbol};
 use std::fmt::Write;
 use std::ops::ControlFlow;
 
@@ -138,9 +138,9 @@ fn find_method_and_type<'tcx>(
                     Some(("is_some()", op_ty))
                 } else if Some(id) == lang_items.poll_ready_variant() {
                     Some(("is_ready()", op_ty))
-                } else if is_pat_variant(cx, check_pat, qpath, Item::Diag(sym::IpAddr, sym!(V4))) {
+                } else if is_pat_variant(cx, check_pat, qpath, Item::Diag(sym::IpAddr, sym::V4)) {
                     Some(("is_ipv4()", op_ty))
-                } else if is_pat_variant(cx, check_pat, qpath, Item::Diag(sym::IpAddr, sym!(V6))) {
+                } else if is_pat_variant(cx, check_pat, qpath, Item::Diag(sym::IpAddr, sym::V6)) {
                     Some(("is_ipv6()", op_ty))
                 } else {
                     None
@@ -255,7 +255,7 @@ fn find_method_sugg_for_if_let<'tcx>(
             };
 
             let sugg = Sugg::hir_with_context(cx, result_expr, ctxt, "_", &mut app)
-                .maybe_par()
+                .maybe_paren()
                 .to_string();
 
             diag.span_suggestion(span, "try", format!("{keyword} {sugg}.{good_method}"), app);
@@ -279,7 +279,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
                 _ => op,
             };
             let mut app = Applicability::MachineApplicable;
-            let receiver_sugg = Sugg::hir_with_applicability(cx, result_expr, "_", &mut app).maybe_par();
+            let receiver_sugg = Sugg::hir_with_applicability(cx, result_expr, "_", &mut app).maybe_paren();
             let mut sugg = format!("{receiver_sugg}.{good_method}");
 
             if let Some(guard) = maybe_guard {
@@ -303,7 +303,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
                 }
 
                 let guard = Sugg::hir(cx, guard, "..");
-                let _ = write!(sugg, " && {}", guard.maybe_par());
+                let _ = write!(sugg, " && {}", guard.maybe_paren());
             }
 
             span_lint_and_sugg(
@@ -345,8 +345,8 @@ fn found_good_method<'tcx>(
                         arms,
                         path_left,
                         path_right,
-                        Item::Diag(sym::IpAddr, sym!(V4)),
-                        Item::Diag(sym::IpAddr, sym!(V6)),
+                        Item::Diag(sym::IpAddr, sym::V4),
+                        Item::Diag(sym::IpAddr, sym::V6),
                         "is_ipv4()",
                         "is_ipv6()",
                     )
@@ -437,8 +437,8 @@ fn get_good_method<'tcx>(
             "None" => (Item::Lang(OptionNone), "is_none()", "is_some()"),
             "Ready" => (Item::Lang(PollReady), "is_ready()", "is_pending()"),
             "Pending" => (Item::Lang(PollPending), "is_pending()", "is_ready()"),
-            "V4" => (Item::Diag(sym::IpAddr, sym!(V4)), "is_ipv4()", "is_ipv6()"),
-            "V6" => (Item::Diag(sym::IpAddr, sym!(V6)), "is_ipv6()", "is_ipv4()"),
+            "V4" => (Item::Diag(sym::IpAddr, sym::V4), "is_ipv4()", "is_ipv6()"),
+            "V6" => (Item::Diag(sym::IpAddr, sym::V6), "is_ipv6()", "is_ipv4()"),
             _ => return None,
         };
         return find_good_method_for_matches_macro(
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 37bac561a6e..d7dc7604088 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -182,17 +182,16 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
     }
 
     fn has_sig_drop_attr_impl(&mut self, ty: Ty<'tcx>) -> bool {
-        if let Some(adt) = ty.ty_adt_def() {
-            if get_attr(
+        if let Some(adt) = ty.ty_adt_def()
+            && get_attr(
                 self.cx.sess(),
                 self.cx.tcx.get_attrs_unchecked(adt.did()),
                 "has_significant_drop",
             )
             .count()
                 > 0
-            {
-                return true;
-            }
+        {
+            return true;
         }
 
         if !self.seen_types.insert(ty) {
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 836c46240ce..08c0caa4266 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{SpanRangeExt, expr_block, snippet, snippet_block_with_context};
+use clippy_utils::source::{
+    SpanRangeExt, expr_block, snippet, snippet_block_with_context, snippet_with_applicability, snippet_with_context,
+};
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{
     is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
@@ -34,8 +36,7 @@ fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
 #[rustfmt::skip]
 pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>], expr: &'tcx Expr<'_>, contains_comments: bool) {
     if let [arm1, arm2] = arms
-        && arm1.guard.is_none()
-        && arm2.guard.is_none()
+        && !arms.iter().any(|arm| arm.guard.is_some() || arm.pat.span.from_expansion())
         && !expr.span.from_expansion()
         // don't lint for or patterns for now, this makes
         // the lint noisy in unnecessary situations
@@ -106,7 +107,7 @@ fn report_single_pattern(
         format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
     });
 
-    if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
+    if ex.span.eq_ctxt(expr.span) && snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
         let msg = "this pattern is irrefutable, `match` is useless";
         let (sugg, help) = if is_unit_expr(arm.body) {
             (String::new(), "`match` expression can be removed")
@@ -163,10 +164,10 @@ fn report_single_pattern(
         let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`";
         let sugg = format!(
             "if {} == {}{} {}{els_str}",
-            snippet(cx, ex.span, ".."),
+            snippet_with_context(cx, ex.span, ctxt, "..", &mut app).0,
             // PartialEq for different reference counts may not exist.
             "&".repeat(ref_count_diff),
-            snippet(cx, arm.pat.span, ".."),
+            snippet_with_applicability(cx, arm.pat.span, "..", &mut app),
             expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app),
         );
         (msg, sugg)
@@ -174,8 +175,8 @@ fn report_single_pattern(
         let msg = "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`";
         let sugg = format!(
             "if let {} = {} {}{els_str}",
-            snippet(cx, arm.pat.span, ".."),
-            snippet(cx, ex.span, ".."),
+            snippet_with_applicability(cx, arm.pat.span, "..", &mut app),
+            snippet_with_context(cx, ex.span, ctxt, "..", &mut app).0,
             expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app),
         );
         (msg, sugg)
diff --git a/src/tools/clippy/clippy_lints/src/matches/wild_in_or_pats.rs b/src/tools/clippy/clippy_lints/src/matches/wild_in_or_pats.rs
index b75d1ab9a7a..43102d78bfe 100644
--- a/src/tools/clippy/clippy_lints/src/matches/wild_in_or_pats.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/wild_in_or_pats.rs
@@ -15,18 +15,18 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arms: &[Arm<'_>]) {
         return;
     }
     for arm in arms {
-        if let PatKind::Or(fields) = arm.pat.kind {
+        if let PatKind::Or(fields) = arm.pat.kind
             // look for multiple fields in this arm that contains at least one Wild pattern
-            if fields.len() > 1 && fields.iter().any(is_wild) {
-                span_lint_and_help(
-                    cx,
-                    WILDCARD_IN_OR_PATTERNS,
-                    arm.pat.span,
-                    "wildcard pattern covers any other pattern as it will match anyway",
-                    None,
-                    "consider handling `_` separately",
-                );
-            }
+            && fields.len() > 1 && fields.iter().any(is_wild)
+        {
+            span_lint_and_help(
+                cx,
+                WILDCARD_IN_OR_PATTERNS,
+                arm.pat.span,
+                "wildcard pattern covers any other pattern as it will match anyway",
+                None,
+                "consider handling `_` separately",
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index a0919947b3f..a54d835b538 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -145,7 +145,7 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &E
             "consider `Option::take()` instead",
             format!(
                 "{}.take()",
-                Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_par()
+                Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_paren()
             ),
             applicability,
         );
@@ -178,7 +178,7 @@ fn check_replace_option_with_some(
             "consider `Option::replace()` instead",
             format!(
                 "{}.replace({})",
-                Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "_", &mut applicability).maybe_par(),
+                Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "_", &mut applicability).maybe_paren(),
                 snippet_with_applicability(cx, src_arg.span, "_", &mut applicability)
             ),
             applicability,
@@ -304,14 +304,12 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
             && let ExprKind::Path(ref func_qpath) = func.kind
             && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
             && cx.tcx.is_diagnostic_item(sym::mem_replace, def_id)
-        {
             // Check that second argument is `Option::None`
-            if !check_replace_option_with_none(cx, src, dest, expr.span)
-                && !check_replace_option_with_some(cx, src, dest, expr.span, self.msrv)
-                && !check_replace_with_default(cx, src, dest, expr, self.msrv)
-            {
-                check_replace_with_uninit(cx, src, dest, expr.span);
-            }
+            && !check_replace_option_with_none(cx, src, dest, expr.span)
+            && !check_replace_option_with_some(cx, src, dest, expr.span, self.msrv)
+            && !check_replace_with_default(cx, src, dest, expr, self.msrv)
+        {
+            check_replace_with_uninit(cx, src, dest, expr.span);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 1e9b29f567f..f8520c23ea5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -192,10 +192,10 @@ impl BindInsteadOfMap {
     }
 
     fn is_variant(&self, cx: &LateContext<'_>, res: Res) -> bool {
-        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
-            if let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item) {
-                return cx.tcx.parent(id) == variant_id;
-            }
+        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res
+            && let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item)
+        {
+            return cx.tcx.parent(id) == variant_id;
         }
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index 18568e3661f..d07870d4951 100644
--- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
 use clippy_utils::ty::is_type_lang_item;
 use rustc_ast::ast::LitKind;
@@ -16,14 +17,15 @@ pub(super) fn check<'tcx>(
     call_span: Span,
     recv: &'tcx Expr<'_>,
     arg: &'tcx Expr<'_>,
+    msrv: Msrv,
 ) {
-    if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
-        if matches!(
+    if let ExprKind::MethodCall(path_segment, ..) = recv.kind
+        && matches!(
             path_segment.ident.name.as_str(),
             "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
-        ) {
-            return;
-        }
+        )
+    {
+        return;
     }
 
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
@@ -58,11 +60,15 @@ pub(super) fn check<'tcx>(
 
                     let suggestion_source = reindent_multiline(
                         &format!(
-                            "std::path::Path::new({})
+                            "std::path::Path::new({recv_source})
                                 .extension()
-                                .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
-                            recv_source,
-                            ext_str.strip_prefix('.').unwrap()
+                                .{}|ext| ext.eq_ignore_ascii_case(\"{}\"))",
+                            if msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) {
+                                "is_some_and("
+                            } else {
+                                "map_or(false, "
+                            },
+                            ext_str.strip_prefix('.').unwrap(),
                         ),
                         true,
                         Some(indent_of(cx, call_span).unwrap_or(0) + 4),
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 1ee27d90d05..2ecf3eb8979 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -40,10 +40,10 @@ pub(super) fn check(
         .map_or_else(|| cx.typeck_results().expr_ty(arg), |a| a.target);
 
     let ty = cx.typeck_results().expr_ty(expr);
-    if let ty::Ref(_, inner, _) = arg_ty.kind() {
-        if let ty::Ref(..) = inner.kind() {
-            return; // don't report clone_on_copy
-        }
+    if let ty::Ref(_, inner, _) = arg_ty.kind()
+        && let ty::Ref(..) = inner.kind()
+    {
+        return; // don't report clone_on_copy
     }
 
     if is_copy(cx, ty) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs b/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs
index b5adc69e9a7..e666f31217c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::ty::implements_trait;
+use clippy_utils::ty::{has_non_owning_mutable_access, implements_trait};
 use clippy_utils::{is_mutable, is_trait_method, path_to_local};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Node, PatKind};
@@ -27,10 +27,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp
         && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name().as_str() == "last")
         // if the resolved method is the same as the provided definition
         && fn_def.def_id() == last_def.def_id
+        && let self_ty = cx.typeck_results().expr_ty(self_expr)
+        && !has_non_owning_mutable_access(cx, self_ty)
     {
         let mut sugg = vec![(call_span, String::from("next_back()"))];
         let mut dont_apply = false;
+
         // if `self_expr` is a reference, it is mutable because it is used for `.last()`
+        // TODO: Change this to lint only when the referred iterator is not used later. If it is used later,
+        // changing to `next_back()` may change its behavior.
         if !(is_mutable(cx, self_expr) || self_type.is_ref()) {
             if let Some(hir_id) = path_to_local(self_expr)
                 && let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index daa6e0e7f94..f5688e370a4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -54,10 +54,11 @@ pub(super) fn check<'tcx>(
         if is_type_lang_item(cx, arg_ty, hir::LangItem::String) {
             return false;
         }
-        if let ty::Ref(_, ty, ..) = arg_ty.kind() {
-            if ty.is_str() && can_be_static_str(cx, arg) {
-                return false;
-            }
+        if let ty::Ref(_, ty, ..) = arg_ty.kind()
+            && ty.is_str()
+            && can_be_static_str(cx, arg)
+        {
+            return false;
         }
         true
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index ae300cd5fe5..da123f13d46 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::macros::{is_panic, matching_root_macro_call, root_macro_call};
 use clippy_utils::source::{indent_of, reindent_multiline, snippet};
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{SpanlessEq, higher, is_trait_method, path_to_local_id, peel_blocks};
+use clippy_utils::{SpanlessEq, higher, is_trait_method, path_to_local_id, peel_blocks, sym};
 use hir::{Body, HirId, MatchSource, Pat};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -11,7 +11,7 @@ use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_span::Span;
-use rustc_span::symbol::{Ident, Symbol, sym};
+use rustc_span::symbol::{Ident, Symbol};
 
 use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP};
 
@@ -43,10 +43,10 @@ fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool
 }
 
 fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool {
-    is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some))
+    is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym::is_some)
 }
 fn is_ok_filter_map(cx: &LateContext<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool {
-    is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_ok))
+    is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym::is_ok)
 }
 
 #[derive(Debug, Copy, Clone)]
@@ -429,16 +429,15 @@ fn is_find_or_filter<'a>(
 }
 
 fn acceptable_methods(method: &PathSegment<'_>) -> bool {
-    let methods: [Symbol; 8] = [
-        sym::clone,
-        sym::as_ref,
-        sym!(copied),
-        sym!(cloned),
-        sym!(as_deref),
-        sym!(as_mut),
-        sym!(as_deref_mut),
-        sym!(to_owned),
-    ];
-
-    methods.contains(&method.ident.name)
+    matches!(
+        method.ident.name,
+        sym::clone
+            | sym::as_ref
+            | sym::copied
+            | sym::cloned
+            | sym::as_deref
+            | sym::as_mut
+            | sym::as_deref_mut
+            | sym::to_owned
+    )
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
index f7e116c5310..965993808f6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -1,10 +1,14 @@
 use super::FILTER_MAP_BOOL_THEN;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_copy;
-use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks};
+use clippy_utils::{
+    CaptureKind, can_move_expr_to_closure, contains_return, is_from_proc_macro, is_trait_method, peel_blocks,
+};
+use rustc_ast::Mutability;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, HirId, Param, Pat};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty::Binder;
 use rustc_middle::ty::adjustment::Adjust;
@@ -44,17 +48,69 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
         && let Some(filter) = recv.span.get_source_text(cx)
         && let Some(map) = then_body.span.get_source_text(cx)
     {
-        span_lint_and_sugg(
+        span_lint_and_then(
             cx,
             FILTER_MAP_BOOL_THEN,
             call_span,
             "usage of `bool::then` in `filter_map`",
-            "use `filter` then `map` instead",
-            format!(
-                "filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})",
-                derefs = "*".repeat(needed_derefs)
-            ),
-            Applicability::MachineApplicable,
+            |diag| {
+                if can_filter_and_then_move_to_closure(cx, &param, recv, then_body) {
+                    diag.span_suggestion(
+                        call_span,
+                        "use `filter` then `map` instead",
+                        format!(
+                            "filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})",
+                            derefs = "*".repeat(needed_derefs)
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    diag.help("consider using `filter` then `map` instead");
+                }
+            },
         );
     }
 }
+
+/// Returns a set of all bindings found in the given pattern.
+fn find_bindings_from_pat(pat: &Pat<'_>) -> FxHashSet<HirId> {
+    let mut bindings = FxHashSet::default();
+    pat.walk(|p| {
+        if let rustc_hir::PatKind::Binding(_, hir_id, _, _) = p.kind {
+            bindings.insert(hir_id);
+        }
+        true
+    });
+    bindings
+}
+
+/// Returns true if we can take a closure parameter and have it in both the `filter` function and
+/// the`map` function. This is not the case if:
+///
+/// - The `filter` would contain an early return,
+/// - `filter` and `then` contain captures, and any of those are &mut
+fn can_filter_and_then_move_to_closure<'tcx>(
+    cx: &LateContext<'tcx>,
+    param: &Param<'tcx>,
+    filter: &'tcx Expr<'tcx>,
+    then: &'tcx Expr<'tcx>,
+) -> bool {
+    if contains_return(filter) {
+        return false;
+    }
+
+    let Some(filter_captures) = can_move_expr_to_closure(cx, filter) else {
+        return true;
+    };
+    let Some(then_captures) = can_move_expr_to_closure(cx, then) else {
+        return true;
+    };
+
+    let param_bindings = find_bindings_from_pat(param.pat);
+    filter_captures.iter().all(|(hir_id, filter_cap)| {
+        param_bindings.contains(hir_id)
+            || !then_captures
+                .get(hir_id)
+                .is_some_and(|then_cap| matches!(*filter_cap | *then_cap, CaptureKind::Ref(Mutability::Mut)))
+    })
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index f4840785584..045363058d1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -1,25 +1,31 @@
+use std::fmt::Write as _;
+
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::SpanRangeExt;
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{is_path_diagnostic_item, sugg};
 use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::{self as hir, Expr, ExprKind, GenericArg, QPath, TyKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::GenericParamDefKind;
 use rustc_span::sym;
 
 use super::FROM_ITER_INSTEAD_OF_COLLECT;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) {
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>], func: &Expr<'_>) {
     if is_path_diagnostic_item(cx, func, sym::from_iter_fn)
-        && let ty = cx.typeck_results().expr_ty(expr)
         && let arg_ty = cx.typeck_results().expr_ty(&args[0])
         && let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
         && implements_trait(cx, arg_ty, iter_id, &[])
     {
-        // `expr` implements `FromIterator` trait
-        let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par();
-        let turbofish = extract_turbofish(cx, expr, ty);
+        let mut app = Applicability::MaybeIncorrect;
+        let turbofish = match func.kind {
+            ExprKind::Path(QPath::TypeRelative(hir_ty, _)) => build_full_type(cx, hir_ty, &mut app),
+            ExprKind::Path(QPath::Resolved(Some(self_ty), _)) => build_full_type(cx, self_ty, &mut app),
+            _ => return,
+        };
+        let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_paren();
         let sugg = format!("{iter_expr}.collect::<{turbofish}>()");
         span_lint_and_sugg(
             cx,
@@ -28,54 +34,47 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
             "usage of `FromIterator::from_iter`",
             "use `.collect()` instead of `::from_iter()`",
             sugg,
-            Applicability::MaybeIncorrect,
+            app,
         );
     }
 }
 
-fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) -> String {
-    fn strip_angle_brackets(s: &str) -> Option<&str> {
-        s.strip_prefix('<')?.strip_suffix('>')
-    }
-
-    let call_site = expr.span.source_callsite();
-    if let Some(snippet) = call_site.get_source_text(cx)
-        && let snippet_split = snippet.split("::").collect::<Vec<_>>()
-        && let Some((_, elements)) = snippet_split.split_last()
+/// Build a type which can be used in a turbofish syntax from `hir_ty`, either by copying the
+/// existing generic arguments with the exception of elided lifetimes, or by inserting placeholders
+/// for types and consts without default values.
+fn build_full_type(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, app: &mut Applicability) -> String {
+    if let TyKind::Path(ty_qpath) = hir_ty.kind
+        && let QPath::Resolved(None, ty_path) = &ty_qpath
+        && let Res::Def(_, ty_did) = ty_path.res
     {
-        if let [type_specifier, _] = snippet_split.as_slice()
-            && let Some(type_specifier) = strip_angle_brackets(type_specifier)
-            && let Some((type_specifier, ..)) = type_specifier.split_once(" as ")
-        {
-            type_specifier.to_string()
+        let mut ty_str = itertools::join(ty_path.segments.iter().map(|s| s.ident), "::");
+        let mut first = true;
+        let mut append = |arg: &str| {
+            write!(&mut ty_str, "{}{arg}", [", ", "<"][usize::from(first)]).unwrap();
+            first = false;
+        };
+        if let Some(args) = ty_path.segments.last().and_then(|segment| segment.args) {
+            args.args
+                .iter()
+                .filter(|arg| !matches!(arg, GenericArg::Lifetime(lt) if lt.is_elided()))
+                .for_each(|arg| append(&snippet_with_applicability(cx, arg.span().source_callsite(), "_", app)));
         } else {
-            // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
-            if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) {
-                // remove the type specifier from the path elements
-                let without_ts = elements
-                    .iter()
-                    .filter_map(|e| {
-                        if e == type_specifier {
-                            None
-                        } else {
-                            Some((*e).to_string())
-                        }
-                    })
-                    .collect::<Vec<_>>();
-                // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
-                format!("{}{type_specifier}", without_ts.join("::"))
-            } else {
-                // type is not explicitly specified so wildcards are needed
-                // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
-                let ty_str = ty.to_string();
-                let start = ty_str.find('<').unwrap_or(0);
-                let end = ty_str.find('>').unwrap_or(ty_str.len());
-                let nb_wildcard = ty_str[start..end].split(',').count();
-                let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
-                format!("{}<{wildcards}>", elements.join("::"))
-            }
+            cx.tcx
+                .generics_of(ty_did)
+                .own_params
+                .iter()
+                .filter(|param| {
+                    matches!(
+                        param.kind,
+                        GenericParamDefKind::Type { has_default: false, .. }
+                            | GenericParamDefKind::Const { has_default: false, .. }
+                    )
+                })
+                .for_each(|_| append("_"));
         }
+        ty_str.push_str([">", ""][usize::from(first)]);
+        ty_str
     } else {
-        ty.to_string()
+        snippet_with_applicability(cx, hir_ty.span.source_callsite(), "_", app).into()
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
index 4c81b22861b..545bef1a4c5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -14,15 +14,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
     if expr.span.in_external_macro(cx.sess().source_map()) || !receiver.span.eq_ctxt(expr.span) {
         return;
     }
-    if let Some(parent) = get_parent_expr(cx, expr) {
-        if let Some(parent) = get_parent_expr(cx, parent) {
-            if is_inside_always_const_context(cx.tcx, expr.hir_id)
-                && let Some(macro_call) = root_macro_call(parent.span)
-                && is_assert_macro(cx, macro_call.def_id)
-            {
-                return;
-            }
-        }
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let Some(parent) = get_parent_expr(cx, parent)
+        && is_inside_always_const_context(cx.tcx, expr.hir_id)
+        && let Some(macro_call) = root_macro_call(parent.span)
+        && is_assert_macro(cx, macro_call.def_id)
+    {
+        return;
     }
     let init_expr = expr_or_init(cx, receiver);
     if !receiver.span.eq_ctxt(init_expr.span) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
index 49de83885a1..17cc07b91c5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -1,16 +1,22 @@
 use crate::methods::utils::derefs_to_slice;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{get_iterator_item_ty, is_type_diagnostic_item};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_middle::ty;
 use rustc_span::sym;
 
 use super::ITER_CLONED_COLLECT;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) {
-    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec)
+    let expr_ty = cx.typeck_results().expr_ty(expr);
+    if is_type_diagnostic_item(cx, expr_ty, sym::Vec)
         && let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv))
+        && let ty::Adt(_, args) = expr_ty.kind()
+        && let Some(iter_item_ty) = get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv))
+        && let ty::Ref(_, iter_item_ty, _) = iter_item_ty.kind()
+        && *iter_item_ty == args.type_at(0)
         && let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite())
     {
         span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
index bafabec7e06..adeff375c8a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
@@ -6,12 +6,12 @@ use super::{ITER_FILTER_IS_OK, ITER_FILTER_IS_SOME};
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, reindent_multiline};
-use clippy_utils::{get_parent_expr, is_trait_method, peel_blocks, span_contains_comment};
+use clippy_utils::{get_parent_expr, is_trait_method, peel_blocks, span_contains_comment, sym};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::QPath;
 use rustc_span::Span;
-use rustc_span::symbol::{Ident, Symbol, sym};
+use rustc_span::symbol::{Ident, Symbol};
 
 ///
 /// Returns true if the expression is a method call to `method_name`
@@ -154,7 +154,7 @@ fn expression_type(
         if let Some(opt_defid) = cx.tcx.get_diagnostic_item(sym::Option)
             && let opt_ty = cx.tcx.type_of(opt_defid).skip_binder()
             && iter_item_ty.ty_adt_def() == opt_ty.ty_adt_def()
-            && is_method(cx, filter_arg, sym::Option, sym!(is_some), &[])
+            && is_method(cx, filter_arg, sym::Option, sym::is_some, &[])
         {
             return Some(FilterType::IsSome);
         }
@@ -162,7 +162,7 @@ fn expression_type(
         if let Some(opt_defid) = cx.tcx.get_diagnostic_item(sym::Result)
             && let opt_ty = cx.tcx.type_of(opt_defid).skip_binder()
             && iter_item_ty.ty_adt_def() == opt_ty.ty_adt_def()
-            && is_method(cx, filter_arg, sym::Result, sym!(is_ok), &[])
+            && is_method(cx, filter_arg, sym::Result, sym::is_ok, &[])
         {
             return Some(FilterType::IsOk);
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 94415fc9106..3ac9299ba91 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(
             (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
             _ => return,
         }
-        && let ty = cx.typeck_results().expr_ty(recv)
+        && let ty = cx.typeck_results().expr_ty_adjusted(recv).peel_refs()
         && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
     {
         let mut applicability = rustc_errors::Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 9b358235a40..90d5d9df55e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -8,14 +8,14 @@ use rustc_span::sym;
 use super::ITERATOR_STEP_BY_ZERO;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
-    if is_trait_method(cx, expr, sym::Iterator) {
-        if let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) {
-            span_lint(
-                cx,
-                ITERATOR_STEP_BY_ZERO,
-                expr.span,
-                "`Iterator::step_by(0)` will panic at runtime",
-            );
-        }
+    if is_trait_method(cx, expr, sym::Iterator)
+        && let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg)
+    {
+        span_lint(
+            cx,
+            ITERATOR_STEP_BY_ZERO,
+            expr.span,
+            "`Iterator::step_by(0)` will panic at runtime",
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 13918ed11b8..18978a1d2bc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -106,15 +106,15 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
     };
 
     let check_lit = |expr: &hir::Expr<'_>, check_min: bool| {
-        if let hir::ExprKind::Lit(lit) = &expr.kind {
-            if let ast::LitKind::Int(value, _) = lit.node {
-                if value == maxval {
-                    return Some(MinMax::Max);
-                }
-
-                if check_min && value == minval {
-                    return Some(MinMax::Min);
-                }
+        if let hir::ExprKind::Lit(lit) = &expr.kind
+            && let ast::LitKind::Int(value, _) = lit.node
+        {
+            if value == maxval {
+                return Some(MinMax::Max);
+            }
+
+            if check_min && value == minval {
+                return Some(MinMax::Min);
             }
         }
 
@@ -125,10 +125,10 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
         return r;
     }
 
-    if ty.is_signed() {
-        if let hir::ExprKind::Unary(hir::UnOp::Neg, val) = &expr.kind {
-            return check_lit(val, true);
-        }
+    if ty.is_signed()
+        && let hir::ExprKind::Unary(hir::UnOp::Neg, val) = &expr.kind
+    {
+        return check_lit(val, true);
     }
 
     None
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
index 098721dc046..8167e4f9605 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -77,7 +77,7 @@ pub(super) fn check(
                 s @ Cow::Borrowed(_) => s,
             },
             RepeatKind::String => Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app)
-                .maybe_par()
+                .maybe_paren()
                 .to_string()
                 .into(),
         };
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 128b3695f48..333a33f7527 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -51,19 +51,19 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
                 let closure_expr = peel_blocks(closure_body.value);
                 match closure_body.params[0].pat.kind {
                     hir::PatKind::Ref(inner, Mutability::Not) => {
-                        if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind {
-                            if ident_eq(name, closure_expr) {
-                                lint_explicit_closure(cx, e.span, recv.span, true, msrv);
-                            }
+                        if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind
+                            && ident_eq(name, closure_expr)
+                        {
+                            lint_explicit_closure(cx, e.span, recv.span, true, msrv);
                         }
                     },
                     hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) => {
                         match closure_expr.kind {
                             hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
-                                if ident_eq(name, inner) {
-                                    if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() {
-                                        lint_explicit_closure(cx, e.span, recv.span, true, msrv);
-                                    }
+                                if ident_eq(name, inner)
+                                    && let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind()
+                                {
+                                    lint_explicit_closure(cx, e.span, recv.span, true, msrv);
                                 }
                             },
                             hir::ExprKind::MethodCall(method, obj, [], _) => {
@@ -114,19 +114,17 @@ fn handle_path(
 ) {
     if let Some(path_def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
         && cx.tcx.lang_items().get(LangItem::CloneFn) == Some(path_def_id)
-    {
         // The `copied` and `cloned` methods are only available on `&T` and `&mut T` in `Option`
         // and `Result`.
-        if let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind()
-            && let args = args.as_slice()
-            && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type())
-            && let ty::Ref(_, ty, Mutability::Not) = ty.kind()
-            && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind()
-            && lst.iter().all(|l| l.as_type() == Some(*ty))
-            && !should_call_clone_as_function(cx, *ty)
-        {
-            lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs()));
-        }
+        && let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind()
+        && let args = args.as_slice()
+        && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type())
+        && let ty::Ref(_, ty, Mutability::Not) = ty.kind()
+        && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind()
+        && lst.iter().all(|l| l.as_type() == Some(*ty))
+        && !should_call_clone_as_function(cx, *ty)
+    {
+        lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs()));
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
index 6cf0936c598..a2a522a6068 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
@@ -41,7 +41,7 @@ fn extract_count_with_applicability(
             return Some(format!("{count}"));
         }
         let end_snippet = Sugg::hir_with_applicability(cx, end, "...", applicability)
-            .maybe_par()
+            .maybe_paren()
             .into_string();
         if lower_bound == 0 {
             if range.limits == RangeLimits::Closed {
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 1d9296016e2..ad374dee516 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -114,6 +114,7 @@ mod suspicious_command_arg_space;
 mod suspicious_map;
 mod suspicious_splitn;
 mod suspicious_to_owned;
+mod swap_with_temporary;
 mod type_id_on_box;
 mod unbuffered_bytes;
 mod uninit_assumed_init;
@@ -478,9 +479,6 @@ declare_clippy_lint! {
     /// Because you usually call `expect()` on the `Result`
     /// directly to get a better error message.
     ///
-    /// ### Known problems
-    /// The error type needs to implement `Debug`
-    ///
     /// ### Example
     /// ```no_run
     /// # let x = Ok::<_, ()>(());
@@ -2429,7 +2427,7 @@ declare_clippy_lint! {
     ///
     /// ### Limitations
     /// This lint currently only looks for usages of
-    /// `.then_some(..).unwrap_or(..)` and `.then(..).unwrap_or(..)`, but will be expanded
+    /// `.{then, then_some}(..).{unwrap_or, unwrap_or_else, unwrap_or_default}(..)`, but will be expanded
     /// to account for similar patterns.
     ///
     /// ### Example
@@ -4286,7 +4284,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// let last_arg = "echo hello world".split(' ').next_back();
     /// ```
-    #[clippy::version = "1.85.0"]
+    #[clippy::version = "1.86.0"]
     pub DOUBLE_ENDED_ITERATOR_LAST,
     perf,
     "using `Iterator::last` on a `DoubleEndedIterator`"
@@ -4478,12 +4476,59 @@ declare_clippy_lint! {
     /// ```no_run
     /// let _ = std::io::Error::other("bad".to_string());
     /// ```
-    #[clippy::version = "1.86.0"]
+    #[clippy::version = "1.87.0"]
     pub IO_OTHER_ERROR,
     style,
     "calling `std::io::Error::new(std::io::ErrorKind::Other, _)`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `std::mem::swap` with temporary values.
+    ///
+    /// ### Why is this bad?
+    /// Storing a new value in place of a temporary value which will
+    /// be dropped right after the `swap` is an inefficient way of performing
+    /// an assignment. The same result can be achieved by using a regular
+    /// assignment.
+    ///
+    /// ### Examples
+    /// ```no_run
+    /// fn replace_string(s: &mut String) {
+    ///     std::mem::swap(s, &mut String::from("replaced"));
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// fn replace_string(s: &mut String) {
+    ///     *s = String::from("replaced");
+    /// }
+    /// ```
+    ///
+    /// Also, swapping two temporary values has no effect, as they will
+    /// both be dropped right after swapping them. This is likely an indication
+    /// of a bug. For example, the following code swaps the references to
+    /// the last element of the vectors, instead of swapping the elements
+    /// themselves:
+    ///
+    /// ```no_run
+    /// fn bug(v1: &mut [i32], v2: &mut [i32]) {
+    ///     // Incorrect: swapping temporary references (`&mut &mut` passed to swap)
+    ///     std::mem::swap(&mut v1.last_mut().unwrap(), &mut v2.last_mut().unwrap());
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// fn correct(v1: &mut [i32], v2: &mut [i32]) {
+    ///     std::mem::swap(v1.last_mut().unwrap(), v2.last_mut().unwrap());
+    /// }
+    /// ```
+    #[clippy::version = "1.88.0"]
+    pub SWAP_WITH_TEMPORARY,
+    complexity,
+    "detect swap with a temporary value"
+}
+
 #[expect(clippy::struct_excessive_bools)]
 pub struct Methods {
     avoid_breaking_exported_api: bool,
@@ -4661,17 +4706,19 @@ impl_lint_pass!(Methods => [
     UNBUFFERED_BYTES,
     MANUAL_CONTAINS,
     IO_OTHER_ERROR,
+    SWAP_WITH_TEMPORARY,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
 pub fn method_call<'tcx>(
     recv: &'tcx Expr<'tcx>,
 ) -> Option<(&'tcx str, &'tcx Expr<'tcx>, &'tcx [Expr<'tcx>], Span, Span)> {
-    if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind {
-        if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() {
-            let name = path.ident.name.as_str();
-            return Some((name, receiver, args, path.ident.span, call_span));
-        }
+    if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind
+        && !args.iter().any(|e| e.span.from_expansion())
+        && !receiver.span.from_expansion()
+    {
+        let name = path.ident.name.as_str();
+        return Some((name, receiver, args, path.ident.span, call_span));
     }
     None
 }
@@ -4691,6 +4738,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 manual_c_str_literals::check(cx, expr, func, args, self.msrv);
                 useless_nonzero_new_unchecked::check(cx, expr, func, args, self.msrv);
                 io_other_error::check(cx, expr, func, args, self.msrv);
+                swap_with_temporary::check(cx, expr, func, args);
             },
             ExprKind::MethodCall(method_call, receiver, args, _) => {
                 let method_span = method_call.ident.span;
@@ -4992,7 +5040,7 @@ impl Methods {
                 },
                 ("ends_with", [arg]) => {
                     if let ExprKind::MethodCall(.., span) = expr.kind {
-                        case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
+                        case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg, self.msrv);
                     }
                     path_ends_with_ext::check(cx, recv, arg, expr, self.msrv, &self.allowed_dotfiles);
                 },
@@ -5421,15 +5469,21 @@ impl Methods {
                             option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, self.msrv);
                         },
                         Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => {
-                            obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method, "unwrap_or");
+                            obfuscated_if_else::check(cx, expr, t_recv, t_arg, Some(u_arg), then_method, "unwrap_or");
                         },
                         _ => {},
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
                 ("unwrap_or_default", []) => {
-                    if let Some(("map", m_recv, [arg], span, _)) = method_call(recv) {
-                        manual_is_variant_and::check(cx, expr, m_recv, arg, span, self.msrv);
+                    match method_call(recv) {
+                        Some(("map", m_recv, [arg], span, _)) => {
+                            manual_is_variant_and::check(cx, expr, m_recv, arg, span, self.msrv);
+                        },
+                        Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => {
+                            obfuscated_if_else::check(cx, expr, t_recv, t_arg, None, then_method, "unwrap_or_default");
+                        },
+                        _ => {},
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
@@ -5441,7 +5495,15 @@ impl Methods {
                         Some(("map", recv, [map_arg], _, _))
                             if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {},
                         Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => {
-                            obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method, "unwrap_or_else");
+                            obfuscated_if_else::check(
+                                cx,
+                                expr,
+                                t_recv,
+                                t_arg,
+                                Some(u_arg),
+                                then_method,
+                                "unwrap_or_else",
+                            );
                         },
                         _ => {
                             unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index e4a29b6560e..6efaba525e3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -4,7 +4,9 @@ use super::NEEDLESS_COLLECT;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection};
+use clippy_utils::ty::{
+    get_type_diagnostic_name, has_non_owning_mutable_access, make_normalized_projection, make_projection,
+};
 use clippy_utils::{
     CaptureKind, can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local,
     path_to_local_id,
@@ -23,6 +25,7 @@ use rustc_span::{Span, sym};
 
 const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
 
+#[expect(clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     name_span: Span,
@@ -30,6 +33,11 @@ pub(super) fn check<'tcx>(
     iter_expr: &'tcx Expr<'tcx>,
     call_span: Span,
 ) {
+    let iter_ty = cx.typeck_results().expr_ty(iter_expr);
+    if has_non_owning_mutable_access(cx, iter_ty) {
+        return; // don't lint if the iterator has side effects
+    }
+
     match cx.tcx.parent_hir_node(collect_expr.hir_id) {
         Node::Expr(parent) => {
             check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
@@ -377,20 +385,20 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
                 return;
             }
 
-            if let Some(hir_id) = path_to_local(recv) {
-                if let Some(index) = self.hir_id_uses_map.remove(&hir_id) {
-                    if self
-                        .illegal_mutable_capture_ids
-                        .intersection(&self.current_mutably_captured_ids)
-                        .next()
-                        .is_none()
-                    {
-                        if let Some(hir_id) = self.current_statement_hir_id {
-                            self.hir_id_uses_map.insert(hir_id, index);
-                        }
-                    } else {
-                        self.uses[index] = None;
+            if let Some(hir_id) = path_to_local(recv)
+                && let Some(index) = self.hir_id_uses_map.remove(&hir_id)
+            {
+                if self
+                    .illegal_mutable_capture_ids
+                    .intersection(&self.current_mutably_captured_ids)
+                    .next()
+                    .is_none()
+                {
+                    if let Some(hir_id) = self.current_statement_hir_id {
+                        self.hir_id_uses_map.insert(hir_id, index);
                     }
+                } else {
+                    self.uses[index] = None;
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs b/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs
index 88b9c69f6f9..cd1b97f3c51 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs
@@ -9,26 +9,27 @@ use super::NEEDLESS_OPTION_TAKE;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
     // Checks if expression type is equal to sym::Option and if the expr is not a syntactic place
-    if !recv.is_syntactic_place_expr() && is_expr_option(cx, recv) {
-        if let Some(function_name) = source_of_temporary_value(recv) {
-            span_lint_and_then(
-                cx,
-                NEEDLESS_OPTION_TAKE,
-                expr.span,
-                "called `Option::take()` on a temporary value",
-                |diag| {
-                    diag.note(format!(
-                        "`{function_name}` creates a temporary value, so calling take() has no effect"
-                    ));
-                    diag.span_suggestion(
-                        expr.span.with_lo(recv.span.hi()),
-                        "remove",
-                        "",
-                        Applicability::MachineApplicable,
-                    );
-                },
-            );
-        }
+    if !recv.is_syntactic_place_expr()
+        && is_expr_option(cx, recv)
+        && let Some(function_name) = source_of_temporary_value(recv)
+    {
+        span_lint_and_then(
+            cx,
+            NEEDLESS_OPTION_TAKE,
+            expr.span,
+            "called `Option::take()` on a temporary value",
+            |diag| {
+                diag.note(format!(
+                    "`{function_name}` creates a temporary value, so calling take() has no effect"
+                ));
+                diag.span_suggestion(
+                    expr.span.with_lo(recv.span.hi()),
+                    "remove",
+                    "",
+                    Applicability::MachineApplicable,
+                );
+            },
+        );
     }
 }
 
@@ -44,10 +45,10 @@ fn is_expr_option(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 fn source_of_temporary_value<'a>(expr: &'a Expr<'_>) -> Option<&'a str> {
     match expr.peel_borrows().kind {
         ExprKind::Call(function, _) => {
-            if let ExprKind::Path(QPath::Resolved(_, func_path)) = function.kind {
-                if !func_path.segments.is_empty() {
-                    return Some(func_path.segments[0].ident.name.as_str());
-                }
+            if let ExprKind::Path(QPath::Resolved(_, func_path)) = function.kind
+                && !func_path.segments.is_empty()
+            {
+                return Some(func_path.segments[0].ident.name.as_str());
             }
             if let ExprKind::Path(QPath::TypeRelative(_, func_path_segment)) = function.kind {
                 return Some(func_path_segment.ident.name.as_str());
diff --git a/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs b/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
index 9a5ffdeaf4e..1cc56de4876 100644
--- a/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/obfuscated_if_else.rs
@@ -14,14 +14,17 @@ pub(super) fn check<'tcx>(
     expr: &'tcx hir::Expr<'_>,
     then_recv: &'tcx hir::Expr<'_>,
     then_arg: &'tcx hir::Expr<'_>,
-    unwrap_arg: &'tcx hir::Expr<'_>,
+    unwrap_arg: Option<&'tcx hir::Expr<'_>>,
     then_method_name: &str,
     unwrap_method_name: &str,
 ) {
     let recv_ty = cx.typeck_results().expr_ty(then_recv);
 
     if recv_ty.is_bool() {
-        let mut applicability = if switch_to_eager_eval(cx, then_arg) && switch_to_eager_eval(cx, unwrap_arg) {
+        let then_eager = switch_to_eager_eval(cx, then_arg);
+        let unwrap_eager = unwrap_arg.is_none_or(|arg| switch_to_eager_eval(cx, arg));
+
+        let mut applicability = if then_eager && unwrap_eager {
             Applicability::MachineApplicable
         } else {
             Applicability::MaybeIncorrect
@@ -36,16 +39,17 @@ pub(super) fn check<'tcx>(
             _ => return,
         };
 
-        // FIXME: Add `unwrap_or_else` symbol
+        // FIXME: Add `unwrap_or_else` and `unwrap_or_default` symbol
         let els = match unwrap_method_name {
-            "unwrap_or" => snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability),
-            "unwrap_or_else" if let ExprKind::Closure(closure) = unwrap_arg.kind => {
+            "unwrap_or" => snippet_with_applicability(cx, unwrap_arg.unwrap().span, "..", &mut applicability),
+            "unwrap_or_else" if let ExprKind::Closure(closure) = unwrap_arg.unwrap().kind => {
                 let body = cx.tcx.hir_body(closure.body);
                 snippet_with_applicability(cx, body.value.span, "..", &mut applicability)
             },
-            "unwrap_or_else" if let ExprKind::Path(_) = unwrap_arg.kind => {
-                snippet_with_applicability(cx, unwrap_arg.span, "_", &mut applicability) + "()"
+            "unwrap_or_else" if let ExprKind::Path(_) = unwrap_arg.unwrap().kind => {
+                snippet_with_applicability(cx, unwrap_arg.unwrap().span, "_", &mut applicability) + "()"
             },
+            "unwrap_or_default" => "Default::default()".into(),
             _ => return,
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index 6eeeea5d77c..b78b082e460 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -6,13 +6,13 @@ use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{expr_type_is_certain, implements_trait, is_type_diagnostic_item};
 use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{
-    contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment, peel_blocks,
+    contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment, peel_blocks, sym,
 };
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Span;
-use rustc_span::symbol::{self, Symbol, sym};
+use rustc_span::symbol::{self, Symbol};
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT};
@@ -66,8 +66,8 @@ pub(super) fn check<'tcx>(
         };
 
         let sugg = match (name, call_expr.is_some()) {
-            ("unwrap_or", true) | ("unwrap_or_else", false) => sym!(unwrap_or_default),
-            ("or_insert", true) | ("or_insert_with", false) => sym!(or_default),
+            ("unwrap_or", true) | ("unwrap_or_else", false) => sym::unwrap_or_default,
+            ("or_insert", true) | ("or_insert_with", false) => sym::or_default,
             _ => return false,
         };
 
@@ -78,8 +78,7 @@ pub(super) fn check<'tcx>(
                 .iter()
                 .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
                 .find_map(|assoc| {
-                    if assoc.is_method()
-                        && cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1
+                    if assoc.is_method() && cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1
                     {
                         Some(assoc.def_id)
                     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
index d318462e584..8b51268da46 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
@@ -3,33 +3,33 @@ use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::sym;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_enum_variant_ctor;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::{is_enum_variant_ctor, sym};
 
 use super::SEEK_FROM_CURRENT;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
     let ty = cx.typeck_results().expr_ty(recv);
 
-    if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) {
-        if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) {
-            let mut applicability = Applicability::MachineApplicable;
-            let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
+    if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek)
+        && implements_trait(cx, ty, def_id, &[])
+        && arg_is_seek_from_current(cx, arg)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
 
-            span_lint_and_sugg(
-                cx,
-                SEEK_FROM_CURRENT,
-                expr.span,
-                "using `SeekFrom::Current` to start from current position",
-                "replace with",
-                format!("{snip}.stream_position()"),
-                applicability,
-            );
-        }
+        span_lint_and_sugg(
+            cx,
+            SEEK_FROM_CURRENT,
+            expr.span,
+            "using `SeekFrom::Current` to start from current position",
+            "replace with",
+            format!("{snip}.stream_position()"),
+            applicability,
+        );
     }
 }
 
@@ -37,14 +37,12 @@ fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)
     if let ExprKind::Call(f, [arg]) = expr.kind
         && let ExprKind::Path(ref path) = f.kind
         && let Some(ctor_call_id) = cx.qpath_res(path, f.hir_id).opt_def_id()
-        && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Current), ctor_call_id)
-    {
+        && is_enum_variant_ctor(cx, sym::SeekFrom, sym::Current, ctor_call_id)
         // check if argument of `SeekFrom::Current` is `0`
-        if let ExprKind::Lit(lit) = arg.kind
-            && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
-        {
-            return true;
-        }
+        && let ExprKind::Lit(lit) = arg.kind
+        && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
+    {
+        return true;
     }
 
     false
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index 7b1dd9e58c5..b8405a78f23 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_enum_variant_ctor, is_expr_used_or_unified};
+use clippy_utils::{is_enum_variant_ctor, is_expr_used_or_unified, sym};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::{Span, sym};
+use rustc_span::Span;
 
 use super::SEEK_TO_START_INSTEAD_OF_REWIND;
 
@@ -29,7 +29,7 @@ pub(super) fn check<'tcx>(
         && let ExprKind::Call(func, [arg]) = arg.kind
         && let ExprKind::Path(ref path) = func.kind
         && let Some(ctor_call_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-        && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Start), ctor_call_id)
+        && is_enum_variant_ctor(cx, sym::SeekFrom, sym::Start, ctor_call_id)
         && let ExprKind::Lit(lit) = arg.kind
         && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
     {
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 4ccefb7ec9d..d183457da25 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -238,15 +238,14 @@ fn indirect_usage<'tcx>(
             unwrap_kind: Some(unwrap_kind),
             ..
         } = iter_usage
+            && parent_id == local_hir_id
         {
-            if parent_id == local_hir_id {
-                return Some(IndirectUsage {
-                    name: ident.name,
-                    span: stmt.span,
-                    init_expr,
-                    unwrap_kind,
-                });
-            }
+            return Some(IndirectUsage {
+                name: ident.name,
+                span: stmt.span,
+                init_expr,
+                unwrap_kind,
+            });
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
index 1bd48525f12..788014d9bb6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
@@ -13,11 +13,11 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<
         && let closure_body = cx.tcx.hir_body(closure.body)
         && !cx.typeck_results().expr_ty(closure_body.value).is_unit()
     {
-        if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) {
+        if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx)
             // A variable is used mutably inside of the closure. Suppress the lint.
-            if !map_mutated_vars.is_empty() {
-                return;
-            }
+            && !map_mutated_vars.is_empty()
+        {
+            return;
         }
         span_lint_and_help(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs b/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs
new file mode 100644
index 00000000000..de729fb343a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs
@@ -0,0 +1,125 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg::Sugg;
+use rustc_ast::BorrowKind;
+use rustc_errors::{Applicability, Diag};
+use rustc_hir::{Expr, ExprKind, Node, QPath};
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+use super::SWAP_WITH_TEMPORARY;
+
+const MSG_TEMPORARY: &str = "this expression returns a temporary value";
+const MSG_TEMPORARY_REFMUT: &str = "this is a mutable reference to a temporary value";
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>]) {
+    if let ExprKind::Path(QPath::Resolved(_, func_path)) = func.kind
+        && let Some(func_def_id) = func_path.res.opt_def_id()
+        && cx.tcx.is_diagnostic_item(sym::mem_swap, func_def_id)
+    {
+        match (ArgKind::new(&args[0]), ArgKind::new(&args[1])) {
+            (ArgKind::RefMutToTemp(left_temp), ArgKind::RefMutToTemp(right_temp)) => {
+                emit_lint_useless(cx, expr, &args[0], &args[1], left_temp, right_temp);
+            },
+            (ArgKind::RefMutToTemp(left_temp), right) => emit_lint_assign(cx, expr, &right, &args[0], left_temp),
+            (left, ArgKind::RefMutToTemp(right_temp)) => emit_lint_assign(cx, expr, &left, &args[1], right_temp),
+            _ => {},
+        }
+    }
+}
+
+enum ArgKind<'tcx> {
+    // Mutable reference to a place, coming from a macro
+    RefMutToPlaceAsMacro(&'tcx Expr<'tcx>),
+    // Place behind a mutable reference
+    RefMutToPlace(&'tcx Expr<'tcx>),
+    // Temporary value behind a mutable reference
+    RefMutToTemp(&'tcx Expr<'tcx>),
+    // Any other case
+    Expr(&'tcx Expr<'tcx>),
+}
+
+impl<'tcx> ArgKind<'tcx> {
+    fn new(arg: &'tcx Expr<'tcx>) -> Self {
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, target) = arg.kind {
+            if target.is_syntactic_place_expr() {
+                if arg.span.from_expansion() {
+                    ArgKind::RefMutToPlaceAsMacro(arg)
+                } else {
+                    ArgKind::RefMutToPlace(target)
+                }
+            } else {
+                ArgKind::RefMutToTemp(target)
+            }
+        } else {
+            ArgKind::Expr(arg)
+        }
+    }
+}
+
+// Emits a note either on the temporary expression if it can be found in the same context as the
+// base and returns `true`, or on the mutable reference to the temporary expression otherwise and
+// returns `false`.
+fn emit_note(diag: &mut Diag<'_, ()>, base: &Expr<'_>, expr: &Expr<'_>, expr_temp: &Expr<'_>) -> bool {
+    if base.span.eq_ctxt(expr.span) {
+        diag.span_note(expr_temp.span.source_callsite(), MSG_TEMPORARY);
+        true
+    } else {
+        diag.span_note(expr.span.source_callsite(), MSG_TEMPORARY_REFMUT);
+        false
+    }
+}
+
+fn emit_lint_useless(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    left: &Expr<'_>,
+    right: &Expr<'_>,
+    left_temp: &Expr<'_>,
+    right_temp: &Expr<'_>,
+) {
+    span_lint_and_then(
+        cx,
+        SWAP_WITH_TEMPORARY,
+        expr.span,
+        "swapping temporary values has no effect",
+        |diag| {
+            emit_note(diag, expr, left, left_temp);
+            emit_note(diag, expr, right, right_temp);
+        },
+    );
+}
+
+fn emit_lint_assign(cx: &LateContext<'_>, expr: &Expr<'_>, target: &ArgKind<'_>, reftemp: &Expr<'_>, temp: &Expr<'_>) {
+    span_lint_and_then(
+        cx,
+        SWAP_WITH_TEMPORARY,
+        expr.span,
+        "swapping with a temporary value is inefficient",
+        |diag| {
+            if !emit_note(diag, expr, reftemp, temp) {
+                return;
+            }
+
+            // Make the suggestion only when the original `swap()` call is a statement
+            // or the last expression in a block.
+            if matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(..) | Node::Block(..)) {
+                let mut applicability = Applicability::MachineApplicable;
+                let ctxt = expr.span.ctxt();
+                let assign_target = match target {
+                    ArgKind::Expr(target) | ArgKind::RefMutToPlaceAsMacro(target) => {
+                        Sugg::hir_with_context(cx, target, ctxt, "_", &mut applicability).deref()
+                    },
+                    ArgKind::RefMutToPlace(target) => Sugg::hir_with_context(cx, target, ctxt, "_", &mut applicability),
+                    ArgKind::RefMutToTemp(_) => unreachable!(),
+                };
+                let assign_source = Sugg::hir_with_context(cx, temp, ctxt, "_", &mut applicability);
+                diag.span_suggestion(
+                    expr.span,
+                    "use assignment instead",
+                    format!("{assign_target} = {assign_source}"),
+                    applicability,
+                );
+            }
+        },
+    );
+}
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 ca42a9ac04e..f920f306bc1 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
@@ -1,11 +1,10 @@
 use super::utils::clone_or_copy_needed;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_copy;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
 use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
 use core::ops::ControlFlow;
-use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_lint::LateContext;
@@ -45,30 +44,32 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
                 && is_res_lang_ctor(cx, path_res(cx, expr), OptionSome)
                 && let hir::ExprKind::Path(_) = args[0].kind
             {
-                span_lint_and_sugg(
+                span_lint(
                     cx,
                     UNNECESSARY_FILTER_MAP,
                     expr.span,
-                    format!("{name} is unnecessary"),
-                    "try removing the filter_map",
-                    String::new(),
-                    Applicability::MaybeIncorrect,
+                    String::from("this call to `.filter_map(..)` is unnecessary"),
                 );
+                return;
+            }
+            if name == "filter_map" {
+                "map(..)"
+            } else {
+                "map(..).next()"
             }
-            if name == "filter_map" { "map" } else { "map(..).next()" }
         } else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) {
             match cx.typeck_results().expr_ty(body.value).kind() {
                 ty::Adt(adt, subst)
                     if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && in_ty == subst.type_at(0) =>
                 {
-                    if name == "filter_map" { "filter" } else { "find" }
+                    if name == "filter_map" { "filter(..)" } else { "find(..)" }
                 },
                 _ => return,
             }
         } else {
             return;
         };
-        span_lint_and_sugg(
+        span_lint(
             cx,
             if name == "filter_map" {
                 UNNECESSARY_FILTER_MAP
@@ -76,10 +77,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
                 UNNECESSARY_FIND_MAP
             },
             expr.span,
-            format!("this `.{name}` can be written more simply"),
-            "try instead",
-            sugg.to_string(),
-            Applicability::MaybeIncorrect,
+            format!("this `.{name}(..)` can be written more simply using `.{sugg}`"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 9f4080100da..71e606add52 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -23,56 +23,61 @@ pub(super) fn check<'tcx>(
     let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
     let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
 
-    if is_option || is_result || is_bool {
-        if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind {
-            let body = cx.tcx.hir_body(body);
-            let body_expr = &body.value;
+    if (is_option || is_result || is_bool)
+        && let hir::ExprKind::Closure(&hir::Closure {
+            body,
+            fn_decl,
+            kind: hir::ClosureKind::Closure,
+            ..
+        }) = arg.kind
+    {
+        let body = cx.tcx.hir_body(body);
+        let body_expr = &body.value;
 
-            if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
-                return false;
-            }
+        if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
+            return false;
+        }
 
-            if eager_or_lazy::switch_to_eager_eval(cx, body_expr) {
-                let msg = if is_option {
-                    "unnecessary closure used to substitute value for `Option::None`"
-                } else if is_result {
-                    "unnecessary closure used to substitute value for `Result::Err`"
-                } else {
-                    "unnecessary closure used with `bool::then`"
-                };
-                let applicability = if body
-                    .params
-                    .iter()
-                    // bindings are checked to be unused above
-                    .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild))
-                    && matches!(
-                        fn_decl.output,
-                        FnRetTy::DefaultReturn(_)
-                            | FnRetTy::Return(hir::Ty {
-                                kind: hir::TyKind::Infer(()),
-                                ..
-                            })
-                    ) {
-                    Applicability::MachineApplicable
-                } else {
-                    // replacing the lambda may break type inference
-                    Applicability::MaybeIncorrect
-                };
+        if eager_or_lazy::switch_to_eager_eval(cx, body_expr) {
+            let msg = if is_option {
+                "unnecessary closure used to substitute value for `Option::None`"
+            } else if is_result {
+                "unnecessary closure used to substitute value for `Result::Err`"
+            } else {
+                "unnecessary closure used with `bool::then`"
+            };
+            let applicability = if body
+                .params
+                .iter()
+                // bindings are checked to be unused above
+                .all(|param| matches!(param.pat.kind, hir::PatKind::Binding(..) | hir::PatKind::Wild))
+                && matches!(
+                    fn_decl.output,
+                    FnRetTy::DefaultReturn(_)
+                        | FnRetTy::Return(hir::Ty {
+                            kind: hir::TyKind::Infer(()),
+                            ..
+                        })
+                ) {
+                Applicability::MachineApplicable
+            } else {
+                // replacing the lambda may break type inference
+                Applicability::MaybeIncorrect
+            };
 
-                // This is a duplicate of what's happening in clippy_lints::methods::method_call,
-                // which isn't ideal, We want to get the method call span,
-                // but prefer to avoid changing the signature of the function itself.
-                if let hir::ExprKind::MethodCall(.., span) = expr.kind {
-                    span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
-                        diag.span_suggestion_verbose(
-                            span,
-                            format!("use `{simplify_using}` instead"),
-                            format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
-                            applicability,
-                        );
-                    });
-                    return true;
-                }
+            // This is a duplicate of what's happening in clippy_lints::methods::method_call,
+            // which isn't ideal, We want to get the method call span,
+            // but prefer to avoid changing the signature of the function itself.
+            if let hir::ExprKind::MethodCall(.., span) = expr.kind {
+                span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
+                    diag.span_suggestion_verbose(
+                        span,
+                        format!("use `{simplify_using}` instead"),
+                        format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
+                        applicability,
+                    );
+                });
+                return true;
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
index d7bd522ddab..b90748dd158 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
@@ -76,7 +76,7 @@ pub(super) fn check<'a>(
             && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool))
             && let non_binding_location = if path_to_local_id(l, hir_id) { r } else { l }
             && switch_to_eager_eval(cx, non_binding_location)
-            // xor, because if its both then thats a strange edge case and
+            // xor, because if its both then that's a strange edge case and
             // we can just ignore it, since by default clippy will error on this
             && (path_to_local_id(l, hir_id) ^ path_to_local_id(r, hir_id))
             && !is_local_used(cx, non_binding_location, hir_id)
@@ -92,7 +92,7 @@ pub(super) fn check<'a>(
         // we may need to add parens around the suggestion
         // in case the parent expression has additional method calls,
         // since for example `Some(5).map_or(false, |x| x == 5).then(|| 1)`
-        // being converted to `Some(5) == Some(5).then(|| 1)` isnt
+        // being converted to `Some(5) == Some(5).then(|| 1)` isn't
         // the same thing
 
         let inner_non_binding = Sugg::NonParen(Cow::Owned(format!(
@@ -109,8 +109,8 @@ pub(super) fn check<'a>(
 
         let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr) {
             match parent_expr.kind {
-                ExprKind::Binary(..) | ExprKind::Unary(..) | ExprKind::Cast(..) => binop.maybe_par(),
-                ExprKind::MethodCall(_, receiver, _, _) if receiver.hir_id == expr.hir_id => binop.maybe_par(),
+                ExprKind::Binary(..) | ExprKind::Unary(..) | ExprKind::Cast(..) => binop.maybe_paren(),
+                ExprKind::MethodCall(_, receiver, _, _) if receiver.hir_id == expr.hir_id => binop.maybe_paren(),
                 _ => binop,
             }
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 3611b341897..b0cc7a785bc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -8,6 +8,9 @@ use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_span::symbol::sym;
 
+/// Checks if `expr`, of type `ty`, corresponds to a slice or can be dereferenced to a slice, or if
+/// `expr` is a method call to `.iter()` on such a type. In these cases, return the slice-like
+/// expression.
 pub(super) fn derefs_to_slice<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/builtin_type_shadow.rs b/src/tools/clippy/clippy_lints/src/misc_early/builtin_type_shadow.rs
index 662f7cd8500..9ee1e2f3fd1 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/builtin_type_shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/builtin_type_shadow.rs
@@ -6,14 +6,14 @@ use rustc_lint::EarlyContext;
 use super::BUILTIN_TYPE_SHADOW;
 
 pub(super) fn check(cx: &EarlyContext<'_>, param: &GenericParam) {
-    if let GenericParamKind::Type { .. } = param.kind {
-        if let Some(prim_ty) = PrimTy::from_name(param.ident.name) {
-            span_lint(
-                cx,
-                BUILTIN_TYPE_SHADOW,
-                param.ident.span,
-                format!("this generic shadows the built-in type `{}`", prim_ty.name()),
-            );
-        }
+    if let GenericParamKind::Type { .. } = param.kind
+        && let Some(prim_ty) = PrimTy::from_name(param.ident.name)
+    {
+        span_lint(
+            cx,
+            BUILTIN_TYPE_SHADOW,
+            param.ident.span,
+            format!("this generic shadows the built-in type `{}`", prim_ty.name()),
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/redundant_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/redundant_pattern.rs
index d5b5b2bf2dd..3cb51671aaf 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/redundant_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/redundant_pattern.rs
@@ -6,20 +6,20 @@ use rustc_lint::EarlyContext;
 use super::REDUNDANT_PATTERN;
 
 pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
-    if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind {
-        if let PatKind::Wild = right.kind {
-            span_lint_and_sugg(
-                cx,
-                REDUNDANT_PATTERN,
-                pat.span,
-                format!(
-                    "the `{} @ _` pattern can be written as just `{}`",
-                    ident.name, ident.name,
-                ),
-                "try",
-                format!("{}{}", ann.prefix_str(), ident.name),
-                Applicability::MachineApplicable,
-            );
-        }
+    if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind
+        && let PatKind::Wild = right.kind
+    {
+        span_lint_and_sugg(
+            cx,
+            REDUNDANT_PATTERN,
+            pat.span,
+            format!(
+                "the `{} @ _` pattern can be written as just `{}`",
+                ident.name, ident.name,
+            ),
+            "try",
+            format!("{}{}", ann.prefix_str(), ident.name),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
index 00f46629f10..fffaf40c9d1 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
@@ -7,30 +7,30 @@ use rustc_span::Span;
 use super::UNNEEDED_WILDCARD_PATTERN;
 
 pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
-    if let PatKind::TupleStruct(_, _, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind {
-        if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) {
-            if let Some((left_index, left_pat)) = patterns[..rest_index]
-                .iter()
-                .rev()
-                .take_while(|pat| matches!(pat.kind, PatKind::Wild))
-                .enumerate()
-                .last()
-            {
-                span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0);
-            }
+    if let PatKind::TupleStruct(_, _, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind
+        && let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest())
+    {
+        if let Some((left_index, left_pat)) = patterns[..rest_index]
+            .iter()
+            .rev()
+            .take_while(|pat| matches!(pat.kind, PatKind::Wild))
+            .enumerate()
+            .last()
+        {
+            span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0);
+        }
 
-            if let Some((right_index, right_pat)) = patterns[rest_index + 1..]
-                .iter()
-                .take_while(|pat| matches!(pat.kind, PatKind::Wild))
-                .enumerate()
-                .last()
-            {
-                span_lint(
-                    cx,
-                    patterns[rest_index].span.shrink_to_hi().to(right_pat.span),
-                    right_index == 0,
-                );
-            }
+        if let Some((right_index, right_pat)) = patterns[rest_index + 1..]
+            .iter()
+            .take_while(|pat| matches!(pat.kind, PatKind::Wild))
+            .enumerate()
+            .last()
+        {
+            span_lint(
+                cx,
+                patterns[rest_index].span.shrink_to_hi().to(right_pat.span),
+                right_index == 0,
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
index d52fe7e7d5b..394bc4aef1c 100644
--- a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
+++ b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
@@ -111,10 +111,10 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
 // Checks if impl_param_name is the same as one of type_param_names,
 // and is in a different position
 fn mismatch_param_name(i: usize, impl_param_name: &String, type_param_names: &FxHashMap<&String, usize>) -> bool {
-    if let Some(j) = type_param_names.get(impl_param_name) {
-        if i != *j {
-            return true;
-        }
+    if let Some(j) = type_param_names.get(impl_param_name)
+        && i != *j
+    {
+        return true;
     }
     false
 }
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 cdd6f4e5b03..c8e3462b24e 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
@@ -3,14 +3,15 @@ use std::ops::ControlFlow;
 
 use clippy_utils::comparisons::{Rel, normalize_comparison};
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace};
 use clippy_utils::source::snippet;
 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_ast::{BinOpKind, LitKind, RangeLimits};
 use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnindexMap;
 use rustc_errors::{Applicability, Diag};
-use rustc_hir::{BinOpKind, Block, Body, Expr, ExprKind, UnOp};
+use rustc_hir::{Block, Body, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
@@ -134,19 +135,31 @@ fn assert_len_expr<'hir>(
     cx: &LateContext<'_>,
     expr: &'hir Expr<'hir>,
 ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> {
-    if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr)
+    let (cmp, asserted_len, slice_len) = if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr)
         && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind
         && let ExprKind::Binary(bin_op, left, right) = &condition.kind
-
-        && let Some((cmp, asserted_len, slice_len)) = len_comparison(bin_op.node, left, right)
-        && let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind
-        && cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice()
-        && method.ident.name == sym::len
-
         // check if `then` block has a never type expression
         && let ExprKind::Block(Block { expr: Some(then_expr), .. }, _) = then.kind
         && cx.typeck_results().expr_ty(then_expr).is_never()
     {
+        len_comparison(bin_op.node, left, right)?
+    } else if let Some((macro_call, bin_op)) = first_node_macro_backtrace(cx, expr).find_map(|macro_call| {
+        match cx.tcx.get_diagnostic_name(macro_call.def_id) {
+            Some(sym::assert_eq_macro) => Some((macro_call, BinOpKind::Eq)),
+            Some(sym::assert_ne_macro) => Some((macro_call, BinOpKind::Ne)),
+            _ => None,
+        }
+    }) && let Some((left, right, _)) = find_assert_eq_args(cx, expr, macro_call.expn)
+    {
+        len_comparison(bin_op, left, right)?
+    } else {
+        return None;
+    };
+
+    if let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind
+        && cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice()
+        && method.ident.name == sym::len
+    {
         Some((cmp, asserted_len, recv))
     } else {
         None
@@ -168,6 +181,7 @@ enum IndexEntry<'hir> {
     /// if the `assert!` asserts the right length.
     AssertWithIndex {
         highest_index: usize,
+        is_first_highest: bool,
         asserted_len: usize,
         assert_span: Span,
         slice: &'hir Expr<'hir>,
@@ -177,6 +191,7 @@ enum IndexEntry<'hir> {
     /// Indexing without an `assert!`
     IndexWithoutAssert {
         highest_index: usize,
+        is_first_highest: bool,
         indexes: Vec<Span>,
         slice: &'hir Expr<'hir>,
     },
@@ -244,28 +259,41 @@ fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Uni
                     assert_span,
                     slice,
                 } => {
-                    *entry = IndexEntry::AssertWithIndex {
-                        highest_index: index,
-                        asserted_len: *asserted_len,
-                        assert_span: *assert_span,
-                        slice,
-                        indexes: vec![expr.span],
-                        comparison: *comparison,
-                    };
+                    if slice.span.lo() > assert_span.lo() {
+                        *entry = IndexEntry::AssertWithIndex {
+                            highest_index: index,
+                            is_first_highest: true,
+                            asserted_len: *asserted_len,
+                            assert_span: *assert_span,
+                            slice,
+                            indexes: vec![expr.span],
+                            comparison: *comparison,
+                        };
+                    }
                 },
                 IndexEntry::IndexWithoutAssert {
-                    highest_index, indexes, ..
+                    highest_index,
+                    indexes,
+                    is_first_highest,
+                    ..
                 }
                 | IndexEntry::AssertWithIndex {
-                    highest_index, indexes, ..
+                    highest_index,
+                    indexes,
+                    is_first_highest,
+                    ..
                 } => {
                     indexes.push(expr.span);
+                    if *is_first_highest {
+                        (*is_first_highest) = *highest_index >= index;
+                    }
                     *highest_index = (*highest_index).max(index);
                 },
             }
         } else {
             indexes.push(IndexEntry::IndexWithoutAssert {
                 highest_index: index,
+                is_first_highest: true,
                 indexes: vec![expr.span],
                 slice,
             });
@@ -284,15 +312,18 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un
         if let Some(entry) = entry {
             if let IndexEntry::IndexWithoutAssert {
                 highest_index,
+                is_first_highest,
                 indexes,
                 slice,
             } = entry
+                && expr.span.lo() <= slice.span.lo()
             {
                 *entry = IndexEntry::AssertWithIndex {
                     highest_index: *highest_index,
                     indexes: mem::take(indexes),
+                    is_first_highest: *is_first_highest,
                     slice,
-                    assert_span: expr.span,
+                    assert_span: expr.span.source_callsite(),
                     comparison,
                     asserted_len,
                 };
@@ -301,7 +332,7 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un
             indexes.push(IndexEntry::StrayAssert {
                 asserted_len,
                 comparison,
-                assert_span: expr.span,
+                assert_span: expr.span.source_callsite(),
                 slice,
             });
         }
@@ -325,12 +356,13 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap<u64, Vec<IndexEntry<'_>
             match *entry {
                 IndexEntry::AssertWithIndex {
                     highest_index,
+                    is_first_highest,
                     asserted_len,
                     ref indexes,
                     comparison,
                     assert_span,
                     slice,
-                } if indexes.len() > 1 => {
+                } if indexes.len() > 1 && !is_first_highest => {
                     // if we have found an `assert!`, let's also check that it's actually right
                     // and if it covers the highest index and if not, suggest the correct length
                     let sugg = match comparison {
@@ -378,8 +410,9 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap<u64, Vec<IndexEntry<'_>
                 IndexEntry::IndexWithoutAssert {
                     ref indexes,
                     highest_index,
+                    is_first_highest,
                     slice,
-                } if indexes.len() > 1 => {
+                } if indexes.len() > 1 && !is_first_highest => {
                     // if there was no `assert!` but more than one index, suggest
                     // adding an `assert!` that covers the highest index
                     report_lint(
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 38a19dd2999..67537a251da 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
@@ -139,12 +139,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
         // Const fns are not allowed as methods in a trait.
         {
             let parent = cx.tcx.hir_get_parent_item(hir_id).def_id;
-            if parent != CRATE_DEF_ID {
-                if let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) {
-                    if let hir::ItemKind::Trait(..) = &item.kind {
-                        return;
-                    }
-                }
+            if parent != CRATE_DEF_ID
+                && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(parent)
+                && let hir::ItemKind::Trait(..) = &item.kind
+            {
+                return;
             }
         }
 
@@ -156,9 +155,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
             return;
         }
 
-        let mir = cx.tcx.optimized_mir(def_id);
+        let mir = cx.tcx.mir_drops_elaborated_and_const_checked(def_id);
 
-        if let Ok(()) = is_min_const_fn(cx, mir, self.msrv)
+        if let Ok(()) = is_min_const_fn(cx, &mir.borrow(), self.msrv)
             && let hir::Node::Item(hir::Item { vis_span, .. }) | hir::Node::ImplItem(hir::ImplItem { vis_span, .. }) =
                 cx.tcx.hir_node_by_def_id(def_id)
         {
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 28dc2427428..1932d2d5f97 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
@@ -209,7 +209,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
             && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, self_path_did) = self_path.res
             && cx.tcx.is_diagnostic_item(sym::Debug, trait_def_id)
             // don't trigger if this impl was derived
-            && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
+            && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
             && !item.span.from_expansion()
             // find `Debug::fmt` function
             && let Some(fmt_item) = items.iter().find(|i| i.ident.name == sym::fmt)
@@ -224,11 +224,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
             // NB: can't call cx.typeck_results() as we are not in a body
             && let typeck_results = cx.tcx.typeck_body(*body_id)
             && should_lint(cx, typeck_results, block)
-        {
             // we intentionally only lint structs, see lint description
-            if let ItemKind::Struct(_, data, _) = &self_item.kind {
-                check_struct(cx, typeck_results, block, self_ty, item, data);
-            }
+            && let ItemKind::Struct(_, data, _) = &self_item.kind
+        {
+            check_struct(cx, typeck_results, block, self_ty, item, data);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index f49e03ea765..1f613171b46 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -160,12 +160,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
             AssocItemContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
         };
 
-        if let Some(trait_def_id) = trait_def_id {
-            if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
-                // If a trait is being implemented for an item, and the
-                // trait is not exported, we don't need #[inline]
-                return;
-            }
+        if let Some(trait_def_id) = trait_def_id
+            && trait_def_id.is_local()
+            && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id)
+        {
+            // If a trait is being implemented for an item, and the
+            // trait is not exported, we don't need #[inline]
+            return;
         }
 
         let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index fbd287f5285..0e085585962 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -135,10 +135,10 @@ impl<'tcx> DivergenceVisitor<'_, 'tcx> {
     }
 
     fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) {
-        if let Some(macro_call) = root_macro_call_first_node(self.cx, e) {
-            if self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
-                return;
-            }
+        if let Some(macro_call) = root_macro_call_first_node(self.cx, e)
+            && self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo"
+        {
+            return;
         }
         span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges");
     }
@@ -328,22 +328,22 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
             return;
         }
 
-        if path_to_local_id(expr, self.var) {
+        if path_to_local_id(expr, self.var)
             // Check that this is a read, not a write.
-            if !is_in_assignment_position(self.cx, expr) {
-                span_lint_and_then(
-                    self.cx,
-                    MIXED_READ_WRITE_IN_EXPRESSION,
-                    expr.span,
-                    format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)),
-                    |diag| {
-                        diag.span_note(
-                            self.write_expr.span,
-                            "whether read occurs before this write depends on evaluation order",
-                        );
-                    },
-                );
-            }
+            && !is_in_assignment_position(self.cx, expr)
+        {
+            span_lint_and_then(
+                self.cx,
+                MIXED_READ_WRITE_IN_EXPRESSION,
+                expr.span,
+                format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)),
+                |diag| {
+                    diag.span_note(
+                        self.write_expr.span,
+                        "whether read occurs before this write depends on evaluation order",
+                    );
+                },
+            );
         }
         match expr.kind {
             // We're about to descend a closure. Since we don't know when (or
@@ -373,10 +373,10 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
 
 /// Returns `true` if `expr` is the LHS of an assignment, like `expr = ...`.
 fn is_in_assignment_position(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    if let Some(parent) = get_parent_expr(cx, expr) {
-        if let ExprKind::Assign(lhs, ..) = parent.kind {
-            return lhs.hir_id == expr.hir_id;
-        }
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let ExprKind::Assign(lhs, ..) = parent.kind
+    {
+        return lhs.hir_id == expr.hir_id;
     }
     false
 }
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 7287193326f..98614baffce 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -119,22 +119,22 @@ impl EarlyLintPass for ModStyle {
         }
 
         for folder in &folder_segments {
-            if !mod_folders.contains(folder) {
-                if let Some((file, path)) = file_map.get(folder) {
-                    span_lint_and_then(
-                        cx,
-                        SELF_NAMED_MODULE_FILES,
-                        Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
-                        format!("`mod.rs` files are required, found `{}`", path.display()),
-                        |diag| {
-                            let mut correct = path.to_path_buf();
-                            correct.pop();
-                            correct.push(folder);
-                            correct.push("mod.rs");
-                            diag.help(format!("move `{}` to `{}`", path.display(), correct.display(),));
-                        },
-                    );
-                }
+            if !mod_folders.contains(folder)
+                && let Some((file, path)) = file_map.get(folder)
+            {
+                span_lint_and_then(
+                    cx,
+                    SELF_NAMED_MODULE_FILES,
+                    Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
+                    format!("`mod.rs` files are required, found `{}`", path.display()),
+                    |diag| {
+                        let mut correct = path.to_path_buf();
+                        correct.pop();
+                        correct.push(folder);
+                        correct.push("mod.rs");
+                        diag.help(format!("move `{}` to `{}`", path.display(), correct.display(),));
+                    },
+                );
             }
         }
     }
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 2adc27c0b70..c6c27e22b90 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
@@ -142,10 +142,9 @@ fn collect_unsafe_exprs<'tcx>(
                     .typeck_results()
                     .type_dependent_def_id(expr.hir_id)
                     .map(|def_id| cx.tcx.fn_sig(def_id))
+                    && sig.skip_binder().safety().is_unsafe()
                 {
-                    if sig.skip_binder().safety().is_unsafe() {
-                        unsafe_ops.push(("unsafe method call occurs here", expr.span));
-                    }
+                    unsafe_ops.push(("unsafe method call occurs here", expr.span));
                 }
             },
 
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 7abc5870d00..a45031ce22b 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -82,10 +82,10 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
-        if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
-            if trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
-                self.check_sig(cx, item.owner_id.def_id, sig.decl);
-            }
+        if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind
+            && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
+        {
+            self.check_sig(cx, item.owner_id.def_id, sig.decl);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs
index 3c4ba5141dd..d98c70e7f5a 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs
@@ -77,16 +77,16 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> {
                     expr.span,
                     "generally you want to avoid `&mut &mut _` if possible",
                 );
-            } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() {
-                if ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) {
-                    span_lint_hir(
-                        self.cx,
-                        MUT_MUT,
-                        expr.hir_id,
-                        expr.span,
-                        "this expression mutably borrows a mutable reference. Consider reborrowing",
-                    );
-                }
+            } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind()
+                && ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env())
+            {
+                span_lint_hir(
+                    self.cx,
+                    MUT_MUT,
+                    expr.hir_id,
+                    expr.span,
+                    "this expression mutably borrows a mutable reference. Consider reborrowing",
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 13a23a13b9c..270eebe0758 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -101,14 +101,13 @@ impl<'tcx> Visitor<'tcx> for MutArgVisitor<'_, 'tcx> {
                 return;
             },
             ExprKind::Path(_) => {
-                if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
-                    if adj
+                if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id)
+                    && adj
                         .iter()
                         .any(|a| matches!(a.target.kind(), ty::Ref(_, _, Mutability::Mut)))
-                    {
-                        self.found = true;
-                        return;
-                    }
+                {
+                    self.found = true;
+                    return;
                 }
             },
             // Don't check await desugars
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index 49fd29d1dd6..fe2157ca533 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -91,19 +91,19 @@ declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]);
 impl<'tcx> LateLintPass<'tcx> for Mutex {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let ty = cx.typeck_results().expr_ty(expr);
-        if let ty::Adt(_, subst) = ty.kind() {
-            if is_type_diagnostic_item(cx, ty, sym::Mutex) {
-                let mutex_param = subst.type_at(0);
-                if let Some(atomic_name) = get_atomic_name(mutex_param) {
-                    let msg = format!(
-                        "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \
+        if let ty::Adt(_, subst) = ty.kind()
+            && is_type_diagnostic_item(cx, ty, sym::Mutex)
+        {
+            let mutex_param = subst.type_at(0);
+            if let Some(atomic_name) = get_atomic_name(mutex_param) {
+                let msg = format!(
+                    "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \
                          behavior and not the internal type, consider using `Mutex<()>`"
-                    );
-                    match *mutex_param.kind() {
-                        ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, msg),
-                        ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, msg),
-                        _ => span_lint(cx, MUTEX_ATOMIC, expr.span, msg),
-                    }
+                );
+                match *mutex_param.kind() {
+                    ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, msg),
+                    ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, msg),
+                    _ => span_lint(cx, MUTEX_ATOMIC, expr.span, msg),
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 2eacd6875d6..f768e11a4a2 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                     || is_receiver_of_method_call(cx, e)
                     || is_as_argument(cx, e)
                 {
-                    snip = snip.maybe_par();
+                    snip = snip.maybe_paren();
                 }
 
                 span_lint_and_sugg(
@@ -426,10 +426,10 @@ fn fetch_bool_block(expr: &Expr<'_>) -> Option<Expression> {
 }
 
 fn fetch_bool_expr(expr: &Expr<'_>) -> Option<bool> {
-    if let ExprKind::Lit(lit_ptr) = peel_blocks(expr).kind {
-        if let LitKind::Bool(value) = lit_ptr.node {
-            return Some(value);
-        }
+    if let ExprKind::Lit(lit_ptr) = peel_blocks(expr).kind
+        && let LitKind::Bool(value) = lit_ptr.node
+    {
+        return Some(value);
     }
     None
 }
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 b61061d076b..7052e1d0fbe 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
@@ -86,11 +86,11 @@ fn should_skip<'tcx>(
         return false;
     }
 
-    if let PatKind::Binding(.., name, _) = arg.pat.kind {
+    if let PatKind::Binding(.., name, _) = arg.pat.kind
         // If it's a potentially unused variable, we don't check it.
-        if name.name == kw::Underscore || name.as_str().starts_with('_') {
-            return true;
-        }
+        && (name.name == kw::Underscore || name.as_str().starts_with('_'))
+    {
+        return true;
     }
 
     // All spans generated from a proc-macro invocation are the same...
@@ -164,13 +164,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
         };
 
         // Exclude non-inherent impls
-        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
-            if matches!(
+        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id)
+            && matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
-            ) {
-                return;
-            }
+            )
+        {
+            return;
         }
 
         let fn_sig = cx.tcx.fn_sig(fn_def_id).instantiate_identity();
@@ -353,10 +353,10 @@ impl MutablyUsedVariablesCtxt<'_> {
         for (parent, node) in self.tcx.hir_parent_iter(item) {
             if let Some(fn_sig) = self.tcx.hir_fn_sig_by_hir_id(parent) {
                 return fn_sig.header.is_unsafe();
-            } else if let Node::Block(block) = node {
-                if matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) {
-                    return true;
-                }
+            } else if let Node::Block(block) = node
+                && matches!(block.rules, BlockCheckMode::UnsafeBlock(_))
+            {
+                return true;
             }
         }
         false
@@ -426,10 +426,10 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 // upon!
                 self.add_mutably_used_var(*vid);
             }
-        } else if borrow == ty::BorrowKind::Immutable {
+        } else if borrow == ty::BorrowKind::Immutable
             // If there is an `async block`, it'll contain a call to a closure which we need to
             // go into to ensure all "mutate" checks are found.
-            if let Node::Expr(Expr {
+            && let Node::Expr(Expr {
                 kind:
                     ExprKind::Call(
                         _,
@@ -442,9 +442,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                     ),
                 ..
             }) = self.tcx.hir_node(cmt.hir_id)
-            {
-                self.async_closures.insert(*def_id);
-            }
+        {
+            self.async_closures.insert(*def_id);
         }
     }
 
@@ -460,10 +459,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 }),
             ..
         } = &cmt.place
+            && !projections.is_empty()
         {
-            if !projections.is_empty() {
-                self.add_mutably_used_var(*vid);
-            }
+            self.add_mutably_used_var(*vid);
         }
     }
 
@@ -477,10 +475,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 }),
             ..
         } = &cmt.place
+            && self.is_in_unsafe_block(id)
         {
-            if self.is_in_unsafe_block(id) {
-                self.add_mutably_used_var(*vid);
-            }
+            self.add_mutably_used_var(*vid);
         }
         self.prev_bind = None;
     }
@@ -499,15 +496,14 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 }),
             ..
         } = &cmt.place
+            && let FakeReadCause::ForLet(Some(inner)) = cause
         {
-            if let FakeReadCause::ForLet(Some(inner)) = cause {
-                // Seems like we are inside an async function. We need to store the closure `DefId`
-                // to go through it afterwards.
-                self.async_closures.insert(inner);
-                self.add_alias(cmt.hir_id, *vid);
-                self.prev_move_to_closure.insert(*vid);
-                self.prev_bind = None;
-            }
+            // Seems like we are inside an async function. We need to store the closure `DefId`
+            // to go through it afterwards.
+            self.async_closures.insert(inner);
+            self.add_alias(cmt.hir_id, *vid);
+            self.prev_move_to_closure.insert(*vid);
+            self.prev_bind = None;
         }
     }
 
@@ -522,10 +518,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 }),
             ..
         } = &cmt.place
+            && self.is_in_unsafe_block(id)
         {
-            if self.is_in_unsafe_block(id) {
-                self.add_mutably_used_var(*vid);
-            }
+            self.add_mutably_used_var(*vid);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 978fde33d51..275d710c76a 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -98,13 +98,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         }
 
         // Exclude non-inherent impls
-        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
-            if matches!(
+        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id)
+            && matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
-            ) {
-                return;
-            }
+            )
+        {
+            return;
         }
 
         // Allow `Borrow` or functions to be taken by value
@@ -197,20 +197,18 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
             {
                 // Dereference suggestion
                 let sugg = |diag: &mut Diag<'_, ()>| {
-                    if let ty::Adt(def, ..) = ty.kind() {
-                        if let Some(span) = cx.tcx.hir_span_if_local(def.did()) {
-                            if type_allowed_to_implement_copy(
-                                cx.tcx,
-                                cx.param_env,
-                                ty,
-                                traits::ObligationCause::dummy_with_span(span),
-                                rustc_hir::Safety::Safe,
-                            )
-                            .is_ok()
-                            {
-                                diag.span_help(span, "or consider marking this type as `Copy`");
-                            }
-                        }
+                    if let ty::Adt(def, ..) = ty.kind()
+                        && let Some(span) = cx.tcx.hir_span_if_local(def.did())
+                        && type_allowed_to_implement_copy(
+                            cx.tcx,
+                            cx.param_env,
+                            ty,
+                            traits::ObligationCause::dummy_with_span(span),
+                            rustc_hir::Safety::Safe,
+                        )
+                        .is_ok()
+                    {
+                        diag.span_help(span, "or consider marking this type as `Copy`");
                     }
 
                     if is_type_diagnostic_item(cx, ty, sym::Vec)
@@ -254,29 +252,28 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                         return;
                     }
 
-                    if is_type_lang_item(cx, ty, LangItem::String) {
-                        if let Some(clone_spans) =
+                    if is_type_lang_item(cx, ty, LangItem::String)
+                        && let Some(clone_spans) =
                             get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")])
-                        {
+                    {
+                        diag.span_suggestion(
+                            input.span,
+                            "consider changing the type to",
+                            "&str",
+                            Applicability::Unspecified,
+                        );
+
+                        for (span, suggestion) in clone_spans {
                             diag.span_suggestion(
-                                input.span,
-                                "consider changing the type to",
-                                "&str",
+                                span,
+                                span.get_source_text(cx)
+                                    .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")),
+                                suggestion,
                                 Applicability::Unspecified,
                             );
-
-                            for (span, suggestion) in clone_spans {
-                                diag.span_suggestion(
-                                    span,
-                                    span.get_source_text(cx)
-                                        .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")),
-                                    suggestion,
-                                    Applicability::Unspecified,
-                                );
-                            }
-
-                            return;
                         }
+
+                        return;
                     }
 
                     diag.span_suggestion_verbose(
diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs
index cce0617ba39..4a86c3720ca 100644
--- a/src/tools/clippy/clippy_lints/src/needless_update.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_update.rs
@@ -53,18 +53,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind {
             let ty = cx.typeck_results().expr_ty(expr);
-            if let ty::Adt(def, _) = ty.kind() {
-                let variant = def.non_enum_variant();
-                if fields.len() == variant.fields.len()
-                    && !variant.is_field_list_non_exhaustive()
-                {
-                    span_lint(
-                        cx,
-                        NEEDLESS_UPDATE,
-                        base.span,
-                        "struct update has no effect, all the fields in the struct have already been specified",
-                    );
-                }
+            if let ty::Adt(def, _) = ty.kind()
+                && fields.len() == def.non_enum_variant().fields.len()
+                && !def.variant(0_usize.into()).is_field_list_non_exhaustive()
+            {
+                span_lint(
+                    cx,
+                    NEEDLESS_UPDATE,
+                    base.span,
+                    "struct update has no effect, all the fields in the struct have already been specified",
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index 429afff9b66..74c8142787e 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -16,9 +16,6 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// It's more readable to just negate.
     ///
-    /// ### Known problems
-    /// This only catches integers (for now).
-    ///
     /// ### Example
     /// ```rust,ignore
     /// let a = x * -1;
@@ -38,23 +35,32 @@ declare_lint_pass!(NegMultiply => [NEG_MULTIPLY]);
 
 impl<'tcx> LateLintPass<'tcx> for NegMultiply {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref op, left, right) = e.kind {
-            if BinOpKind::Mul == op.node {
-                match (&left.kind, &right.kind) {
-                    (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {},
-                    (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right),
-                    (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left),
-                    _ => {},
-                }
+        if let ExprKind::Binary(ref op, left, right) = e.kind
+            && BinOpKind::Mul == op.node
+        {
+            match (&left.kind, &right.kind) {
+                (&ExprKind::Unary(..), &ExprKind::Unary(..)) => {},
+                (&ExprKind::Unary(UnOp::Neg, lit), _) => check_mul(cx, e.span, lit, right),
+                (_, &ExprKind::Unary(UnOp::Neg, lit)) => check_mul(cx, e.span, lit, left),
+                _ => {},
             }
         }
     }
 }
 
 fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
+    const F16_ONE: u16 = 1.0_f16.to_bits();
+    const F128_ONE: u128 = 1.0_f128.to_bits();
     if let ExprKind::Lit(l) = lit.kind
-        && consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1)
-        && cx.typeck_results().expr_ty(exp).is_integral()
+        && matches!(
+            consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)),
+            Constant::Int(1)
+                | Constant::F16(F16_ONE)
+                | Constant::F32(1.0)
+                | Constant::F64(1.0)
+                | Constant::F128(F128_ONE)
+        )
+        && cx.typeck_results().expr_ty(exp).is_numeric()
     {
         let mut applicability = Applicability::MachineApplicable;
         let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index 1e469c3b63a..4b73a4455f5 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -99,10 +99,10 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                 let mut impls = HirIdSet::default();
                                 for &d in cx.tcx.local_trait_impls(default_trait_id) {
                                     let ty = cx.tcx.type_of(d).instantiate_identity();
-                                    if let Some(ty_def) = ty.ty_adt_def() {
-                                        if let Some(local_def_id) = ty_def.did().as_local() {
-                                            impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
-                                        }
+                                    if let Some(ty_def) = ty.ty_adt_def()
+                                        && let Some(local_def_id) = ty_def.did().as_local()
+                                    {
+                                        impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
                                     }
                                 }
                                 self.impling_types = Some(impls);
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 7187a8f2c11..7ab7976d569 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -182,23 +182,22 @@ impl NoEffect {
                 );
                 return true;
             }
-        } else if let StmtKind::Let(local) = stmt.kind {
-            if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id)
-                && !matches!(local.source, LocalSource::AsyncFn)
-                && let Some(init) = local.init
-                && local.els.is_none()
-                && !local.pat.span.from_expansion()
-                && has_no_effect(cx, init)
-                && let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
-                && ident.name.to_ident_string().starts_with('_')
-                && !in_automatically_derived(cx.tcx, local.hir_id)
-            {
-                if let Some(l) = self.local_bindings.last_mut() {
-                    l.push(hir_id);
-                    self.underscore_bindings.insert(hir_id, ident.span);
-                }
-                return true;
+        } else if let StmtKind::Let(local) = stmt.kind
+            && !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id)
+            && !matches!(local.source, LocalSource::AsyncFn)
+            && let Some(init) = local.init
+            && local.els.is_none()
+            && !local.pat.span.from_expansion()
+            && has_no_effect(cx, init)
+            && let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
+            && ident.name.to_ident_string().starts_with('_')
+            && !in_automatically_derived(cx.tcx, local.hir_id)
+        {
+            if let Some(l) = self.local_bindings.last_mut() {
+                l.push(hir_id);
+                self.underscore_bindings.insert(hir_id, ident.span);
             }
+            return true;
         }
         false
     }
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 448bb603cf2..93865197ec9 100644
--- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
@@ -1,6 +1,8 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_from_proc_macro, is_res_lang_ctor, last_path_segment, path_res, std_or_core};
+use clippy_utils::{
+    is_diag_trait_item, 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};
@@ -98,7 +100,7 @@ declare_clippy_lint! {
     ///
     /// impl PartialOrd for A {
     ///     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-    ///         Some(self.cmp(other))
+    ///         Some(self.cmp(other))   // or self.cmp(other).into()
     ///     }
     /// }
     /// ```
@@ -185,65 +187,66 @@ impl LateLintPass<'_> for NonCanonicalImpls {
 
             if block.stmts.is_empty()
                 && let Some(expr) = block.expr
-                && expr_is_cmp(cx, &expr.kind, impl_item, &mut needs_fully_qualified)
+                && expr_is_cmp(cx, expr, impl_item, &mut needs_fully_qualified)
             {
+                return;
             }
             // Fix #12683, allow [`needless_return`] here
             else if block.expr.is_none()
                 && let Some(stmt) = block.stmts.first()
                 && let rustc_hir::StmtKind::Semi(Expr {
-                    kind: ExprKind::Ret(Some(Expr { kind: ret_kind, .. })),
+                    kind: ExprKind::Ret(Some(ret)),
                     ..
                 }) = stmt.kind
-                && expr_is_cmp(cx, ret_kind, impl_item, &mut needs_fully_qualified)
+                && expr_is_cmp(cx, ret, impl_item, &mut needs_fully_qualified)
             {
-            } else {
-                // If `Self` and `Rhs` are not the same type, bail. This makes creating a valid
-                // suggestion tons more complex.
-                if let [lhs, rhs, ..] = trait_impl.args.as_slice()
-                    && lhs != rhs
-                {
-                    return;
-                }
+                return;
+            }
+            // If `Self` and `Rhs` are not the same type, bail. This makes creating a valid
+            // suggestion tons more complex.
+            else if let [lhs, rhs, ..] = trait_impl.args.as_slice()
+                && lhs != rhs
+            {
+                return;
+            }
 
-                span_lint_and_then(
-                    cx,
-                    NON_CANONICAL_PARTIAL_ORD_IMPL,
-                    item.span,
-                    "non-canonical implementation of `partial_cmp` on an `Ord` type",
-                    |diag| {
-                        let [_, other] = body.params else {
-                            return;
-                        };
-                        let Some(std_or_core) = std_or_core(cx) else {
-                            return;
-                        };
+            span_lint_and_then(
+                cx,
+                NON_CANONICAL_PARTIAL_ORD_IMPL,
+                item.span,
+                "non-canonical implementation of `partial_cmp` on an `Ord` type",
+                |diag| {
+                    let [_, other] = body.params else {
+                        return;
+                    };
+                    let Some(std_or_core) = std_or_core(cx) else {
+                        return;
+                    };
 
-                        let suggs = match (other.pat.simple_ident(), needs_fully_qualified) {
-                            (Some(other_ident), true) => vec![(
+                    let suggs = match (other.pat.simple_ident(), needs_fully_qualified) {
+                        (Some(other_ident), true) => vec![(
+                            block.span,
+                            format!("{{ Some({std_or_core}::cmp::Ord::cmp(self, {})) }}", other_ident.name),
+                        )],
+                        (Some(other_ident), false) => {
+                            vec![(block.span, format!("{{ Some(self.cmp({})) }}", other_ident.name))]
+                        },
+                        (None, true) => vec![
+                            (
                                 block.span,
-                                format!("{{ Some({std_or_core}::cmp::Ord::cmp(self, {})) }}", other_ident.name),
-                            )],
-                            (Some(other_ident), false) => {
-                                vec![(block.span, format!("{{ Some(self.cmp({})) }}", other_ident.name))]
-                            },
-                            (None, true) => vec![
-                                (
-                                    block.span,
-                                    format!("{{ Some({std_or_core}::cmp::Ord::cmp(self, other)) }}"),
-                                ),
-                                (other.pat.span, "other".to_owned()),
-                            ],
-                            (None, false) => vec![
-                                (block.span, "{ Some(self.cmp(other)) }".to_owned()),
-                                (other.pat.span, "other".to_owned()),
-                            ],
-                        };
+                                format!("{{ Some({std_or_core}::cmp::Ord::cmp(self, other)) }}"),
+                            ),
+                            (other.pat.span, "other".to_owned()),
+                        ],
+                        (None, false) => vec![
+                            (block.span, "{ Some(self.cmp(other)) }".to_owned()),
+                            (other.pat.span, "other".to_owned()),
+                        ],
+                    };
 
-                        diag.multipart_suggestion("change this to", suggs, Applicability::Unspecified);
-                    },
-                );
-            }
+                    diag.multipart_suggestion("change this to", suggs, Applicability::Unspecified);
+                },
+            );
         }
     }
 }
@@ -251,10 +254,11 @@ impl LateLintPass<'_> for NonCanonicalImpls {
 /// Return true if `expr_kind` is a `cmp` call.
 fn expr_is_cmp<'tcx>(
     cx: &LateContext<'tcx>,
-    expr_kind: &'tcx ExprKind<'tcx>,
+    expr: &'tcx Expr<'tcx>,
     impl_item: &ImplItem<'_>,
     needs_fully_qualified: &mut bool,
 ) -> bool {
+    let impl_item_did = impl_item.owner_id.def_id;
     if let ExprKind::Call(
         Expr {
             kind: ExprKind::Path(some_path),
@@ -262,11 +266,17 @@ fn expr_is_cmp<'tcx>(
             ..
         },
         [cmp_expr],
-    ) = expr_kind
+    ) = expr.kind
     {
         is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome)
             // Fix #11178, allow `Self::cmp(self, ..)` too
-            && self_cmp_call(cx, cmp_expr, impl_item.owner_id.def_id, needs_fully_qualified)
+            && self_cmp_call(cx, cmp_expr, impl_item_did, needs_fully_qualified)
+    } else if let ExprKind::MethodCall(_, recv, [], _) = expr.kind {
+        cx.tcx
+            .typeck(impl_item_did)
+            .type_dependent_def_id(expr.hir_id)
+            .is_some_and(|def_id| is_diag_trait_item(cx, def_id, sym::Into))
+            && self_cmp_call(cx, recv, impl_item_did, needs_fully_qualified)
     } else {
         false
     }
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 9b53608ae7f..63859c0396e 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -449,7 +449,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
 
                             dereferenced_expr = parent_expr;
                         },
-                        ExprKind::Index(e, _, _) if ptr::eq(&**e, cur_expr) => {
+                        ExprKind::Index(e, _, _) if ptr::eq(&raw const **e, cur_expr) => {
                             // `e[i]` => desugared to `*Index::index(&e, i)`,
                             // meaning `e` must be referenced.
                             // no need to go further up since a method call is involved now.
diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
index 8305bf345ef..f6bc9428d65 100644
--- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
+++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
@@ -37,7 +37,7 @@ declare_clippy_lint! {
     /// static FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "FOO".to_lowercase());
     /// static BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "BAR".to_lowercase());
     /// ```
-    #[clippy::version = "1.81.0"]
+    #[clippy::version = "1.86.0"]
     pub NON_STD_LAZY_STATICS,
     pedantic,
     "lazy static that could be replaced by `std::sync::LazyLock`"
@@ -121,7 +121,7 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic {
                 cx,
                 NON_STD_LAZY_STATICS,
                 macro_call.span,
-                "this macro has been superceded by `std::sync::LazyLock`",
+                "this macro has been superseded by `std::sync::LazyLock`",
             );
             return;
         }
@@ -240,7 +240,7 @@ impl LazyInfo {
             cx,
             NON_STD_LAZY_STATICS,
             self.ty_span_no_args,
-            "this type has been superceded by `LazyLock` in the standard library",
+            "this type has been superseded by `LazyLock` in the standard library",
             |diag| {
                 diag.multipart_suggestion("use `std::sync::LazyLock` instead", suggs, appl);
             },
diff --git a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
index 16c4391c0fb..635f5678e2a 100644
--- a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
@@ -82,11 +82,10 @@ fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicabilit
         if let ty::Adt(adt_def, _) = receiver_ty.kind()
             && adt_def.is_struct()
             && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero)
+            && let Some(target_non_zero_type) = get_target_non_zero_type(target_ty)
         {
-            if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
-                let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
-                suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet, applicability);
-            }
+            let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
+            suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet, applicability);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index cf6b8992973..9b2cfd91b85 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -98,7 +98,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
             let arg_snip = snippet(cx, arg_span, "..");
             let expr_snip;
             let eq_impl;
-            if with_deref.is_implemented() {
+            if with_deref.is_implemented() && !arg_ty.peel_refs().is_str() {
                 expr_snip = format!("*{arg_snip}");
                 eq_impl = with_deref;
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
index 74e0a6333db..047a5a0159c 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
@@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>(
         // format the suggestion
         let suggestion = format!(
             "{}.abs()",
-            sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_par()
+            sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_paren()
         );
         // spans the lint
         span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
index 03582322827..e1fd09549a4 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -103,7 +103,7 @@ enum Parens {
 ///
 /// e.g. `-(x + y + 0)` cannot be reduced to `-x + y`, as the behavior changes silently.
 /// e.g. `1u64 + ((x + y + 0i32) as u64)` cannot be reduced to `1u64 + x + y as u64`, since
-/// the the cast expression will not apply to the same expression.
+/// the cast expression will not apply to the same expression.
 /// e.g. `0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }` cannot be reduced
 /// to `if b { 1 } else { 2 } + if b { 3 } else { 4 }` where the `if` could be
 /// interpreted as a statement. The same behavior happens for `match`, `loop`,
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs
index fc5565e821e..2e6a071eb18 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_one.rs
@@ -12,15 +12,15 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, right:
             span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
         }
 
-        if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() {
-            if is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) {
-                span_lint(
-                    cx,
-                    MODULO_ONE,
-                    expr.span,
-                    "any number modulo -1 will panic/overflow or result in 0",
-                );
-            }
+        if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind()
+            && is_integer_const(cx, right, unsext(cx.tcx, -1, *ity))
+        {
+            span_lint(
+                cx,
+                MODULO_ONE,
+                expr.span,
+                "any number modulo -1 will panic/overflow or result in 0",
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 96c9775e292..e6be536ca0f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -75,10 +75,10 @@ impl Context {
             hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => {
                 let body_span = cx.tcx.hir_span_with_body(body_owner);
 
-                if let Some(span) = self.const_span {
-                    if span.contains(body_span) {
-                        return;
-                    }
+                if let Some(span) = self.const_span
+                    && span.contains(body_span)
+                {
+                    return;
                 }
                 self.const_span = Some(body_span);
             },
@@ -90,10 +90,10 @@ impl Context {
         let body_owner = cx.tcx.hir_body_owner(body.id());
         let body_span = cx.tcx.hir_span_with_body(body_owner);
 
-        if let Some(span) = self.const_span {
-            if span.contains(body_span) {
-                return;
-            }
+        if let Some(span) = self.const_span
+            && span.contains(body_span)
+        {
+            return;
         }
         self.const_span = None;
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
index 378fed481f4..0faa7b9e646 100644
--- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
@@ -47,12 +47,11 @@ pub(crate) fn check<'tcx>(
                 let rty = cx.typeck_results().expr_ty(r);
                 let lcpy = is_copy(cx, lty);
                 let rcpy = is_copy(cx, rty);
-                if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id) {
-                    if (are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty))
-                        || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty))
-                    {
-                        return; // Don't lint
-                    }
+                if let Some((self_ty, other_ty)) = in_impl(cx, e, trait_id)
+                    && ((are_equal(cx, rty, self_ty) && are_equal(cx, lty, other_ty))
+                        || (are_equal(cx, rty, other_ty) && are_equal(cx, lty, self_ty)))
+                {
+                    return; // Don't lint
                 }
                 // either operator autorefs or both args are copyable
                 if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) {
@@ -86,7 +85,7 @@ pub(crate) fn check<'tcx>(
                                 left.span,
                                 "use the left value directly",
                                 lsnip,
-                                Applicability::MaybeIncorrect, // FIXME #2597
+                                Applicability::MachineApplicable,
                             );
                         },
                     );
@@ -105,7 +104,7 @@ pub(crate) fn check<'tcx>(
                                 right.span,
                                 "use the right value directly",
                                 rsnip,
-                                Applicability::MaybeIncorrect, // FIXME #2597
+                                Applicability::MachineApplicable,
                             );
                         },
                     );
@@ -137,7 +136,7 @@ pub(crate) fn check<'tcx>(
                                 left.span,
                                 "use the left value directly",
                                 lsnip,
-                                Applicability::MaybeIncorrect, // FIXME #2597
+                                Applicability::MachineApplicable,
                             );
                         },
                     );
@@ -164,7 +163,7 @@ pub(crate) fn check<'tcx>(
                             right.span,
                             "use the right value directly",
                             rsnip,
-                            Applicability::MaybeIncorrect, // FIXME #2597
+                            Applicability::MachineApplicable,
                         );
                     });
                 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
index a6aba33e431..14773789141 100644
--- a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
             e.span,
             "bit mask could be simplified with a call to `trailing_zeros`",
             |diag| {
-                let sugg = Sugg::hir(cx, left1, "...").maybe_par();
+                let sugg = Sugg::hir(cx, left1, "...").maybe_paren();
                 diag.span_suggestion(
                     e.span,
                     "try",
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index 6f302ea1962..9487cec87ef 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -4,8 +4,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_copy;
 use clippy_utils::{
-    CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context,
-    is_res_lang_ctor, peel_blocks, peel_hir_expr_while,
+    CaptureKind, can_move_expr_to_closure, eager_or_lazy, expr_requires_coercion, higher, is_else_clause,
+    is_in_const_context, is_res_lang_ctor, peel_blocks, peel_hir_expr_while,
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -106,7 +106,7 @@ struct OptionOccurrence {
 fn format_option_in_sugg(cond_sugg: Sugg<'_>, as_ref: bool, as_mut: bool) -> String {
     format!(
         "{}{}",
-        cond_sugg.maybe_par(),
+        cond_sugg.maybe_paren(),
         if as_mut {
             ".as_mut()"
         } else if as_ref {
@@ -212,6 +212,15 @@ fn try_get_option_occurrence<'tcx>(
             }
         }
 
+        let some_body_ty = cx.typeck_results().expr_ty(some_body);
+        let none_body_ty = cx.typeck_results().expr_ty(none_body);
+        // Check if coercion is needed for the `None` arm. If so, we cannot suggest because it will
+        // introduce a type mismatch. A special case is when both arms have the same type, then
+        // coercion is fine.
+        if some_body_ty != none_body_ty && expr_requires_coercion(cx, none_body) {
+            return None;
+        }
+
         let mut app = Applicability::Unspecified;
 
         let (none_body, is_argless_call) = match none_body.kind {
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
index 65671b478ba..8eaf65e6306 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
@@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
             items: impl_items,
             ..
         }) = item.kind
-            && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
+            && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
             && let Some(eq_trait) = cx.tcx.lang_items().eq_trait()
             && trait_ref.path.res.def_id() == eq_trait
         {
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
index 6d4216970cc..9b9024c8105 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialeqToNone {
             let sugg = format!(
                 "{}.{}",
                 sugg::Sugg::hir_with_applicability(cx, peel_ref_operators(cx, scrutinee), "..", &mut applicability)
-                    .maybe_par(),
+                    .maybe_paren(),
                 if is_eq { "is_none()" } else { "is_some()" }
             );
 
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 0a8e2885648..5d30b66def2 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -178,19 +178,18 @@ impl PassByRefOrValue {
                         && size <= self.ref_min_size
                         && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind
                     {
-                        if let Some(typeck) = cx.maybe_typeck_results() {
+                        if let Some(typeck) = cx.maybe_typeck_results()
                             // Don't lint if a raw pointer is created.
                             // TODO: Limit the check only to raw pointers to the argument (or part of the argument)
                             //       which escape the current function.
-                            if typeck.node_types().items().any(|(_, &ty)| ty.is_raw_ptr())
+                            && (typeck.node_types().items().any(|(_, &ty)| ty.is_raw_ptr())
                                 || typeck
                                     .adjustments()
                                     .items()
                                     .flat_map(|(_, a)| a)
-                                    .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer)))
-                            {
-                                continue;
-                            }
+                                    .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer))))
+                        {
+                            continue;
                         }
                         let value_type = if fn_body.and_then(|body| body.params.get(index)).is_some_and(is_self) {
                             "self".into()
@@ -282,12 +281,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
                 }
                 let attrs = cx.tcx.hir_attrs(hir_id);
                 for a in attrs {
-                    if let Some(meta_items) = a.meta_item_list() {
-                        if a.has_name(sym::proc_macro_derive)
-                            || (a.has_name(sym::inline) && attr::list_contains_name(&meta_items, sym::always))
-                        {
-                            return;
-                        }
+                    if let Some(meta_items) = a.meta_item_list()
+                        && (a.has_name(sym::proc_macro_derive)
+                            || (a.has_name(sym::inline) && attr::list_contains_name(&meta_items, sym::always)))
+                    {
+                        return;
                     }
                 }
             },
@@ -296,13 +294,13 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
         }
 
         // Exclude non-inherent impls
-        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
-            if matches!(
+        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id)
+            && matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
-            ) {
-                return;
-            }
+            )
+        {
+            return;
         }
 
         self.check_poly_fn(cx, def_id, decl, Some(span));
diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
index b653b459b04..35caac855cf 100644
--- a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
@@ -173,16 +173,15 @@ impl<'tcx> LateLintPass<'tcx> for PathbufThenPush<'tcx> {
     }
 
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if let Some(mut searcher) = self.searcher.take() {
-            if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
-                && let ExprKind::MethodCall(name, self_arg, [arg_expr], _) = expr.kind
-                && path_to_local_id(self_arg, searcher.local_id)
-                && name.ident.as_str() == "push"
-            {
-                searcher.err_span = searcher.err_span.to(stmt.span);
-                searcher.arg = Some(*arg_expr);
-                searcher.display_err(cx);
-            }
+        if let Some(mut searcher) = self.searcher.take()
+            && let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
+            && let ExprKind::MethodCall(name, self_arg, [arg_expr], _) = expr.kind
+            && path_to_local_id(self_arg, searcher.local_id)
+            && name.ident.as_str() == "push"
+        {
+            searcher.err_span = searcher.err_span.to(stmt.span);
+            searcher.arg = Some(*arg_expr);
+            searcher.display_err(cx);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index 96d3f7196c0..19d9acfc930 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -177,17 +177,16 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut
             PatKind::Or([p, ..]) => p,
             _ => p,
         };
-        if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) {
-            if let [first, ..] = **adjustments {
-                if let ty::Ref(.., mutability) = *first.source.kind() {
-                    let level = if p.hir_id == pat.hir_id {
-                        Level::Top
-                    } else {
-                        Level::Lower
-                    };
-                    result = Some((p.span, mutability, level));
-                }
-            }
+        if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id)
+            && let [first, ..] = **adjustments
+            && let ty::Ref(.., mutability) = *first.source.kind()
+        {
+            let level = if p.hir_id == pat.hir_id {
+                Level::Top
+            } else {
+                Level::Lower
+            };
+            result = Some((p.span, mutability, level));
         }
         result.is_none()
     });
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 901a1634ddc..491961408ad 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -264,8 +264,8 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
                 is_null_path(cx, l),
                 is_null_path(cx, r),
             ) {
-                (false, true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(),
-                (false, false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(),
+                (false, true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_paren(),
+                (false, false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_paren(),
                 _ => return check_ptr_eq(cx, expr, op.node, l, r),
             };
 
@@ -498,29 +498,33 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
 }
 
 fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&Body<'tcx>>) {
-    if let FnRetTy::Return(ty) = sig.decl.output
-        && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty)
-    {
+    let FnRetTy::Return(ty) = sig.decl.output else { return };
+    for (out, mutability, out_span) in get_lifetimes(ty) {
+        if mutability != Some(Mutability::Mut) {
+            continue;
+        }
         let out_region = cx.tcx.named_bound_var(out.hir_id);
-        let args: Option<Vec<_>> = sig
+        // `None` if one of the types contains `&'a mut T` or `T<'a>`.
+        // Else, contains all the locations of `&'a T` types.
+        let args_immut_refs: Option<Vec<Span>> = sig
             .decl
             .inputs
             .iter()
-            .filter_map(get_ref_lm)
+            .flat_map(get_lifetimes)
             .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region)
-            .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
+            .map(|(_, mutability, span)| (mutability == Some(Mutability::Not)).then_some(span))
             .collect();
-        if let Some(args) = args
-            && !args.is_empty()
+        if let Some(args_immut_refs) = args_immut_refs
+            && !args_immut_refs.is_empty()
             && body.is_none_or(|body| sig.header.is_unsafe() || contains_unsafe_block(cx, body.value))
         {
             span_lint_and_then(
                 cx,
                 MUT_FROM_REF,
-                ty.span,
+                out_span,
                 "mutable borrow from immutable input(s)",
                 |diag| {
-                    let ms = MultiSpan::from_spans(args);
+                    let ms = MultiSpan::from_spans(args_immut_refs);
                     diag.span_note(ms, "immutable borrow here");
                 },
             );
@@ -686,12 +690,36 @@ fn matches_preds<'tcx>(
         })
 }
 
-fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
-    if let TyKind::Ref(lt, ref m) = ty.kind {
-        Some((lt, m.mutbl, ty.span))
-    } else {
-        None
+struct LifetimeVisitor<'tcx> {
+    result: Vec<(&'tcx Lifetime, Option<Mutability>, Span)>,
+}
+
+impl<'tcx> Visitor<'tcx> for LifetimeVisitor<'tcx> {
+    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
+        if let TyKind::Ref(lt, ref m) = ty.kind {
+            self.result.push((lt, Some(m.mutbl), ty.span));
+        }
+        hir::intravisit::walk_ty(self, ty);
     }
+
+    fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
+        if let GenericArg::Lifetime(lt) = generic_arg {
+            self.result.push((lt, None, generic_arg.span()));
+        }
+        hir::intravisit::walk_generic_arg(self, generic_arg);
+    }
+}
+
+/// Visit `ty` and collect the all the lifetimes appearing in it, implicit or not.
+///
+/// The second field of the vector's elements indicate if the lifetime is attached to a
+/// shared reference, a mutable reference, or neither.
+fn get_lifetimes<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Vec<(&'tcx Lifetime, Option<Mutability>, Span)> {
+    use hir::intravisit::VisitorExt as _;
+
+    let mut visitor = LifetimeVisitor { result: Vec::new() };
+    visitor.visit_ty_unambig(ty);
+    visitor.result
 }
 
 fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
@@ -728,8 +756,9 @@ fn check_ptr_eq<'tcx>(
 
     let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
 
-    if let Some(left_snip) = left_var.span.get_source_text(cx)
-        && let Some(right_snip) = right_var.span.get_source_text(cx)
+    let mut app = Applicability::MachineApplicable;
+    let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
+    let right_snip = Sugg::hir_with_context(cx, right_var, expr.span.ctxt(), "_", &mut app);
     {
         let Some(top_crate) = std_or_core(cx) else { return };
         let invert = if op == BinOpKind::Eq { "" } else { "!" };
@@ -740,7 +769,7 @@ fn check_ptr_eq<'tcx>(
             format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
             "try",
             format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"),
-            Applicability::MachineApplicable,
+            app,
         );
     }
 }
@@ -748,7 +777,8 @@ fn check_ptr_eq<'tcx>(
 // If the given expression is a cast to a usize, return the lhs of the cast
 // E.g., `foo as *const _ as usize` returns `foo as *const _`.
 fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
-    if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
+    if !cast_expr.span.from_expansion()
+        && cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
         && let ExprKind::Cast(expr, _) = cast_expr.kind
     {
         Some(expr)
@@ -759,7 +789,8 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
 
 // Peel raw casts if the remaining expression can be coerced to it
 fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
-    if let ExprKind::Cast(inner, _) = expr.kind
+    if !expr.span.from_expansion()
+        && let ExprKind::Cast(inner, _) = expr.kind
         && let ty::RawPtr(target_ty, _) = expr_ty.kind()
         && let inner_ty = cx.typeck_results().expr_ty(inner)
         && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
index 68ae575c906..7f74a2fff9f 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
@@ -77,10 +77,10 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast {
 
 // If the given expression is a cast from a usize, return the lhs of the cast
 fn expr_as_cast_from_usize<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    if let ExprKind::Cast(cast_lhs_expr, _) = expr.kind {
-        if is_expr_ty_usize(cx, cast_lhs_expr) {
-            return Some(cast_lhs_expr);
-        }
+    if let ExprKind::Cast(cast_lhs_expr, _) = expr.kind
+        && is_expr_ty_usize(cx, cast_lhs_expr)
+    {
+        return Some(cast_lhs_expr);
     }
     None
 }
@@ -91,14 +91,14 @@ fn expr_as_ptr_offset_call<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
-    if let ExprKind::MethodCall(path_segment, arg_0, [arg_1], _) = &expr.kind {
-        if is_expr_ty_raw_ptr(cx, arg_0) {
-            if path_segment.ident.name == sym::offset {
-                return Some((arg_0, arg_1, Method::Offset));
-            }
-            if path_segment.ident.name.as_str() == "wrapping_offset" {
-                return Some((arg_0, arg_1, Method::WrappingOffset));
-            }
+    if let ExprKind::MethodCall(path_segment, arg_0, [arg_1], _) = &expr.kind
+        && is_expr_ty_raw_ptr(cx, arg_0)
+    {
+        if path_segment.ident.name == sym::offset {
+            return Some((arg_0, arg_1, Method::Offset));
+        }
+        if path_segment.ident.name.as_str() == "wrapping_offset" {
+            return Some((arg_0, arg_1, Method::WrappingOffset));
         }
     }
     None
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index a80e1f79bbc..d318897443d 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -5,6 +5,7 @@ use clippy_config::types::MatchLintBehaviour;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{
     eq_expr_value, higher, is_else_clause, is_in_const_context, is_lint_allowed, is_path_lang_item, is_res_lang_ctor,
@@ -144,7 +145,7 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
         && !span_contains_comment(cx.tcx.sess.source_map(), els.span)
     {
         let mut applicability = Applicability::MaybeIncorrect;
-        let init_expr_str = snippet_with_applicability(cx, init_expr.span, "..", &mut applicability);
+        let init_expr_str = Sugg::hir_with_applicability(cx, init_expr, "..", &mut applicability).maybe_paren();
         // Take care when binding is `ref`
         let sugg = if let PatKind::Binding(
             BindingMode(ByRef::Yes(ref_mutability), binding_mutability),
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index cc423eca74f..d292ed86ea4 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -179,10 +179,10 @@ impl_lint_pass!(Ranges => [
 
 impl<'tcx> LateLintPass<'tcx> for Ranges {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref op, l, r) = expr.kind {
-            if self.msrv.meets(cx, msrvs::RANGE_CONTAINS) {
-                check_possible_range_contains(cx, op.node, l, r, expr, expr.span);
-            }
+        if let ExprKind::Binary(ref op, l, r) = expr.kind
+            && self.msrv.meets(cx, msrvs::RANGE_CONTAINS)
+        {
+            check_possible_range_contains(cx, op.node, l, r, expr, expr.span);
         }
 
         check_exclusive_range_plus_one(cx, expr);
@@ -327,18 +327,18 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) ->
                     inc: inclusive,
                 });
             }
-        } else if let Some(id) = path_to_local(r) {
-            if let Some(c) = ConstEvalCtxt::new(cx).eval(l) {
-                return Some(RangeBounds {
-                    val: c,
-                    expr: l,
-                    id,
-                    name_span: r.span,
-                    val_span: l.span,
-                    ord: ordering.reverse(),
-                    inc: inclusive,
-                });
-            }
+        } else if let Some(id) = path_to_local(r)
+            && let Some(c) = ConstEvalCtxt::new(cx).eval(l)
+        {
+            return Some(RangeBounds {
+                val: c,
+                expr: l,
+                id,
+                name_span: r.span,
+                val_span: l.span,
+                ord: ordering.reverse(),
+                inc: inclusive,
+            });
         }
     }
     None
@@ -361,8 +361,8 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
             span,
             "an inclusive range would be more readable",
             |diag| {
-                let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
-                let end = Sugg::hir(cx, y, "y").maybe_par();
+                let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_paren().to_string());
+                let end = Sugg::hir(cx, y, "y").maybe_paren();
                 match span.with_source_text(cx, |src| src.starts_with('(') && src.ends_with(')')) {
                     Some(true) => {
                         diag.span_suggestion(span, "use", format!("({start}..={end})"), Applicability::MaybeIncorrect);
@@ -398,8 +398,8 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
             expr.span,
             "an exclusive range would be more readable",
             |diag| {
-                let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
-                let end = Sugg::hir(cx, y, "y").maybe_par();
+                let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_paren().to_string());
+                let end = Sugg::hir(cx, y, "y").maybe_paren();
                 diag.span_suggestion(
                     expr.span,
                     "use",
diff --git a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
index 6bb7650a7e1..689a2ac4c6a 100644
--- a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
@@ -1,14 +1,14 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::VecArgs;
-use clippy_utils::last_path_segment;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::{indent_of, snippet};
+use clippy_utils::{last_path_segment, sym};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, Symbol, sym};
+use rustc_span::{Span, Symbol};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -135,7 +135,7 @@ fn ref_init(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(Symbol, Span)> {
         if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind()
             && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak))
         {
-            return Some((Symbol::intern("Weak"), func.span));
+            return Some((sym::Weak, func.span));
         }
     }
 
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 8289ec47bc7..d2442ad0f37 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
@@ -1,14 +1,9 @@
-use std::ops::ControlFlow;
-
 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_without_closures;
+use clippy_utils::{desugar_await, peel_blocks};
 use rustc_errors::Applicability;
-use rustc_hir::{
-    Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource,
-};
+use rustc_hir::{Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::UpvarCapture;
 use rustc_session::declare_lint_pass;
@@ -99,20 +94,3 @@ fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Op
         None
     }
 }
-
-/// If `expr` is a desugared `.await`, return the original expression if it does not come from a
-/// macro expansion.
-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_without_closures(into_future_arg, |e| {
-            walk_span_to_context(e.span, ctxt).map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(()))
-        })
-        .is_none()
-    {
-        Some(into_future_arg)
-    } else {
-        None
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index cfa622aea58..e57b8cc2d84 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -109,10 +109,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 continue;
             }
 
-            if let ty::Adt(def, _) = arg_ty.kind() {
-                if def.is_manually_drop() {
-                    continue;
-                }
+            if let ty::Adt(def, _) = arg_ty.kind()
+                && def.is_manually_drop()
+            {
+                continue;
             }
 
             // `{ arg = &cloned; clone(move arg); }` or `{ arg = &cloned; to_path_buf(arg); }`
@@ -182,20 +182,25 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
 
             let clone_usage = if local == ret_local {
                 CloneUsage {
-                    cloned_used: false,
+                    cloned_use_loc: None.into(),
                     cloned_consume_or_mutate_loc: None,
                     clone_consumed_or_mutated: true,
                 }
             } else {
                 let clone_usage = visit_clone_usage(local, ret_local, mir, bb);
-                if clone_usage.cloned_used && clone_usage.clone_consumed_or_mutated {
+                if clone_usage.cloned_use_loc.maybe_used() && clone_usage.clone_consumed_or_mutated {
                     // cloned value is used, and the clone is modified or moved
                     continue;
-                } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc {
+                } else if let MirLocalUsage::Used(loc) = clone_usage.cloned_use_loc
+                    && possible_borrower.local_is_alive_at(ret_local, loc)
+                {
+                    // cloned value is used, and the clone is alive.
+                    continue;
+                } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc
                     // cloned value is mutated, and the clone is alive.
-                    if possible_borrower.local_is_alive_at(ret_local, loc) {
-                        continue;
-                    }
+                    && possible_borrower.local_is_alive_at(ret_local, loc)
+                {
+                    continue;
                 }
                 clone_usage
             };
@@ -216,19 +221,18 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
 
                 let call_snip = &snip[dot + 1..];
                 // Machine applicable when `call_snip` looks like `foobar()`
-                if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) {
-                    if call_snip
+                if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim)
+                    && call_snip
                         .as_bytes()
                         .iter()
                         .all(|b| b.is_ascii_alphabetic() || *b == b'_')
-                    {
-                        app = Applicability::MachineApplicable;
-                    }
+                {
+                    app = Applicability::MachineApplicable;
                 }
 
                 span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| {
                     diag.span_suggestion(sugg_span, "remove this", "", app);
-                    if clone_usage.cloned_used {
+                    if clone_usage.cloned_use_loc.maybe_used() {
                         diag.span_note(span, "cloned value is neither consumed nor mutated");
                     } else {
                         diag.span_note(
@@ -329,10 +333,33 @@ fn base_local_and_movability<'tcx>(
     (place.local, deref || field || slice)
 }
 
-#[derive(Default)]
+#[derive(Debug, Default)]
+enum MirLocalUsage {
+    /// The local maybe used, but we are not sure how.
+    Unknown,
+    /// The local is not used.
+    #[default]
+    Unused,
+    /// The local is used at a specific location.
+    Used(mir::Location),
+}
+
+impl MirLocalUsage {
+    fn maybe_used(&self) -> bool {
+        matches!(self, MirLocalUsage::Unknown | MirLocalUsage::Used(_))
+    }
+}
+
+impl From<Option<mir::Location>> for MirLocalUsage {
+    fn from(loc: Option<mir::Location>) -> Self {
+        loc.map_or(MirLocalUsage::Unused, MirLocalUsage::Used)
+    }
+}
+
+#[derive(Debug, Default)]
 struct CloneUsage {
-    /// Whether the cloned value is used after the clone.
-    cloned_used: bool,
+    /// The first location where the cloned value is used, if any.
+    cloned_use_loc: MirLocalUsage,
     /// The first location where the cloned value is consumed or mutated, if any.
     cloned_consume_or_mutate_loc: Option<mir::Location>,
     /// Whether the clone value is mutated.
@@ -360,7 +387,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
     .map(|mut vec| (vec.remove(0), vec.remove(0)))
     {
         CloneUsage {
-            cloned_used: !cloned_use_locs.is_empty(),
+            cloned_use_loc: cloned_use_locs.first().copied().into(),
             cloned_consume_or_mutate_loc: cloned_consume_or_mutate_locs.first().copied(),
             // Consider non-temporary clones consumed.
             // TODO: Actually check for mutation of non-temporaries.
@@ -369,7 +396,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
         }
     } else {
         CloneUsage {
-            cloned_used: true,
+            cloned_use_loc: MirLocalUsage::Unknown,
             cloned_consume_or_mutate_loc: None,
             clone_consumed_or_mutated: true,
         }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 1498a49a7a4..84597269a58 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
 
                         // avoid clippy::double_parens
                         if !is_in_fn_call_arg {
-                            hint = hint.maybe_par();
+                            hint = hint.maybe_paren();
                         }
 
                         diag.span_suggestion(full_expr.span, "try doing something like", hint, applicability);
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index f2fdac5a8af..7b381fac5f1 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -52,13 +52,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
             && is_not_macro_export(item)
             && !item.span.in_external_macro(cx.sess().source_map())
         {
-            // FIXME: `DUMMY_SP` isn't right here, because it causes the
-            // resulting span to begin at the start of the file.
-            let span = item.span.with_hi(
-                item.kind
-                    .ident()
-                    .map_or(rustc_span::DUMMY_SP.hi(), |ident| ident.span.hi()),
-            );
+            let span = item
+                .kind
+                .ident()
+                .map_or(item.span, |ident| item.span.with_hi(ident.span.hi()));
             let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
             span_lint_and_then(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 7038b19d275..1117dea703c 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -135,25 +135,24 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
                     };
                     diag.span_suggestion(expr.span, help_msg, sugg, app);
                 });
-            } else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
-                if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
+            } else if let Some(target_id) = cx.tcx.lang_items().deref_target()
+                && let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
                     cx.typing_env(),
                     Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
-                ) {
-                    if deref_ty == expr_ty {
-                        let (lint, msg) = DEREF_BY_SLICING_LINT;
-                        span_lint_and_then(cx, lint, expr.span, msg, |diag| {
-                            let mut app = Applicability::MachineApplicable;
-                            let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
-                            let sugg = if needs_parens_for_prefix {
-                                format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
-                            } else {
-                                format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
-                            };
-                            diag.span_suggestion(expr.span, "dereference the original value instead", sugg, app);
-                        });
-                    }
-                }
+                )
+                && deref_ty == expr_ty
+            {
+                let (lint, msg) = DEREF_BY_SLICING_LINT;
+                span_lint_and_then(cx, lint, expr.span, msg, |diag| {
+                    let mut app = Applicability::MachineApplicable;
+                    let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
+                    let sugg = if needs_parens_for_prefix {
+                        format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
+                    } else {
+                        format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
+                    };
+                    diag.span_suggestion(expr.span, "dereference the original value instead", sugg, app);
+                });
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs b/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs
new file mode 100644
index 00000000000..84276e32165
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs
@@ -0,0 +1,161 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_test_function;
+use clippy_utils::visitors::for_each_expr;
+use rustc_errors::Applicability;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{self as hir, Body, ExprKind, FnDecl};
+use rustc_lexer::is_ident;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::def_id::LocalDefId;
+use rustc_span::{Span, Symbol, edition};
+use std::borrow::Cow;
+use std::ops::ControlFlow;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for test functions (functions annotated with `#[test]`) that are prefixed
+    /// with `test_` which is redundant.
+    ///
+    /// ### Why is this bad?
+    /// This is redundant because test functions are already annotated with `#[test]`.
+    /// Moreover, it clutters the output of `cargo test` since test functions are expanded as
+    /// `module::tests::test_use_case` in the output. Without the redundant prefix, the output
+    /// becomes `module::tests::use_case`, which is more readable.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(test)]
+    /// mod tests {
+    ///   use super::*;
+    ///
+    ///   #[test]
+    ///   fn test_use_case() {
+    ///       // test code
+    ///   }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(test)]
+    /// mod tests {
+    ///   use super::*;
+    ///
+    ///   #[test]
+    ///   fn use_case() {
+    ///       // test code
+    ///   }
+    /// }
+    /// ```
+    #[clippy::version = "1.88.0"]
+    pub REDUNDANT_TEST_PREFIX,
+    restriction,
+    "redundant `test_` prefix in test function name"
+}
+
+declare_lint_pass!(RedundantTestPrefix => [REDUNDANT_TEST_PREFIX]);
+
+impl<'tcx> LateLintPass<'tcx> for RedundantTestPrefix {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        kind: FnKind<'_>,
+        _decl: &FnDecl<'_>,
+        body: &'tcx Body<'_>,
+        _span: Span,
+        fn_def_id: LocalDefId,
+    ) {
+        // Ignore methods and closures.
+        let FnKind::ItemFn(ref ident, ..) = kind else {
+            return;
+        };
+
+        // Skip the lint if the function is within a macro expansion.
+        if ident.span.from_expansion() {
+            return;
+        }
+
+        // Skip if the function name does not start with `test_`.
+        if !ident.as_str().starts_with("test_") {
+            return;
+        }
+
+        // If the function is not a test function, skip the lint.
+        if !is_test_function(cx.tcx, fn_def_id) {
+            return;
+        }
+
+        span_lint_and_then(
+            cx,
+            REDUNDANT_TEST_PREFIX,
+            ident.span,
+            "redundant `test_` prefix in test function name",
+            |diag| {
+                let non_prefixed = Symbol::intern(ident.as_str().trim_start_matches("test_"));
+                if is_invalid_ident(non_prefixed) {
+                    // If the prefix-trimmed name is not a valid function name, do not provide an
+                    // automatic fix, just suggest renaming the function.
+                    diag.help(
+                        "consider function renaming (just removing `test_` prefix will produce invalid function name)",
+                    );
+                } else {
+                    let (sugg, msg): (Cow<'_, str>, _) = if name_conflicts(cx, body, non_prefixed) {
+                        // If `non_prefixed` conflicts with another function in the same module/scope,
+                        // do not provide an automatic fix, but still emit a fix suggestion.
+                        (
+                            format!("{non_prefixed}_works").into(),
+                            "consider function renaming (just removing `test_` prefix will cause a name conflict)",
+                        )
+                    } else {
+                        // If `non_prefixed` is a valid identifier and does not conflict with another function,
+                        // so we can suggest an auto-fix.
+                        (non_prefixed.as_str().into(), "consider removing the `test_` prefix")
+                    };
+                    diag.span_suggestion(ident.span, msg, sugg, Applicability::MaybeIncorrect);
+                }
+            },
+        );
+    }
+}
+
+/// Checks whether removal of the `_test` prefix from the function name will cause a name conflict.
+///
+/// There should be no other function with the same name in the same module/scope. Also, there
+/// should not be any function call with the same name within the body of the function, to avoid
+/// recursion.
+fn name_conflicts<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, fn_name: Symbol) -> bool {
+    let tcx = cx.tcx;
+    let id = body.id().hir_id;
+
+    // Iterate over items in the same module/scope
+    let (module, _module_span, _module_hir) = tcx.hir_get_module(tcx.parent_module(id));
+    if module
+        .item_ids
+        .iter()
+        .any(|item| matches!(tcx.hir_item(*item).kind, hir::ItemKind::Fn { ident, .. } if ident.name == fn_name))
+    {
+        // Name conflict found
+        return true;
+    }
+
+    // Also check that within the body of the function there is also no function call
+    // with the same name (since it will result in recursion)
+    for_each_expr(cx, body, |expr| {
+        if let ExprKind::Path(qpath) = &expr.kind
+            && let Some(def_id) = cx.qpath_res(qpath, expr.hir_id).opt_def_id()
+            && let Some(name) = tcx.opt_item_name(def_id)
+            && name == fn_name
+        {
+            // Function call with the same name found
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
+        }
+    })
+    .is_some()
+}
+
+fn is_invalid_ident(ident: Symbol) -> bool {
+    // The identifier is either a reserved keyword, or starts with an invalid sequence.
+    ident.is_reserved(|| edition::LATEST_STABLE_EDITION) || !is_ident(ident.as_str())
+}
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 9443dca154e..834ff2af0e8 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -3,7 +3,7 @@ use std::fmt::Display;
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::source::SpanRangeExt;
-use clippy_utils::{def_path_res_with_base, find_crates, path_def_id, paths};
+use clippy_utils::{def_path_res_with_base, find_crates, path_def_id, paths, sym};
 use rustc_ast::ast::{LitKind, StrStyle};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{BorrowKind, Expr, ExprKind, OwnerId};
@@ -76,7 +76,7 @@ declare_clippy_lint! {
     /// This is documented as an antipattern [on the regex documentation](https://docs.rs/regex/latest/regex/#avoid-re-compiling-regexes-especially-in-a-loop)
     ///
     /// ### Example
-    /// ```no_run
+    /// ```rust,ignore
     /// # let haystacks = [""];
     /// # const MY_REGEX: &str = "a.b";
     /// for haystack in haystacks {
@@ -87,7 +87,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     /// can be replaced with
-    /// ```no_run
+    /// ```rust,ignore
     /// # let haystacks = [""];
     /// # const MY_REGEX: &str = "a.b";
     /// let regex = regex::Regex::new(MY_REGEX).unwrap();
@@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
         //
         // `def_path_res_with_base` will resolve through re-exports but is relatively heavy, so we only
         // perform the operation once and store the results
-        let regex_crates = find_crates(cx.tcx, sym!(regex));
+        let regex_crates = find_crates(cx.tcx, sym::regex);
         let mut resolve = |path: &[&str], kind: RegexKind| {
             for res in def_path_res_with_base(cx.tcx, regex_crates.clone(), &path[1..]) {
                 if let Some(id) = res.opt_def_id() {
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 33815cc3bac..226e8ff6adb 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -3,6 +3,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{HirId, Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::AssocItem;
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 use rustc_span::symbol::Symbol;
@@ -85,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
                                 .associated_items(did)
                                 .in_definition_order()
                                 .filter(|assoc_item| assoc_item.is_fn())
-                                .map(|assoc_item| assoc_item.name())
+                                .map(AssocItem::name)
                                 .collect()
                         } else {
                             BTreeSet::new()
diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs
index 6a0dfde2d9c..a8c6518b592 100644
--- a/src/tools/clippy/clippy_lints/src/serde_api.rs
+++ b/src/tools/clippy/clippy_lints/src/serde_api.rs
@@ -32,28 +32,28 @@ impl<'tcx> LateLintPass<'tcx> for SerdeApi {
         }) = item.kind
         {
             let did = trait_ref.path.res.def_id();
-            if let Some(visit_did) = get_trait_def_id(cx.tcx, &paths::SERDE_DE_VISITOR) {
-                if did == visit_did {
-                    let mut seen_str = None;
-                    let mut seen_string = None;
-                    for item in *items {
-                        match item.ident.as_str() {
-                            "visit_str" => seen_str = Some(item.span),
-                            "visit_string" => seen_string = Some(item.span),
-                            _ => {},
-                        }
-                    }
-                    if let Some(span) = seen_string {
-                        if seen_str.is_none() {
-                            span_lint(
-                                cx,
-                                SERDE_API_MISUSE,
-                                span,
-                                "you should not implement `visit_string` without also implementing `visit_str`",
-                            );
-                        }
+            if let Some(visit_did) = get_trait_def_id(cx.tcx, &paths::SERDE_DE_VISITOR)
+                && did == visit_did
+            {
+                let mut seen_str = None;
+                let mut seen_string = None;
+                for item in *items {
+                    match item.ident.as_str() {
+                        "visit_str" => seen_str = Some(item.span),
+                        "visit_string" => seen_string = Some(item.span),
+                        _ => {},
                     }
                 }
+                if let Some(span) = seen_string
+                    && seen_str.is_none()
+                {
+                    span_lint(
+                        cx,
+                        SERDE_API_MISUSE,
+                        span,
+                        "you should not implement `visit_string` without also implementing `visit_str`",
+                    );
+                }
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs b/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
index 1185d67b125..ff6e6ef214b 100644
--- a/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
+++ b/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
@@ -3,12 +3,12 @@ use std::ops::ControlFlow;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::for_each_expr;
-use clippy_utils::{SpanlessEq, higher, peel_hir_expr_while};
+use clippy_utils::{SpanlessEq, higher, peel_hir_expr_while, sym};
 use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
+use rustc_span::Span;
 use rustc_span::symbol::Symbol;
-use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for SetContainsOrInsert {
                 then: then_expr,
                 ..
             }) = higher::If::hir(expr)
-            && let Some((contains_expr, sym)) = try_parse_op_call(cx, cond_expr, sym!(contains))//try_parse_contains(cx, cond_expr)
+            && let Some((contains_expr, sym)) = try_parse_op_call(cx, cond_expr, sym::contains)//try_parse_contains(cx, cond_expr)
             && let Some(insert_expr) = find_insert_calls(cx, &contains_expr, then_expr)
         {
             span_lint(
@@ -118,7 +118,7 @@ fn find_insert_calls<'tcx>(
     expr: &'tcx Expr<'_>,
 ) -> Option<OpExpr<'tcx>> {
     for_each_expr(cx, expr, |e| {
-        if let Some((insert_expr, _)) = try_parse_op_call(cx, e, sym!(insert))
+        if let Some((insert_expr, _)) = try_parse_op_call(cx, e, sym::insert)
             && SpanlessEq::new(cx).eq_expr(contains_expr.receiver, insert_expr.receiver)
             && SpanlessEq::new(cx).eq_expr(contains_expr.value, insert_expr.value)
         {
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index b82ddedd56c..14399867f31 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -8,7 +8,9 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::hir_id::ItemLocalId;
-use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, LetExpr, Node, Pat, PatKind, QPath, UnOp};
+use rustc_hir::{
+    Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, LetExpr, LocalSource, Node, Pat, PatKind, QPath, UnOp,
+};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::{Span, Symbol};
@@ -65,7 +67,7 @@ declare_clippy_lint! {
     #[clippy::version = "pre 1.29.0"]
     pub SHADOW_REUSE,
     restriction,
-    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
+    "rebinding a name to an expression that reuses the original value, e.g., `let x = x + 1`"
 }
 
 declare_clippy_lint! {
@@ -125,6 +127,17 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
             return;
         }
 
+        // Desugaring of a destructuring assignment may reuse the same identifier internally.
+        // Peel `Pat` and `PatField` nodes and check if we reach a desugared `Let` assignment.
+        if let Some((_, Node::LetStmt(let_stmt))) = cx
+            .tcx
+            .hir_parent_iter(pat.hir_id)
+            .find(|(_, node)| !matches!(node, Node::Pat(_) | Node::PatField(_)))
+            && let LocalSource::AssignDesugar(_) = let_stmt.source
+        {
+            return;
+        }
+
         let HirId { owner, local_id } = id;
         // get (or insert) the list of items for this owner and symbol
         let (ref mut data, scope_owner) = *self.bindings.last_mut().unwrap();
@@ -167,10 +180,10 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
 
 fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool {
     let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id());
-    if let Some(first_scope) = scope_tree.var_scope(first) {
-        if let Some(second_scope) = scope_tree.var_scope(second) {
-            return scope_tree.is_subscope_of(second_scope, first_scope);
-        }
+    if let Some(first_scope) = scope_tree.var_scope(first)
+        && let Some(second_scope) = scope_tree.var_scope(second)
+    {
+        return scope_tree.is_subscope_of(second_scope, first_scope);
     }
 
     false
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 76874cc3420..ccb1209c6fc 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -124,8 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                     diag.span_label(
                         apa.first_block_span,
                         format!(
-                            "temporary `{}` is currently being dropped at the end of its contained scope",
-                            first_bind_ident
+                            "temporary `{first_bind_ident}` is currently being dropped at the end of its contained scope"
                         ),
                     );
                 },
@@ -145,7 +144,10 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
         Self { cx, type_cache }
     }
 
-    fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+    fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>, depth: usize) -> bool {
+        if !self.cx.tcx.recursion_limit().value_within_limit(depth) {
+            return false;
+        }
         let ty = self
             .cx
             .tcx
@@ -157,12 +159,12 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
                 e.insert(false);
             },
         }
-        let value = self.has_sig_drop_attr_uncached(ty);
+        let value = self.has_sig_drop_attr_uncached(ty, depth + 1);
         self.type_cache.insert(ty, value);
         value
     }
 
-    fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
+    fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>, depth: usize) -> bool {
         if let Some(adt) = ty.ty_adt_def() {
             let mut iter = get_attr(
                 self.cx.sess(),
@@ -177,15 +179,15 @@ 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_sig_drop_attr(ty) {
+                    if self.has_sig_drop_attr(ty, depth) {
                         return true;
                     }
                 }
                 for generic_arg in *b {
-                    if let GenericArgKind::Type(ty) = generic_arg.unpack() {
-                        if self.has_sig_drop_attr(ty) {
-                            return true;
-                        }
+                    if let GenericArgKind::Type(ty) = generic_arg.unpack()
+                        && self.has_sig_drop_attr(ty, depth)
+                    {
+                        return true;
                     }
                 }
                 false
@@ -193,7 +195,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
             rustc_middle::ty::Array(ty, _)
             | rustc_middle::ty::RawPtr(ty, _)
             | rustc_middle::ty::Ref(_, ty, _)
-            | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty),
+            | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty, depth),
             _ => false,
         }
     }
@@ -269,7 +271,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
             apa.has_expensive_expr_after_last_attr = false;
         };
         let mut ac = AttrChecker::new(self.cx, self.type_cache);
-        if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
+        if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr), 0) {
             if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
                 && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
                 && !self.ap.apas.contains_key(&hir_id)
@@ -317,7 +319,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
                         }
                     },
                     hir::StmtKind::Semi(semi_expr) => {
-                        if has_drop(semi_expr, &apa.first_bind_ident, self.cx) {
+                        if has_drop(semi_expr, apa.first_bind_ident, self.cx) {
                             apa.has_expensive_expr_after_last_attr = false;
                             apa.last_stmt_span = DUMMY_SP;
                             return;
@@ -414,7 +416,7 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
     }
 }
 
-fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option<Ident>, lcx: &LateContext<'_>) -> bool {
+fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: Option<Ident>, lcx: &LateContext<'_>) -> bool {
     if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind
         && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
         && let Res::Def(DefKind::Fn, did) = fun_path.res
@@ -424,7 +426,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option<Ident>, lcx: &LateCo
             if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind
                 && let [first_arg_ps, ..] = arg_path.segments
                 && let Some(first_bind_ident) = first_bind_ident
-                && &first_arg_ps.ident == first_bind_ident
+                && first_arg_ps.ident == first_bind_ident
             {
                 true
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs
index 50a6ee316c8..8c34da0d14a 100644
--- a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs
+++ b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs
@@ -45,19 +45,20 @@ impl EarlyLintPass for SingleCharLifetimeNames {
             return;
         }
 
-        if let GenericParamKind::Lifetime = param.kind {
-            if !param.is_placeholder && param.ident.as_str().len() <= 2 {
-                #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
-                span_lint_and_then(
-                    ctx,
-                    SINGLE_CHAR_LIFETIME_NAMES,
-                    param.ident.span,
-                    "single-character lifetime names are likely uninformative",
-                    |diag| {
-                        diag.help("use a more informative name");
-                    },
-                );
-            }
+        if let GenericParamKind::Lifetime = param.kind
+            && !param.is_placeholder
+            && param.ident.as_str().len() <= 2
+        {
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
+                ctx,
+                SINGLE_CHAR_LIFETIME_NAMES,
+                param.ident.span,
+                "single-character lifetime names are likely uninformative",
+                |diag| {
+                    diag.help("use a more informative name");
+                },
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 35f80b2acda..62939912304 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -204,17 +204,17 @@ impl SingleComponentPathImports {
                     if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
                         for tree in items {
                             let segments = &tree.0.prefix.segments;
-                            if segments.len() == 1 {
-                                if let UseTreeKind::Simple(None) = tree.0.kind {
-                                    let name = segments[0].ident.name;
-                                    if !macros.contains(&name) {
-                                        single_use_usages.push(SingleUse {
-                                            name,
-                                            span: tree.0.span,
-                                            item_id: item.id,
-                                            can_suggest: false,
-                                        });
-                                    }
+                            if segments.len() == 1
+                                && let UseTreeKind::Simple(None) = tree.0.kind
+                            {
+                                let name = segments[0].ident.name;
+                                if !macros.contains(&name) {
+                                    single_use_usages.push(SingleUse {
+                                        name,
+                                        span: tree.0.span,
+                                        item_id: item.id,
+                                        can_suggest: false,
+                                    });
                                 }
                             }
                         }
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 27c548bed9f..43a3e696105 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{
     SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, method_calls, path_def_id,
-    peel_blocks,
+    peel_blocks, sym,
 };
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
@@ -12,7 +12,6 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::sym;
 
 use std::ops::ControlFlow;
 
@@ -162,13 +161,12 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
                 if is_string(cx, left) {
                     if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
                         let parent = get_parent_expr(cx, e);
-                        if let Some(p) = parent {
-                            if let ExprKind::Assign(target, _, _) = p.kind {
+                        if let Some(p) = parent
+                            && let ExprKind::Assign(target, _, _) = p.kind
                                 // avoid duplicate matches
-                                if SpanlessEq::new(cx).eq_expr(target, left) {
-                                    return;
-                                }
-                            }
+                                && SpanlessEq::new(cx).eq_expr(target, left)
+                        {
+                            return;
                         }
                     }
                     span_lint(
@@ -263,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
             && let ExprKind::AddrOf(BorrowKind::Ref, _, args) = bytes_arg.kind
             && let ExprKind::Index(left, right, _) = args.kind
             && let (method_names, expressions, _) = method_calls(left, 1)
-            && method_names == [sym!(as_bytes)]
+            && method_names == [sym::as_bytes]
             && expressions.len() == 1
             && expressions[0].1.is_empty()
 
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 56bd8fefdb4..83241f97a99 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -59,25 +59,18 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         match expr.kind {
             hir::ExprKind::Binary(op, _, _) => {
-                self.check_expr_inner(cx, expr, op.node, op.span);
-            }
+                check_expr_inner(cx, expr, op.node, op.span);
+            },
             hir::ExprKind::AssignOp(op, _, _) => {
-                self.check_expr_inner(cx, expr, op.node.into(), op.span);
-            }
-            _ => {}
+                check_expr_inner(cx, expr, op.node.into(), op.span);
+            },
+            _ => {},
         }
     }
 }
 
-impl<'tcx> SuspiciousImpl {
-    fn check_expr_inner(
-        &mut self,
-        cx: &LateContext<'tcx>,
-        expr: &'tcx hir::Expr<'_>,
-        binop: hir::BinOpKind,
-        span: Span,
-    ) {
-        if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop)
+fn check_expr_inner<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, binop: hir::BinOpKind, span: Span) {
+    if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop)
             && let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang)
             && let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang)
 
@@ -98,18 +91,17 @@ impl<'tcx> SuspiciousImpl {
                 .iter()
                 .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t)))
             && count_binops(body.value) == 1
-        {
-            span_lint(
-                cx,
-                lint,
-                span,
-                format!(
-                    "suspicious use of `{}` in `{}` impl",
-                    binop.as_str(),
-                    cx.tcx.item_name(trait_id)
-                ),
-            );
-        }
+    {
+        span_lint(
+            cx,
+            lint,
+            span,
+            format!(
+                "suspicious use of `{}` in `{}` impl",
+                binop.as_str(),
+                cx.tcx.item_name(trait_id)
+            ),
+        );
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 0337b74b4b1..e3ecd6508bf 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -133,7 +133,7 @@ fn generate_swap_warning<'tcx>(
                             applicability: &mut applicability,
                         }
                         .snippet_index_bindings(&[idx1, idx2, rhs1, rhs2]),
-                        slice.maybe_par(),
+                        slice.maybe_paren(),
                         snippet_with_context(cx, idx1.span, ctxt, "..", &mut applicability).0,
                         snippet_with_context(cx, idx2.span, ctxt, "..", &mut applicability).0,
                     ),
@@ -269,12 +269,11 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr<
         if let ExprKind::Assign(lhs, rhs, _) = expr.kind {
             return Some((ExprOrIdent::Expr(lhs), rhs));
         }
-    } else if let StmtKind::Let(expr) = stmt.kind {
-        if let Some(rhs) = expr.init {
-            if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind {
-                return Some((ExprOrIdent::Ident(ident_l), rhs));
-            }
-        }
+    } else if let StmtKind::Let(expr) = stmt.kind
+        && let Some(rhs) = expr.init
+        && let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind
+    {
+        return Some((ExprOrIdent::Ident(ident_l), rhs));
     }
     None
 }
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index fa36c9a21f6..8aac3a59102 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -151,20 +151,19 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
                     .iter()
                     .filter_map(get_trait_info_from_bound)
                     .for_each(|(trait_item_res, trait_item_segments, span)| {
-                        if let Some(self_segments) = self_bounds_map.get(&trait_item_res) {
-                            if SpanlessEq::new(cx)
+                        if let Some(self_segments) = self_bounds_map.get(&trait_item_res)
+                            && SpanlessEq::new(cx)
                                 .paths_by_resolution()
                                 .eq_path_segments(self_segments, trait_item_segments)
-                            {
-                                span_lint_and_help(
-                                    cx,
-                                    TRAIT_DUPLICATION_IN_BOUNDS,
-                                    span,
-                                    "this trait bound is already specified in trait declaration",
-                                    None,
-                                    "consider removing this trait bound",
-                                );
-                            }
+                        {
+                            span_lint_and_help(
+                                cx,
+                                TRAIT_DUPLICATION_IN_BOUNDS,
+                                span,
+                                "this trait bound is already specified in trait declaration",
+                                None,
+                                "consider removing this trait bound",
+                            );
                         }
                     });
             }
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index f2c757952af..df2f681a162 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(
                         }
                     }
 
-                    sugg = sugg::Sugg::NonParen(format!("{}.to_bits()", sugg.maybe_par()).into());
+                    sugg = sugg::Sugg::NonParen(format!("{}.to_bits()", sugg.maybe_paren()).into());
 
                     // cast the result of `to_bits` if `to_ty` is signed
                     sugg = if let ty::Int(int_ty) = to_ty.kind() {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
index fcc763763bd..933e25fe98c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
@@ -33,7 +33,7 @@ pub(super) fn check<'tcx>(
                             diag.span_suggestion_verbose(
                                 e.span,
                                 "use `pointer::cast` instead",
-                                format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_par()),
+                                format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_paren()),
                                 Applicability::MaybeIncorrect,
                             );
                         } else if from_pointee_ty == to_pointee_ty
@@ -48,7 +48,7 @@ pub(super) fn check<'tcx>(
                             diag.span_suggestion_verbose(
                                 e.span,
                                 format!("use `pointer::{method}` instead"),
-                                format!("{}.{method}()", arg.maybe_par()),
+                                format!("{}.{method}()", arg.maybe_paren()),
                                 Applicability::MaybeIncorrect,
                             );
                         } else {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index 45ee83c78ab..e58212fae15 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(
                     let sugg = if let Some(ty) = get_explicit_type(path) {
                         let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app);
                         if msrv.meets(cx, msrvs::POINTER_CAST) {
-                            format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par())
+                            format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_paren())
                         } else if from_ptr_ty.has_erased_regions() {
                             sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string()
                         } else {
@@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(
                     } else if *from_ptr_ty == *to_ref_ty {
                         if from_ptr_ty.has_erased_regions() {
                             if msrv.meets(cx, msrvs::POINTER_CAST) {
-                                format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par())
+                                format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_paren())
                             } else {
                                 sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}")))
                                     .to_string()
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index b6f4c4d7f0a..3147058b4cd 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -591,26 +591,26 @@ impl Types {
             TyKind::Path(ref qpath) if !context.in_body => {
                 let hir_id = hir_ty.hir_id;
                 let res = cx.qpath_res(qpath, hir_id);
-                if let Some(def_id) = res.opt_def_id() {
-                    if self.is_type_change_allowed(context) {
-                        // All lints that are being checked in this block are guarded by
-                        // the `avoid_breaking_exported_api` configuration. When adding a
-                        // new lint, please also add the name to the configuration documentation
-                        // in `clippy_config::conf`
-
-                        let mut triggered = false;
-                        triggered |= box_collection::check(cx, hir_ty, qpath, def_id);
-                        triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id);
-                        triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id);
-                        triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
-                        triggered |= option_option::check(cx, hir_ty, qpath, def_id);
-                        triggered |= linked_list::check(cx, hir_ty, def_id);
-                        triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
-                        triggered |= owned_cow::check(cx, qpath, def_id);
-
-                        if triggered {
-                            return;
-                        }
+                if let Some(def_id) = res.opt_def_id()
+                    && self.is_type_change_allowed(context)
+                {
+                    // All lints that are being checked in this block are guarded by
+                    // the `avoid_breaking_exported_api` configuration. When adding a
+                    // new lint, please also add the name to the configuration documentation
+                    // in `clippy_config::conf`
+
+                    let mut triggered = false;
+                    triggered |= box_collection::check(cx, hir_ty, qpath, def_id);
+                    triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id);
+                    triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id);
+                    triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
+                    triggered |= option_option::check(cx, hir_ty, qpath, def_id);
+                    triggered |= linked_list::check(cx, hir_ty, def_id);
+                    triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
+                    triggered |= owned_cow::check(cx, qpath, def_id);
+
+                    if triggered {
+                        return;
                     }
                 }
                 match *qpath {
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 0c17cc5d8f6..d321c48f6af 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -23,8 +23,8 @@ declare_clippy_lint! {
     /// implementations.
     ///
     /// ### Why is this bad?
-    /// This is a hard to find infinite recursion that will crash any code
-    /// using it.
+    /// Infinite recursion in trait implementation will either cause crashes
+    /// or result in an infinite loop, and it is hard to detect.
     ///
     /// ### Example
     /// ```no_run
@@ -39,9 +39,31 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
+    ///
     /// Use instead:
     ///
-    /// In such cases, either use `#[derive(PartialEq)]` or don't implement it.
+    /// ```no_run
+    /// #[derive(PartialEq)]
+    /// enum Foo {
+    ///     A,
+    ///     B,
+    /// }
+    /// ```
+    ///
+    /// As an alternative, rewrite the logic without recursion:
+    ///
+    /// ```no_run
+    /// enum Foo {
+    ///     A,
+    ///     B,
+    /// }
+    ///
+    /// impl PartialEq for Foo {
+    ///     fn eq(&self, other: &Self) -> bool {
+    ///         matches!((self, other), (Foo::A, Foo::A) | (Foo::B, Foo::B))
+    ///     }
+    /// }
+    /// ```
     #[clippy::version = "1.77.0"]
     pub UNCONDITIONAL_RECURSION,
     suspicious,
@@ -113,7 +135,7 @@ fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Opt
         }),
     )) = cx.tcx.hir_parent_iter(hir_id).next()
         // We exclude `impl` blocks generated from rustc's proc macros.
-        && !cx.tcx.has_attr(*owner_id, sym::automatically_derived)
+        && !cx.tcx.is_automatically_derived(owner_id.to_def_id())
         // It is a implementation of a trait.
         && let Some(trait_) = impl_.of_trait
     {
@@ -218,7 +240,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local
             }),
         )) = cx.tcx.hir_parent_iter(hir_id).next()
         // We exclude `impl` blocks generated from rustc's proc macros.
-        && !cx.tcx.has_attr(*owner_id, sym::automatically_derived)
+        && !cx.tcx.is_automatically_derived(owner_id.to_def_id())
         // It is a implementation of a trait.
         && let Some(trait_) = impl_.of_trait
         && let Some(trait_def_id) = trait_.trait_def_id()
@@ -315,7 +337,7 @@ impl UnconditionalRecursion {
             for (ty, impl_def_ids) in impls.non_blanket_impls() {
                 let Some(self_def_id) = ty.def() else { continue };
                 for impl_def_id in impl_def_ids {
-                    if !cx.tcx.has_attr(*impl_def_id, sym::automatically_derived) &&
+                    if !cx.tcx.is_automatically_derived(*impl_def_id) &&
                         let Some(assoc_item) = cx
                             .tcx
                             .associated_items(impl_def_id)
diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs
index e1fc644e4ce..79571b0409d 100644
--- a/src/tools/clippy/clippy_lints/src/unicode.rs
+++ b/src/tools/clippy/clippy_lints/src/unicode.rs
@@ -76,10 +76,10 @@ declare_lint_pass!(Unicode => [INVISIBLE_CHARACTERS, NON_ASCII_LITERAL, UNICODE_
 
 impl LateLintPass<'_> for Unicode {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
-        if let ExprKind::Lit(lit) = expr.kind {
-            if let LitKind::Str(_, _) | LitKind::Char(_) = lit.node {
-                check_str(cx, lit.span, expr.hir_id);
-            }
+        if let ExprKind::Lit(lit) = expr.kind
+            && let LitKind::Str(_, _) | LitKind::Char(_) = lit.node
+        {
+            check_str(cx, lit.span, expr.hir_id);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 937e35dea96..bcd05cceca9 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -93,13 +93,13 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
 
         // Abort if the method is implementing a trait or of it a trait method.
         let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
-        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
-            if matches!(
+        if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id)
+            && matches!(
                 item.kind,
                 ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
-            ) {
-                return;
-            }
+            )
+        {
+            return;
         }
 
         // Get the wrapper and inner types, if can't, abort.
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 8966e6851ac..9ad184450de 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -69,10 +69,10 @@ impl EarlyLintPass for UnnestedOrPatterns {
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
-        if self.msrv.meets(msrvs::OR_PATTERNS) {
-            if let ast::ExprKind::Let(pat, _, _, _) = &e.kind {
-                lint_unnested_or_patterns(cx, pat);
-            }
+        if self.msrv.meets(msrvs::OR_PATTERNS)
+            && let ast::ExprKind::Let(pat, _, _, _) = &e.kind
+        {
+            lint_unnested_or_patterns(cx, pat);
         }
     }
 
@@ -120,18 +120,25 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
 
 /// Remove all `(p)` patterns in `pat`.
 fn remove_all_parens(pat: &mut P<Pat>) {
-    struct Visitor;
+    #[derive(Default)]
+    struct Visitor {
+        /// If is not in the outer most pattern. This is needed to avoid removing the outermost
+        /// parens because top-level or-patterns are not allowed in let statements.
+        is_inner: bool,
+    }
+
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut P<Pat>) {
+            let is_inner = mem::replace(&mut self.is_inner, true);
             walk_pat(self, pat);
             let inner = match &mut pat.kind {
-                Paren(i) => mem::replace(&mut i.kind, Wild),
+                Paren(i) if is_inner => mem::replace(&mut i.kind, Wild),
                 _ => return,
             };
             pat.kind = inner;
         }
     }
-    Visitor.visit_pat(pat);
+    Visitor::default().visit_pat(pat);
 }
 
 /// Insert parens where necessary according to Rust's precedence rules for patterns.
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index 0687fc319af..2d88c490b1a 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -265,15 +265,14 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
 /// If `expr` is an (e).await, return the inner expression "e" that's being
 /// waited on.  Otherwise return None.
 fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
-    if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
-        if let ExprKind::Call(func, [arg_0]) = expr.kind {
-            if matches!(
-                func.kind,
-                ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
-            ) {
-                return arg_0;
-            }
-        }
+    if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind
+        && let ExprKind::Call(func, [arg_0]) = expr.kind
+        && matches!(
+            func.kind,
+            ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
+        )
+    {
+        return arg_0;
     }
     expr
 }
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index b466a8e127a..ce82b56eb94 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::is_potentially_local_place;
-use clippy_utils::{higher, path_to_local};
+use clippy_utils::{higher, path_to_local, sym};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
@@ -11,8 +11,8 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::declare_lint_pass;
+use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -307,8 +307,8 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
             if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind
                 && let (self_arg, as_ref_kind) = consume_option_as_ref(self_arg)
                 && let Some(id) = path_to_local(self_arg)
-                && [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name)
-                && let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name)
+                && matches!(method_name.ident.name, sym::unwrap | sym::expect | sym::unwrap_err)
+                && let call_to_unwrap = matches!(method_name.ident.name, sym::unwrap | sym::expect)
                 && let Some(unwrappable) = self.unwrappables.iter()
                     .find(|u| u.local_id == id)
                 // Span contexts should not differ with the conditional branch
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 57bb2fc27f1..3a9c997a579 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -92,36 +92,36 @@ fn into_iter_bound<'tcx>(
     let mut into_iter_span = None;
 
     for (pred, span) in cx.tcx.explicit_predicates_of(fn_did).predicates {
-        if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() {
-            if tr.self_ty().is_param(param_index) {
-                if tr.def_id() == into_iter_did {
-                    into_iter_span = Some(*span);
-                } else {
-                    let tr = cx.tcx.erase_regions(tr);
-                    if tr.has_escaping_bound_vars() {
-                        return None;
-                    }
-
-                    // Substitute generics in the predicate and replace the IntoIterator type parameter with the
-                    // `.into_iter()` receiver to see if the bound also holds for that type.
-                    let args = cx.tcx.mk_args_from_iter(node_args.iter().enumerate().map(|(i, arg)| {
-                        if i == param_index as usize {
-                            GenericArg::from(into_iter_receiver)
-                        } else {
-                            arg
-                        }
-                    }));
+        if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder()
+            && tr.self_ty().is_param(param_index)
+        {
+            if tr.def_id() == into_iter_did {
+                into_iter_span = Some(*span);
+            } else {
+                let tr = cx.tcx.erase_regions(tr);
+                if tr.has_escaping_bound_vars() {
+                    return None;
+                }
 
-                    let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args);
-                    let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
-                    if !cx
-                        .tcx
-                        .infer_ctxt()
-                        .build(cx.typing_mode())
-                        .predicate_must_hold_modulo_regions(&obligation)
-                    {
-                        return None;
+                // Substitute generics in the predicate and replace the IntoIterator type parameter with the
+                // `.into_iter()` receiver to see if the bound also holds for that type.
+                let args = cx.tcx.mk_args_from_iter(node_args.iter().enumerate().map(|(i, arg)| {
+                    if i == param_index as usize {
+                        GenericArg::from(into_iter_receiver)
+                    } else {
+                        arg
                     }
+                }));
+
+                let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args);
+                let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
+                if !cx
+                    .tcx
+                    .infer_ctxt()
+                    .build(cx.typing_mode())
+                    .predicate_must_hold_modulo_regions(&obligation)
+                {
+                    return None;
                 }
             }
         }
@@ -356,7 +356,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
 
                     if cx.tcx.is_diagnostic_item(sym::from_fn, def_id) && same_type_and_consts(a, b) {
                         let mut app = Applicability::MachineApplicable;
-                        let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "<expr>", &mut app).maybe_par();
+                        let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "<expr>", &mut app).maybe_paren();
                         let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
                         span_lint_and_sugg(
                             cx,
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
deleted file mode 100644
index deb983b6971..00000000000
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-pub mod almost_standard_lint_formulation;
-pub mod collapsible_calls;
-pub mod interning_defined_symbol;
-pub mod invalid_paths;
-pub mod lint_without_lint_pass;
-pub mod msrv_attr_impl;
-pub mod outer_expn_data_pass;
-pub mod produce_ice;
-pub mod slow_symbol_comparisons;
-pub mod unnecessary_def_path;
-pub mod unsorted_clippy_utils_paths;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
deleted file mode 100644
index e454427adde..00000000000
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ /dev/null
@@ -1,241 +0,0 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant};
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
-use clippy_utils::ty::match_type;
-use clippy_utils::{def_path_def_ids, is_expn_of, match_def_path, paths};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::Applicability;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
-use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::ConstValue;
-use rustc_middle::ty;
-use rustc_session::impl_lint_pass;
-use rustc_span::sym;
-use rustc_span::symbol::Symbol;
-
-use std::borrow::Cow;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for interning symbols that have already been pre-interned and defined as constants.
-    ///
-    /// ### Why is this bad?
-    /// It's faster and easier to use the symbol constant.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// let _ = sym!(f32);
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust,ignore
-    /// let _ = sym::f32;
-    /// ```
-    pub INTERNING_DEFINED_SYMBOL,
-    internal,
-    "interning a symbol that is pre-interned and defined as a constant"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for unnecessary conversion from Symbol to a string.
-    ///
-    /// ### Why is this bad?
-    /// It's faster use symbols directly instead of strings.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// symbol.as_str() == "clippy";
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust,ignore
-    /// symbol == sym::clippy;
-    /// ```
-    pub UNNECESSARY_SYMBOL_STR,
-    internal,
-    "unnecessary conversion between Symbol and string"
-}
-
-#[derive(Default)]
-pub struct InterningDefinedSymbol {
-    // Maps the symbol value to the constant DefId.
-    symbol_map: FxHashMap<u32, DefId>,
-}
-
-impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL, UNNECESSARY_SYMBOL_STR]);
-
-impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
-    fn check_crate(&mut self, cx: &LateContext<'_>) {
-        if !self.symbol_map.is_empty() {
-            return;
-        }
-
-        for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
-            for def_id in def_path_def_ids(cx.tcx, module) {
-                for item in cx.tcx.module_children(def_id) {
-                    if let Res::Def(DefKind::Const, item_def_id) = item.res
-                        && let ty = cx.tcx.type_of(item_def_id).instantiate_identity()
-                        && match_type(cx, ty, &paths::SYMBOL)
-                        && let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id)
-                        && let Some(value) = value.to_u32().discard_err()
-                    {
-                        self.symbol_map.insert(value, item_def_id);
-                    }
-                }
-            }
-        }
-    }
-
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Call(func, [arg]) = &expr.kind
-            && let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
-            && cx.tcx.is_diagnostic_item(sym::SymbolIntern, *def_id)
-            && let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg)
-            && let value = Symbol::intern(&arg).as_u32()
-            && let Some(&def_id) = self.symbol_map.get(&value)
-        {
-            span_lint_and_sugg(
-                cx,
-                INTERNING_DEFINED_SYMBOL,
-                is_expn_of(expr.span, "sym").unwrap_or(expr.span),
-                "interning a defined symbol",
-                "try",
-                cx.tcx.def_path_str(def_id),
-                Applicability::MachineApplicable,
-            );
-        }
-        if let ExprKind::Binary(op, left, right) = expr.kind {
-            if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) {
-                let data = [
-                    (left, self.symbol_str_expr(left, cx)),
-                    (right, self.symbol_str_expr(right, cx)),
-                ];
-                match data {
-                    // both operands are a symbol string
-                    [(_, Some(left)), (_, Some(right))] => {
-                        span_lint_and_sugg(
-                            cx,
-                            UNNECESSARY_SYMBOL_STR,
-                            expr.span,
-                            "unnecessary `Symbol` to string conversion",
-                            "try",
-                            format!(
-                                "{} {} {}",
-                                left.as_symbol_snippet(cx),
-                                op.node.as_str(),
-                                right.as_symbol_snippet(cx),
-                            ),
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                    // one of the operands is a symbol string
-                    [(expr, Some(symbol)), _] | [_, (expr, Some(symbol))] => {
-                        // creating an owned string for comparison
-                        if matches!(symbol, SymbolStrExpr::Expr { is_to_owned: true, .. }) {
-                            span_lint_and_sugg(
-                                cx,
-                                UNNECESSARY_SYMBOL_STR,
-                                expr.span,
-                                "unnecessary string allocation",
-                                "try",
-                                format!("{}.as_str()", symbol.as_symbol_snippet(cx)),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    },
-                    // nothing found
-                    [(_, None), (_, None)] => {},
-                }
-            }
-        }
-    }
-}
-
-impl InterningDefinedSymbol {
-    fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option<SymbolStrExpr<'tcx>> {
-        static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR];
-        static SYMBOL_STR_PATHS: &[&[&str]] = &[&paths::SYMBOL_AS_STR, &paths::SYMBOL_TO_IDENT_STRING];
-        let call = if let ExprKind::AddrOf(_, _, e) = expr.kind
-            && let ExprKind::Unary(UnOp::Deref, e) = e.kind
-        {
-            e
-        } else {
-            expr
-        };
-        if let ExprKind::MethodCall(_, item, [], _) = call.kind
-            // is a method call
-            && let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id)
-            && let ty = cx.typeck_results().expr_ty(item)
-            // ...on either an Ident or a Symbol
-            && let Some(is_ident) = if match_type(cx, ty, &paths::SYMBOL) {
-                Some(false)
-            } else if match_type(cx, ty, &paths::IDENT) {
-                Some(true)
-            } else {
-                None
-            }
-            // ...which converts it to a string
-            && let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS }
-            && let Some(is_to_owned) = paths
-                .iter()
-                .find_map(|path| if match_def_path(cx, did, path) {
-                    Some(path == &paths::SYMBOL_TO_IDENT_STRING)
-                } else {
-                    None
-                })
-                .or_else(|| if cx.tcx.is_diagnostic_item(sym::to_string_method, did) {
-                    Some(true)
-                } else {
-                    None
-                })
-        {
-            return Some(SymbolStrExpr::Expr {
-                item,
-                is_ident,
-                is_to_owned,
-            });
-        }
-        // is a string constant
-        if let Some(Constant::Str(s)) = ConstEvalCtxt::new(cx).eval_simple(expr) {
-            let value = Symbol::intern(&s).as_u32();
-            // ...which matches a symbol constant
-            if let Some(&def_id) = self.symbol_map.get(&value) {
-                return Some(SymbolStrExpr::Const(def_id));
-            }
-        }
-        None
-    }
-}
-
-enum SymbolStrExpr<'tcx> {
-    /// a string constant with a corresponding symbol constant
-    Const(DefId),
-    /// a "symbol to string" expression like `symbol.as_str()`
-    Expr {
-        /// part that evaluates to `Symbol` or `Ident`
-        item: &'tcx Expr<'tcx>,
-        is_ident: bool,
-        /// whether an owned `String` is created like `to_ident_string()`
-        is_to_owned: bool,
-    },
-}
-
-impl<'tcx> SymbolStrExpr<'tcx> {
-    /// Returns a snippet that evaluates to a `Symbol` and is const if possible
-    fn as_symbol_snippet(&self, cx: &LateContext<'_>) -> Cow<'tcx, str> {
-        match *self {
-            Self::Const(def_id) => cx.tcx.def_path_str(def_id).into(),
-            Self::Expr { item, is_ident, .. } => {
-                let mut snip = snippet(cx, item.span.source_callsite(), "..");
-                if is_ident {
-                    // get `Ident.name`
-                    snip.to_mut().push_str(".name");
-                }
-                snip
-            },
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs
deleted file mode 100644
index b8bcb9b3756..00000000000
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant};
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::paths;
-use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::match_type;
-use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
-use rustc_span::{Span, sym};
-
-declare_clippy_lint! {
-    /// ### What it does
-    ///
-    /// Detects symbol comparison using `Symbol::intern`.
-    ///
-    /// ### Why is this bad?
-    ///
-    /// Comparison via `Symbol::as_str()` is faster if the interned symbols are not reused.
-    ///
-    /// ### Example
-    ///
-    /// None, see suggestion.
-    pub SLOW_SYMBOL_COMPARISONS,
-    internal,
-    "detects slow comparisons of symbol"
-}
-
-declare_lint_pass!(SlowSymbolComparisons => [SLOW_SYMBOL_COMPARISONS]);
-
-fn check_slow_comparison<'tcx>(
-    cx: &LateContext<'tcx>,
-    op1: &'tcx Expr<'tcx>,
-    op2: &'tcx Expr<'tcx>,
-) -> Option<(Span, String)> {
-    if match_type(cx, cx.typeck_results().expr_ty(op1), &paths::SYMBOL)
-        && let ExprKind::Call(fun, args) = op2.kind
-        && let ExprKind::Path(ref qpath) = fun.kind
-        && cx
-            .tcx
-            .is_diagnostic_item(sym::SymbolIntern, cx.qpath_res(qpath, fun.hir_id).opt_def_id()?)
-        && let [symbol_name_expr] = args
-        && let Some(Constant::Str(symbol_name)) = ConstEvalCtxt::new(cx).eval_simple(symbol_name_expr)
-    {
-        Some((op1.span, symbol_name))
-    } else {
-        None
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for SlowSymbolComparisons {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-        if let ExprKind::Binary(op, left, right) = expr.kind
-            && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne)
-            && let Some((symbol_span, symbol_name)) =
-                check_slow_comparison(cx, left, right).or_else(|| check_slow_comparison(cx, right, left))
-        {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                SLOW_SYMBOL_COMPARISONS,
-                expr.span,
-                "comparing `Symbol` via `Symbol::intern`",
-                "use `Symbol::as_str` and check the string instead",
-                format!(
-                    "{}.as_str() {} \"{symbol_name}\"",
-                    snippet_with_applicability(cx, symbol_span, "symbol", &mut applicability),
-                    op.node.as_str()
-                ),
-                applicability,
-            );
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs
deleted file mode 100644
index a5c4bf474f7..00000000000
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use rustc_ast::ast::{Crate, ItemKind, ModKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::declare_lint_pass;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks that [`clippy_utils::paths`] is sorted lexically
-    ///
-    /// ### Why is this bad?
-    /// We like to pretend we're an example of tidy code.
-    ///
-    /// ### Example
-    /// Wrong ordering of the util::paths constants.
-    pub UNSORTED_CLIPPY_UTILS_PATHS,
-    internal,
-    "various things that will negatively affect your clippy experience"
-}
-
-declare_lint_pass!(UnsortedClippyUtilsPaths => [UNSORTED_CLIPPY_UTILS_PATHS]);
-
-impl EarlyLintPass for UnsortedClippyUtilsPaths {
-    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
-        if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") {
-            if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind {
-                if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") {
-                    if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = paths.kind {
-                        let mut last_name: Option<&str> = None;
-                        for item in items {
-                            let name = item.ident.as_str();
-                            if let Some(last_name) = last_name {
-                                if *last_name > *name {
-                                    span_lint(
-                                        cx,
-                                        UNSORTED_CLIPPY_UTILS_PATHS,
-                                        item.span,
-                                        "this constant should be before the previous constant due to lexical \
-                                         ordering",
-                                    );
-                                }
-                            }
-                            last_name = Some(name);
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 4476cd1005e..16066dd96c0 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -2,6 +2,3 @@ pub mod attr_collector;
 pub mod author;
 pub mod dump_hir;
 pub mod format_args_collector;
-
-#[cfg(feature = "internal")]
-pub mod internal_lints;
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 405310512df..5b3f60ad6ab 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -68,6 +68,8 @@ declare_clippy_lint! {
     /// (including the standard library) provide modules named "prelude" specifically designed
     /// for wildcard import.
     ///
+    /// Wildcard imports reexported through `pub use` are also allowed.
+    ///
     /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name.
     ///
     /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag.
@@ -121,7 +123,9 @@ impl LateLintPass<'_> for WildcardImports {
         }
 
         let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id);
-        if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
+        if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id())
+            && !self.warn_on_all
+        {
             return;
         }
         if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index f6948be7f67..a97643e0eac 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -74,10 +74,10 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
 fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     let parent_id = cx.tcx.hir_get_parent_item(hir_id);
     let second_parent_id = cx.tcx.hir_get_parent_item(parent_id.into()).def_id;
-    if let Node::Item(item) = cx.tcx.hir_node_by_def_id(second_parent_id) {
-        if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
-            return true;
-        }
+    if let Node::Item(item) = cx.tcx.hir_node_by_def_id(second_parent_id)
+        && let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind
+    {
+        return true;
     }
     false
 }
diff --git a/src/tools/clippy/clippy_lints/src/zombie_processes.rs b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
index 7667db46968..39c1aab8967 100644
--- a/src/tools/clippy/clippy_lints/src/zombie_processes.rs
+++ b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
@@ -131,7 +131,7 @@ struct WaitFinder<'a, 'tcx> {
     local_id: HirId,
     state: VisitorState,
     early_return: Option<Span>,
-    // When joining two if branches where one of them doesn't call `wait()`, stores its span for more targetted help
+    // When joining two if branches where one of them doesn't call `wait()`, stores its span for more targeted help
     // messages
     missing_wait_branch: Option<MissingWaitBranch>,
 }
diff --git a/src/tools/clippy/clippy_lints_internal/Cargo.toml b/src/tools/clippy/clippy_lints_internal/Cargo.toml
new file mode 100644
index 00000000000..2a0ceac27a3
--- /dev/null
+++ b/src/tools/clippy/clippy_lints_internal/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "clippy_lints_internal"
+version = "0.0.1"
+edition = "2021"
+
+[dependencies]
+clippy_config = { path = "../clippy_config" }
+clippy_utils = { path = "../clippy_utils" }
+regex = { version = "1.5" }
+rustc-semver = "1.1"
+
+[package.metadata.rust-analyzer]
+# This crate uses #[feature(rustc_private)]
+rustc_private = true
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs
index 0a01a364a75..4fd5ea459a5 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs
@@ -1,11 +1,12 @@
-use crate::utils::internal_lints::lint_without_lint_pass::is_lint_ref_type;
+use crate::lint_without_lint_pass::is_lint_ref_type;
 use clippy_utils::diagnostics::span_lint_and_help;
 use regex::Regex;
 use rustc_hir::{Attribute, Item, ItemKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_session::impl_lint_pass;
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks if lint formulations have a standardized format.
     ///
@@ -14,9 +15,10 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// `Checks for use...` can be written as `Checks for usage...` .
-    pub ALMOST_STANDARD_LINT_FORMULATION,
-    internal,
-    "lint formulations must have a standardized format."
+    pub clippy::ALMOST_STANDARD_LINT_FORMULATION,
+    Warn,
+    "lint formulations must have a standardized format.",
+    report_in_external_macro: true
 }
 
 impl_lint_pass!(AlmostStandardFormulation => [ALMOST_STANDARD_LINT_FORMULATION]);
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/src/tools/clippy/clippy_lints_internal/src/collapsible_calls.rs
index 2e6fb7c4ce4..d7967a0cc02 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/collapsible_calls.rs
@@ -4,12 +4,13 @@ use clippy_utils::{SpanlessEq, is_expr_path_def_path, is_lint_allowed, peel_bloc
 use rustc_errors::Applicability;
 use rustc_hir::{Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
 use std::borrow::{Borrow, Cow};
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Lints `span_lint_and_then` function calls, where the
     /// closure argument has only one statement and that statement is a method
@@ -64,9 +65,10 @@ declare_clippy_lint! {
     /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg);
     /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg);
     /// ```
-    pub COLLAPSIBLE_SPAN_LINT_CALLS,
-    internal,
-    "found collapsible `span_lint_and_then` calls"
+    pub clippy::COLLAPSIBLE_SPAN_LINT_CALLS,
+    Warn,
+    "found collapsible `span_lint_and_then` calls",
+    report_in_external_macro: true
 }
 
 declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
diff --git a/src/tools/clippy/clippy_lints_internal/src/interning_literals.rs b/src/tools/clippy/clippy_lints_internal/src/interning_literals.rs
new file mode 100644
index 00000000000..6cee3744234
--- /dev/null
+++ b/src/tools/clippy/clippy_lints_internal/src/interning_literals.rs
@@ -0,0 +1,102 @@
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::match_type;
+use clippy_utils::{def_path_def_ids, paths};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
+use rustc_middle::mir::ConstValue;
+use rustc_middle::ty;
+use rustc_session::impl_lint_pass;
+use rustc_span::sym;
+use rustc_span::symbol::Symbol;
+
+declare_tool_lint! {
+    /// ### What it does
+    /// Checks for interning string literals as symbols
+    ///
+    /// ### Why is this bad?
+    /// It's faster and easier to use the symbol constant. If one doesn't exist it can be added to `clippy_utils/src/sym.rs`
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// let _ = Symbol::intern("f32");
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust,ignore
+    /// let _ = sym::f32;
+    /// ```
+    pub clippy::INTERNING_LITERALS,
+    Warn,
+    "interning a symbol that is a literal",
+    report_in_external_macro: true
+}
+
+#[derive(Default)]
+pub struct InterningDefinedSymbol {
+    // Maps the symbol to the import path
+    symbol_map: FxHashMap<u32, (&'static str, Symbol)>,
+}
+
+impl_lint_pass!(InterningDefinedSymbol => [INTERNING_LITERALS]);
+
+impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
+    fn check_crate(&mut self, cx: &LateContext<'_>) {
+        let modules = [
+            ("kw", &paths::KW_MODULE[..]),
+            ("sym", &paths::SYM_MODULE),
+            ("sym", &paths::CLIPPY_SYM_MODULE),
+        ];
+        for (prefix, module) in modules {
+            for def_id in def_path_def_ids(cx.tcx, module) {
+                // When linting `clippy_utils` itself we can't use `module_children` as it's a local def id. It will
+                // still lint but the suggestion will say to add it to `sym.rs` even if it's already there
+                if def_id.is_local() {
+                    continue;
+                }
+
+                for item in cx.tcx.module_children(def_id) {
+                    if let Res::Def(DefKind::Const, item_def_id) = item.res
+                        && let ty = cx.tcx.type_of(item_def_id).instantiate_identity()
+                        && match_type(cx, ty, &paths::SYMBOL)
+                        && let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id)
+                        && let Some(value) = value.to_u32().discard_err()
+                    {
+                        self.symbol_map.insert(value, (prefix, item.ident.name));
+                    }
+                }
+            }
+        }
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if let ExprKind::Call(func, [arg]) = &expr.kind
+            && let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
+            && cx.tcx.is_diagnostic_item(sym::SymbolIntern, *def_id)
+            && let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg)
+        {
+            span_lint_and_then(
+                cx,
+                INTERNING_LITERALS,
+                expr.span,
+                "interning a string literal",
+                |diag| {
+                    let value = Symbol::intern(&arg).as_u32();
+                    let (message, path) = if let Some((prefix, name)) = self.symbol_map.get(&value) {
+                        ("use the preinterned symbol", format!("{prefix}::{name}"))
+                    } else {
+                        (
+                            "add the symbol to `clippy_utils/src/sym.rs` and use it",
+                            format!("sym::{}", arg.replace(|ch: char| !ch.is_alphanumeric(), "_")),
+                        )
+                    };
+                    diag.span_suggestion_verbose(expr.span, message, path, Applicability::MaybeIncorrect);
+                },
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints_internal/src/invalid_paths.rs
index 252ac5e6768..bee87efa3fc 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/invalid_paths.rs
@@ -5,12 +5,13 @@ use rustc_hir as hir;
 use rustc_hir::Item;
 use rustc_hir::def::DefKind;
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::{self, FloatTy};
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks the paths module for invalid paths.
     ///
@@ -19,9 +20,10 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// None.
-    pub INVALID_PATHS,
-    internal,
-    "invalid path"
+    pub clippy::INVALID_PATHS,
+    Warn,
+    "invalid path",
+    report_in_external_macro: true
 }
 
 declare_lint_pass!(InvalidPaths => [INVALID_PATHS]);
@@ -80,22 +82,22 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
     .copied();
     for item_def_id in lang_items.iter().map(|(_, def_id)| def_id).chain(incoherent_impls) {
         let lang_item_path = cx.get_def_path(item_def_id);
-        if path_syms.starts_with(&lang_item_path) {
-            if let [item] = &path_syms[lang_item_path.len()..] {
-                if matches!(
-                    cx.tcx.def_kind(item_def_id),
-                    DefKind::Mod | DefKind::Enum | DefKind::Trait
-                ) {
-                    for child in cx.tcx.module_children(item_def_id) {
-                        if child.ident.name == *item {
-                            return true;
-                        }
+        if path_syms.starts_with(&lang_item_path)
+            && let [item] = &path_syms[lang_item_path.len()..]
+        {
+            if matches!(
+                cx.tcx.def_kind(item_def_id),
+                DefKind::Mod | DefKind::Enum | DefKind::Trait
+            ) {
+                for child in cx.tcx.module_children(item_def_id) {
+                    if child.ident.name == *item {
+                        return true;
                     }
-                } else {
-                    for child in cx.tcx.associated_item_def_ids(item_def_id) {
-                        if cx.tcx.item_name(*child) == *item {
-                            return true;
-                        }
+                }
+            } else {
+                for child in cx.tcx.associated_item_def_ids(item_def_id) {
+                    if cx.tcx.item_name(*child) == *item {
+                        return true;
                     }
                 }
             }
diff --git a/src/tools/clippy/clippy_lints_internal/src/lib.rs b/src/tools/clippy/clippy_lints_internal/src/lib.rs
new file mode 100644
index 00000000000..1c42f4112f9
--- /dev/null
+++ b/src/tools/clippy/clippy_lints_internal/src/lib.rs
@@ -0,0 +1,74 @@
+#![feature(let_chains, rustc_private)]
+#![allow(
+    clippy::missing_docs_in_private_items,
+    clippy::must_use_candidate,
+    rustc::diagnostic_outside_of_impl,
+    rustc::untranslatable_diagnostic
+)]
+#![warn(
+    trivial_casts,
+    trivial_numeric_casts,
+    rust_2018_idioms,
+    unused_lifetimes,
+    unused_qualifications,
+    rustc::internal
+)]
+// Disable this rustc lint for now, as it was also done in rustc
+#![allow(rustc::potential_query_instability)]
+// None of these lints need a version.
+#![allow(clippy::missing_clippy_version_attribute)]
+
+extern crate rustc_ast;
+extern crate rustc_attr_parsing;
+extern crate rustc_data_structures;
+extern crate rustc_errors;
+extern crate rustc_hir;
+extern crate rustc_lint;
+extern crate rustc_lint_defs;
+extern crate rustc_middle;
+extern crate rustc_session;
+extern crate rustc_span;
+
+mod almost_standard_lint_formulation;
+mod collapsible_calls;
+mod interning_literals;
+mod invalid_paths;
+mod lint_without_lint_pass;
+mod msrv_attr_impl;
+mod outer_expn_data_pass;
+mod produce_ice;
+mod unnecessary_def_path;
+mod unsorted_clippy_utils_paths;
+
+use rustc_lint::{Lint, LintStore};
+
+static LINTS: &[&Lint] = &[
+    almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION,
+    collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS,
+    interning_literals::INTERNING_LITERALS,
+    invalid_paths::INVALID_PATHS,
+    lint_without_lint_pass::DEFAULT_LINT,
+    lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE,
+    lint_without_lint_pass::LINT_WITHOUT_LINT_PASS,
+    lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE,
+    msrv_attr_impl::MISSING_MSRV_ATTR_IMPL,
+    outer_expn_data_pass::OUTER_EXPN_EXPN_DATA,
+    produce_ice::PRODUCE_ICE,
+    unnecessary_def_path::UNNECESSARY_DEF_PATH,
+    unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS,
+];
+
+pub fn register_lints(store: &mut LintStore) {
+    store.register_lints(LINTS);
+
+    store.register_early_pass(|| Box::new(unsorted_clippy_utils_paths::UnsortedClippyUtilsPaths));
+    store.register_early_pass(|| Box::new(produce_ice::ProduceIce));
+    store.register_late_pass(|_| Box::new(collapsible_calls::CollapsibleCalls));
+    store.register_late_pass(|_| Box::new(invalid_paths::InvalidPaths));
+    store.register_late_pass(|_| Box::<interning_literals::InterningDefinedSymbol>::default());
+    store.register_late_pass(|_| Box::<lint_without_lint_pass::LintWithoutLintPass>::default());
+    store.register_late_pass(|_| Box::<unnecessary_def_path::UnnecessaryDefPath>::default());
+    store.register_late_pass(|_| Box::new(outer_expn_data_pass::OuterExpnDataPass));
+    store.register_late_pass(|_| Box::new(msrv_attr_impl::MsrvAttrImpl));
+    store.register_late_pass(|_| Box::new(almost_standard_lint_formulation::AlmostStandardFormulation::new()));
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs
index 94a2e598522..6a75defcce3 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs
@@ -9,13 +9,14 @@ use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_middle::hir::nested_filter;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, sym};
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Ensures every lint is associated to a `LintPass`.
     ///
@@ -37,12 +38,14 @@ declare_clippy_lint! {
     /// declare_lint_pass!(Pass => [LINT_1, LINT_2]);
     /// // missing FORGOTTEN_LINT
     /// ```
-    pub LINT_WITHOUT_LINT_PASS,
-    internal,
-    "declaring a lint without associating it in a LintPass"
+    pub clippy::LINT_WITHOUT_LINT_PASS,
+    Warn,
+    "declaring a lint without associating it in a LintPass",
+    report_in_external_macro: true
+
 }
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks for cases of an auto-generated lint without an updated description,
     /// i.e. `default lint description`.
@@ -59,30 +62,32 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// declare_lint! { pub COOL_LINT, nursery, "a great new lint" }
     /// ```
-    pub DEFAULT_LINT,
-    internal,
-    "found 'default lint description' in a lint declaration"
+    pub clippy::DEFAULT_LINT,
+    Warn,
+    "found 'default lint description' in a lint declaration",
+    report_in_external_macro: true
 }
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks for invalid `clippy::version` attributes.
     ///
     /// Valid values are:
     /// * "pre 1.29.0"
     /// * any valid semantic version
-    pub INVALID_CLIPPY_VERSION_ATTRIBUTE,
-    internal,
-    "found an invalid `clippy::version` attribute"
+    pub clippy::INVALID_CLIPPY_VERSION_ATTRIBUTE,
+    Warn,
+    "found an invalid `clippy::version` attribute",
+    report_in_external_macro: true
 }
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks for declared clippy lints without the `clippy::version` attribute.
-    ///
-    pub MISSING_CLIPPY_VERSION_ATTRIBUTE,
-    internal,
-    "found clippy lint without `clippy::version` attribute"
+    pub clippy::MISSING_CLIPPY_VERSION_ATTRIBUTE,
+    Warn,
+    "found clippy lint without `clippy::version` attribute",
+    report_in_external_macro: true
 }
 
 #[derive(Clone, Debug, Default)]
@@ -100,10 +105,6 @@ impl_lint_pass!(LintWithoutLintPass => [
 
 impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id()) {
-            return;
-        }
-
         if let hir::ItemKind::Static(ident, ty, Mutability::Not, body_id) = item.kind {
             if is_lint_ref_type(cx, ty) {
                 check_invalid_clippy_version_attribute(cx, item);
@@ -205,12 +206,10 @@ pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
             mutbl: Mutability::Not,
         },
     ) = ty.kind
+        && let TyKind::Path(ref path) = inner.kind
+        && let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id)
     {
-        if let TyKind::Path(ref path) = inner.kind {
-            if let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) {
-                return match_def_path(cx, def_id, &paths::LINT);
-            }
-        }
+        return match_def_path(cx, def_id, &paths::LINT);
     }
 
     false
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs
index 558acacb972..dda054546e2 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs
@@ -5,16 +5,17 @@ use clippy_utils::{match_def_path, paths};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_middle::ty::{self, EarlyBinder, GenericArgKind};
 use rustc_session::declare_lint_pass;
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Check that the `extract_msrv_attr!` macro is used, when a lint has a MSRV.
-    ///
-    pub MISSING_MSRV_ATTR_IMPL,
-    internal,
-    "checking if all necessary steps were taken when adding a MSRV to a lint"
+    pub clippy::MISSING_MSRV_ATTR_IMPL,
+    Warn,
+    "checking if all necessary steps were taken when adding a MSRV to a lint",
+    report_in_external_macro: true
 }
 
 declare_lint_pass!(MsrvAttrImpl => [MISSING_MSRV_ATTR_IMPL]);
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs b/src/tools/clippy/clippy_lints_internal/src/outer_expn_data_pass.rs
index 326e1721461..e9441964797 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/outer_expn_data_pass.rs
@@ -4,10 +4,11 @@ use clippy_utils::{is_lint_allowed, method_calls, paths};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks for calls to `cx.outer().expn_data()` and suggests to use
     /// the `cx.outer_expn_data()`
@@ -24,9 +25,10 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// expr.span.ctxt().outer_expn_data()
     /// ```
-    pub OUTER_EXPN_EXPN_DATA,
-    internal,
-    "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`"
+    pub clippy::OUTER_EXPN_EXPN_DATA,
+    Warn,
+    "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`",
+    report_in_external_macro: true
 }
 
 declare_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs b/src/tools/clippy/clippy_lints_internal/src/produce_ice.rs
index 0a07919d659..14e93dc6d5f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/produce_ice.rs
@@ -1,10 +1,11 @@
 use rustc_ast::ast::NodeId;
 use rustc_ast::visit::FnKind;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Not an actual lint. This lint is only meant for testing our customized internal compiler
     /// error message by calling `panic`.
@@ -16,9 +17,10 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// 🍦🍦🍦🍦🍦
     /// ```
-    pub PRODUCE_ICE,
-    internal,
-    "this message should not appear anywhere as we ICE before and don't emit the lint"
+    pub clippy::PRODUCE_ICE,
+    Warn,
+    "this message should not appear anywhere as we ICE before and don't emit the lint",
+    report_in_external_macro: true
 }
 
 declare_lint_pass!(ProduceIce => [PRODUCE_ICE]);
@@ -35,7 +37,7 @@ impl EarlyLintPass for ProduceIce {
 
 fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool {
     match fn_kind {
-        FnKind::Fn(_, ident, ..) => ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy",
+        FnKind::Fn(_, _, func) => func.ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy",
         FnKind::Closure(..) => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints_internal/src/unnecessary_def_path.rs
index 76b0a52621b..6bdfbed55b0 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/unnecessary_def_path.rs
@@ -8,6 +8,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, LetStmt, Mutability, Node};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint_defs::declare_tool_lint;
 use rustc_middle::mir::ConstValue;
 use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
 use rustc_middle::ty::{self, Ty};
@@ -17,7 +18,7 @@ use rustc_span::symbol::Symbol;
 
 use std::str;
 
-declare_clippy_lint! {
+declare_tool_lint! {
     /// ### What it does
     /// Checks for usage of def paths when a diagnostic item or a `LangItem` could be used.
     ///
@@ -34,9 +35,10 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// utils::is_type_diagnostic_item(cx, ty, sym::Vec)
     /// ```
-    pub UNNECESSARY_DEF_PATH,
-    internal,
-    "using a def path when a diagnostic item or a `LangItem` is available"
+    pub clippy::UNNECESSARY_DEF_PATH,
+    Warn,
+    "using a def path when a diagnostic item or a `LangItem` is available",
+    report_in_external_macro: true
 }
 
 impl_lint_pass!(UnnecessaryDefPath => [UNNECESSARY_DEF_PATH]);
@@ -281,10 +283,10 @@ fn path_from_array(exprs: &[Expr<'_>]) -> Option<Vec<String>> {
     exprs
         .iter()
         .map(|expr| {
-            if let ExprKind::Lit(lit) = &expr.kind {
-                if let LitKind::Str(sym, _) = lit.node {
-                    return Some((*sym.as_str()).to_owned());
-                }
+            if let ExprKind::Lit(lit) = &expr.kind
+                && let LitKind::Str(sym, _) = lit.node
+            {
+                return Some((*sym.as_str()).to_owned());
             }
 
             None
diff --git a/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs b/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs
new file mode 100644
index 00000000000..8e281ecb2ee
--- /dev/null
+++ b/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs
@@ -0,0 +1,54 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::ast::{Crate, ItemKind, ModKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint_defs::declare_tool_lint;
+use rustc_session::declare_lint_pass;
+
+declare_tool_lint! {
+    /// ### What it does
+    /// Checks that [`clippy_utils::paths`] is sorted lexically
+    ///
+    /// ### Why is this bad?
+    /// We like to pretend we're an example of tidy code.
+    ///
+    /// ### Example
+    /// Wrong ordering of the util::paths constants.
+    pub clippy::UNSORTED_CLIPPY_UTILS_PATHS,
+    Warn,
+    "various things that will negatively affect your clippy experience",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(UnsortedClippyUtilsPaths => [UNSORTED_CLIPPY_UTILS_PATHS]);
+
+impl EarlyLintPass for UnsortedClippyUtilsPaths {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
+        if let Some(utils) = krate
+            .items
+            .iter()
+            .find(|item| item.kind.ident().is_some_and(|i| i.name.as_str() == "utils"))
+            && let ItemKind::Mod(_, _, ModKind::Loaded(ref items, ..)) = utils.kind
+            && let Some(paths) = items
+                .iter()
+                .find(|item| item.kind.ident().is_some_and(|i| i.name.as_str() == "paths"))
+            && let ItemKind::Mod(_, _, ModKind::Loaded(ref items, ..)) = paths.kind
+        {
+            let mut last_name: Option<String> = None;
+            for item in items {
+                let name = item.kind.ident().expect("const items have idents").to_string();
+                if let Some(last_name) = last_name
+                    && *last_name > *name
+                {
+                    span_lint(
+                        cx,
+                        UNSORTED_CLIPPY_UTILS_PATHS,
+                        item.span,
+                        "this constant should be before the previous constant due to lexical \
+                                         ordering",
+                    );
+                }
+                last_name = Some(name);
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index ba4bb1d177c..b98e9901750 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_utils"
 # begin autogenerated version
-version = "0.1.87"
+version = "0.1.88"
 # end autogenerated version
 edition = "2024"
 description = "Helpful tools for writing lints, provided as they are used in Clippy"
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
index 7c665b42497..aceff14a159 100644
--- a/src/tools/clippy/clippy_utils/README.md
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2025-03-20
+nightly-2025-04-22
 ```
 <!-- end autogenerated nightly -->
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index c5dce26143b..8996b694ed8 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -348,11 +348,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 safety: rs,
                 define_opaque: _,
             }),
-        ) => eq_id(*li, *ri)
-                && lm == rm
-                && ls == rs
-                && eq_ty(lt, rt)
-                && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
         (
             Const(box ConstItem {
                 defaultness: ld,
@@ -370,11 +366,13 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 expr: re,
                 define_opaque: _,
             }),
-        ) => eq_defaultness(*ld, *rd)
+        ) => {
+            eq_defaultness(*ld, *rd)
                 && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_ty(lt, rt)
-                && eq_expr_opt(le.as_ref(), re.as_ref()),
+                && eq_expr_opt(le.as_ref(), re.as_ref())
+        },
         (
             Fn(box ast::Fn {
                 defaultness: ld,
@@ -440,7 +438,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         },
         (Enum(li, le, lg), Enum(ri, re, rg)) => {
             eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
-        }
+        },
         (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
             eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
         },
@@ -471,7 +469,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         },
         (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => {
             eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
-        }
+        },
         (
             Impl(box ast::Impl {
                 safety: lu,
@@ -506,7 +504,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         (MacroDef(li, ld), MacroDef(ri, rd)) => {
             eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body)
-        }
+        },
         _ => false,
     }
 }
@@ -531,13 +529,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
                 safety: rs,
                 define_opaque: _,
             }),
-        ) => {
-            eq_id(*li, *ri)
-                && eq_ty(lt, rt)
-                && lm == rm
-                && eq_expr_opt(le.as_ref(), re.as_ref())
-                && ls == rs
-        }
+        ) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
         (
             Fn(box ast::Fn {
                 defaultness: ld,
@@ -620,7 +612,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
                 && eq_generics(lg, rg)
                 && eq_ty(lt, rt)
                 && eq_expr_opt(le.as_ref(), re.as_ref())
-        }
+        },
         (
             Fn(box ast::Fn {
                 defaultness: ld,
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 17751e824c0..b9928b8eed4 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -43,14 +43,16 @@ pub enum Constant<'tcx> {
     Char(char),
     /// An integer's bit representation.
     Int(u128),
-    /// An `f16`.
-    F16(f16),
+    /// An `f16` bitcast to a `u16`.
+    // FIXME(f16_f128): use `f16` once builtins are available on all host tools platforms.
+    F16(u16),
     /// An `f32`.
     F32(f32),
     /// An `f64`.
     F64(f64),
-    /// An `f128`.
-    F128(f128),
+    /// An `f128` bitcast to a `u128`.
+    // FIXME(f16_f128): use `f128` once builtins are available on all host tools platforms.
+    F128(u128),
     /// `true` or `false`.
     Bool(bool),
     /// An array of constants.
@@ -177,7 +179,7 @@ impl Hash for Constant<'_> {
             },
             Self::F16(f) => {
                 // FIXME(f16_f128): once conversions to/from `f128` are available on all platforms,
-                f.to_bits().hash(state);
+                f.hash(state);
             },
             Self::F32(f) => {
                 f64::from(f).to_bits().hash(state);
@@ -186,7 +188,7 @@ impl Hash for Constant<'_> {
                 f.to_bits().hash(state);
             },
             Self::F128(f) => {
-                f.to_bits().hash(state);
+                f.hash(state);
             },
             Self::Bool(b) => {
                 b.hash(state);
@@ -292,12 +294,12 @@ impl Constant<'_> {
 
     fn parse_f16(s: &str) -> Self {
         let f: Half = s.parse().unwrap();
-        Self::F16(f16::from_bits(f.to_bits().try_into().unwrap()))
+        Self::F16(f.to_bits().try_into().unwrap())
     }
 
     fn parse_f128(s: &str) -> Self {
         let f: Quad = s.parse().unwrap();
-        Self::F128(f128::from_bits(f.to_bits()))
+        Self::F128(f.to_bits())
     }
 }
 
@@ -868,10 +870,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option
             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::F16) => Some(Constant::F16(f16::from_bits(int.into()))),
+            ty::Float(FloatTy::F16) => Some(Constant::F16(int.into())),
             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::Float(FloatTy::F128) => Some(Constant::F128(f128::from_bits(int.into()))),
+            ty::Float(FloatTy::F128) => Some(Constant::F128(int.into())),
             ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
             _ => None,
         },
@@ -892,10 +894,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option
                 let range = alloc_range(offset + size * idx, size);
                 let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?;
                 res.push(match flt {
-                    FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().discard_err()?)),
+                    FloatTy::F16 => Constant::F16(val.to_u16().discard_err()?),
                     FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().discard_err()?)),
                     FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().discard_err()?)),
-                    FloatTy::F128 => Constant::F128(f128::from_bits(val.to_u128().discard_err()?)),
+                    FloatTy::F128 => Constant::F128(val.to_u128().discard_err()?),
                 });
             }
             Some(Constant::Vec(res))
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 292792408c6..cd2098a8989 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -17,16 +17,16 @@ use rustc_span::Span;
 use std::env;
 
 fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
-    if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
-        if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
-            diag.help(format!(
-                "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
-                &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
-                    // extract just major + minor version and ignore patch versions
-                    format!("rust-{}", n.rsplit_once('.').unwrap().1)
-                })
-            ));
-        }
+    if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err()
+        && let Some(lint) = lint.name_lower().strip_prefix("clippy::")
+    {
+        diag.help(format!(
+            "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
+            &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
+                // extract just major + minor version and ignore patch versions
+                format!("rust-{}", n.rsplit_once('.').unwrap().1)
+            })
+        ));
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index c4d00002292..d4e66ebd8e1 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -118,18 +118,17 @@ impl<'hir> IfLet<'hir> {
         ) = expr.kind
         {
             let mut iter = cx.tcx.hir_parent_iter(expr.hir_id);
-            if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
-                if let Some((
+            if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next()
+                && let Some((
                     _,
                     Node::Expr(Expr {
                         kind: ExprKind::Loop(_, _, LoopSource::While, _),
                         ..
                     }),
                 )) = iter.next()
-                {
-                    // while loop desugar
-                    return None;
-                }
+            {
+                // while loop desugar
+                return None;
             }
             return Some(Self {
                 let_pat,
@@ -176,6 +175,12 @@ impl<'hir> IfLetOrMatch<'hir> {
             ),
         }
     }
+
+    pub fn scrutinee(&self) -> &'hir Expr<'hir> {
+        match self {
+            Self::Match(scrutinee, _, _) | Self::IfLet(scrutinee, _, _, _, _) => scrutinee,
+        }
+    }
 }
 
 /// An `if` or `if let` expression
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index be295b59f60..fe1fd70a9fa 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -148,7 +148,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> {
 impl HirEqInterExpr<'_, '_, '_> {
     pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
         match (&left.kind, &right.kind) {
-            (&StmtKind::Let(l), &StmtKind::Let(r)) => {
+            (StmtKind::Let(l), StmtKind::Let(r)) => {
                 // This additional check ensures that the type of the locals are equivalent even if the init
                 // expression or type have some inferred parts.
                 if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results {
@@ -166,7 +166,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                     && both(l.els.as_ref(), r.els.as_ref(), |l, r| self.eq_block(l, r))
                     && self.eq_pat(l.pat, r.pat)
             },
-            (&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r),
+            (StmtKind::Expr(l), StmtKind::Expr(r)) | (StmtKind::Semi(l), StmtKind::Semi(r)) => self.eq_expr(l, r),
             _ => false,
         }
     }
@@ -260,7 +260,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
         macro_backtrace(expr.span).last().is_some_and(|macro_call| {
             matches!(
-                &self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
+                self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
                 Some(sym::todo_macro | sym::unimplemented_macro)
             )
         })
@@ -301,58 +301,58 @@ impl HirEqInterExpr<'_, '_, '_> {
             reduce_exprkind(self.inner.cx, &left.kind),
             reduce_exprkind(self.inner.cx, &right.kind),
         ) {
-            (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
+            (ExprKind::AddrOf(lb, l_mut, le), ExprKind::AddrOf(rb, r_mut, re)) => {
                 lb == rb && l_mut == r_mut && self.eq_expr(le, re)
             },
-            (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
-            (&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => {
+            (ExprKind::Array(l), ExprKind::Array(r)) => self.eq_exprs(l, r),
+            (ExprKind::Assign(ll, lr, _), ExprKind::Assign(rl, rr, _)) => {
                 self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
             },
-            (&ExprKind::AssignOp(ref lo, ll, lr), &ExprKind::AssignOp(ref ro, rl, rr)) => {
+            (ExprKind::AssignOp(lo, ll, lr), ExprKind::AssignOp(ro, rl, rr)) => {
                 self.inner.allow_side_effects && lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
             },
-            (&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r),
-            (&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => {
+            (ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r),
+            (ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => {
                 l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
                     || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| {
                         l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
                     })
             },
-            (&ExprKind::Break(li, ref le), &ExprKind::Break(ri, ref re)) => {
+            (ExprKind::Break(li, le), ExprKind::Break(ri, re)) => {
                 both(li.label.as_ref(), ri.label.as_ref(), |l, r| l.ident.name == r.ident.name)
                     && both(le.as_ref(), re.as_ref(), |l, r| self.eq_expr(l, r))
             },
-            (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
+            (ExprKind::Call(l_fun, l_args), ExprKind::Call(r_fun, r_args)) => {
                 self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
             },
-            (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) => {
+            (ExprKind::Cast(lx, lt), ExprKind::Cast(rx, rt)) => {
                 self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
             },
-            (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false,
-            (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
-            (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
+            (ExprKind::Closure(_l), ExprKind::Closure(_r)) => false,
+            (ExprKind::ConstBlock(lb), ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
+            (ExprKind::Continue(li), ExprKind::Continue(ri)) => {
                 both(li.label.as_ref(), ri.label.as_ref(), |l, r| l.ident.name == r.ident.name)
             },
-            (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
-            (&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => {
+            (ExprKind::DropTemps(le), ExprKind::DropTemps(re)) => self.eq_expr(le, re),
+            (ExprKind::Field(l_f_exp, l_f_ident), ExprKind::Field(r_f_exp, r_f_ident)) => {
                 l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp)
             },
-            (&ExprKind::Index(la, li, _), &ExprKind::Index(ra, ri, _)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
-            (&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => {
+            (ExprKind::Index(la, li, _), ExprKind::Index(ra, ri, _)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
+            (ExprKind::If(lc, lt, le), ExprKind::If(rc, rt, re)) => {
                 self.eq_expr(lc, rc) && self.eq_expr(lt, rt)
                     && both(le.as_ref(), re.as_ref(), |l, r| self.eq_expr(l, r))
             },
-            (&ExprKind::Let(l), &ExprKind::Let(r)) => {
+            (ExprKind::Let(l), ExprKind::Let(r)) => {
                 self.eq_pat(l.pat, r.pat)
                     && both(l.ty.as_ref(), r.ty.as_ref(), |l, r| self.eq_ty(l, r))
                     && self.eq_expr(l.init, r.init)
             },
             (ExprKind::Lit(l), ExprKind::Lit(r)) => l.node == r.node,
-            (&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => {
+            (ExprKind::Loop(lb, ll, lls, _), ExprKind::Loop(rb, rl, rls, _)) => {
                 lls == rls && self.eq_block(lb, rb)
                     && both(ll.as_ref(), rl.as_ref(), |l, r| l.ident.name == r.ident.name)
             },
-            (&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => {
+            (ExprKind::Match(le, la, ls), ExprKind::Match(re, ra, rs)) => {
                 (ls == rs || (matches!((ls, rs), (TryDesugar(_), TryDesugar(_)))))
                     && self.eq_expr(le, re)
                     && over(la, ra, |l, r| {
@@ -362,27 +362,27 @@ impl HirEqInterExpr<'_, '_, '_> {
                     })
             },
             (
-                &ExprKind::MethodCall(l_path, l_receiver, l_args, _),
-                &ExprKind::MethodCall(r_path, r_receiver, r_args, _),
+                ExprKind::MethodCall(l_path, l_receiver, l_args, _),
+                ExprKind::MethodCall(r_path, r_receiver, r_args, _),
             ) => {
                 self.inner.allow_side_effects
                     && self.eq_path_segment(l_path, r_path)
                     && self.eq_expr(l_receiver, r_receiver)
                     && self.eq_exprs(l_args, r_args)
             },
-            (&ExprKind::UnsafeBinderCast(lkind, le, None), &ExprKind::UnsafeBinderCast(rkind, re, None)) =>
+            (ExprKind::UnsafeBinderCast(lkind, le, None), ExprKind::UnsafeBinderCast(rkind, re, None)) =>
                 lkind == rkind && self.eq_expr(le, re),
-            (&ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), &ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) =>
+            (ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) =>
                 lkind == rkind && self.eq_expr(le, re) && self.eq_ty(lt, rt),
-            (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
+            (ExprKind::OffsetOf(l_container, l_fields), ExprKind::OffsetOf(r_container, r_fields)) => {
                 self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
             },
             (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
-            (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
+            (ExprKind::Repeat(le, ll), ExprKind::Repeat(re, rl)) => {
                 self.eq_expr(le, re) && self.eq_const_arg(ll, rl)
             },
             (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)),
-            (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
+            (ExprKind::Struct(l_path, lf, lo), ExprKind::Struct(r_path, rf, ro)) => {
                 self.eq_qpath(l_path, r_path)
                     && match (lo, ro) {
                         (StructTailExpr::Base(l),StructTailExpr::Base(r)) => self.eq_expr(l, r),
@@ -392,58 +392,58 @@ impl HirEqInterExpr<'_, '_, '_> {
                     }
                     && over(lf, rf, |l, r| self.eq_expr_field(l, r))
             },
-            (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
-            (&ExprKind::Use(l_expr, _), &ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr),
-            (&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
-            (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
-            (&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
+            (ExprKind::Tup(l_tup), ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
+            (ExprKind::Use(l_expr, _), ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr),
+            (ExprKind::Type(le, lt), ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
+            (ExprKind::Unary(l_op, le), ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
+            (ExprKind::Yield(le, _), ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
             (
                 // Else branches for branches above, grouped as per `match_same_arms`.
-                | &ExprKind::AddrOf(..)
-                | &ExprKind::Array(..)
-                | &ExprKind::Assign(..)
-                | &ExprKind::AssignOp(..)
-                | &ExprKind::Binary(..)
-                | &ExprKind::Become(..)
-                | &ExprKind::Block(..)
-                | &ExprKind::Break(..)
-                | &ExprKind::Call(..)
-                | &ExprKind::Cast(..)
-                | &ExprKind::ConstBlock(..)
-                | &ExprKind::Continue(..)
-                | &ExprKind::DropTemps(..)
-                | &ExprKind::Field(..)
-                | &ExprKind::Index(..)
-                | &ExprKind::If(..)
-                | &ExprKind::Let(..)
-                | &ExprKind::Lit(..)
-                | &ExprKind::Loop(..)
-                | &ExprKind::Match(..)
-                | &ExprKind::MethodCall(..)
-                | &ExprKind::OffsetOf(..)
-                | &ExprKind::Path(..)
-                | &ExprKind::Repeat(..)
-                | &ExprKind::Ret(..)
-                | &ExprKind::Struct(..)
-                | &ExprKind::Tup(..)
-                | &ExprKind::Use(..)
-                | &ExprKind::Type(..)
-                | &ExprKind::Unary(..)
-                | &ExprKind::Yield(..)
-                | &ExprKind::UnsafeBinderCast(..)
+                | ExprKind::AddrOf(..)
+                | ExprKind::Array(..)
+                | ExprKind::Assign(..)
+                | ExprKind::AssignOp(..)
+                | ExprKind::Binary(..)
+                | ExprKind::Become(..)
+                | ExprKind::Block(..)
+                | ExprKind::Break(..)
+                | ExprKind::Call(..)
+                | ExprKind::Cast(..)
+                | ExprKind::ConstBlock(..)
+                | ExprKind::Continue(..)
+                | ExprKind::DropTemps(..)
+                | ExprKind::Field(..)
+                | ExprKind::Index(..)
+                | ExprKind::If(..)
+                | ExprKind::Let(..)
+                | ExprKind::Lit(..)
+                | ExprKind::Loop(..)
+                | ExprKind::Match(..)
+                | ExprKind::MethodCall(..)
+                | ExprKind::OffsetOf(..)
+                | ExprKind::Path(..)
+                | ExprKind::Repeat(..)
+                | ExprKind::Ret(..)
+                | ExprKind::Struct(..)
+                | ExprKind::Tup(..)
+                | ExprKind::Use(..)
+                | ExprKind::Type(..)
+                | ExprKind::Unary(..)
+                | ExprKind::Yield(..)
+                | ExprKind::UnsafeBinderCast(..)
 
                 // --- Special cases that do not have a positive branch.
 
                 // `Err` represents an invalid expression, so let's never assume that
                 // an invalid expressions is equal to anything.
-                | &ExprKind::Err(..)
+                | ExprKind::Err(..)
 
                 // For the time being, we always consider that two closures are unequal.
                 // This behavior may change in the future.
-                | &ExprKind::Closure(..)
+                | ExprKind::Closure(..)
                 // For the time being, we always consider that two instances of InlineAsm are different.
                 // This behavior may change in the future.
-                | &ExprKind::InlineAsm(_)
+                | ExprKind::InlineAsm(_)
                 , _
             ) => false,
         };
@@ -494,11 +494,11 @@ impl HirEqInterExpr<'_, '_, '_> {
     fn eq_pat_expr(&mut self, left: &PatExpr<'_>, right: &PatExpr<'_>) -> bool {
         match (&left.kind, &right.kind) {
             (
-                &PatExprKind::Lit {
+                PatExprKind::Lit {
                     lit: left,
                     negated: left_neg,
                 },
-                &PatExprKind::Lit {
+                PatExprKind::Lit {
                     lit: right,
                     negated: right_neg,
                 },
@@ -512,47 +512,47 @@ impl HirEqInterExpr<'_, '_, '_> {
     /// Checks whether two patterns are the same.
     fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
         match (&left.kind, &right.kind) {
-            (&PatKind::Box(l), &PatKind::Box(r)) => self.eq_pat(l, r),
-            (&PatKind::Struct(ref lp, la, ..), &PatKind::Struct(ref rp, ra, ..)) => {
+            (PatKind::Box(l), PatKind::Box(r)) => self.eq_pat(l, r),
+            (PatKind::Struct(lp, la, ..), PatKind::Struct(rp, ra, ..)) => {
                 self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r))
             },
-            (&PatKind::TupleStruct(ref lp, la, ls), &PatKind::TupleStruct(ref rp, ra, rs)) => {
+            (PatKind::TupleStruct(lp, la, ls), PatKind::TupleStruct(rp, ra, rs)) => {
                 self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
             },
-            (&PatKind::Binding(lb, li, _, ref lp), &PatKind::Binding(rb, ri, _, ref rp)) => {
+            (PatKind::Binding(lb, li, _, lp), PatKind::Binding(rb, ri, _, rp)) => {
                 let eq = lb == rb && both(lp.as_ref(), rp.as_ref(), |l, r| self.eq_pat(l, r));
                 if eq {
-                    self.locals.insert(li, ri);
+                    self.locals.insert(*li, *ri);
                 }
                 eq
             },
-            (&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r),
-            (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
-            (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
+            (PatKind::Expr(l), PatKind::Expr(r)) => self.eq_pat_expr(l, r),
+            (PatKind::Tuple(l, ls), PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
+            (PatKind::Range(ls, le, li), PatKind::Range(rs, re, ri)) => {
                 both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(a, b))
                     && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b))
                     && (li == ri)
             },
-            (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
-            (&PatKind::Slice(ls, ref li, le), &PatKind::Slice(rs, ref ri, re)) => {
+            (PatKind::Ref(le, lm), PatKind::Ref(re, rm)) => lm == rm && self.eq_pat(le, re),
+            (PatKind::Slice(ls, li, le), PatKind::Slice(rs, ri, re)) => {
                 over(ls, rs, |l, r| self.eq_pat(l, r))
                     && over(le, re, |l, r| self.eq_pat(l, r))
                     && both(li.as_ref(), ri.as_ref(), |l, r| self.eq_pat(l, r))
             },
-            (&PatKind::Wild, &PatKind::Wild) => true,
+            (PatKind::Wild, PatKind::Wild) => true,
             _ => false,
         }
     }
 
     fn eq_qpath(&mut self, left: &QPath<'_>, right: &QPath<'_>) -> bool {
         match (left, right) {
-            (&QPath::Resolved(ref lty, lpath), &QPath::Resolved(ref rty, rpath)) => {
+            (QPath::Resolved(lty, lpath), QPath::Resolved(rty, rpath)) => {
                 both(lty.as_ref(), rty.as_ref(), |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath)
             },
-            (&QPath::TypeRelative(lty, lseg), &QPath::TypeRelative(rty, rseg)) => {
+            (QPath::TypeRelative(lty, lseg), QPath::TypeRelative(rty, rseg)) => {
                 self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
             },
-            (&QPath::LangItem(llang_item, ..), &QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item,
+            (QPath::LangItem(llang_item, ..), QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item,
             _ => false,
         }
     }
@@ -611,15 +611,15 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
         match (&left.kind, &right.kind) {
-            (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
-            (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl),
+            (TyKind::Slice(l_vec), TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
+            (TyKind::Array(lt, ll), TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl),
             (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
             (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => {
                 l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
             },
             (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
-            (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
-            (&TyKind::Infer(()), &TyKind::Infer(())) => true,
+            (TyKind::Tup(l), TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
+            (TyKind::Infer(()), TyKind::Infer(())) => true,
             _ => false,
         }
     }
@@ -853,9 +853,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
         std::mem::discriminant(&e.kind).hash(&mut self.s);
 
-        match e.kind {
+        match &e.kind {
             ExprKind::AddrOf(kind, m, e) => {
-                std::mem::discriminant(&kind).hash(&mut self.s);
+                std::mem::discriminant(kind).hash(&mut self.s);
                 m.hash(&mut self.s);
                 self.hash_expr(e);
             },
@@ -871,7 +871,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(l);
                 self.hash_expr(r);
             },
-            ExprKind::AssignOp(ref o, l, r) => {
+            ExprKind::AssignOp(o, l, r) => {
                 std::mem::discriminant(&o.node).hash(&mut self.s);
                 self.hash_expr(l);
                 self.hash_expr(r);
@@ -887,11 +887,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(l);
                 self.hash_expr(r);
             },
-            ExprKind::Break(i, ref j) => {
+            ExprKind::Break(i, j) => {
                 if let Some(i) = i.label {
                     self.hash_name(i.ident.name);
                 }
-                if let Some(j) = *j {
+                if let Some(j) = j {
                     self.hash_expr(j);
                 }
             },
@@ -903,20 +903,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(e);
                 self.hash_ty(ty);
             },
-            ExprKind::Closure(&Closure {
+            ExprKind::Closure(Closure {
                 capture_clause, body, ..
             }) => {
-                std::mem::discriminant(&capture_clause).hash(&mut self.s);
+                std::mem::discriminant(capture_clause).hash(&mut self.s);
                 // closures inherit TypeckResults
-                self.hash_expr(self.cx.tcx.hir_body(body).value);
+                self.hash_expr(self.cx.tcx.hir_body(*body).value);
             },
-            ExprKind::ConstBlock(ref l_id) => {
+            ExprKind::ConstBlock(l_id) => {
                 self.hash_body(l_id.body);
             },
             ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
                 self.hash_expr(e);
             },
-            ExprKind::Field(e, ref f) => {
+            ExprKind::Field(e, f) => {
                 self.hash_expr(e);
                 self.hash_name(f.name);
             },
@@ -991,23 +991,23 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             ExprKind::Lit(l) => {
                 l.node.hash(&mut self.s);
             },
-            ExprKind::Loop(b, ref i, ..) => {
+            ExprKind::Loop(b, i, ..) => {
                 self.hash_block(b);
-                if let Some(i) = *i {
+                if let Some(i) = i {
                     self.hash_name(i.ident.name);
                 }
             },
-            ExprKind::If(cond, then, ref else_opt) => {
+            ExprKind::If(cond, then, else_opt) => {
                 self.hash_expr(cond);
                 self.hash_expr(then);
-                if let Some(e) = *else_opt {
+                if let Some(e) = else_opt {
                     self.hash_expr(e);
                 }
             },
-            ExprKind::Match(e, arms, ref s) => {
+            ExprKind::Match(e, arms, s) => {
                 self.hash_expr(e);
 
-                for arm in arms {
+                for arm in *arms {
                     self.hash_pat(arm.pat);
                     if let Some(e) = arm.guard {
                         self.hash_expr(e);
@@ -1017,38 +1017,38 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
                 s.hash(&mut self.s);
             },
-            ExprKind::MethodCall(path, receiver, args, ref _fn_span) => {
+            ExprKind::MethodCall(path, receiver, args, _fn_span) => {
                 self.hash_name(path.ident.name);
                 self.hash_expr(receiver);
                 self.hash_exprs(args);
             },
             ExprKind::OffsetOf(container, fields) => {
                 self.hash_ty(container);
-                for field in fields {
+                for field in *fields {
                     self.hash_name(field.name);
                 }
             },
-            ExprKind::Path(ref qpath) => {
+            ExprKind::Path(qpath) => {
                 self.hash_qpath(qpath);
             },
             ExprKind::Repeat(e, len) => {
                 self.hash_expr(e);
                 self.hash_const_arg(len);
             },
-            ExprKind::Ret(ref e) => {
-                if let Some(e) = *e {
+            ExprKind::Ret(e) => {
+                if let Some(e) = e {
                     self.hash_expr(e);
                 }
             },
-            ExprKind::Struct(path, fields, ref expr) => {
+            ExprKind::Struct(path, fields, expr) => {
                 self.hash_qpath(path);
 
-                for f in fields {
+                for f in *fields {
                     self.hash_name(f.ident.name);
                     self.hash_expr(f.expr);
                 }
 
-                if let StructTailExpr::Base(e) = *expr {
+                if let StructTailExpr::Base(e) = expr {
                     self.hash_expr(e);
                 }
             },
@@ -1059,11 +1059,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(expr);
             },
             ExprKind::Unary(lop, le) => {
-                std::mem::discriminant(&lop).hash(&mut self.s);
+                std::mem::discriminant(lop).hash(&mut self.s);
                 self.hash_expr(le);
             },
             ExprKind::UnsafeBinderCast(kind, expr, ty) => {
-                std::mem::discriminant(&kind).hash(&mut self.s);
+                std::mem::discriminant(kind).hash(&mut self.s);
                 self.hash_expr(expr);
                 if let Some(ty) = ty {
                     self.hash_ty(ty);
@@ -1084,7 +1084,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     }
 
     pub fn hash_qpath(&mut self, p: &QPath<'_>) {
-        match *p {
+        match p {
             QPath::Resolved(_, path) => {
                 self.hash_path(path);
             },
@@ -1092,7 +1092,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_name(path.ident.name);
             },
             QPath::LangItem(lang_item, ..) => {
-                std::mem::discriminant(&lang_item).hash(&mut self.s);
+                std::mem::discriminant(lang_item).hash(&mut self.s);
             },
         }
         // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
@@ -1123,11 +1123,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
     pub fn hash_pat(&mut self, pat: &Pat<'_>) {
         std::mem::discriminant(&pat.kind).hash(&mut self.s);
-        match pat.kind {
+        match &pat.kind {
             PatKind::Missing => unreachable!(),
             PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => {
-                std::mem::discriminant(&by_ref).hash(&mut self.s);
-                std::mem::discriminant(&mutability).hash(&mut self.s);
+                std::mem::discriminant(by_ref).hash(&mut self.s);
+                std::mem::discriminant(mutability).hash(&mut self.s);
                 if let Some(pat) = pat {
                     self.hash_pat(pat);
                 }
@@ -1135,7 +1135,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
             PatKind::Expr(expr) => self.hash_pat_expr(expr),
             PatKind::Or(pats) => {
-                for pat in pats {
+                for pat in *pats {
                     self.hash_pat(pat);
                 }
             },
@@ -1146,44 +1146,44 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 if let Some(e) = e {
                     self.hash_pat_expr(e);
                 }
-                std::mem::discriminant(&i).hash(&mut self.s);
+                std::mem::discriminant(i).hash(&mut self.s);
             },
             PatKind::Ref(pat, mu) => {
                 self.hash_pat(pat);
-                std::mem::discriminant(&mu).hash(&mut self.s);
+                std::mem::discriminant(mu).hash(&mut self.s);
             },
             PatKind::Guard(pat, guard) => {
                 self.hash_pat(pat);
                 self.hash_expr(guard);
             },
             PatKind::Slice(l, m, r) => {
-                for pat in l {
+                for pat in *l {
                     self.hash_pat(pat);
                 }
                 if let Some(pat) = m {
                     self.hash_pat(pat);
                 }
-                for pat in r {
+                for pat in *r {
                     self.hash_pat(pat);
                 }
             },
-            PatKind::Struct(ref qpath, fields, e) => {
+            PatKind::Struct(qpath, fields, e) => {
                 self.hash_qpath(qpath);
-                for f in fields {
+                for f in *fields {
                     self.hash_name(f.ident.name);
                     self.hash_pat(f.pat);
                 }
                 e.hash(&mut self.s);
             },
             PatKind::Tuple(pats, e) => {
-                for pat in pats {
+                for pat in *pats {
                     self.hash_pat(pat);
                 }
                 e.hash(&mut self.s);
             },
-            PatKind::TupleStruct(ref qpath, pats, e) => {
+            PatKind::TupleStruct(qpath, pats, e) => {
                 self.hash_qpath(qpath);
-                for pat in pats {
+                for pat in *pats {
                     self.hash_pat(pat);
                 }
                 e.hash(&mut self.s);
@@ -1261,7 +1261,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             TyKind::Slice(ty) => {
                 self.hash_ty(ty);
             },
-            &TyKind::Array(ty, len) => {
+            TyKind::Array(ty, len) => {
                 self.hash_ty(ty);
                 self.hash_const_arg(len);
             },
@@ -1334,11 +1334,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
     fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
         for arg in arg_list {
-            match *arg {
+            match arg {
                 GenericArg::Lifetime(l) => self.hash_lifetime(l),
                 GenericArg::Type(ty) => self.hash_ty(ty.as_unambig_ty()),
                 GenericArg::Const(ca) => self.hash_const_arg(ca.as_unambig_ct()),
-                GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
+                GenericArg::Infer(inf) => self.hash_ty(&inf.to_ty()),
             }
         }
     }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index f715fc86e4e..264b9b0406d 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,10 +1,8 @@
 #![feature(array_chunks)]
 #![feature(box_patterns)]
-#![feature(f128)]
-#![feature(f16)]
 #![feature(if_let_guard)]
-#![feature(macro_metavar_expr)]
 #![feature(macro_metavar_expr_concat)]
+#![feature(macro_metavar_expr)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustc_private)]
@@ -53,9 +51,6 @@ extern crate rustc_span;
 extern crate rustc_trait_selection;
 extern crate smallvec;
 
-#[macro_use]
-pub mod sym_helper;
-
 pub mod ast_utils;
 pub mod attrs;
 mod check_proc_macro;
@@ -108,10 +103,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
 use rustc_hir::{
     self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
-    Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItem,
-    ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
-    Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem,
-    TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def,
+    CoroutineDesugaring, CoroutineKind, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg,
+    GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource,
+    Mutability, Node, OwnerId, OwnerNode, Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath,
+    Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def,
 };
 use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -129,6 +124,7 @@ use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{Ident, Symbol, kw};
 use rustc_span::{InnerSpan, Span};
+use source::walk_span_to_context;
 use visitors::{Visitable, for_each_unconsumed_temporary};
 
 use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
@@ -370,10 +366,10 @@ pub fn is_inherent_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 
 /// 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) {
-        if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() {
-            return cx.tcx.is_diagnostic_item(diag_item, adt.did());
-        }
+    if let Some(impl_did) = cx.tcx.impl_of_method(def_id)
+        && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
+    {
+        return cx.tcx.is_diagnostic_item(diag_item, adt.did());
     }
     false
 }
@@ -460,10 +456,10 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
         QPath::Resolved(_, path) => match_path(path, segments),
         QPath::TypeRelative(ty, segment) => match ty.kind {
             TyKind::Path(ref inner_path) => {
-                if let [prefix @ .., end] = segments {
-                    if match_qpath(inner_path, prefix) {
-                        return segment.ident.name.as_str() == *end;
-                    }
+                if let [prefix @ .., end] = segments
+                    && match_qpath(inner_path, prefix)
+                {
+                    return segment.ident.name.as_str() == *end;
                 }
                 false
             },
@@ -526,10 +522,10 @@ pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
 
 /// If the expression is a path to a local, returns the canonical `HirId` of the local.
 pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
-    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
-        if let Res::Local(id) = path.res {
-            return Some(id);
-        }
+    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind
+        && let Res::Local(id) = path.res
+    {
+        return Some(id);
     }
     None
 }
@@ -896,16 +892,14 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
         sym::BinaryHeap,
     ];
 
-    if let QPath::TypeRelative(_, method) = path {
-        if method.ident.name == sym::new {
-            if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
-                if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() {
-                    return std_types_symbols.iter().any(|&symbol| {
-                        cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
-                    });
-                }
-            }
-        }
+    if let QPath::TypeRelative(_, method) = path
+        && method.ident.name == sym::new
+        && let Some(impl_did) = cx.tcx.impl_of_method(def_id)
+        && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
+    {
+        return std_types_symbols.iter().any(|&symbol| {
+            cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
+        });
     }
     false
 }
@@ -1030,6 +1024,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
         ExprKind::Call(from_func, [arg]) => is_default_equivalent_from(cx, from_func, arg),
         ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
         ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
+        ExprKind::Block(Block { stmts: [], expr, .. }, _) => expr.is_some_and(|e| is_default_equivalent(cx, e)),
         _ => false,
     }
 }
@@ -1206,12 +1201,10 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
             .adjustments()
             .get(child_id)
             .map_or(&[][..], |x| &**x)
-        {
-            if let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) =
+            && let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) =
                 *adjust.last().map_or(target, |a| a.target).kind()
-            {
-                return CaptureKind::Ref(mutability);
-            }
+        {
+            return CaptureKind::Ref(mutability);
         }
 
         match parent {
@@ -1739,10 +1732,10 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
 /// Checks whether the given expression is a constant literal of the given value.
 pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
     // FIXME: use constant folding
-    if let ExprKind::Lit(spanned) = expr.kind {
-        if let LitKind::Int(v, _) = spanned.node {
-            return v == value;
-        }
+    if let ExprKind::Lit(spanned) = expr.kind
+        && let LitKind::Int(v, _) = spanned.node
+    {
+        return v == value;
     }
     false
 }
@@ -1779,10 +1772,10 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
             let data = span.ctxt().outer_expn_data();
             let new_span = data.call_site;
 
-            if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
-                if mac_name.as_str() == name {
-                    return Some(new_span);
-                }
+            if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind
+                && mac_name.as_str() == name
+            {
+                return Some(new_span);
             }
 
             span = new_span;
@@ -1808,10 +1801,10 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
         let data = span.ctxt().outer_expn_data();
         let new_span = data.call_site;
 
-        if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
-            if mac_name.as_str() == name {
-                return Some(new_span);
-            }
+        if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind
+            && mac_name.as_str() == name
+        {
+            return Some(new_span);
         }
     }
 
@@ -1832,15 +1825,15 @@ pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId, nth: usize) ->
 
 /// Checks if an expression is constructing a tuple-like enum variant or struct
 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    if let ExprKind::Call(fun, _) = expr.kind {
-        if let ExprKind::Path(ref qp) = fun.kind {
-            let res = cx.qpath_res(qp, fun.hir_id);
-            return match res {
-                Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
-                Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
-                _ => false,
-            };
-        }
+    if let ExprKind::Call(fun, _) = expr.kind
+        && let ExprKind::Path(ref qp) = fun.kind
+    {
+        let res = cx.qpath_res(qp, fun.hir_id);
+        return match res {
+            Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
+            Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
+            _ => false,
+        };
     }
     false
 }
@@ -1914,10 +1907,10 @@ pub fn is_self(slf: &Param<'_>) -> bool {
 }
 
 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
-    if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind {
-        if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res {
-            return true;
-        }
+    if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind
+        && let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res
+    {
+        return true;
     }
     false
 }
@@ -2122,10 +2115,10 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
     }
 
     // final `else {..}`
-    if !blocks.is_empty() {
-        if let ExprKind::Block(block, _) = expr.kind {
-            blocks.push(block);
-        }
+    if !blocks.is_empty()
+        && let ExprKind::Block(block, _) = expr.kind
+    {
+        blocks.push(block);
     }
 
     (conds, blocks)
@@ -2140,26 +2133,34 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
     }
 }
 
-/// Peels away all the compiler generated code surrounding the body of an async function,
-pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
-    if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
-        if let ExprKind::Block(
+/// Peels away all the compiler generated code surrounding the body of an async closure.
+pub fn get_async_closure_expr<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+    if let ExprKind::Closure(&Closure {
+        body,
+        kind: hir::ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)),
+        ..
+    }) = expr.kind
+        && let ExprKind::Block(
             Block {
-                stmts: [],
                 expr:
                     Some(Expr {
-                        kind: ExprKind::DropTemps(expr),
+                        kind: ExprKind::DropTemps(inner_expr),
                         ..
                     }),
                 ..
             },
             _,
         ) = tcx.hir_body(body).value.kind
-        {
-            return Some(expr);
-        }
+    {
+        Some(inner_expr)
+    } else {
+        None
     }
-    None
+}
+
+/// Peels away all the compiler generated code surrounding the body of an async function,
+pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
+    get_async_closure_expr(tcx, body.value)
 }
 
 // check if expr is calling method or function with #[must_use] attribute
@@ -2631,17 +2632,19 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>
 }
 
 pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
-    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
-        if let Res::Def(_, def_id) = path.res {
-            return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr);
-        }
+    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
+        && let Res::Def(_, def_id) = path.res
+    {
+        return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
     }
     false
 }
 
 static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalModDefId, Vec<Symbol>>>> = OnceLock::new();
 
-fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
+/// Apply `f()` to the set of test item names.
+/// The names are sorted using the default `Symbol` ordering.
+fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(&[Symbol]) -> bool) -> bool {
     let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
     let mut map: MutexGuard<'_, FxHashMap<LocalModDefId, Vec<Symbol>>> = cache.lock().unwrap();
     let value = map.entry(module);
@@ -2653,18 +2656,16 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
                 if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
                     && let item = tcx.hir_item(id)
                     && let ItemKind::Const(ident, ty, _generics, _body) = item.kind
-                {
-                    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
+                    && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
                         // We could also check for the type name `test::TestDescAndFn`
-                        if let Res::Def(DefKind::Struct, _) = path.res {
-                            let has_test_marker = tcx
-                                .hir_attrs(item.hir_id())
-                                .iter()
-                                .any(|a| a.has_name(sym::rustc_test_marker));
-                            if has_test_marker {
-                                names.push(ident.name);
-                            }
-                        }
+                        && let Res::Def(DefKind::Struct, _) = path.res
+                {
+                    let has_test_marker = tcx
+                        .hir_attrs(item.hir_id())
+                        .iter()
+                        .any(|a| a.has_name(sym::rustc_test_marker));
+                    if has_test_marker {
+                        names.push(ident.name);
                     }
                 }
             }
@@ -2685,18 +2686,37 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
             // Since you can nest functions we need to collect all until we leave
             // function scope
             .any(|(_id, node)| {
-                if let Node::Item(item) = node {
-                    if let ItemKind::Fn { ident, .. } = item.kind {
-                        // Note that we have sorted the item names in the visitor,
-                        // so the binary_search gets the same as `contains`, but faster.
-                        return names.binary_search(&ident.name).is_ok();
-                    }
+                if let Node::Item(item) = node
+                    && let ItemKind::Fn { ident, .. } = item.kind
+                {
+                    // Note that we have sorted the item names in the visitor,
+                    // so the binary_search gets the same as `contains`, but faster.
+                    return names.binary_search(&ident.name).is_ok();
                 }
                 false
             })
     })
 }
 
+/// Checks if `fn_def_id` has a `#[test]` attribute applied
+///
+/// This only checks directly applied attributes. To see if a node has a parent function marked with
+/// `#[test]` use [`is_in_test_function`].
+///
+/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function
+pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool {
+    let id = tcx.local_def_id_to_hir_id(fn_def_id);
+    if let Node::Item(item) = tcx.hir_node(id)
+        && let ItemKind::Fn { ident, .. } = item.kind
+    {
+        with_test_item_names(tcx, tcx.parent_module(id), |names| {
+            names.binary_search(&ident.name).is_ok()
+        })
+    } else {
+        false
+    }
+}
+
 /// Checks if `id` has a `#[cfg(test)]` attribute applied
 ///
 /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
@@ -3728,3 +3748,20 @@ pub fn peel_hir_ty_options<'tcx>(cx: &LateContext<'tcx>, mut hir_ty: &'tcx hir::
     }
     hir_ty
 }
+
+/// If `expr` is a desugared `.await`, return the original expression if it does not come from a
+/// macro expansion.
+pub 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_without_closures(into_future_arg, |e| {
+            walk_span_to_context(e.span, ctxt).map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(()))
+        })
+        .is_none()
+    {
+        Some(into_future_arg)
+    } else {
+        None
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
index ffcfcd240ea..9ba644fdd20 100644
--- a/src/tools/clippy/clippy_utils/src/mir/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -76,7 +76,7 @@ impl<'tcx> Visitor<'tcx> for V<'_> {
                 }
                 if matches!(
                     ctx,
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move | NonMutatingUseContext::Inspect)
                         | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
                 ) {
                     self.results[i].local_consume_or_mutate_locs.push(loc);
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 86f4f190b95..19061b574ff 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -1,10 +1,10 @@
+use crate::sym;
 use rustc_ast::Attribute;
 use rustc_ast::attr::AttributeExt;
-
 use rustc_attr_parsing::{RustcVersion, parse_version};
 use rustc_lint::LateContext;
 use rustc_session::Session;
-use rustc_span::{Symbol, sym};
+use rustc_span::Symbol;
 use serde::Deserialize;
 use smallvec::SmallVec;
 use std::iter::once;
@@ -24,10 +24,10 @@ macro_rules! msrv_aliases {
 msrv_aliases! {
     1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT }
     1,85,0 { UINT_FLOAT_MIDPOINT }
-    1,84,0 { CONST_OPTION_AS_SLICE }
+    1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR }
     1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP }
     1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
-    1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION }
+    1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION, DURATION_ABS_DIFF }
     1,80,0 { BOX_INTO_ITER, LAZY_CELL }
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
@@ -40,6 +40,7 @@ msrv_aliases! {
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
     1,63,0 { CLONE_INTO }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN }
+    1,60,0 { ABS_DIFF }
     1,59,0 { THREAD_LOCAL_CONST_INIT }
     1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
     1,57,0 { MAP_WHILE }
@@ -63,6 +64,7 @@ msrv_aliases! {
     1,35,0 { OPTION_COPIED, RANGE_CONTAINS }
     1,34,0 { TRY_FROM }
     1,33,0 { UNDERSCORE_IMPORTS }
+    1,32,0 { CONST_IS_POWER_OF_TWO }
     1,31,0 { OPTION_REPLACE }
     1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
     1,29,0 { ITER_FLATTEN }
@@ -182,8 +184,7 @@ impl MsrvStack {
 }
 
 fn parse_attrs(sess: &Session, attrs: &[impl AttributeExt]) -> Option<RustcVersion> {
-    let sym_msrv = Symbol::intern("msrv");
-    let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv]));
+    let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym::msrv]));
 
     if let Some(msrv_attr) = msrv_attrs.next() {
         if let Some(duplicate) = msrv_attrs.next_back() {
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 51d06ad9b1a..7f64ebd3b64 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -30,9 +30,11 @@ pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]
 pub const CHAR_IS_ASCII: [&str; 5] = ["core", "char", "methods", "<impl char>", "is_ascii"];
 pub const IO_ERROR_NEW: [&str; 5] = ["std", "io", "error", "Error", "new"];
 pub const IO_ERRORKIND_OTHER: [&str; 5] = ["std", "io", "error", "ErrorKind", "Other"];
+pub const ALIGN_OF: [&str; 3] = ["core", "mem", "align_of"];
 
 // Paths in clippy itself
 pub const MSRV_STACK: [&str; 3] = ["clippy_utils", "msrvs", "MsrvStack"];
+pub const CLIPPY_SYM_MODULE: [&str; 2] = ["clippy_utils", "sym"];
 
 // Paths in external crates
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 80066e9702d..8645d5730fe 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -142,7 +142,20 @@ pub trait SpanRangeExt: SpanRange {
         map_range(cx.sess().source_map(), self.into_range(), f)
     }
 
-    /// Extends the range to include all preceding whitespace characters.
+    #[allow(rustdoc::invalid_rust_codeblocks, reason = "The codeblock is intentionally broken")]
+    /// Extends the range to include all preceding whitespace characters, unless there
+    /// are non-whitespace characters left on the same line after `self`.
+    ///
+    /// This extra condition prevents a problem when removing the '}' in:
+    /// ```ignore
+    ///   ( // There was an opening bracket after the parenthesis, which has been removed
+    ///     // This is a comment
+    ///    })
+    /// ```
+    /// Removing the whitespaces, including the linefeed, before the '}', would put the
+    /// closing parenthesis at the end of the `// This is a comment` line, which would
+    /// make it part of the comment as well. In this case, it is best to keep the span
+    /// on the '}' alone.
     fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
         with_leading_whitespace(cx.sess().source_map(), self.into_range())
     }
@@ -263,10 +276,15 @@ fn map_range(
 }
 
 fn with_leading_whitespace(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
-    map_range(sm, sp.clone(), |src, range| {
-        Some(src.get(..range.start)?.trim_end().len()..range.end)
+    map_range(sm, sp, |src, range| {
+        let non_blank_after = src.len() - src.get(range.end..)?.trim_start().len();
+        if src.get(range.end..non_blank_after)?.contains(['\r', '\n']) {
+            Some(src.get(..range.start)?.trim_end().len()..range.end)
+        } else {
+            Some(range)
+        }
     })
-    .unwrap_or(sp)
+    .unwrap()
 }
 
 fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
@@ -384,10 +402,10 @@ pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option<String> {
 // For some reason these attributes don't have any expansion info on them, so
 // we have to check it this way until there is a better way.
 pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool {
-    if let Some(snippet) = snippet_opt(sess, span) {
-        if snippet.is_empty() {
-            return false;
-        }
+    if let Some(snippet) = snippet_opt(sess, span)
+        && snippet.is_empty()
+    {
+        return false;
     }
     true
 }
@@ -408,11 +426,11 @@ pub fn position_before_rarrow(s: &str) -> Option<usize> {
         let mut rpos = rpos;
         let chars: Vec<char> = s.chars().collect();
         while rpos > 1 {
-            if let Some(c) = chars.get(rpos - 1) {
-                if c.is_whitespace() {
-                    rpos -= 1;
-                    continue;
-                }
+            if let Some(c) = chars.get(rpos - 1)
+                && c.is_whitespace()
+            {
+                rpos -= 1;
+                continue;
             }
             break;
         }
diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs
index 421b25a77fe..f0f82c8dddc 100644
--- a/src/tools/clippy/clippy_utils/src/str_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/str_utils.rs
@@ -1,4 +1,4 @@
-/// Dealing with sting indices can be hard, this struct ensures that both the
+/// Dealing with string indices can be hard, this struct ensures that both the
 /// character and byte index are provided for correct indexing.
 #[derive(Debug, Default, PartialEq, Eq)]
 pub struct StrIndex {
@@ -165,7 +165,7 @@ pub fn camel_case_split(s: &str) -> Vec<&str> {
     offsets.windows(2).map(|w| &s[w[0]..w[1]]).collect()
 }
 
-/// Dealing with sting comparison can be complicated, this struct ensures that both the
+/// Dealing with string comparison can be complicated, this struct ensures that both the
 /// character and byte count are provided for correct indexing.
 #[derive(Debug, Default, PartialEq, Eq)]
 pub struct StrCount {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index e92c0c79b25..93dec113d31 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -326,7 +326,7 @@ impl<'a> Sugg<'a> {
     /// `self` argument of a method call
     /// (e.g., to build `bar.foo()` or `(1 + 2).foo()`).
     #[must_use]
-    pub fn maybe_par(self) -> Self {
+    pub fn maybe_paren(self) -> Self {
         match self {
             Sugg::NonParen(..) => self,
             // `(x)` and `(x).y()` both don't need additional parens.
@@ -494,7 +494,7 @@ impl<T: Display> Display for ParenHelper<T> {
 /// operators have the same
 /// precedence.
 pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
-    Sugg::MaybeParen(format!("{op}{}", expr.maybe_par()).into())
+    Sugg::MaybeParen(format!("{op}{}", expr.maybe_paren()).into())
 }
 
 /// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
@@ -946,10 +946,9 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                             // some items do not need explicit deref, such as array accesses,
                             // so we mark them as already processed
                             // i.e.: don't suggest `*sub[1..4].len()` for `|sub| sub[1..4].len() == 3`
-                            if let ty::Ref(_, inner, _) = cmt.place.ty_before_projection(i).kind() {
-                                if matches!(inner.kind(), ty::Ref(_, innermost, _) if innermost.is_array()) {
-                                    projections_handled = true;
-                                }
+                            if let ty::Ref(_, inner, _) = cmt.place.ty_before_projection(i).kind()
+                                && matches!(inner.kind(), ty::Ref(_, innermost, _) if innermost.is_array()) {
+                                projections_handled = true;
                             }
                         },
                     }
@@ -1008,12 +1007,12 @@ mod test {
     }
 
     #[test]
-    fn binop_maybe_par() {
+    fn binop_maybe_paren() {
         let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "1".into(), "1".into());
-        assert_eq!("(1 + 1)", sugg.maybe_par().to_string());
+        assert_eq!("(1 + 1)", sugg.maybe_paren().to_string());
 
         let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into());
-        assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string());
+        assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_paren().to_string());
     }
     #[test]
     fn not_op() {
diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs
index 9cc72a5b3aa..1a30b473d10 100644
--- a/src/tools/clippy/clippy_utils/src/sym.rs
+++ b/src/tools/clippy/clippy_utils/src/sym.rs
@@ -1,23 +1,69 @@
 #![allow(non_upper_case_globals)]
 
-use rustc_span::symbol::{Symbol, PREDEFINED_SYMBOLS_COUNT};
+use rustc_span::symbol::{PREDEFINED_SYMBOLS_COUNT, Symbol};
 
+#[doc(no_inline)]
 pub use rustc_span::sym::*;
 
+macro_rules! val {
+    ($name:ident) => {
+        stringify!($name)
+    };
+    ($name:ident $value:literal) => {
+        $value
+    };
+}
+
 macro_rules! generate {
-    ($($sym:ident,)*) => {
+    ($($name:ident $(: $value:literal)? ,)*) => {
         /// To be supplied to `rustc_interface::Config`
         pub const EXTRA_SYMBOLS: &[&str] = &[
-            $(stringify!($sym),)*
+            $(
+                val!($name $($value)?),
+            )*
         ];
 
         $(
-            pub const $sym: Symbol = Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()});
+            pub const $name: Symbol = Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()});
         )*
     };
 }
 
 generate! {
+    as_bytes,
+    as_deref_mut,
+    as_deref,
+    as_mut,
+    Binary,
+    Cargo_toml: "Cargo.toml",
+    CLIPPY_ARGS,
+    CLIPPY_CONF_DIR,
+    cloned,
+    contains,
+    copied,
+    Current,
+    get,
+    insert,
+    int_roundings,
+    IntoIter,
+    is_empty,
+    is_ok,
+    is_some,
+    LowerExp,
+    LowerHex,
+    msrv,
+    Octal,
+    or_default,
+    regex,
     rustfmt_skip,
+    Start,
+    to_owned,
     unused_extern_crates,
+    unwrap_err,
+    unwrap_or_default,
+    UpperExp,
+    UpperHex,
+    V4,
+    V6,
+    Weak,
 }
diff --git a/src/tools/clippy/clippy_utils/src/sym_helper.rs b/src/tools/clippy/clippy_utils/src/sym_helper.rs
deleted file mode 100644
index f47dc80ebad..00000000000
--- a/src/tools/clippy/clippy_utils/src/sym_helper.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#[macro_export]
-/// Convenience wrapper around rustc's `Symbol::intern`
-macro_rules! sym {
-    ($tt:tt) => {
-        rustc_span::symbol::Symbol::intern(stringify!($tt))
-    };
-}
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index d33e59342a5..8db9cd593b3 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -19,9 +19,9 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::traits::EvaluationResult;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{
-    self, AdtDef, AliasTy, AssocItem, AssocTag, 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, AssocTag, 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::{DUMMY_SP, Span, Symbol, sym};
@@ -128,10 +128,10 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                             // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
                             // so we check the term for `U`.
                             ty::ClauseKind::Projection(projection_predicate) => {
-                                if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
-                                    if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
-                                        return true;
-                                    }
+                                if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack()
+                                    && contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen)
+                                {
+                                    return true;
                                 }
                             },
                             _ => (),
@@ -337,20 +337,20 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)),
         ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() {
-                if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
-                    if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
-                        return true;
-                    }
+                if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
+                    && cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use)
+                {
+                    return true;
                 }
             }
             false
         },
         ty::Dynamic(binder, _, _) => {
             for predicate in *binder {
-                if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
-                    if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) {
-                        return true;
-                    }
+                if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
+                    && cx.tcx.has_attr(trait_ref.def_id, sym::must_use)
+                {
+                    return true;
                 }
             }
             false
@@ -1352,7 +1352,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n
     }
 }
 
-/// Get's the type of a field by name.
+/// Gets the type of a field by name.
 pub fn get_field_by_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
     match *ty.kind() {
         ty::Adt(def, args) if def.is_union() || def.is_struct() => def
@@ -1376,3 +1376,49 @@ pub fn option_arg_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
         _ => None,
     }
 }
+
+/// Check if a Ty<'_> of `Iterator` contains any mutable access to non-owning types by checking if
+/// it contains fields of mutable references or pointers, or references/pointers to non-`Freeze`
+/// types, or `PhantomData` types containing any of the previous. This can be used to check whether
+/// skipping iterating over an iterator will change its behavior.
+pub fn has_non_owning_mutable_access<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>) -> bool {
+    fn normalize_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+        cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty)
+    }
+
+    /// Check if `ty` contains mutable references or equivalent, which includes:
+    /// - A mutable reference/pointer.
+    /// - A reference/pointer to a non-`Freeze` type.
+    /// - A `PhantomData` type containing any of the previous.
+    fn has_non_owning_mutable_access_inner<'tcx>(
+        cx: &LateContext<'tcx>,
+        phantoms: &mut FxHashSet<Ty<'tcx>>,
+        ty: Ty<'tcx>,
+    ) -> bool {
+        match ty.kind() {
+            ty::Adt(adt_def, args) if adt_def.is_phantom_data() => {
+                phantoms.insert(ty)
+                    && args
+                        .types()
+                        .any(|arg_ty| has_non_owning_mutable_access_inner(cx, phantoms, arg_ty))
+            },
+            ty::Adt(adt_def, args) => adt_def.all_fields().any(|field| {
+                has_non_owning_mutable_access_inner(cx, phantoms, normalize_ty(cx, field.ty(cx.tcx, args)))
+            }),
+            ty::Array(elem_ty, _) | ty::Slice(elem_ty) => has_non_owning_mutable_access_inner(cx, phantoms, *elem_ty),
+            ty::RawPtr(pointee_ty, mutability) | ty::Ref(_, pointee_ty, mutability) => {
+                mutability.is_mut() || !pointee_ty.is_freeze(cx.tcx, cx.typing_env())
+            },
+            ty::Closure(_, closure_args) => {
+                matches!(closure_args.types().next_back(), Some(captures) if has_non_owning_mutable_access_inner(cx, phantoms, captures))
+            },
+            ty::Tuple(tuple_args) => tuple_args
+                .iter()
+                .any(|arg_ty| has_non_owning_mutable_access_inner(cx, phantoms, arg_ty)),
+            _ => false,
+        }
+    }
+
+    let mut phantoms = FxHashSet::default();
+    has_non_owning_mutable_access_inner(cx, &mut phantoms, iter_ty)
+}
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index a079fd940c0..1b049b6d12c 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -126,10 +126,10 @@ impl<'tcx> Visitor<'tcx> for BindingUsageFinder<'_, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) -> Self::Result {
-        if let Res::Local(id) = path.res {
-            if self.binding_ids.contains(&id) {
-                return ControlFlow::Break(());
-            }
+        if let Res::Local(id) = path.res
+            && self.binding_ids.contains(&id)
+        {
+            return ControlFlow::Break(());
         }
 
         ControlFlow::Continue(())
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 63dd00f2de0..fc6e30a9804 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -297,10 +297,10 @@ 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(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(());
-            }
+        if let ExprKind::Path(p) = &e.kind
+            && cx.qpath_res(p, e.hir_id) == res
+        {
+            return ControlFlow::Break(());
         }
         ControlFlow::Continue(())
     })
diff --git a/src/tools/clippy/lintcheck/ci-config/clippy.toml b/src/tools/clippy/lintcheck/ci-config/clippy.toml
new file mode 100644
index 00000000000..9853465c83f
--- /dev/null
+++ b/src/tools/clippy/lintcheck/ci-config/clippy.toml
@@ -0,0 +1,7 @@
+# Configuration applied when running lintcheck from the CI
+#
+# The CI will set the `CLIPPY_CONF_DIR` environment variable
+# to `$PWD/lintcheck/ci-config`.
+
+avoid-breaking-exported-api = false
+lint-commented-code = false
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 8d0d41ab945..fe488ef89da 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -120,14 +120,17 @@ impl Crate {
 
         if config.perf {
             cmd = Command::new("perf");
+            let perf_data_filename = get_perf_data_filename(&self.path);
             cmd.args(&[
                 "record",
                 "-e",
                 "instructions", // Only count instructions
                 "-g",           // Enable call-graph, useful for flamegraphs and produces richer reports
                 "--quiet",      // Do not tamper with lintcheck's normal output
+                "--compression-level=22",
+                "--freq=3000", // Slow down program to capture all events
                 "-o",
-                "perf.data",
+                &perf_data_filename,
                 "--",
                 "cargo",
             ]);
@@ -165,7 +168,7 @@ impl Crate {
             return Vec::new();
         }
 
-        if !config.fix {
+        if !config.fix && !config.perf {
             cmd.arg("--message-format=json");
         }
 
@@ -203,6 +206,11 @@ impl Crate {
             return Vec::new();
         }
 
+        // We don't want to keep target directories if benchmarking
+        if config.perf {
+            let _ = fs::remove_dir_all(&shared_target_dir);
+        }
+
         // get all clippy warnings and ICEs
         let mut entries: Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
             .filter_map(|msg| match msg {
@@ -441,6 +449,35 @@ fn lintcheck(config: LintcheckConfig) {
     fs::write(&config.lintcheck_results_path, text).unwrap();
 }
 
+/// Traverse a directory looking for `perf.data.<number>` files, and adds one
+/// to the most recent of those files, returning the new most recent `perf.data`
+/// file name.
+fn get_perf_data_filename(source_path: &Path) -> String {
+    if source_path.join("perf.data").exists() {
+        let mut max_number = 0;
+        fs::read_dir(source_path)
+            .unwrap()
+            .filter_map(Result::ok)
+            .filter(|path| {
+                path.file_name()
+                    .as_os_str()
+                    .to_string_lossy() // We don't care about data loss, as we're checking for equality
+                    .starts_with("perf.data")
+            })
+            .for_each(|path| {
+                let file_name = path.file_name();
+                let file_name = file_name.as_os_str().to_str().unwrap().split('.').next_back().unwrap();
+                if let Ok(parsed_file_name) = file_name.parse::<usize>()
+                    && parsed_file_name >= max_number
+                {
+                    max_number = parsed_file_name + 1;
+                }
+            });
+        return format!("perf.data.{max_number}");
+    }
+    String::from("perf.data")
+}
+
 /// Returns the path to the Clippy project directory
 #[must_use]
 fn clippy_project_root() -> &'static Path {
diff --git a/src/tools/clippy/lintcheck/src/recursive.rs b/src/tools/clippy/lintcheck/src/recursive.rs
index 57073f52364..6406b2dcb64 100644
--- a/src/tools/clippy/lintcheck/src/recursive.rs
+++ b/src/tools/clippy/lintcheck/src/recursive.rs
@@ -64,7 +64,7 @@ fn process_stream(
 
     // It's 99% likely that dependencies compiled with recursive mode are on crates.io
     // and therefore on docs.rs. This links to the sources directly, do avoid invalid
-    // links due to remaped paths. See rust-lang/docs.rs#2551 for more details.
+    // links due to remapped paths. See rust-lang/docs.rs#2551 for more details.
     let base_url = format!(
         "https://docs.rs/crate/{}/{}/source/src/{{file}}#{{line}}",
         driver_info.package_name, driver_info.version
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain.toml
index fcaeedc9a66..d2f79da1a54 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain.toml
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2025-03-20"
+channel = "nightly-2025-04-22"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/rustc_tools_util/src/lib.rs b/src/tools/clippy/rustc_tools_util/src/lib.rs
index 423154a69fa..b45edf23455 100644
--- a/src/tools/clippy/rustc_tools_util/src/lib.rs
+++ b/src/tools/clippy/rustc_tools_util/src/lib.rs
@@ -121,7 +121,7 @@ fn get_output(cmd: &str, args: &[&str]) -> Option<String> {
 pub fn rerun_if_git_changes() -> Option<()> {
     // Make sure we get rerun when the git commit changes.
     // We want to watch two files: HEAD, which tracks which branch we are on,
-    // and the file for that branch that tracks which commit is is on.
+    // and the file for that branch that tracks which commit is checked out.
 
     // First, find the `HEAD` file. This should work even with worktrees.
     let git_head_file = PathBuf::from(get_output("git", &["rev-parse", "--git-path", "HEAD"])?);
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index df9c4e8e6ae..87ca9c5bedd 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -14,6 +14,7 @@ extern crate rustc_interface;
 extern crate rustc_session;
 extern crate rustc_span;
 
+use clippy_utils::sym;
 use rustc_interface::interface;
 use rustc_session::EarlyDiagCtxt;
 use rustc_session::config::ErrorOutputType;
@@ -78,7 +79,7 @@ fn track_clippy_args(psess: &mut ParseSess, args_env_var: Option<&str>) {
     psess
         .env_depinfo
         .get_mut()
-        .insert((Symbol::intern("CLIPPY_ARGS"), args_env_var.map(Symbol::intern)));
+        .insert((sym::CLIPPY_ARGS, args_env_var.map(Symbol::intern)));
 }
 
 /// Track files that may be accessed at runtime in `file_depinfo` so that cargo will re-run clippy
@@ -89,7 +90,7 @@ fn track_files(psess: &mut ParseSess) {
     // Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver`
     // with the current directory set to `CARGO_MANIFEST_DIR` so a relative path is fine
     if Path::new("Cargo.toml").exists() {
-        file_depinfo.insert(Symbol::intern("Cargo.toml"));
+        file_depinfo.insert(sym::Cargo_toml);
     }
 
     // `clippy.toml` will be automatically tracked as it's loaded with `sess.source_map().load_file()`
@@ -145,7 +146,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
             // Trigger a rebuild if CLIPPY_CONF_DIR changes. The value must be a valid string so
             // changes between dirs that are invalid UTF-8 will not trigger rebuilds
             psess.env_depinfo.get_mut().insert((
-                Symbol::intern("CLIPPY_CONF_DIR"),
+                sym::CLIPPY_CONF_DIR,
                 env::var("CLIPPY_CONF_DIR").ok().map(|dir| Symbol::intern(&dir)),
             ));
         }));
@@ -158,9 +159,10 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
 
             let conf = clippy_config::Conf::read(sess, &conf_path);
             clippy_lints::register_lints(lint_store, conf);
-            clippy_lints::register_pre_expansion_lints(lint_store, conf);
+            #[cfg(feature = "internal")]
+            clippy_lints_internal::register_lints(lint_store);
         }));
-        config.extra_symbols = clippy_utils::sym::EXTRA_SYMBOLS.into();
+        config.extra_symbols = sym::EXTRA_SYMBOLS.into();
 
         // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
         // run on the unoptimized MIR. On the other hand this results in some false negatives. If
@@ -208,12 +210,12 @@ pub fn main() {
             // Beside checking for existence of `--sysroot` on the command line, we need to
             // check for the arg files that are prefixed with @ as well to be consistent with rustc
             for arg in args.iter() {
-                if let Some(arg_file_path) = arg.strip_prefix('@') {
-                    if let Ok(arg_file) = read_to_string(arg_file_path) {
-                        let split_arg_file: Vec<String> = arg_file.lines().map(ToString::to_string).collect();
-                        if has_arg(&split_arg_file, "--sysroot") {
-                            return true;
-                        }
+                if let Some(arg_file_path) = arg.strip_prefix('@')
+                    && let Ok(arg_file) = read_to_string(arg_file_path)
+                {
+                    let split_arg_file: Vec<String> = arg_file.lines().map(ToString::to_string).collect();
+                    if has_arg(&split_arg_file, "--sysroot") {
+                        return true;
                     }
                 }
             }
@@ -222,10 +224,10 @@ pub fn main() {
 
         let sys_root_env = std::env::var("SYSROOT").ok();
         let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
-            if let Some(sys_root) = sys_root_env {
-                if !has_sysroot_arg(args) {
-                    args.extend(vec!["--sysroot".into(), sys_root]);
-                }
+            if let Some(sys_root) = sys_root_env
+                && !has_sysroot_arg(args)
+            {
+                args.extend(vec!["--sysroot".into(), sys_root]);
             }
         };
 
diff --git a/src/tools/clippy/tests/clippy.toml b/src/tools/clippy/tests/clippy.toml
index 5eb7ac03541..91a2e55180b 100644
--- a/src/tools/clippy/tests/clippy.toml
+++ b/src/tools/clippy/tests/clippy.toml
@@ -1 +1,2 @@
 # default config for tests, overrides clippy.toml at the project root
+lint-commented-code = false
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 956a05288f3..6d391bd622a 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -2,6 +2,8 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(unused_extern_crates)]
 
+use askama::Template;
+use askama::filters::Safe;
 use cargo_metadata::Message;
 use cargo_metadata::diagnostic::{Applicability, Diagnostic};
 use clippy_config::ClippyConfiguration;
@@ -9,11 +11,10 @@ use clippy_lints::LintInfo;
 use clippy_lints::declared_lints::LINTS;
 use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED};
 use pulldown_cmark::{Options, Parser, html};
-use rinja::Template;
-use rinja::filters::Safe;
 use serde::Deserialize;
 use test_utils::IS_RUSTC_TEST_SUITE;
 use ui_test::custom_flags::Flag;
+use ui_test::custom_flags::edition::Edition;
 use ui_test::custom_flags::rustfix::RustfixMode;
 use ui_test::spanned::Spanned;
 use ui_test::{Args, CommandBuilder, Config, Match, error_on_output_conflict, status_emitter};
@@ -86,13 +87,13 @@ fn extern_flags() -> Vec<String> {
             let name = name.strip_prefix("lib").unwrap_or(name);
             Some((name, path_str))
         };
-        if let Some((name, path)) = parse_name_path() {
-            if TEST_DEPENDENCIES.contains(&name) {
-                // A dependency may be listed twice if it is available in sysroot,
-                // and the sysroot dependencies are listed first. As of the writing,
-                // this only seems to apply to if_chain.
-                crates.insert(name, path);
-            }
+        if let Some((name, path)) = parse_name_path()
+            && TEST_DEPENDENCIES.contains(&name)
+        {
+            // A dependency may be listed twice if it is available in sysroot,
+            // and the sysroot dependencies are listed first. As of the writing,
+            // this only seems to apply to if_chain.
+            crates.insert(name, path);
         }
     }
     let not_found: Vec<&str> = TEST_DEPENDENCIES
@@ -147,11 +148,16 @@ impl TestContext {
                 .map(|filters| filters.split(',').map(str::to_string).collect())
                 .unwrap_or_default(),
             target: None,
-            bless_command: Some("cargo uibless".into()),
+            bless_command: Some(if IS_RUSTC_TEST_SUITE {
+                "./x test src/tools/clippy --bless".into()
+            } else {
+                "cargo uibless".into()
+            }),
             out_dir: target_dir.join("ui_test"),
             ..Config::rustc(Path::new("tests").join(test_dir))
         };
         let defaults = config.comment_defaults.base();
+        defaults.set_custom("edition", Edition("2024".into()));
         defaults.exit_status = None.into();
         if mandatory_annotations {
             defaults.require_annotations = Some(Spanned::dummy(true)).into();
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 858be389a9e..16a1a415102 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -36,6 +36,7 @@ fn dogfood() {
     for package in [
         "./",
         "clippy_dev",
+        "clippy_lints_internal",
         "clippy_lints",
         "clippy_utils",
         "clippy_config",
@@ -80,11 +81,9 @@ fn run_clippy_for_package(project: &str, args: &[&str]) -> bool {
 
     command.arg("--").args(args);
     command.arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
+    command.args(["-D", "clippy::dbg_macro"]);
 
-    if cfg!(feature = "internal") {
-        // internal lints only exist if we build with the internal feature
-        command.args(["-D", "clippy::internal"]);
-    } else {
+    if !cfg!(feature = "internal") {
         // running a clippy built without internal lints on the clippy source
         // that contains e.g. `allow(clippy::invalid_paths)`
         command.args(["-A", "unknown_lints"]);
diff --git a/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs b/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs
index 52fcaec4df3..f730f564a09 100644
--- a/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs
+++ b/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs
@@ -1,2 +1,4 @@
+#![allow(clippy::unnecessary_def_path)]
+
 pub static OPTION: [&str; 3] = ["core", "option", "Option"];
 pub const RESULT: &[&str] = &["core", "result", "Result"];
diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs
index e5f6001b74d..897002949e6 100644
--- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs
+++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs
@@ -1,5 +1,5 @@
-#![deny(clippy::internal)]
 #![feature(rustc_private)]
+#![deny(clippy::invalid_clippy_version_attribute, clippy::missing_clippy_version_attribute)]
 
 #[macro_use]
 extern crate rustc_middle;
@@ -86,6 +86,15 @@ mod internal_clippy_lints {
 }
 
 use crate::internal_clippy_lints::ALLOW_MISSING_ATTRIBUTE_ONE;
-declare_lint_pass!(Pass2 => [VALID_ONE, VALID_TWO, VALID_THREE, INVALID_ONE, INVALID_TWO, MISSING_ATTRIBUTE_ONE, MISSING_ATTRIBUTE_TWO, ALLOW_MISSING_ATTRIBUTE_ONE]);
+declare_lint_pass!(Pass2 => [
+    VALID_ONE,
+    VALID_TWO,
+    VALID_THREE,
+    INVALID_ONE,
+    INVALID_TWO,
+    MISSING_ATTRIBUTE_ONE,
+    MISSING_ATTRIBUTE_TWO,
+    ALLOW_MISSING_ATTRIBUTE_ONE,
+]);
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr
index 1129c35d1d0..952bc944030 100644
--- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr
+++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr
@@ -12,11 +12,10 @@ LL | | }
    |
    = help: please use a valid semantic version, see `doc/adding_lints.md`
 note: the lint level is defined here
-  --> tests/ui-internal/check_clippy_version_attribute.rs:1:9
+  --> tests/ui-internal/check_clippy_version_attribute.rs:2:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::invalid_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::invalid_clippy_version_attribute, clippy::missing_clippy_version_attribute)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this item has an invalid `clippy::version` attribute
@@ -47,7 +46,11 @@ LL | | }
    | |_^
    |
    = help: please use a `clippy::version` attribute, see `doc/adding_lints.md`
-   = note: `#[deny(clippy::missing_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
+note: the lint level is defined here
+  --> tests/ui-internal/check_clippy_version_attribute.rs:2:51
+   |
+LL | #![deny(clippy::invalid_clippy_version_attribute, clippy::missing_clippy_version_attribute)]
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this lint is missing the `clippy::version` attribute or version value
diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.rs b/src/tools/clippy/tests/ui-internal/check_formulation.rs
index 8265a78769d..bcbb0d78319 100644
--- a/src/tools/clippy/tests/ui-internal/check_formulation.rs
+++ b/src/tools/clippy/tests/ui-internal/check_formulation.rs
@@ -1,4 +1,5 @@
-#![warn(clippy::almost_standard_lint_formulation)]
+#![deny(clippy::almost_standard_lint_formulation)]
+#![allow(clippy::lint_without_lint_pass)]
 #![feature(rustc_private)]
 
 #[macro_use]
diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.stderr b/src/tools/clippy/tests/ui-internal/check_formulation.stderr
index b16e1bf8687..9aeb9e1f2d4 100644
--- a/src/tools/clippy/tests/ui-internal/check_formulation.stderr
+++ b/src/tools/clippy/tests/ui-internal/check_formulation.stderr
@@ -1,15 +1,18 @@
 error: non-standard lint formulation
-  --> tests/ui-internal/check_formulation.rs:23:5
+  --> tests/ui-internal/check_formulation.rs:24:5
    |
 LL |     /// Check for lint formulations that are correct
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using `Checks for`
-   = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::almost_standard_lint_formulation)]`
+note: the lint level is defined here
+  --> tests/ui-internal/check_formulation.rs:1:9
+   |
+LL | #![deny(clippy::almost_standard_lint_formulation)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: non-standard lint formulation
-  --> tests/ui-internal/check_formulation.rs:34:5
+  --> tests/ui-internal/check_formulation.rs:35:5
    |
 LL |     /// Detects uses of incorrect formulations
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
index 918e33345a7..76f68686ee2 100644
--- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
+++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::collapsible_span_lint_calls)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs
index 2f289ae2b48..214c8783a66 100644
--- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs
+++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::collapsible_span_lint_calls)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr
index a2be1f1cd36..9c83538947c 100644
--- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr
+++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr
@@ -10,9 +10,8 @@ LL | |         });
 note: the lint level is defined here
   --> tests/ui-internal/collapsible_span_lint_calls.rs:1:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::collapsible_span_lint_calls)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call is collapsible
   --> tests/ui-internal/collapsible_span_lint_calls.rs:39:9
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index 71819fe3707..c7e92b1bf16 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -6,7 +6,7 @@
 //@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc <version> running on <target>"
 //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
 
-#![deny(clippy::internal)]
+#![deny(clippy::produce_ice)]
 #![allow(clippy::missing_clippy_version_attribute)]
 
 fn it_looks_like_you_are_trying_to_kill_clippy() {}
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index 589e1190a90..884d3d035a2 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -8,7 +8,7 @@ error: internal compiler error: Would you like some help with that?
 LL | fn it_looks_like_you_are_trying_to_kill_clippy() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: delayed at clippy_lints/src/utils/internal_lints/produce_ice.rs - disabled backtrace
+note: delayed at clippy_lints_internal/src/produce_ice.rs - disabled backtrace
   --> tests/ui-internal/custom_ice_message.rs:12:1
    |
 LL | fn it_looks_like_you_are_trying_to_kill_clippy() {}
diff --git a/src/tools/clippy/tests/ui-internal/default_lint.rs b/src/tools/clippy/tests/ui-internal/default_lint.rs
index 959bfd27e38..809f2c4d080 100644
--- a/src/tools/clippy/tests/ui-internal/default_lint.rs
+++ b/src/tools/clippy/tests/ui-internal/default_lint.rs
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::default_lint)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/default_lint.stderr b/src/tools/clippy/tests/ui-internal/default_lint.stderr
index 9d4c2e15349..2c700ec82dc 100644
--- a/src/tools/clippy/tests/ui-internal/default_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/default_lint.stderr
@@ -13,9 +13,8 @@ LL | | }
 note: the lint level is defined here
   --> tests/ui-internal/default_lint.rs:1:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::default_lint)]
+   |         ^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
index 3fed38cab64..36e4158f6e6 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
@@ -1,4 +1,5 @@
 #![feature(rustc_private)]
+#![deny(clippy::disallowed_methods)]
 
 extern crate rustc_errors;
 extern crate rustc_hir;
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
index 9a7a7ecbbff..f03a745963e 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -1,15 +1,18 @@
 error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
-  --> tests/ui-internal/disallow_span_lint.rs:14:8
+  --> tests/ui-internal/disallow_span_lint.rs:15:8
    |
 LL |     cx.span_lint(lint, span, |lint| {
    |        ^^^^^^^^^
    |
    = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead
-   = note: `-D clippy::disallowed-methods` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
+note: the lint level is defined here
+  --> tests/ui-internal/disallow_span_lint.rs:2:9
+   |
+LL | #![deny(clippy::disallowed_methods)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint`
-  --> tests/ui-internal/disallow_span_lint.rs:21:9
+  --> tests/ui-internal/disallow_span_lint.rs:22:9
    |
 LL |     tcx.node_span_lint(lint, hir_id, span, |lint| {
    |         ^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed
deleted file mode 100644
index 92d3b1537e0..00000000000
--- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed
+++ /dev/null
@@ -1,40 +0,0 @@
-#![deny(clippy::internal)]
-#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
-#![feature(rustc_private)]
-
-extern crate rustc_span;
-
-use rustc_span::symbol::Symbol;
-
-macro_rules! sym {
-    ($tt:tt) => {
-        rustc_span::symbol::Symbol::intern(stringify!($tt))
-    };
-}
-
-fn main() {
-    // Direct use of Symbol::intern
-    let _ = rustc_span::sym::f32;
-    //~^ interning_defined_symbol
-
-    // Using a sym macro
-    let _ = rustc_span::sym::f32;
-    //~^ interning_defined_symbol
-
-    // Correct suggestion when symbol isn't stringified constant name
-    let _ = rustc_span::sym::proc_dash_macro;
-    //~^ interning_defined_symbol
-
-    // interning a keyword
-    let _ = rustc_span::kw::SelfLower;
-    //~^ interning_defined_symbol
-
-    // Interning a symbol that is not defined
-    let _ = Symbol::intern("xyz123");
-    let _ = sym!(xyz123);
-
-    // Using a different `intern` function
-    let _ = intern("f32");
-}
-
-fn intern(_: &str) {}
diff --git a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs
deleted file mode 100644
index d1e6f9cb1c4..00000000000
--- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#![deny(clippy::internal)]
-#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
-#![feature(rustc_private)]
-
-extern crate rustc_span;
-
-use rustc_span::symbol::Symbol;
-
-macro_rules! sym {
-    ($tt:tt) => {
-        rustc_span::symbol::Symbol::intern(stringify!($tt))
-    };
-}
-
-fn main() {
-    // Direct use of Symbol::intern
-    let _ = Symbol::intern("f32");
-    //~^ interning_defined_symbol
-
-    // Using a sym macro
-    let _ = sym!(f32);
-    //~^ interning_defined_symbol
-
-    // Correct suggestion when symbol isn't stringified constant name
-    let _ = Symbol::intern("proc-macro");
-    //~^ interning_defined_symbol
-
-    // interning a keyword
-    let _ = Symbol::intern("self");
-    //~^ interning_defined_symbol
-
-    // Interning a symbol that is not defined
-    let _ = Symbol::intern("xyz123");
-    let _ = sym!(xyz123);
-
-    // Using a different `intern` function
-    let _ = intern("f32");
-}
-
-fn intern(_: &str) {}
diff --git a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr
deleted file mode 100644
index c84a566436a..00000000000
--- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-error: interning a defined symbol
-  --> tests/ui-internal/interning_defined_symbol.rs:17:13
-   |
-LL |     let _ = Symbol::intern("f32");
-   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::f32`
-   |
-note: the lint level is defined here
-  --> tests/ui-internal/interning_defined_symbol.rs:1:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::interning_defined_symbol)]` implied by `#[deny(clippy::internal)]`
-
-error: interning a defined symbol
-  --> tests/ui-internal/interning_defined_symbol.rs:21:13
-   |
-LL |     let _ = sym!(f32);
-   |             ^^^^^^^^^ help: try: `rustc_span::sym::f32`
-
-error: interning a defined symbol
-  --> tests/ui-internal/interning_defined_symbol.rs:25:13
-   |
-LL |     let _ = Symbol::intern("proc-macro");
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::proc_dash_macro`
-
-error: interning a defined symbol
-  --> tests/ui-internal/interning_defined_symbol.rs:29:13
-   |
-LL |     let _ = Symbol::intern("self");
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::kw::SelfLower`
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui-internal/interning_literals.fixed b/src/tools/clippy/tests/ui-internal/interning_literals.fixed
new file mode 100644
index 00000000000..03e97768b99
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/interning_literals.fixed
@@ -0,0 +1,31 @@
+#![allow(clippy::let_unit_value)]
+#![feature(rustc_private)]
+
+extern crate rustc_span;
+
+use clippy_utils::sym;
+use rustc_span::{Symbol, kw};
+
+fn main() {
+    let _ = sym::f32;
+    //~^ interning_literals
+
+    // Correct suggestion when symbol isn't stringified constant name
+    let _ = sym::proc_dash_macro;
+    //~^ interning_literals
+
+    // Interning a keyword
+    let _ = kw::SelfLower;
+    //~^ interning_literals
+
+    // Defined in clippy_utils
+    let _ = sym::msrv;
+    //~^ interning_literals
+    let _ = sym::Cargo_toml;
+    //~^ interning_literals
+
+    // Using a different `intern` function
+    let _ = intern("f32");
+}
+
+fn intern(_: &str) {}
diff --git a/src/tools/clippy/tests/ui-internal/interning_literals.rs b/src/tools/clippy/tests/ui-internal/interning_literals.rs
new file mode 100644
index 00000000000..561fd5702a5
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/interning_literals.rs
@@ -0,0 +1,31 @@
+#![allow(clippy::let_unit_value)]
+#![feature(rustc_private)]
+
+extern crate rustc_span;
+
+use clippy_utils::sym;
+use rustc_span::{Symbol, kw};
+
+fn main() {
+    let _ = Symbol::intern("f32");
+    //~^ interning_literals
+
+    // Correct suggestion when symbol isn't stringified constant name
+    let _ = Symbol::intern("proc-macro");
+    //~^ interning_literals
+
+    // Interning a keyword
+    let _ = Symbol::intern("self");
+    //~^ interning_literals
+
+    // Defined in clippy_utils
+    let _ = Symbol::intern("msrv");
+    //~^ interning_literals
+    let _ = Symbol::intern("Cargo.toml");
+    //~^ interning_literals
+
+    // Using a different `intern` function
+    let _ = intern("f32");
+}
+
+fn intern(_: &str) {}
diff --git a/src/tools/clippy/tests/ui-internal/interning_literals.stderr b/src/tools/clippy/tests/ui-internal/interning_literals.stderr
new file mode 100644
index 00000000000..628b97eff84
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/interning_literals.stderr
@@ -0,0 +1,64 @@
+error: interning a string literal
+  --> tests/ui-internal/interning_literals.rs:10:13
+   |
+LL |     let _ = Symbol::intern("f32");
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::interning-literals` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::interning_literals)]`
+help: use the preinterned symbol
+   |
+LL -     let _ = Symbol::intern("f32");
+LL +     let _ = sym::f32;
+   |
+
+error: interning a string literal
+  --> tests/ui-internal/interning_literals.rs:14:13
+   |
+LL |     let _ = Symbol::intern("proc-macro");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     let _ = Symbol::intern("proc-macro");
+LL +     let _ = sym::proc_dash_macro;
+   |
+
+error: interning a string literal
+  --> tests/ui-internal/interning_literals.rs:18:13
+   |
+LL |     let _ = Symbol::intern("self");
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     let _ = Symbol::intern("self");
+LL +     let _ = kw::SelfLower;
+   |
+
+error: interning a string literal
+  --> tests/ui-internal/interning_literals.rs:22:13
+   |
+LL |     let _ = Symbol::intern("msrv");
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     let _ = Symbol::intern("msrv");
+LL +     let _ = sym::msrv;
+   |
+
+error: interning a string literal
+  --> tests/ui-internal/interning_literals.rs:24:13
+   |
+LL |     let _ = Symbol::intern("Cargo.toml");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     let _ = Symbol::intern("Cargo.toml");
+LL +     let _ = sym::Cargo_toml;
+   |
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/interning_literals_unfixable.rs b/src/tools/clippy/tests/ui-internal/interning_literals_unfixable.rs
new file mode 100644
index 00000000000..43872e95a58
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/interning_literals_unfixable.rs
@@ -0,0 +1,16 @@
+//@no-rustfix: paths that don't exist yet
+#![feature(rustc_private)]
+
+extern crate rustc_span;
+
+use rustc_span::Symbol;
+
+fn main() {
+    // Not yet defined
+    let _ = Symbol::intern("xyz123");
+    //~^ interning_literals
+    let _ = Symbol::intern("with-dash");
+    //~^ interning_literals
+    let _ = Symbol::intern("with.dot");
+    //~^ interning_literals
+}
diff --git a/src/tools/clippy/tests/ui-internal/interning_literals_unfixable.stderr b/src/tools/clippy/tests/ui-internal/interning_literals_unfixable.stderr
new file mode 100644
index 00000000000..8294453a8f9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/interning_literals_unfixable.stderr
@@ -0,0 +1,40 @@
+error: interning a string literal
+  --> tests/ui-internal/interning_literals_unfixable.rs:10:13
+   |
+LL |     let _ = Symbol::intern("xyz123");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::interning-literals` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::interning_literals)]`
+help: add the symbol to `clippy_utils/src/sym.rs` and use it
+   |
+LL -     let _ = Symbol::intern("xyz123");
+LL +     let _ = sym::xyz123;
+   |
+
+error: interning a string literal
+  --> tests/ui-internal/interning_literals_unfixable.rs:12:13
+   |
+LL |     let _ = Symbol::intern("with-dash");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add the symbol to `clippy_utils/src/sym.rs` and use it
+   |
+LL -     let _ = Symbol::intern("with-dash");
+LL +     let _ = sym::with_dash;
+   |
+
+error: interning a string literal
+  --> tests/ui-internal/interning_literals_unfixable.rs:14:13
+   |
+LL |     let _ = Symbol::intern("with.dot");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add the symbol to `clippy_utils/src/sym.rs` and use it
+   |
+LL -     let _ = Symbol::intern("with.dot");
+LL +     let _ = sym::with_dot;
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed
index 6804e2bbae8..238ef9ae6d0 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed
+++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::missing_msrv_attr_impl)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs
index c625a5d9a45..7753dcaad71 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs
+++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::missing_msrv_attr_impl)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr
index 0a7636313ef..d5928d8c0c2 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr
+++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr
@@ -7,9 +7,8 @@ LL | impl EarlyLintPass for Pass {
 note: the lint level is defined here
   --> tests/ui-internal/invalid_msrv_attr_impl.rs:1:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::missing_msrv_attr_impl)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::missing_msrv_attr_impl)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: add `extract_msrv_attr!()` to the `EarlyLintPass` implementation
    |
 LL ~ impl EarlyLintPass for Pass {
diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.rs b/src/tools/clippy/tests/ui-internal/invalid_paths.rs
index abfb111f938..7317abc2185 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_paths.rs
+++ b/src/tools/clippy/tests/ui-internal/invalid_paths.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::internal)]
+#![deny(clippy::invalid_paths)]
 #![allow(clippy::missing_clippy_version_attribute, clippy::unnecessary_def_path)]
 
 mod paths {
diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.stderr b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr
index 7bde37667be..7b7b25ce8d8 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_paths.stderr
+++ b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr
@@ -4,8 +4,11 @@ error: invalid path
 LL |     pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `-D clippy::invalid-paths` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::invalid_paths)]`
+note: the lint level is defined here
+  --> tests/ui-internal/invalid_paths.rs:1:9
+   |
+LL | #![deny(clippy::invalid_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid path
   --> tests/ui-internal/invalid_paths.rs:19:5
diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs
index 69591523432..6b649132aca 100644
--- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs
+++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::lint_without_lint_pass)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr
index 9cca96ca160..3798293f4c1 100644
--- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr
+++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr
@@ -13,9 +13,8 @@ LL | | }
 note: the lint level is defined here
   --> tests/ui-internal/lint_without_lint_pass.rs:1:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::lint_without_lint_pass)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed
index cb7680b8bb1..900ca5b2ab9 100644
--- a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed
+++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::outer_expn_expn_data)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs
index 41d735110b5..bcfc42aa2ac 100644
--- a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs
+++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs
@@ -1,4 +1,4 @@
-#![deny(clippy::internal)]
+#![deny(clippy::outer_expn_expn_data)]
 #![allow(clippy::missing_clippy_version_attribute)]
 #![feature(rustc_private)]
 
diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr
index 33ac91e4fb0..b86138a5d45 100644
--- a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr
+++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr
@@ -7,9 +7,8 @@ LL |         let _ = expr.span.ctxt().outer_expn().expn_data();
 note: the lint level is defined here
   --> tests/ui-internal/outer_expn_data.rs:1:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::outer_expn_expn_data)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::outer_expn_expn_data)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed
deleted file mode 100644
index 2cbd646a0fd..00000000000
--- a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.fixed
+++ /dev/null
@@ -1,24 +0,0 @@
-#![feature(rustc_private)]
-#![warn(clippy::slow_symbol_comparisons)]
-
-extern crate rustc_span;
-
-use clippy_utils::sym;
-use rustc_span::Symbol;
-
-fn main() {
-    let symbol = sym!(example);
-    let other_symbol = sym!(other_example);
-
-    // Should lint
-    let slow_comparison = symbol.as_str() == "example";
-    //~^ error: comparing `Symbol` via `Symbol::intern`
-    let slow_comparison_macro = symbol.as_str() == "example";
-    //~^ error: comparing `Symbol` via `Symbol::intern`
-    let slow_comparison_backwards = symbol.as_str() == "example";
-    //~^ error: comparing `Symbol` via `Symbol::intern`
-
-    // Should not lint
-    let faster_comparison = symbol.as_str() == "other_example";
-    let preinterned_comparison = symbol == other_symbol;
-}
diff --git a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs
deleted file mode 100644
index 0cea3c3fcff..00000000000
--- a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-#![feature(rustc_private)]
-#![warn(clippy::slow_symbol_comparisons)]
-
-extern crate rustc_span;
-
-use clippy_utils::sym;
-use rustc_span::Symbol;
-
-fn main() {
-    let symbol = sym!(example);
-    let other_symbol = sym!(other_example);
-
-    // Should lint
-    let slow_comparison = symbol == Symbol::intern("example");
-    //~^ error: comparing `Symbol` via `Symbol::intern`
-    let slow_comparison_macro = symbol == sym!(example);
-    //~^ error: comparing `Symbol` via `Symbol::intern`
-    let slow_comparison_backwards = sym!(example) == symbol;
-    //~^ error: comparing `Symbol` via `Symbol::intern`
-
-    // Should not lint
-    let faster_comparison = symbol.as_str() == "other_example";
-    let preinterned_comparison = symbol == other_symbol;
-}
diff --git a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr b/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr
deleted file mode 100644
index 72cb20a7fed..00000000000
--- a/src/tools/clippy/tests/ui-internal/slow_symbol_comparisons.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: comparing `Symbol` via `Symbol::intern`
-  --> tests/ui-internal/slow_symbol_comparisons.rs:14:27
-   |
-LL |     let slow_comparison = symbol == Symbol::intern("example");
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Symbol::as_str` and check the string instead: `symbol.as_str() == "example"`
-   |
-   = note: `-D clippy::slow-symbol-comparisons` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::slow_symbol_comparisons)]`
-
-error: comparing `Symbol` via `Symbol::intern`
-  --> tests/ui-internal/slow_symbol_comparisons.rs:16:33
-   |
-LL |     let slow_comparison_macro = symbol == sym!(example);
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ help: use `Symbol::as_str` and check the string instead: `symbol.as_str() == "example"`
-
-error: comparing `Symbol` via `Symbol::intern`
-  --> tests/ui-internal/slow_symbol_comparisons.rs:18:37
-   |
-LL |     let slow_comparison_backwards = sym!(example) == symbol;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^ help: use `Symbol::as_str` and check the string instead: `symbol.as_str() == "example"`
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
index 577fad9341b..89902ebe4e5 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -1,5 +1,5 @@
 //@aux-build:paths.rs
-#![deny(clippy::internal)]
+#![deny(clippy::unnecessary_def_path)]
 #![feature(rustc_private)]
 #![allow(clippy::unnecessary_map_or)]
 
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
index d4deb3626d0..cfca15267c1 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
@@ -1,5 +1,5 @@
 //@aux-build:paths.rs
-#![deny(clippy::internal)]
+#![deny(clippy::unnecessary_def_path)]
 #![feature(rustc_private)]
 #![allow(clippy::unnecessary_map_or)]
 
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
index 0053ba321bb..d7fb4ea551e 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
@@ -7,9 +7,8 @@ LL |     let _ = match_type(cx, ty, &OPTION);
 note: the lint level is defined here
   --> tests/ui-internal/unnecessary_def_path.rs:2:9
    |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]`
+LL | #![deny(clippy::unnecessary_def_path)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a def path to a diagnostic item
   --> tests/ui-internal/unnecessary_def_path.rs:39:13
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
index 4801d76bd26..bd7a55114ac 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
@@ -1,6 +1,6 @@
 #![feature(rustc_private)]
 #![allow(unused)]
-#![warn(clippy::unnecessary_def_path)]
+#![deny(clippy::unnecessary_def_path)]
 
 extern crate rustc_hir;
 
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index b9383951932..88fdf6f1c18 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -5,8 +5,11 @@ LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: convert all references to use `sym::Deref`
-   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::unnecessary_def_path)]`
+note: the lint level is defined here
+  --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:3:9
+   |
+LL | #![deny(clippy::unnecessary_def_path)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: hardcoded path to a language item
   --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:12:40
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed
deleted file mode 100644
index dc564daef82..00000000000
--- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed
+++ /dev/null
@@ -1,26 +0,0 @@
-#![feature(rustc_private)]
-#![deny(clippy::internal)]
-#![allow(
-    clippy::slow_symbol_comparisons,
-    clippy::borrow_deref_ref,
-    clippy::unnecessary_operation,
-    unused_must_use,
-    clippy::missing_clippy_version_attribute
-)]
-
-extern crate rustc_span;
-
-use rustc_span::symbol::{Ident, Symbol};
-
-fn main() {
-    Symbol::intern("foo") == rustc_span::sym::clippy;
-    //~^ unnecessary_symbol_str
-    Symbol::intern("foo") == rustc_span::kw::SelfLower;
-    //~^ unnecessary_symbol_str
-    Symbol::intern("foo") != rustc_span::kw::SelfUpper;
-    //~^ unnecessary_symbol_str
-    Ident::empty().name == rustc_span::sym::clippy;
-    //~^ unnecessary_symbol_str
-    rustc_span::sym::clippy == Ident::empty().name;
-    //~^ unnecessary_symbol_str
-}
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs
deleted file mode 100644
index d74262d1294..00000000000
--- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#![feature(rustc_private)]
-#![deny(clippy::internal)]
-#![allow(
-    clippy::slow_symbol_comparisons,
-    clippy::borrow_deref_ref,
-    clippy::unnecessary_operation,
-    unused_must_use,
-    clippy::missing_clippy_version_attribute
-)]
-
-extern crate rustc_span;
-
-use rustc_span::symbol::{Ident, Symbol};
-
-fn main() {
-    Symbol::intern("foo").as_str() == "clippy";
-    //~^ unnecessary_symbol_str
-    Symbol::intern("foo").to_string() == "self";
-    //~^ unnecessary_symbol_str
-    Symbol::intern("foo").to_ident_string() != "Self";
-    //~^ unnecessary_symbol_str
-    &*Ident::empty().as_str() == "clippy";
-    //~^ unnecessary_symbol_str
-    "clippy" == Ident::empty().to_string();
-    //~^ unnecessary_symbol_str
-}
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr
deleted file mode 100644
index 517a395e93f..00000000000
--- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error: unnecessary `Symbol` to string conversion
-  --> tests/ui-internal/unnecessary_symbol_str.rs:16:5
-   |
-LL |     Symbol::intern("foo").as_str() == "clippy";
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::sym::clippy`
-   |
-note: the lint level is defined here
-  --> tests/ui-internal/unnecessary_symbol_str.rs:2:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::unnecessary_symbol_str)]` implied by `#[deny(clippy::internal)]`
-
-error: unnecessary `Symbol` to string conversion
-  --> tests/ui-internal/unnecessary_symbol_str.rs:18:5
-   |
-LL |     Symbol::intern("foo").to_string() == "self";
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::kw::SelfLower`
-
-error: unnecessary `Symbol` to string conversion
-  --> tests/ui-internal/unnecessary_symbol_str.rs:20:5
-   |
-LL |     Symbol::intern("foo").to_ident_string() != "Self";
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") != rustc_span::kw::SelfUpper`
-
-error: unnecessary `Symbol` to string conversion
-  --> tests/ui-internal/unnecessary_symbol_str.rs:22:5
-   |
-LL |     &*Ident::empty().as_str() == "clippy";
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy`
-
-error: unnecessary `Symbol` to string conversion
-  --> tests/ui-internal/unnecessary_symbol_str.rs:24:5
-   |
-LL |     "clippy" == Ident::empty().to_string();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name`
-
-error: aborting due to 5 previous errors
-
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs
index b43791521cb..694ef45c75b 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs
@@ -16,6 +16,7 @@
 //@[bad_conf_4] error-in-other-file:
 //@[bad_conf_5] error-in-other-file:
 //@[bad_conf_6] error-in-other-file:
+//@compile-flags: --test
 
 #![allow(dead_code)]
 #![warn(clippy::arbitrary_source_item_ordering)]
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr
index 7fc216b30d5..fcd7864c667 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr
@@ -1,16 +1,16 @@
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:36:5
    |
 LL |     a: bool,
    |     ^
    |
 note: should be placed before `b`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5
    |
 LL |     b: bool,
    |     ^
 note: the lint level is defined here
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:33:8
    |
 LL | #[deny(clippy::arbitrary_source_item_ordering)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr
index 1f75f5099ec..81c35ff778b 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr
@@ -1,33 +1,33 @@
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:25:8
    |
 LL | struct OrderedChecked {
    |        ^^^^^^^^^^^^^^
    |
 note: should be placed before `Unordered`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:19:8
    |
 LL | struct Unordered {
    |        ^^^^^^^^^
 note: the lint level is defined here
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:10:9
    |
 LL | #![deny(clippy::arbitrary_source_item_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:36:5
    |
 LL |     a: bool,
    |     ^
    |
 note: should be placed before `b`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5
    |
 LL |     b: bool,
    |     ^
 note: the lint level is defined here
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:33:8
    |
 LL | #[deny(clippy::arbitrary_source_item_ordering)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr
index 8027f55add6..09ede57f295 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr
@@ -1,16 +1,16 @@
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:25:8
    |
 LL | struct OrderedChecked {
    |        ^^^^^^^^^^^^^^
    |
 note: should be placed before `Unordered`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:19:8
    |
 LL | struct Unordered {
    |        ^^^^^^^^^
 note: the lint level is defined here
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:10:9
    |
 LL | #![deny(clippy::arbitrary_source_item_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr
index 333a601f6a9..7c515f050c1 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr
@@ -1,48 +1,60 @@
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:25:8
    |
 LL | struct OrderedChecked {
    |        ^^^^^^^^^^^^^^
    |
 note: should be placed before `Unordered`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:19:8
    |
 LL | struct Unordered {
    |        ^^^^^^^^^
 note: the lint level is defined here
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:10:9
    |
 LL | #![deny(clippy::arbitrary_source_item_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:45:4
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:46:4
    |
 LL | fn before_main() {}
    |    ^^^^^^^^^^^
    |
 note: should be placed before `main`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:41:4
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:42:4
    |
 LL | fn main() {
    |    ^^^^
 
 error: incorrect ordering of items (must be alphabetically ordered)
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:36:5
    |
 LL |     a: bool,
    |     ^
    |
 note: should be placed before `b`
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5
    |
 LL |     b: bool,
    |     ^
 note: the lint level is defined here
-  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:33:8
    |
 LL | #[deny(clippy::arbitrary_source_item_ordering)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:52:11
+   |
+LL |     const A: i8 = 0;
+   |           ^
+   |
+note: should be placed before `B`
+  --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:51:11
+   |
+LL |     const B: i8 = 1;
+   |           ^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs
index e32b921dd96..cb6d0170b8f 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs
@@ -4,6 +4,7 @@
 //@[ord_within] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_within
 //@[ord_in_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_2
 //@[ord_in_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_3
+//@compile-flags: --test
 
 #![allow(dead_code)]
 #![deny(clippy::arbitrary_source_item_ordering)]
@@ -44,3 +45,10 @@ fn main() {
 
 fn before_main() {}
 //~[ord_within]^ arbitrary_source_item_ordering
+
+#[cfg(test)]
+mod test {
+    const B: i8 = 1;
+    const A: i8 = 0;
+    //~[ord_within]^ arbitrary_source_item_ordering
+}
diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr
index 86e30409af0..d0fce3614a1 100644
--- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr
+++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type_with_replacement/await_holding_invalid_type.stderr
@@ -1,11 +1,8 @@
 error: error reading Clippy's configuration file: replacement not allowed for this configuration
-  --> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:1:31
+  --> $DIR/tests/ui-toml/await_holding_invalid_type_with_replacement/clippy.toml:2:5
    |
-LL |   await-holding-invalid-types = [
-   |  _______________________________^
-LL | |     { path = "std::string::String", replacement = "std::net::Ipv4Addr" },
-LL | | ]
-   | |_^
+LL |     { path = "std::string::String", replacement = "std::net::Ipv4Addr" },
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/clippy.toml b/src/tools/clippy/tests/ui-toml/collapsible_if/clippy.toml
new file mode 100644
index 00000000000..592cea90cff
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/clippy.toml
@@ -0,0 +1 @@
+lint-commented-code = true
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.fixed b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.fixed
new file mode 100644
index 00000000000..6f5cc47ba6c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.fixed
@@ -0,0 +1,34 @@
+#![allow(clippy::eq_op, clippy::nonminimal_bool)]
+
+#[rustfmt::skip]
+#[warn(clippy::collapsible_if)]
+fn main() {
+    let (x, y) = ("hello", "world");
+
+    if x == "hello"
+        // Comment must be kept
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^^ collapsible_if
+
+    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
+    if x == "hello"  // Inner comment
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^ collapsible_if
+
+    if x == "hello"
+        /* Inner comment */
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^^ collapsible_if
+
+    if x == "hello"  /* Inner comment */
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^ collapsible_if
+}
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.rs b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.rs
new file mode 100644
index 00000000000..868b4adcde5
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.rs
@@ -0,0 +1,38 @@
+#![allow(clippy::eq_op, clippy::nonminimal_bool)]
+
+#[rustfmt::skip]
+#[warn(clippy::collapsible_if)]
+fn main() {
+    let (x, y) = ("hello", "world");
+
+    if x == "hello" {
+        // Comment must be kept
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^^ collapsible_if
+
+    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
+    if x == "hello" { // Inner comment
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^ collapsible_if
+
+    if x == "hello" {
+        /* Inner comment */
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^^ collapsible_if
+
+    if x == "hello" { /* Inner comment */
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^ collapsible_if
+}
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.stderr b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.stderr
new file mode 100644
index 00000000000..357ce4ad32d
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if.stderr
@@ -0,0 +1,80 @@
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:8:5
+   |
+LL | /     if x == "hello" {
+LL | |         // Comment must be kept
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::collapsible-if` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]`
+help: collapse nested if block
+   |
+LL ~     if x == "hello"
+LL |         // Comment must be kept
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:17:5
+   |
+LL | /     if x == "hello" { // Inner comment
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if x == "hello"  // Inner comment
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:24:5
+   |
+LL | /     if x == "hello" {
+LL | |         /* Inner comment */
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if x == "hello"
+LL |         /* Inner comment */
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:32:5
+   |
+LL | /     if x == "hello" { /* Inner comment */
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if x == "hello"  /* Inner comment */
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed
new file mode 100644
index 00000000000..f12273954c6
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.fixed
@@ -0,0 +1,25 @@
+#![feature(let_chains)]
+#![warn(clippy::collapsible_if)]
+
+fn main() {
+    if let Some(a) = Some(3)
+        // with comment
+        && let Some(b) = Some(4) {
+            let _ = a + b;
+        }
+    //~^^^^^^ collapsible_if
+
+    if let Some(a) = Some(3)
+        // with comment
+        && a + 1 == 4 {
+            let _ = a;
+        }
+    //~^^^^^^ collapsible_if
+
+    if Some(3) == Some(4).map(|x| x - 1)
+        // with comment
+        && let Some(b) = Some(4) {
+            let _ = b;
+        }
+    //~^^^^^^ collapsible_if
+}
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs
new file mode 100644
index 00000000000..5a984d7a3cb
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs
@@ -0,0 +1,28 @@
+#![feature(let_chains)]
+#![warn(clippy::collapsible_if)]
+
+fn main() {
+    if let Some(a) = Some(3) {
+        // with comment
+        if let Some(b) = Some(4) {
+            let _ = a + b;
+        }
+    }
+    //~^^^^^^ collapsible_if
+
+    if let Some(a) = Some(3) {
+        // with comment
+        if a + 1 == 4 {
+            let _ = a;
+        }
+    }
+    //~^^^^^^ collapsible_if
+
+    if Some(3) == Some(4).map(|x| x - 1) {
+        // with comment
+        if let Some(b) = Some(4) {
+            let _ = b;
+        }
+    }
+    //~^^^^^^ collapsible_if
+}
diff --git a/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr
new file mode 100644
index 00000000000..c22a65a4473
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/collapsible_if/collapsible_if_let_chains.stderr
@@ -0,0 +1,64 @@
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs:5:5
+   |
+LL | /     if let Some(a) = Some(3) {
+LL | |         // with comment
+LL | |         if let Some(b) = Some(4) {
+LL | |             let _ = a + b;
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::collapsible-if` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]`
+help: collapse nested if block
+   |
+LL ~     if let Some(a) = Some(3)
+LL |         // with comment
+LL ~         && let Some(b) = Some(4) {
+LL |             let _ = a + b;
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs:13:5
+   |
+LL | /     if let Some(a) = Some(3) {
+LL | |         // with comment
+LL | |         if a + 1 == 4 {
+LL | |             let _ = a;
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if let Some(a) = Some(3)
+LL |         // with comment
+LL ~         && a + 1 == 4 {
+LL |             let _ = a;
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if_let_chains.rs:21:5
+   |
+LL | /     if Some(3) == Some(4).map(|x| x - 1) {
+LL | |         // with comment
+LL | |         if let Some(b) = Some(4) {
+LL | |             let _ = b;
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if Some(3) == Some(4).map(|x| x - 1)
+LL |         // with comment
+LL ~         && let Some(b) = Some(4) {
+LL |             let _ = b;
+LL ~         }
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
index 2465fe45645..d3d5b0c103e 100644
--- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
+++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
@@ -251,6 +251,16 @@ pub mod issue13219 {
     }
 }
 
+#[macro_export]
+macro_rules! issue14488 {
+    ($e:expr) => {
+        #[expect(clippy::macro_metavars_in_unsafe)]
+        unsafe {
+            $e
+        }
+    };
+}
+
 fn main() {
     allow_works!(1);
     simple!(1);
@@ -271,4 +281,10 @@ fn main() {
     multiple_unsafe_blocks!(1, 1, 1);
     unsafe_from_root_ctxt!(unsafe { 1 });
     nested_macros!(1, 1);
+
+    // These two invocations lead to two expanded unsafe blocks, each with an `#[expect]` on it.
+    // Only of them gets a warning, which used to result in an unfulfilled expectation for the other
+    // expanded unsafe block.
+    issue14488!(1);
+    issue14488!(2);
 }
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
index 36540bf1dcf..2877871d0bf 100644
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
+++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
@@ -1,3 +1,4 @@
+#![allow(clippy::uninlined_format_args)]
 #![deny(clippy::index_refutable_slice)]
 
 fn below_limit() {
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
index da76bb20fd9..f958b92a102 100644
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
+++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::uninlined_format_args)]
 #![deny(clippy::index_refutable_slice)]
 
 fn below_limit() {
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
index 022deb330e6..e1a8941e102 100644
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
+++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
@@ -1,11 +1,11 @@
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:5:17
+  --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:6:17
    |
 LL |     if let Some(slice) = slice {
    |                 ^^^^^
    |
 note: the lint level is defined here
-  --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:1:9
+  --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:2:9
    |
 LL | #![deny(clippy::index_refutable_slice)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs b/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs
index 08a8e1186d5..13e19e9fe14 100644
--- a/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs
+++ b/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs
@@ -29,7 +29,7 @@ unsafe impl<T> Send for MyOption<T> {}
 //~^ non_send_fields_in_send_ty
 
 // All fields are disallowed when raw pointer heuristic is off
-extern "C" {
+unsafe extern "C" {
     type NonSend;
 }
 
diff --git a/src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml
index f43c9d97e82..3cb8523562a 100644
--- a/src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/toml_inconsistent_struct_constructor/clippy.toml
@@ -1 +1 @@
-lint-inconsistent-struct-field-initializers = true
+check-inconsistent-struct-field-initializers = true
diff --git a/src/tools/clippy/tests/ui-toml/toml_invalid_path/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_invalid_path/clippy.toml
new file mode 100644
index 00000000000..6d0d732a922
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/toml_invalid_path/clippy.toml
@@ -0,0 +1,14 @@
+[[disallowed-types]]
+path = "std::result::Result::Err"
+
+[[disallowed-macros]]
+path = "bool"
+
+[[disallowed-methods]]
+path = "std::process::current_exe"
+
+# negative test
+
+[[disallowed-methods]]
+path = "std::current_exe"
+allow-invalid = true
diff --git a/src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs b/src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs
new file mode 100644
index 00000000000..c1520382703
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.rs
@@ -0,0 +1,5 @@
+//@error-in-other-file: expected a macro, found a primitive type
+//@error-in-other-file: `std::process::current_exe` does not refer to an existing function
+//@error-in-other-file: expected a type, found a tuple variant
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr b/src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr
new file mode 100644
index 00000000000..82550108eba
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/toml_invalid_path/conf_invalid_path.stderr
@@ -0,0 +1,23 @@
+warning: expected a macro, found a primitive type
+  --> $DIR/tests/ui-toml/toml_invalid_path/clippy.toml:4:1
+   |
+LL | / [[disallowed-macros]]
+LL | | path = "bool"
+   | |_____________^
+
+warning: `std::process::current_exe` does not refer to an existing function
+  --> $DIR/tests/ui-toml/toml_invalid_path/clippy.toml:7:1
+   |
+LL | / [[disallowed-methods]]
+LL | | path = "std::process::current_exe"
+   | |__________________________________^
+
+warning: expected a type, found a tuple variant
+  --> $DIR/tests/ui-toml/toml_invalid_path/clippy.toml:1:1
+   |
+LL | / [[disallowed-types]]
+LL | | path = "std::result::Result::Err"
+   | |_________________________________^
+
+warning: 3 warnings emitted
+
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index fee5b01b689..f2eaa66a4ae 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -29,12 +29,11 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            array-size-threshold
            avoid-breaking-exported-api
            await-holding-invalid-types
-           blacklisted-names
            cargo-ignore-publish
            check-incompatible-msrv-in-tests
+           check-inconsistent-struct-field-initializers
            check-private-items
            cognitive-complexity-threshold
-           cyclomatic-complexity-threshold
            disallowed-macros
            disallowed-methods
            disallowed-names
@@ -49,7 +48,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
-           lint-inconsistent-struct-field-initializers
+           lint-commented-code
            literal-representation-threshold
            matches-for-let-else
            max-fn-params-bools
@@ -122,12 +121,11 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            array-size-threshold
            avoid-breaking-exported-api
            await-holding-invalid-types
-           blacklisted-names
            cargo-ignore-publish
            check-incompatible-msrv-in-tests
+           check-inconsistent-struct-field-initializers
            check-private-items
            cognitive-complexity-threshold
-           cyclomatic-complexity-threshold
            disallowed-macros
            disallowed-methods
            disallowed-names
@@ -142,7 +140,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
-           lint-inconsistent-struct-field-initializers
+           lint-commented-code
            literal-representation-threshold
            matches-for-let-else
            max-fn-params-bools
@@ -215,12 +213,11 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            array-size-threshold
            avoid-breaking-exported-api
            await-holding-invalid-types
-           blacklisted-names
            cargo-ignore-publish
            check-incompatible-msrv-in-tests
+           check-inconsistent-struct-field-initializers
            check-private-items
            cognitive-complexity-threshold
-           cyclomatic-complexity-threshold
            disallowed-macros
            disallowed-methods
            disallowed-names
@@ -235,7 +232,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
-           lint-inconsistent-struct-field-initializers
+           lint-commented-code
            literal-representation-threshold
            matches-for-let-else
            max-fn-params-bools
diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed
index af72d6be0e0..20511cbed16 100644
--- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed
@@ -15,7 +15,7 @@ mod my_crate {
     }
 }
 
-use utils::{BAR, print};
+pub use utils::{BAR, print};
 //~^ ERROR: usage of wildcard import
 use my_crate::utils::my_util_fn;
 //~^ ERROR: usage of wildcard import
diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs
index 91009dd8835..8d05910f471 100644
--- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs
@@ -15,7 +15,7 @@ mod my_crate {
     }
 }
 
-use utils::*;
+pub use utils::*;
 //~^ ERROR: usage of wildcard import
 use my_crate::utils::*;
 //~^ ERROR: usage of wildcard import
diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr
index 3d3be965aa4..5e624dd6c3c 100644
--- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr
+++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr
@@ -1,8 +1,8 @@
 error: usage of wildcard import
-  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:18:5
+  --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:18:9
    |
-LL | use utils::*;
-   |     ^^^^^^^^ help: try: `utils::{BAR, print}`
+LL | pub use utils::*;
+   |         ^^^^^^^^ help: try: `utils::{BAR, print}`
    |
    = note: `-D clippy::wildcard-imports` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]`
diff --git a/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs b/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs
index edcd5247f18..361bc203393 100644
--- a/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs
+++ b/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs
@@ -8,9 +8,11 @@ mod dont_warn {
     use std::arch::{asm, global_asm};
 
     pub(super) unsafe fn use_asm() {
-        asm!("");
-        asm!("", options());
-        asm!("", options(nostack));
+        unsafe {
+            asm!("");
+            asm!("", options());
+            asm!("", options(nostack));
+        }
     }
 
     global_asm!("");
diff --git a/src/tools/clippy/tests/ui/asm_syntax_x86.rs b/src/tools/clippy/tests/ui/asm_syntax_x86.rs
index 4e91f27cd31..30401c9a044 100644
--- a/src/tools/clippy/tests/ui/asm_syntax_x86.rs
+++ b/src/tools/clippy/tests/ui/asm_syntax_x86.rs
@@ -5,17 +5,19 @@ mod warn_intel {
     use std::arch::{asm, global_asm};
 
     pub(super) unsafe fn use_asm() {
-        asm!("");
-        //~^ inline_asm_x86_intel_syntax
+        unsafe {
+            asm!("");
+            //~^ inline_asm_x86_intel_syntax
 
-        asm!("", options());
-        //~^ inline_asm_x86_intel_syntax
+            asm!("", options());
+            //~^ inline_asm_x86_intel_syntax
 
-        asm!("", options(nostack));
-        //~^ inline_asm_x86_intel_syntax
+            asm!("", options(nostack));
+            //~^ inline_asm_x86_intel_syntax
 
-        asm!("", options(att_syntax));
-        asm!("", options(nostack, att_syntax));
+            asm!("", options(att_syntax));
+            asm!("", options(nostack, att_syntax));
+        }
     }
 
     global_asm!("");
@@ -32,14 +34,16 @@ mod warn_att {
     use std::arch::{asm, global_asm};
 
     pub(super) unsafe fn use_asm() {
-        asm!("");
-        asm!("", options());
-        asm!("", options(nostack));
-        asm!("", options(att_syntax));
-        //~^ inline_asm_x86_att_syntax
-
-        asm!("", options(nostack, att_syntax));
-        //~^ inline_asm_x86_att_syntax
+        unsafe {
+            asm!("");
+            asm!("", options());
+            asm!("", options(nostack));
+            asm!("", options(att_syntax));
+            //~^ inline_asm_x86_att_syntax
+
+            asm!("", options(nostack, att_syntax));
+            //~^ inline_asm_x86_att_syntax
+        }
     }
 
     global_asm!("");
diff --git a/src/tools/clippy/tests/ui/asm_syntax_x86.stderr b/src/tools/clippy/tests/ui/asm_syntax_x86.stderr
index 2dcd955f034..8e068cf2349 100644
--- a/src/tools/clippy/tests/ui/asm_syntax_x86.stderr
+++ b/src/tools/clippy/tests/ui/asm_syntax_x86.stderr
@@ -1,31 +1,31 @@
 error: Intel x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:8:9
+  --> tests/ui/asm_syntax_x86.rs:9:13
    |
-LL |         asm!("");
-   |         ^^^^^^^^
+LL |             asm!("");
+   |             ^^^^^^^^
    |
    = help: use AT&T x86 assembly syntax
    = note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_intel_syntax)]`
 
 error: Intel x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:11:9
+  --> tests/ui/asm_syntax_x86.rs:12:13
    |
-LL |         asm!("", options());
-   |         ^^^^^^^^^^^^^^^^^^^
+LL |             asm!("", options());
+   |             ^^^^^^^^^^^^^^^^^^^
    |
    = help: use AT&T x86 assembly syntax
 
 error: Intel x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:14:9
+  --> tests/ui/asm_syntax_x86.rs:15:13
    |
-LL |         asm!("", options(nostack));
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             asm!("", options(nostack));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use AT&T x86 assembly syntax
 
 error: Intel x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:21:5
+  --> tests/ui/asm_syntax_x86.rs:23:5
    |
 LL |     global_asm!("");
    |     ^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     global_asm!("");
    = help: use AT&T x86 assembly syntax
 
 error: Intel x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:24:5
+  --> tests/ui/asm_syntax_x86.rs:26:5
    |
 LL |     global_asm!("", options());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,25 +41,25 @@ LL |     global_asm!("", options());
    = help: use AT&T x86 assembly syntax
 
 error: AT&T x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:38:9
+  --> tests/ui/asm_syntax_x86.rs:41:13
    |
-LL |         asm!("", options(att_syntax));
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             asm!("", options(att_syntax));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use Intel x86 assembly syntax
    = note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_att_syntax)]`
 
 error: AT&T x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:41:9
+  --> tests/ui/asm_syntax_x86.rs:44:13
    |
-LL |         asm!("", options(nostack, att_syntax));
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             asm!("", options(nostack, att_syntax));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use Intel x86 assembly syntax
 
 error: AT&T x86 assembly syntax used
-  --> tests/ui/asm_syntax_x86.rs:47:5
+  --> tests/ui/asm_syntax_x86.rs:51:5
    |
 LL |     global_asm!("", options(att_syntax));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/author/if.rs b/src/tools/clippy/tests/ui/author/if.rs
index 59bc9f5bfa5..abefc34cf6b 100644
--- a/src/tools/clippy/tests/ui/author/if.rs
+++ b/src/tools/clippy/tests/ui/author/if.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#[allow(clippy::all)]
+#![allow(clippy::all)]
 
 fn main() {
     #[clippy::author]
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.rs b/src/tools/clippy/tests/ui/author/macro_in_closure.rs
index 8a02f38fad8..373f0148d47 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_closure.rs
+++ b/src/tools/clippy/tests/ui/author/macro_in_closure.rs
@@ -1,5 +1,7 @@
 //@ check-pass
 
+#![allow(clippy::uninlined_format_args)]
+
 fn main() {
     #[clippy::author]
     let print_text = |x| println!("{}", x);
diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.rs b/src/tools/clippy/tests/ui/author/macro_in_loop.rs
index 84ffe416e83..f68275fefaa 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_loop.rs
+++ b/src/tools/clippy/tests/ui/author/macro_in_loop.rs
@@ -1,6 +1,7 @@
 //@ check-pass
 
 #![feature(stmt_expr_attributes)]
+#![allow(clippy::uninlined_format_args)]
 
 fn main() {
     #[clippy::author]
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
index 1a2a4ec2311..7a4cc4fa9ee 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
@@ -131,12 +131,12 @@ fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Resul
 pub fn make_it_big(input: TokenStream) -> TokenStream {
     let mut expr_repeat = syn::parse_macro_input!(input as syn::ExprRepeat);
     let len_span = expr_repeat.len.span();
-    if let syn::Expr::Lit(expr_lit) = &mut *expr_repeat.len {
-        if let syn::Lit::Int(lit_int) = &expr_lit.lit {
-            let orig_val = lit_int.base10_parse::<usize>().expect("not a valid length parameter");
-            let new_val = orig_val.saturating_mul(10);
-            expr_lit.lit = syn::parse_quote_spanned!( len_span => #new_val);
-        }
+    if let syn::Expr::Lit(expr_lit) = &mut *expr_repeat.len
+        && let syn::Lit::Int(lit_int) = &expr_lit.lit
+    {
+        let orig_val = lit_int.base10_parse::<usize>().expect("not a valid length parameter");
+        let new_val = orig_val.saturating_mul(10);
+        expr_lit.lit = syn::parse_quote_spanned!( len_span => #new_val);
     }
     quote::quote!(#expr_repeat).into()
 }
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
index cd307e803d0..e696896538e 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
@@ -3,6 +3,7 @@
 #![warn(clippy::blocks_in_conditions)]
 #![allow(
     unused,
+    unnecessary_transmutes,
     clippy::let_and_return,
     clippy::needless_if,
     clippy::missing_transmute_annotations
@@ -71,28 +72,6 @@ fn block_in_assert() {
     );
 }
 
-// issue #11814
-fn block_in_match_expr(num: i32) -> i32 {
-    let res = {
-        //~^ 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`
-        let opt = Some(2);
-        opt
-    }; match res {
-        Some(0) => 1,
-        Some(n) => num * 2,
-        None => 0,
-    };
-
-    match unsafe {
-        let hearty_hearty_hearty = vec![240, 159, 146, 150];
-        String::from_utf8_unchecked(hearty_hearty_hearty).as_str()
-    } {
-        "💖" => 1,
-        "what" => 2,
-        _ => 3,
-    }
-}
-
 // issue #12162
 macro_rules! timed {
     ($name:expr, $body:expr $(,)?) => {{
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
index 6a211c8edfd..8c8f3249b8a 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
@@ -3,6 +3,7 @@
 #![warn(clippy::blocks_in_conditions)]
 #![allow(
     unused,
+    unnecessary_transmutes,
     clippy::let_and_return,
     clippy::needless_if,
     clippy::missing_transmute_annotations
@@ -71,28 +72,6 @@ fn block_in_assert() {
     );
 }
 
-// issue #11814
-fn block_in_match_expr(num: i32) -> i32 {
-    match {
-        //~^ 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`
-        let opt = Some(2);
-        opt
-    } {
-        Some(0) => 1,
-        Some(n) => num * 2,
-        None => 0,
-    };
-
-    match unsafe {
-        let hearty_hearty_hearty = vec![240, 159, 146, 150];
-        String::from_utf8_unchecked(hearty_hearty_hearty).as_str()
-    } {
-        "💖" => 1,
-        "what" => 2,
-        _ => 3,
-    }
-}
-
 // issue #12162
 macro_rules! timed {
     ($name:expr, $body:expr $(,)?) => {{
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
index da21344a842..41ff59c683e 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
@@ -1,5 +1,5 @@
 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.rs:30:5
+  --> tests/ui/blocks_in_conditions.rs:31:5
    |
 LL | /     if {
 LL | |
@@ -20,13 +20,13 @@ LL ~     }; if res {
    |
 
 error: omit braces around single expression condition
-  --> tests/ui/blocks_in_conditions.rs:42:8
+  --> tests/ui/blocks_in_conditions.rs:43:8
    |
 LL |     if { true } { 6 } else { 10 }
    |        ^^^^^^^^ help: try: `true`
 
 error: this boolean expression can be simplified
-  --> tests/ui/blocks_in_conditions.rs:48:8
+  --> tests/ui/blocks_in_conditions.rs:49:8
    |
 LL |     if true && x == 3 { 6 } else { 10 }
    |        ^^^^^^^^^^^^^^ help: try: `x == 3`
@@ -34,24 +34,5 @@ LL |     if true && x == 3 { 6 } else { 10 }
    = note: `-D clippy::nonminimal-bool` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]`
 
-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.rs:76:5
-   |
-LL | /     match {
-LL | |
-LL | |         let opt = Some(2);
-LL | |         opt
-LL | |     } {
-   | |_____^
-   |
-help: try
-   |
-LL ~     let res = {
-LL +
-LL +         let opt = Some(2);
-LL +         opt
-LL ~     }; match res {
-   |
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_2021.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.fixed
new file mode 100644
index 00000000000..c7cc643dba6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.fixed
@@ -0,0 +1,25 @@
+//@edition: 2021
+
+#![allow(clippy::let_and_return)]
+
+// issue #11814
+fn block_in_match_expr(num: i32) -> i32 {
+    let res = {
+        //~^ 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`
+        let opt = Some(2);
+        opt
+    }; match res {
+        Some(0) => 1,
+        Some(n) => num * 2,
+        None => 0,
+    };
+
+    match unsafe {
+        let hearty_hearty_hearty = vec![240, 159, 146, 150];
+        String::from_utf8_unchecked(hearty_hearty_hearty).as_str()
+    } {
+        "💖" => 1,
+        "what" => 2,
+        _ => 3,
+    }
+}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_2021.rs b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.rs
new file mode 100644
index 00000000000..a911237f5f7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.rs
@@ -0,0 +1,25 @@
+//@edition: 2021
+
+#![allow(clippy::let_and_return)]
+
+// issue #11814
+fn block_in_match_expr(num: i32) -> i32 {
+    match {
+        //~^ 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`
+        let opt = Some(2);
+        opt
+    } {
+        Some(0) => 1,
+        Some(n) => num * 2,
+        None => 0,
+    };
+
+    match unsafe {
+        let hearty_hearty_hearty = vec![240, 159, 146, 150];
+        String::from_utf8_unchecked(hearty_hearty_hearty).as_str()
+    } {
+        "💖" => 1,
+        "what" => 2,
+        _ => 3,
+    }
+}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr
new file mode 100644
index 00000000000..497ee9d679d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr
@@ -0,0 +1,23 @@
+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_2021.rs:7:5
+   |
+LL | /     match {
+LL | |
+LL | |         let opt = Some(2);
+LL | |         opt
+LL | |     } {
+   | |_____^
+   |
+   = note: `-D clippy::blocks-in-conditions` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]`
+help: try
+   |
+LL ~     let res = {
+LL +
+LL +         let opt = Some(2);
+LL +         opt
+LL ~     }; match res {
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
index 0080801d46b..ed6141244b4 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
@@ -117,3 +117,27 @@ fn if_let(a: Enum, b: Enum) {
         0
     };
 }
+
+fn issue14628() {
+    macro_rules! mac {
+        (if $cond:expr, $then:expr, $else:expr) => {
+            if $cond { $then } else { $else }
+        };
+        (zero) => {
+            0
+        };
+        (one) => {
+            1
+        };
+    }
+
+    let _ = i32::from(dbg!(4 > 0));
+    //~^ bool_to_int_with_if
+
+    let _ = dbg!(i32::from(4 > 0));
+    //~^ bool_to_int_with_if
+
+    let _ = mac!(if 4 > 0, 1, 0);
+    let _ = if 4 > 0 { mac!(one) } else { 0 };
+    let _ = if 4 > 0 { 1 } else { mac!(zero) };
+}
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
index 72c7e2c71c5..3f1f1c766e4 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
@@ -157,3 +157,27 @@ fn if_let(a: Enum, b: Enum) {
         0
     };
 }
+
+fn issue14628() {
+    macro_rules! mac {
+        (if $cond:expr, $then:expr, $else:expr) => {
+            if $cond { $then } else { $else }
+        };
+        (zero) => {
+            0
+        };
+        (one) => {
+            1
+        };
+    }
+
+    let _ = if dbg!(4 > 0) { 1 } else { 0 };
+    //~^ bool_to_int_with_if
+
+    let _ = dbg!(if 4 > 0 { 1 } else { 0 });
+    //~^ bool_to_int_with_if
+
+    let _ = mac!(if 4 > 0, 1, 0);
+    let _ = if 4 > 0 { mac!(one) } else { 0 };
+    let _ = if 4 > 0 { 1 } else { mac!(zero) };
+}
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
index 415e80f8d73..94089bc6dc8 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
@@ -114,5 +114,21 @@ LL |     if a { 1 } else { 0 }
    |
    = note: `a as u8` or `a.into()` can also be valid options
 
-error: aborting due to 9 previous errors
+error: boolean to int conversion using if
+  --> tests/ui/bool_to_int_with_if.rs:174:13
+   |
+LL |     let _ = if dbg!(4 > 0) { 1 } else { 0 };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `i32::from(dbg!(4 > 0))`
+   |
+   = note: `dbg!(4 > 0) as i32` or `dbg!(4 > 0).into()` can also be valid options
+
+error: boolean to int conversion using if
+  --> tests/ui/bool_to_int_with_if.rs:177:18
+   |
+LL |     let _ = dbg!(if 4 > 0 { 1 } else { 0 });
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `i32::from(4 > 0)`
+   |
+   = note: `(4 > 0) as i32` or `(4 > 0).into()` can also be valid options
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
index 3dca06fce4b..3ba2eea59f0 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
@@ -29,3 +29,21 @@ fn issue_13882() {
     let _raw = (&raw mut x[1]).wrapping_offset(-1);
     //~^ borrow_as_ptr
 }
+
+fn implicit_cast() {
+    let val = 1;
+    let p: *const i32 = &raw const val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    let p: *mut i32 = &raw mut val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    // Only lint the leftmost argument, the rightmost is ref to a temporary
+    core::ptr::eq(&raw const val, &1);
+    //~^ borrow_as_ptr
+
+    // Do not lint references to temporaries
+    core::ptr::eq(&0i32, &1i32);
+}
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.rs b/src/tools/clippy/tests/ui/borrow_as_ptr.rs
index 3559dc23d01..8cdd0512da5 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.rs
@@ -29,3 +29,21 @@ fn issue_13882() {
     let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
     //~^ borrow_as_ptr
 }
+
+fn implicit_cast() {
+    let val = 1;
+    let p: *const i32 = &val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    let p: *mut i32 = &mut val;
+    //~^ borrow_as_ptr
+
+    let mut val = 1;
+    // Only lint the leftmost argument, the rightmost is ref to a temporary
+    core::ptr::eq(&val, &1);
+    //~^ borrow_as_ptr
+
+    // Do not lint references to temporaries
+    core::ptr::eq(&0i32, &1i32);
+}
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.stderr b/src/tools/clippy/tests/ui/borrow_as_ptr.stderr
index 4a9f2ed4aa0..b1fcce49403 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.stderr
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.stderr
@@ -25,5 +25,38 @@ error: borrow as raw pointer
 LL |     let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut x[1]`
 
-error: aborting due to 4 previous errors
+error: implicit borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:35:25
+   |
+LL |     let p: *const i32 = &val;
+   |                         ^^^^
+   |
+help: use a raw pointer instead
+   |
+LL |     let p: *const i32 = &raw const val;
+   |                          +++++++++
+
+error: implicit borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:39:23
+   |
+LL |     let p: *mut i32 = &mut val;
+   |                       ^^^^^^^^
+   |
+help: use a raw pointer instead
+   |
+LL |     let p: *mut i32 = &raw mut val;
+   |                        +++
+
+error: implicit borrow as raw pointer
+  --> tests/ui/borrow_as_ptr.rs:44:19
+   |
+LL |     core::ptr::eq(&val, &1);
+   |                   ^^^^
+   |
+help: use a raw pointer instead
+   |
+LL |     core::ptr::eq(&raw const val, &1);
+   |                    +++++++++
+
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
index 17c224f10bf..765dd75fceb 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
@@ -81,3 +81,46 @@ fn issue_13584() {
     let p = &raw const *s;
     let _ = p as *const i8;
 }
+
+mod issue_9905 {
+    use std::{fs, io};
+
+    pub enum File {
+        Stdio,
+        File(fs::File),
+    }
+
+    impl io::Read for &'_ File {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            match self {
+                File::Stdio => io::stdin().read(buf),
+                File::File(file) => (&*file).read(buf),
+            }
+        }
+    }
+}
+
+mod issue_11346 {
+    struct Struct;
+
+    impl Struct {
+        fn foo(self: &mut &Self) {}
+    }
+
+    trait Trait {
+        fn bar(&mut self) {}
+    }
+
+    impl Trait for &Struct {}
+
+    fn bar() {
+        let s = &Struct;
+        (&*s).foo();
+        (&*s).bar();
+
+        let mut s = &Struct;
+        s.foo(); // To avoid a warning about `s` not needing to be mutable
+        s.foo();
+        //~^ borrow_deref_ref
+    }
+}
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
index 130ed2903dc..8ee66bfa881 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
@@ -81,3 +81,46 @@ fn issue_13584() {
     let p = &raw const *s;
     let _ = p as *const i8;
 }
+
+mod issue_9905 {
+    use std::{fs, io};
+
+    pub enum File {
+        Stdio,
+        File(fs::File),
+    }
+
+    impl io::Read for &'_ File {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            match self {
+                File::Stdio => io::stdin().read(buf),
+                File::File(file) => (&*file).read(buf),
+            }
+        }
+    }
+}
+
+mod issue_11346 {
+    struct Struct;
+
+    impl Struct {
+        fn foo(self: &mut &Self) {}
+    }
+
+    trait Trait {
+        fn bar(&mut self) {}
+    }
+
+    impl Trait for &Struct {}
+
+    fn bar() {
+        let s = &Struct;
+        (&*s).foo();
+        (&*s).bar();
+
+        let mut s = &Struct;
+        s.foo(); // To avoid a warning about `s` not needing to be mutable
+        (&*s).foo();
+        //~^ borrow_deref_ref
+    }
+}
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
index f5868aa8749..3d55da25b9b 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
@@ -19,5 +19,11 @@ error: deref on an immutable reference
 LL |         let addr_y = &&*x as *const _ as usize; // assert ok
    |                       ^^^ help: if you would like to reborrow, try removing `&*`: `x`
 
-error: aborting due to 3 previous errors
+error: deref on an immutable reference
+  --> tests/ui/borrow_deref_ref.rs:123:9
+   |
+LL |         (&*s).foo();
+   |         ^^^^^ help: if you would like to reborrow, try removing `&*`: `s`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/box_collection.rs b/src/tools/clippy/tests/ui/box_collection.rs
index 0f7d3c74ddd..7ae5446924f 100644
--- a/src/tools/clippy/tests/ui/box_collection.rs
+++ b/src/tools/clippy/tests/ui/box_collection.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all)]
 #![allow(
     clippy::boxed_local,
     clippy::needless_pass_by_value,
diff --git a/src/tools/clippy/tests/ui/box_collection.stderr b/src/tools/clippy/tests/ui/box_collection.stderr
index ebbc3d92b57..d730e2dcc11 100644
--- a/src/tools/clippy/tests/ui/box_collection.stderr
+++ b/src/tools/clippy/tests/ui/box_collection.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `Box<Vec<..>>`. Consider using just `Vec<..>`
-  --> tests/ui/box_collection.rs:21:15
+  --> tests/ui/box_collection.rs:20:15
    |
 LL | fn test1(foo: Box<Vec<bool>>) {}
    |               ^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | fn test1(foo: Box<Vec<bool>>) {}
    = help: to override `-D warnings` add `#[allow(clippy::box_collection)]`
 
 error: you seem to be trying to use `Box<String>`. Consider using just `String`
-  --> tests/ui/box_collection.rs:29:15
+  --> tests/ui/box_collection.rs:28:15
    |
 LL | fn test3(foo: Box<String>) {}
    |               ^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL | fn test3(foo: Box<String>) {}
    = help: `String` is already on the heap, `Box<String>` makes an extra allocation
 
 error: you seem to be trying to use `Box<HashMap<..>>`. Consider using just `HashMap<..>`
-  --> tests/ui/box_collection.rs:32:15
+  --> tests/ui/box_collection.rs:31:15
    |
 LL | fn test4(foo: Box<HashMap<String, String>>) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL | fn test4(foo: Box<HashMap<String, String>>) {}
    = help: `HashMap<..>` is already on the heap, `Box<HashMap<..>>` makes an extra allocation
 
 error: you seem to be trying to use `Box<HashSet<..>>`. Consider using just `HashSet<..>`
-  --> tests/ui/box_collection.rs:35:15
+  --> tests/ui/box_collection.rs:34:15
    |
 LL | fn test5(foo: Box<HashSet<i64>>) {}
    |               ^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL | fn test5(foo: Box<HashSet<i64>>) {}
    = help: `HashSet<..>` is already on the heap, `Box<HashSet<..>>` makes an extra allocation
 
 error: you seem to be trying to use `Box<VecDeque<..>>`. Consider using just `VecDeque<..>`
-  --> tests/ui/box_collection.rs:38:15
+  --> tests/ui/box_collection.rs:37:15
    |
 LL | fn test6(foo: Box<VecDeque<i32>>) {}
    |               ^^^^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL | fn test6(foo: Box<VecDeque<i32>>) {}
    = help: `VecDeque<..>` is already on the heap, `Box<VecDeque<..>>` makes an extra allocation
 
 error: you seem to be trying to use `Box<LinkedList<..>>`. Consider using just `LinkedList<..>`
-  --> tests/ui/box_collection.rs:41:15
+  --> tests/ui/box_collection.rs:40:15
    |
 LL | fn test7(foo: Box<LinkedList<i16>>) {}
    |               ^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL | fn test7(foo: Box<LinkedList<i16>>) {}
    = help: `LinkedList<..>` is already on the heap, `Box<LinkedList<..>>` makes an extra allocation
 
 error: you seem to be trying to use `Box<BTreeMap<..>>`. Consider using just `BTreeMap<..>`
-  --> tests/ui/box_collection.rs:44:15
+  --> tests/ui/box_collection.rs:43:15
    |
 LL | fn test8(foo: Box<BTreeMap<i8, String>>) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@ LL | fn test8(foo: Box<BTreeMap<i8, String>>) {}
    = help: `BTreeMap<..>` is already on the heap, `Box<BTreeMap<..>>` makes an extra allocation
 
 error: you seem to be trying to use `Box<BTreeSet<..>>`. Consider using just `BTreeSet<..>`
-  --> tests/ui/box_collection.rs:47:15
+  --> tests/ui/box_collection.rs:46:15
    |
 LL | fn test9(foo: Box<BTreeSet<u64>>) {}
    |               ^^^^^^^^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL | fn test9(foo: Box<BTreeSet<u64>>) {}
    = help: `BTreeSet<..>` is already on the heap, `Box<BTreeSet<..>>` makes an extra allocation
 
 error: you seem to be trying to use `Box<BinaryHeap<..>>`. Consider using just `BinaryHeap<..>`
-  --> tests/ui/box_collection.rs:50:16
+  --> tests/ui/box_collection.rs:49:16
    |
 LL | fn test10(foo: Box<BinaryHeap<u32>>) {}
    |                ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
index bf7635fdf09..0c9d2124354 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
@@ -1,5 +1,4 @@
 #![warn(clippy::case_sensitive_file_extension_comparisons)]
-#![allow(clippy::unnecessary_map_or)]
 
 use std::string::String;
 
@@ -13,7 +12,7 @@ impl TestStruct {
 fn is_rust_file(filename: &str) -> bool {
     std::path::Path::new(filename)
         .extension()
-        .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
+        .is_some_and(|ext| ext.eq_ignore_ascii_case("rs"))
     //~^ case_sensitive_file_extension_comparisons
 }
 
@@ -21,18 +20,18 @@ fn main() {
     // std::string::String and &str should trigger the lint failure with .ext12
     let _ = std::path::Path::new(&String::new())
         .extension()
-        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+        .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12"));
     //~^ case_sensitive_file_extension_comparisons
     let _ = std::path::Path::new("str")
         .extension()
-        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+        .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12"));
     //~^ case_sensitive_file_extension_comparisons
 
     // The fixup should preserve the indentation level
     {
         let _ = std::path::Path::new("str")
             .extension()
-            .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+            .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12"));
         //~^ case_sensitive_file_extension_comparisons
     }
 
@@ -42,11 +41,11 @@ fn main() {
     // std::string::String and &str should trigger the lint failure with .EXT12
     let _ = std::path::Path::new(&String::new())
         .extension()
-        .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+        .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12"));
     //~^ case_sensitive_file_extension_comparisons
     let _ = std::path::Path::new("str")
         .extension()
-        .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+        .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12"));
     //~^ case_sensitive_file_extension_comparisons
 
     // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
@@ -76,3 +75,11 @@ fn main() {
     let _ = "str".ends_with(".123");
     TestStruct {}.ends_with(".123");
 }
+
+#[clippy::msrv = "1.69"]
+fn msrv_check() {
+    let _ = std::path::Path::new(&String::new())
+        .extension()
+        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+    //~^ case_sensitive_file_extension_comparisons
+}
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
index 0c4070a42d4..f8a947aa827 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::case_sensitive_file_extension_comparisons)]
-#![allow(clippy::unnecessary_map_or)]
 
 use std::string::String;
 
@@ -64,3 +63,9 @@ fn main() {
     let _ = "str".ends_with(".123");
     TestStruct {}.ends_with(".123");
 }
+
+#[clippy::msrv = "1.69"]
+fn msrv_check() {
+    let _ = String::new().ends_with(".ext12");
+    //~^ case_sensitive_file_extension_comparisons
+}
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
index e035534d269..93bee8e7667 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
@@ -1,5 +1,5 @@
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:14:5
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:13:5
    |
 LL |     filename.ends_with(".rs")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,11 +11,11 @@ help: use std::path::Path
    |
 LL ~     std::path::Path::new(filename)
 LL +         .extension()
-LL +         .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
+LL +         .is_some_and(|ext| ext.eq_ignore_ascii_case("rs"))
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13
    |
 LL |     let _ = String::new().ends_with(".ext12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,11 +25,11 @@ help: use std::path::Path
    |
 LL ~     let _ = std::path::Path::new(&String::new())
 LL +         .extension()
-LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+LL ~         .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:22:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:21:13
    |
 LL |     let _ = "str".ends_with(".ext12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,11 +39,11 @@ help: use std::path::Path
    |
 LL ~     let _ = std::path::Path::new("str")
 LL +         .extension()
-LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+LL ~         .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:27:17
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:26:17
    |
 LL |         let _ = "str".ends_with(".ext12");
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,11 +53,11 @@ help: use std::path::Path
    |
 LL ~         let _ = std::path::Path::new("str")
 LL +             .extension()
-LL ~             .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+LL ~             .is_some_and(|ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:35:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:34:13
    |
 LL |     let _ = String::new().ends_with(".EXT12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -67,11 +67,11 @@ help: use std::path::Path
    |
 LL ~     let _ = std::path::Path::new(&String::new())
 LL +         .extension()
-LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+LL ~         .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12"));
    |
 
 error: case-sensitive file extension comparison
-  --> tests/ui/case_sensitive_file_extension_comparisons.rs:37:13
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:36:13
    |
 LL |     let _ = "str".ends_with(".EXT12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -81,8 +81,22 @@ help: use std::path::Path
    |
 LL ~     let _ = std::path::Path::new("str")
 LL +         .extension()
-LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+LL ~         .is_some_and(|ext| ext.eq_ignore_ascii_case("EXT12"));
+   |
+
+error: case-sensitive file extension comparison
+  --> tests/ui/case_sensitive_file_extension_comparisons.rs:69:13
+   |
+LL |     let _ = String::new().ends_with(".ext12");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+   |
+LL ~     let _ = std::path::Path::new(&String::new())
+LL +         .extension()
+LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
    |
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed
new file mode 100644
index 00000000000..04c8f6782c5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.fixed
@@ -0,0 +1,65 @@
+#![feature(round_char_boundary)]
+#![warn(clippy::char_indices_as_byte_indices)]
+
+trait StrExt {
+    fn use_index(&self, _: usize);
+}
+impl StrExt for str {
+    fn use_index(&self, _: usize) {}
+}
+
+fn bad(prim: &str, string: String) {
+    for (idx, _) in prim.char_indices() {
+        let _ = prim[..idx];
+        //~^ char_indices_as_byte_indices
+        prim.split_at(idx);
+        //~^ char_indices_as_byte_indices
+
+        // This won't panic, but it can still return a wrong substring
+        let _ = prim[..prim.floor_char_boundary(idx)];
+        //~^ char_indices_as_byte_indices
+
+        // can't use #[expect] here because the .fixed file will still have the attribute and create an
+        // unfulfilled expectation, but make sure lint level attributes work on the use expression:
+        #[allow(clippy::char_indices_as_byte_indices)]
+        let _ = prim[..idx];
+    }
+
+    for c in prim.char_indices() {
+        let _ = prim[..c.0];
+        //~^ char_indices_as_byte_indices
+        prim.split_at(c.0);
+        //~^ char_indices_as_byte_indices
+    }
+
+    for (idx, _) in string.char_indices() {
+        let _ = string[..idx];
+        //~^ char_indices_as_byte_indices
+        string.split_at(idx);
+        //~^ char_indices_as_byte_indices
+    }
+}
+
+fn good(prim: &str, prim2: &str) {
+    for (idx, _) in prim.chars().enumerate() {
+        // Indexing into a different string
+        let _ = prim2[..idx];
+
+        // Unknown use
+        std::hint::black_box(idx);
+
+        // Method call to user defined extension trait
+        prim.use_index(idx);
+
+        // str method taking a usize that doesn't represent a byte index
+        prim.splitn(idx, prim2);
+    }
+
+    let mut string = "äa".to_owned();
+    for (idx, _) in string.clone().chars().enumerate() {
+        // Even though the receiver is the same expression, it should not be treated as the same value.
+        string.clone().remove(idx);
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs
new file mode 100644
index 00000000000..773a4fc65f1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.rs
@@ -0,0 +1,65 @@
+#![feature(round_char_boundary)]
+#![warn(clippy::char_indices_as_byte_indices)]
+
+trait StrExt {
+    fn use_index(&self, _: usize);
+}
+impl StrExt for str {
+    fn use_index(&self, _: usize) {}
+}
+
+fn bad(prim: &str, string: String) {
+    for (idx, _) in prim.chars().enumerate() {
+        let _ = prim[..idx];
+        //~^ char_indices_as_byte_indices
+        prim.split_at(idx);
+        //~^ char_indices_as_byte_indices
+
+        // This won't panic, but it can still return a wrong substring
+        let _ = prim[..prim.floor_char_boundary(idx)];
+        //~^ char_indices_as_byte_indices
+
+        // can't use #[expect] here because the .fixed file will still have the attribute and create an
+        // unfulfilled expectation, but make sure lint level attributes work on the use expression:
+        #[allow(clippy::char_indices_as_byte_indices)]
+        let _ = prim[..idx];
+    }
+
+    for c in prim.chars().enumerate() {
+        let _ = prim[..c.0];
+        //~^ char_indices_as_byte_indices
+        prim.split_at(c.0);
+        //~^ char_indices_as_byte_indices
+    }
+
+    for (idx, _) in string.chars().enumerate() {
+        let _ = string[..idx];
+        //~^ char_indices_as_byte_indices
+        string.split_at(idx);
+        //~^ char_indices_as_byte_indices
+    }
+}
+
+fn good(prim: &str, prim2: &str) {
+    for (idx, _) in prim.chars().enumerate() {
+        // Indexing into a different string
+        let _ = prim2[..idx];
+
+        // Unknown use
+        std::hint::black_box(idx);
+
+        // Method call to user defined extension trait
+        prim.use_index(idx);
+
+        // str method taking a usize that doesn't represent a byte index
+        prim.splitn(idx, prim2);
+    }
+
+    let mut string = "äa".to_owned();
+    for (idx, _) in string.clone().chars().enumerate() {
+        // Even though the receiver is the same expression, it should not be treated as the same value.
+        string.clone().remove(idx);
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr
new file mode 100644
index 00000000000..e2b4c1db78c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/char_indices_as_byte_indices.stderr
@@ -0,0 +1,130 @@
+error: indexing into a string with a character position where a byte index is expected
+  --> tests/ui/char_indices_as_byte_indices.rs:13:24
+   |
+LL |         let _ = prim[..idx];
+   |                        ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:12:10
+   |
+LL |     for (idx, _) in prim.chars().enumerate() {
+   |          ^^^                     ^^^^^^^^^^^
+   = note: `-D clippy::char-indices-as-byte-indices` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::char_indices_as_byte_indices)]`
+help: consider using `.char_indices()` instead
+   |
+LL -     for (idx, _) in prim.chars().enumerate() {
+LL +     for (idx, _) in prim.char_indices() {
+   |
+
+error: passing a character position to a method that expects a byte index
+  --> tests/ui/char_indices_as_byte_indices.rs:15:23
+   |
+LL |         prim.split_at(idx);
+   |                       ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:12:10
+   |
+LL |     for (idx, _) in prim.chars().enumerate() {
+   |          ^^^                     ^^^^^^^^^^^
+help: consider using `.char_indices()` instead
+   |
+LL -     for (idx, _) in prim.chars().enumerate() {
+LL +     for (idx, _) in prim.char_indices() {
+   |
+
+error: passing a character position to a method that expects a byte index
+  --> tests/ui/char_indices_as_byte_indices.rs:19:49
+   |
+LL |         let _ = prim[..prim.floor_char_boundary(idx)];
+   |                                                 ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:12:10
+   |
+LL |     for (idx, _) in prim.chars().enumerate() {
+   |          ^^^                     ^^^^^^^^^^^
+help: consider using `.char_indices()` instead
+   |
+LL -     for (idx, _) in prim.chars().enumerate() {
+LL +     for (idx, _) in prim.char_indices() {
+   |
+
+error: indexing into a string with a character position where a byte index is expected
+  --> tests/ui/char_indices_as_byte_indices.rs:29:24
+   |
+LL |         let _ = prim[..c.0];
+   |                        ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:28:9
+   |
+LL |     for c in prim.chars().enumerate() {
+   |         ^                 ^^^^^^^^^^^
+help: consider using `.char_indices()` instead
+   |
+LL -     for c in prim.chars().enumerate() {
+LL +     for c in prim.char_indices() {
+   |
+
+error: passing a character position to a method that expects a byte index
+  --> tests/ui/char_indices_as_byte_indices.rs:31:23
+   |
+LL |         prim.split_at(c.0);
+   |                       ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:28:9
+   |
+LL |     for c in prim.chars().enumerate() {
+   |         ^                 ^^^^^^^^^^^
+help: consider using `.char_indices()` instead
+   |
+LL -     for c in prim.chars().enumerate() {
+LL +     for c in prim.char_indices() {
+   |
+
+error: indexing into a string with a character position where a byte index is expected
+  --> tests/ui/char_indices_as_byte_indices.rs:36:26
+   |
+LL |         let _ = string[..idx];
+   |                          ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:35:10
+   |
+LL |     for (idx, _) in string.chars().enumerate() {
+   |          ^^^                       ^^^^^^^^^^^
+help: consider using `.char_indices()` instead
+   |
+LL -     for (idx, _) in string.chars().enumerate() {
+LL +     for (idx, _) in string.char_indices() {
+   |
+
+error: passing a character position to a method that expects a byte index
+  --> tests/ui/char_indices_as_byte_indices.rs:38:25
+   |
+LL |         string.split_at(idx);
+   |                         ^^^
+   |
+   = note: a character can take up more than one byte, so they are not interchangeable
+note: position comes from the enumerate iterator
+  --> tests/ui/char_indices_as_byte_indices.rs:35:10
+   |
+LL |     for (idx, _) in string.chars().enumerate() {
+   |          ^^^                       ^^^^^^^^^^^
+help: consider using `.char_indices()` instead
+   |
+LL -     for (idx, _) in string.chars().enumerate() {
+LL +     for (idx, _) in string.char_indices() {
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
index c17eaef2326..bdac1e42309 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -244,8 +244,7 @@ LL |         if X.is_some() {
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
    = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
-   = note: `-D static-mut-refs` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(static_mut_refs)]`
+   = note: `#[deny(static_mut_refs)]` on by default
 
 error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
index eb01633a25f..85d0991bef0 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
+++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
@@ -74,3 +74,12 @@ impl ToOwned for Baz {
         Baz
     }
 }
+
+fn issue_8103() {
+    let foo1 = String::from("foo");
+    let _ = foo1 == "foo";
+    //~^ cmp_owned
+    let foo2 = "foo";
+    let _ = foo1 == foo2;
+    //~^ cmp_owned
+}
diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs
index 82409f27b12..2393757d76f 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs
+++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.rs
@@ -74,3 +74,12 @@ impl ToOwned for Baz {
         Baz
     }
 }
+
+fn issue_8103() {
+    let foo1 = String::from("foo");
+    let _ = foo1 == "foo".to_owned();
+    //~^ cmp_owned
+    let foo2 = "foo";
+    let _ = foo1 == foo2.to_owned();
+    //~^ cmp_owned
+}
diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr
index ca2ab448472..dd9ffa70897 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr
+++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr
@@ -37,5 +37,17 @@ error: this creates an owned instance just for comparison
 LL |     "abc".chars().filter(|c| c.to_owned() != 'X');
    |                              ^^^^^^^^^^^^ help: try: `*c`
 
-error: aborting due to 6 previous errors
+error: this creates an owned instance just for comparison
+  --> tests/ui/cmp_owned/with_suggestion.rs:80:21
+   |
+LL |     let _ = foo1 == "foo".to_owned();
+   |                     ^^^^^^^^^^^^^^^^ help: try: `"foo"`
+
+error: this creates an owned instance just for comparison
+  --> tests/ui/cmp_owned/with_suggestion.rs:83:21
+   |
+LL |     let _ = foo1 == foo2.to_owned();
+   |                     ^^^^^^^^^^^^^^^ help: try: `foo2`
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.rs b/src/tools/clippy/tests/ui/cognitive_complexity.rs
index 2dbec955f63..8080c6775e0 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity.rs
+++ b/src/tools/clippy/tests/ui/cognitive_complexity.rs
@@ -1,6 +1,11 @@
-#![allow(clippy::all)]
 #![warn(clippy::cognitive_complexity)]
-#![allow(unused, unused_crate_dependencies)]
+#![allow(
+    clippy::eq_op,
+    clippy::needless_borrows_for_generic_args,
+    clippy::needless_return,
+    clippy::nonminimal_bool,
+    clippy::uninlined_format_args
+)]
 
 #[rustfmt::skip]
 fn main() {
@@ -448,3 +453,22 @@ mod issue9300 {
         }
     }
 }
+
+#[clippy::cognitive_complexity = "1"]
+mod issue14422 {
+    fn foo() {
+        //~^ cognitive_complexity
+        for _ in 0..10 {
+            println!("hello there");
+        }
+    }
+
+    fn bar() {
+        //~^ cognitive_complexity
+        for _ in 0..10 {
+            println!("hello there");
+        }
+        return;
+        return;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.stderr b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
index 52607b87c60..67ef4e5655b 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity.stderr
+++ b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
@@ -1,5 +1,5 @@
 error: the function has a cognitive complexity of (28/25)
-  --> tests/ui/cognitive_complexity.rs:6:4
+  --> tests/ui/cognitive_complexity.rs:11:4
    |
 LL | fn main() {
    |    ^^^^
@@ -9,7 +9,7 @@ LL | fn main() {
    = help: to override `-D warnings` add `#[allow(clippy::cognitive_complexity)]`
 
 error: the function has a cognitive complexity of (7/1)
-  --> tests/ui/cognitive_complexity.rs:93:4
+  --> tests/ui/cognitive_complexity.rs:98:4
    |
 LL | fn kaboom() {
    |    ^^^^^^
@@ -17,7 +17,7 @@ LL | fn kaboom() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:153:4
+  --> tests/ui/cognitive_complexity.rs:158:4
    |
 LL | fn baa() {
    |    ^^^
@@ -25,7 +25,7 @@ LL | fn baa() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:156:13
+  --> tests/ui/cognitive_complexity.rs:161:13
    |
 LL |     let x = || match 99 {
    |             ^^
@@ -33,7 +33,7 @@ LL |     let x = || match 99 {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:174:4
+  --> tests/ui/cognitive_complexity.rs:179:4
    |
 LL | fn bar() {
    |    ^^^
@@ -41,7 +41,7 @@ LL | fn bar() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:187:4
+  --> tests/ui/cognitive_complexity.rs:192:4
    |
 LL | fn dont_warn_on_tests() {
    |    ^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL | fn dont_warn_on_tests() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:197:4
+  --> tests/ui/cognitive_complexity.rs:202:4
    |
 LL | fn barr() {
    |    ^^^^
@@ -57,7 +57,7 @@ LL | fn barr() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (3/1)
-  --> tests/ui/cognitive_complexity.rs:209:4
+  --> tests/ui/cognitive_complexity.rs:214:4
    |
 LL | fn barr2() {
    |    ^^^^^
@@ -65,7 +65,7 @@ LL | fn barr2() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:227:4
+  --> tests/ui/cognitive_complexity.rs:232:4
    |
 LL | fn barrr() {
    |    ^^^^^
@@ -73,7 +73,7 @@ LL | fn barrr() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (3/1)
-  --> tests/ui/cognitive_complexity.rs:239:4
+  --> tests/ui/cognitive_complexity.rs:244:4
    |
 LL | fn barrr2() {
    |    ^^^^^^
@@ -81,7 +81,7 @@ LL | fn barrr2() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:257:4
+  --> tests/ui/cognitive_complexity.rs:262:4
    |
 LL | fn barrrr() {
    |    ^^^^^^
@@ -89,7 +89,7 @@ LL | fn barrrr() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (3/1)
-  --> tests/ui/cognitive_complexity.rs:269:4
+  --> tests/ui/cognitive_complexity.rs:274:4
    |
 LL | fn barrrr2() {
    |    ^^^^^^^
@@ -97,7 +97,7 @@ LL | fn barrrr2() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:287:4
+  --> tests/ui/cognitive_complexity.rs:292:4
    |
 LL | fn cake() {
    |    ^^^^
@@ -105,7 +105,7 @@ LL | fn cake() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (4/1)
-  --> tests/ui/cognitive_complexity.rs:299:8
+  --> tests/ui/cognitive_complexity.rs:304:8
    |
 LL | pub fn read_file(input_path: &str) -> String {
    |        ^^^^^^^^^
@@ -113,7 +113,7 @@ LL | pub fn read_file(input_path: &str) -> String {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:332:4
+  --> tests/ui/cognitive_complexity.rs:337:4
    |
 LL | fn void(void: Void) {
    |    ^^^^
@@ -121,7 +121,7 @@ LL | fn void(void: Void) {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (8/1)
-  --> tests/ui/cognitive_complexity.rs:385:4
+  --> tests/ui/cognitive_complexity.rs:390:4
    |
 LL | fn early_ret() -> i32 {
    |    ^^^^^^^^^
@@ -129,7 +129,7 @@ LL | fn early_ret() -> i32 {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:408:13
+  --> tests/ui/cognitive_complexity.rs:413:13
    |
 LL |     let x = |a: i32, b: i32| -> i32 {
    |             ^^^^^^^^^^^^^^^^
@@ -137,7 +137,7 @@ LL |     let x = |a: i32, b: i32| -> i32 {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:423:8
+  --> tests/ui/cognitive_complexity.rs:428:8
    |
 LL |     fn moo(&self) {
    |        ^^^
@@ -145,7 +145,7 @@ LL |     fn moo(&self) {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:434:14
+  --> tests/ui/cognitive_complexity.rs:439:14
    |
 LL |     async fn a() {
    |              ^
@@ -153,12 +153,28 @@ LL |     async fn a() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
-  --> tests/ui/cognitive_complexity.rs:443:22
+  --> tests/ui/cognitive_complexity.rs:448:22
    |
 LL |         pub async fn async_method() {
    |                      ^^^^^^^^^^^^
    |
    = help: you could split it up into multiple smaller functions
 
-error: aborting due to 20 previous errors
+error: the function has a cognitive complexity of (2/1)
+  --> tests/ui/cognitive_complexity.rs:459:8
+   |
+LL |     fn foo() {
+   |        ^^^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: the function has a cognitive complexity of (2/1)
+  --> tests/ui/cognitive_complexity.rs:466:8
+   |
+LL |     fn bar() {
+   |        ^^^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index 6e994018aef..e1ceb04f9cb 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -12,34 +12,40 @@
 fn main() {
     let x = "hello";
     let y = "world";
-    if x == "hello" && y == "world" {
-        println!("Hello world!");
-    }
+    if x == "hello"
+        && y == "world" {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
-        println!("Hello world!");
-    }
+    if (x == "hello" || x == "world")
+        && (y == "world" || y == "hello") {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if x == "hello" && x == "world" && (y == "world" || y == "hello") {
-        println!("Hello world!");
-    }
+    if x == "hello" && x == "world"
+        && (y == "world" || y == "hello") {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if (x == "hello" || x == "world") && y == "world" && y == "hello" {
-        println!("Hello world!");
-    }
+    if (x == "hello" || x == "world")
+        && y == "world" && y == "hello" {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if x == "hello" && x == "world" && y == "world" && y == "hello" {
-        println!("Hello world!");
-    }
+    if x == "hello" && x == "world"
+        && y == "world" && y == "hello" {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if 42 == 1337 && 'a' != 'A' {
-        println!("world!")
-    }
+    if 42 == 1337
+        && 'a' != 'A' {
+            println!("world!")
+        }
     //~^^^^^ collapsible_if
 
     // Works because any if with an else statement cannot be collapsed.
@@ -71,37 +77,17 @@ fn main() {
         assert!(true); // assert! is just an `if`
     }
 
-
-    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
-    if x == "hello" {// Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" {
-        // Not collapsible
-        if y == "world" {
+    if x == "hello"
+        && y == "world" { // Collapsible
             println!("Hello world!");
         }
-    }
-
-    if x == "hello" && y == "world" { // Collapsible
-        println!("Hello world!");
-    }
     //~^^^^^ collapsible_if
 
     if x == "hello" {
         print!("Hello ");
     } else {
         // Not collapsible
-        if y == "world" {
+        if let Some(42) = Some(42) {
             println!("world!")
         }
     }
@@ -110,21 +96,8 @@ fn main() {
         print!("Hello ");
     } else {
         // Not collapsible
-        if let Some(42) = Some(42) {
-            println!("world!")
-        }
-    }
-
-    if x == "hello" {
-        /* Not collapsible */
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { /* Not collapsible */
         if y == "world" {
-            println!("Hello world!");
+            println!("world!")
         }
     }
 
@@ -150,11 +123,13 @@ fn main() {
     }
 
     // Fix #5962
-    if matches!(true, true) && matches!(true, true) {}
+    if matches!(true, true)
+        && matches!(true, true) {}
     //~^^^ collapsible_if
 
     // Issue #9375
-    if matches!(true, true) && truth() && matches!(true, true) {}
+    if matches!(true, true) && truth()
+        && matches!(true, true) {}
     //~^^^ collapsible_if
 
     if true {
@@ -163,4 +138,27 @@ fn main() {
             println!("Hello world!");
         }
     }
+
+    if true
+        && true {
+            println!("No comment, linted");
+        }
+    //~^^^^^ collapsible_if
+
+    if true {
+        // Do not collapse because of this comment
+        if true {
+            println!("Hello world!");
+        }
+    }
+}
+
+#[rustfmt::skip]
+fn layout_check() -> u32 {
+    if true
+        && true {
+        }
+        // This is a comment, do not collapse code to it
+    ; 3
+    //~^^^^^ collapsible_if
 }
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index 5cf591a658c..0b996dca22e 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -83,27 +83,6 @@ fn main() {
         assert!(true); // assert! is just an `if`
     }
 
-
-    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
-    if x == "hello" {// Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" {
-        // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
     if x == "hello" {
         if y == "world" { // Collapsible
             println!("Hello world!");
@@ -115,7 +94,7 @@ fn main() {
         print!("Hello ");
     } else {
         // Not collapsible
-        if y == "world" {
+        if let Some(42) = Some(42) {
             println!("world!")
         }
     }
@@ -124,21 +103,8 @@ fn main() {
         print!("Hello ");
     } else {
         // Not collapsible
-        if let Some(42) = Some(42) {
-            println!("world!")
-        }
-    }
-
-    if x == "hello" {
-        /* Not collapsible */
         if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { /* Not collapsible */
-        if y == "world" {
-            println!("Hello world!");
+            println!("world!")
         }
     }
 
@@ -181,4 +147,28 @@ fn main() {
             println!("Hello world!");
         }
     }
+
+    if true {
+        if true {
+            println!("No comment, linted");
+        }
+    }
+    //~^^^^^ collapsible_if
+
+    if true {
+        // Do not collapse because of this comment
+        if true {
+            println!("Hello world!");
+        }
+    }
+}
+
+#[rustfmt::skip]
+fn layout_check() -> u32 {
+    if true {
+        if true {
+        }
+        // This is a comment, do not collapse code to it
+    }; 3
+    //~^^^^^ collapsible_if
 }
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 3cc3fe5534f..53281146239 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -12,9 +12,10 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]`
 help: collapse nested if block
    |
-LL ~     if x == "hello" && y == "world" {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello"
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -29,9 +30,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if (x == "hello" || x == "world") {
+LL ~         && (y == "world" || y == "hello") {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -46,9 +48,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if x == "hello" && x == "world" && (y == "world" || y == "hello") {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello" && x == "world"
+LL ~         && (y == "world" || y == "hello") {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -63,9 +66,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if (x == "hello" || x == "world") && y == "world" && y == "hello" {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if (x == "hello" || x == "world") {
+LL ~         && y == "world" && y == "hello" {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -80,9 +84,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if x == "hello" && x == "world" && y == "world" && y == "hello" {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello" && x == "world"
+LL ~         && y == "world" && y == "hello" {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -97,13 +102,14 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if 42 == 1337 && 'a' != 'A' {
-LL +         println!("world!")
-LL +     }
+LL ~     if 42 == 1337
+LL ~         && 'a' != 'A' {
+LL |             println!("world!")
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
-  --> tests/ui/collapsible_if.rs:107:5
+  --> tests/ui/collapsible_if.rs:86:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" { // Collapsible
@@ -114,26 +120,75 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if x == "hello" && y == "world" { // Collapsible
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello"
+LL ~         && y == "world" { // Collapsible
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
-  --> tests/ui/collapsible_if.rs:167:5
+  --> tests/ui/collapsible_if.rs:133:5
    |
 LL | /     if matches!(true, true) {
 LL | |         if matches!(true, true) {}
 LL | |     }
-   | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if matches!(true, true)
+LL ~         && matches!(true, true) {}
+   |
 
 error: this `if` statement can be collapsed
-  --> tests/ui/collapsible_if.rs:173:5
+  --> tests/ui/collapsible_if.rs:139:5
    |
 LL | /     if matches!(true, true) && truth() {
 LL | |         if matches!(true, true) {}
 LL | |     }
-   | |_____^ help: collapse nested if block: `if matches!(true, true) && truth() && matches!(true, true) {}`
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if matches!(true, true) && truth()
+LL ~         && matches!(true, true) {}
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if.rs:151:5
+   |
+LL | /     if true {
+LL | |         if true {
+LL | |             println!("No comment, linted");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if true
+LL ~         && true {
+LL |             println!("No comment, linted");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if.rs:168:5
+   |
+LL | /     if true {
+LL | |         if true {
+...  |
+LL | |     }; 3
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if true
+LL ~         && true {
+LL |         }
+LL |         // This is a comment, do not collapse code to it
+LL ~     ; 3
+   |
 
-error: aborting due to 9 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/collapsible_if_let_chains.fixed b/src/tools/clippy/tests/ui/collapsible_if_let_chains.fixed
new file mode 100644
index 00000000000..3dd9498a4c9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/collapsible_if_let_chains.fixed
@@ -0,0 +1,29 @@
+#![feature(let_chains)]
+#![warn(clippy::collapsible_if)]
+
+fn main() {
+    if let Some(a) = Some(3) {
+        // with comment, so do not lint
+        if let Some(b) = Some(4) {
+            let _ = a + b;
+        }
+    }
+
+    if let Some(a) = Some(3)
+        && let Some(b) = Some(4) {
+            let _ = a + b;
+        }
+    //~^^^^^ collapsible_if
+
+    if let Some(a) = Some(3)
+        && a + 1 == 4 {
+            let _ = a;
+        }
+    //~^^^^^ collapsible_if
+
+    if Some(3) == Some(4).map(|x| x - 1)
+        && let Some(b) = Some(4) {
+            let _ = b;
+        }
+    //~^^^^^ collapsible_if
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_if_let_chains.rs b/src/tools/clippy/tests/ui/collapsible_if_let_chains.rs
new file mode 100644
index 00000000000..064b9a0be48
--- /dev/null
+++ b/src/tools/clippy/tests/ui/collapsible_if_let_chains.rs
@@ -0,0 +1,32 @@
+#![feature(let_chains)]
+#![warn(clippy::collapsible_if)]
+
+fn main() {
+    if let Some(a) = Some(3) {
+        // with comment, so do not lint
+        if let Some(b) = Some(4) {
+            let _ = a + b;
+        }
+    }
+
+    if let Some(a) = Some(3) {
+        if let Some(b) = Some(4) {
+            let _ = a + b;
+        }
+    }
+    //~^^^^^ collapsible_if
+
+    if let Some(a) = Some(3) {
+        if a + 1 == 4 {
+            let _ = a;
+        }
+    }
+    //~^^^^^ collapsible_if
+
+    if Some(3) == Some(4).map(|x| x - 1) {
+        if let Some(b) = Some(4) {
+            let _ = b;
+        }
+    }
+    //~^^^^^ collapsible_if
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_if_let_chains.stderr b/src/tools/clippy/tests/ui/collapsible_if_let_chains.stderr
new file mode 100644
index 00000000000..64a88114c47
--- /dev/null
+++ b/src/tools/clippy/tests/ui/collapsible_if_let_chains.stderr
@@ -0,0 +1,58 @@
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if_let_chains.rs:12:5
+   |
+LL | /     if let Some(a) = Some(3) {
+LL | |         if let Some(b) = Some(4) {
+LL | |             let _ = a + b;
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::collapsible-if` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]`
+help: collapse nested if block
+   |
+LL ~     if let Some(a) = Some(3)
+LL ~         && let Some(b) = Some(4) {
+LL |             let _ = a + b;
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if_let_chains.rs:19:5
+   |
+LL | /     if let Some(a) = Some(3) {
+LL | |         if a + 1 == 4 {
+LL | |             let _ = a;
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if let Some(a) = Some(3)
+LL ~         && a + 1 == 4 {
+LL |             let _ = a;
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if_let_chains.rs:26:5
+   |
+LL | /     if Some(3) == Some(4).map(|x| x - 1) {
+LL | |         if let Some(b) = Some(4) {
+LL | |             let _ = b;
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if Some(3) == Some(4).map(|x| x - 1)
+LL ~         && let Some(b) = Some(4) {
+LL |             let _ = b;
+LL ~         }
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/collapsible_match.rs b/src/tools/clippy/tests/ui/collapsible_match.rs
index 796cabd4b66..55ef5584495 100644
--- a/src/tools/clippy/tests/ui/collapsible_match.rs
+++ b/src/tools/clippy/tests/ui/collapsible_match.rs
@@ -303,6 +303,18 @@ pub fn test_2(x: Issue9647) {
     }
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/14281
+fn lint_emitted_at_right_node(opt: Option<Result<u64, String>>) {
+    let n = match opt {
+        #[expect(clippy::collapsible_match)]
+        Some(n) => match n {
+            Ok(n) => n,
+            _ => return,
+        },
+        None => return,
+    };
+}
+
 fn make<T>() -> T {
     unimplemented!()
 }
diff --git a/src/tools/clippy/tests/ui/crashes/enum-glob-import-crate.rs b/src/tools/clippy/tests/ui/crashes/enum-glob-import-crate.rs
index bbcd599f6d0..3352e822ef8 100644
--- a/src/tools/clippy/tests/ui/crashes/enum-glob-import-crate.rs
+++ b/src/tools/clippy/tests/ui/crashes/enum-glob-import-crate.rs
@@ -1,8 +1,5 @@
 //@ check-pass
 
-#![deny(clippy::all)]
-#![allow(unused_imports)]
-
 use std::*;
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-11230.fixed b/src/tools/clippy/tests/ui/crashes/ice-11230.fixed
index 181e1ebbe5a..c49a419f0d4 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-11230.fixed
+++ b/src/tools/clippy/tests/ui/crashes/ice-11230.fixed
@@ -12,7 +12,7 @@ fn main() {
 // needless_collect
 trait Helper<'a>: Iterator<Item = fn()> {}
 
+// Should not be linted because we have no idea whether the iterator has side effects
 fn x(w: &mut dyn for<'a> Helper<'a>) {
-    w.next().is_none();
-    //~^ needless_collect
+    w.collect::<Vec<_>>().is_empty();
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-11230.rs b/src/tools/clippy/tests/ui/crashes/ice-11230.rs
index fb05dc781bc..f66b7e961c8 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-11230.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-11230.rs
@@ -12,7 +12,7 @@ fn main() {
 // needless_collect
 trait Helper<'a>: Iterator<Item = fn()> {}
 
+// Should not be linted because we have no idea whether the iterator has side effects
 fn x(w: &mut dyn for<'a> Helper<'a>) {
     w.collect::<Vec<_>>().is_empty();
-    //~^ needless_collect
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-11230.stderr b/src/tools/clippy/tests/ui/crashes/ice-11230.stderr
index b4a3f67081a..91d59121ac4 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-11230.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-11230.stderr
@@ -7,14 +7,5 @@ LL |     for v in A.iter() {}
    = note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::explicit_iter_loop)]`
 
-error: avoid using `collect()` when not needed
-  --> tests/ui/crashes/ice-11230.rs:16:7
-   |
-LL |     w.collect::<Vec<_>>().is_empty();
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `next().is_none()`
-   |
-   = note: `-D clippy::needless-collect` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::needless_collect)]`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-13544-original.rs b/src/tools/clippy/tests/ui/crashes/ice-13544-original.rs
new file mode 100644
index 00000000000..1709eaeb365
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-13544-original.rs
@@ -0,0 +1,45 @@
+//@ check-pass
+#![warn(clippy::significant_drop_tightening)]
+
+use std::mem::ManuallyDrop;
+use std::ops::{Deref, DerefMut};
+
+trait Scopable: Sized {
+    type SubType: Scopable;
+}
+
+struct Subtree<T: Scopable>(ManuallyDrop<Box<Tree<T::SubType>>>);
+
+impl<T: Scopable> Drop for Subtree<T> {
+    fn drop(&mut self) {
+        // SAFETY: The field cannot be used after we drop
+        unsafe { ManuallyDrop::drop(&mut self.0) }
+    }
+}
+
+impl<T: Scopable> Deref for Subtree<T> {
+    type Target = Tree<T::SubType>;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T: Scopable> DerefMut for Subtree<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+enum Tree<T: Scopable> {
+    Group(Vec<Tree<T>>),
+    Subtree(Subtree<T>),
+    Leaf(T),
+}
+
+impl<T: Scopable> Tree<T> {
+    fn foo(self) -> Self {
+        self
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-13544-reduced.rs b/src/tools/clippy/tests/ui/crashes/ice-13544-reduced.rs
new file mode 100644
index 00000000000..9266e71f5d0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-13544-reduced.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+#![warn(clippy::significant_drop_tightening)]
+#![allow(unused, clippy::no_effect)]
+
+use std::marker::PhantomData;
+
+trait Trait {
+    type Assoc: Trait;
+}
+struct S<T: Trait>(*const S<T::Assoc>, PhantomData<T>);
+
+fn f<T: Trait>(x: &mut S<T>) {
+    &mut x.0;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1588.rs b/src/tools/clippy/tests/ui/crashes/ice-1588.rs
index 3ccd33052cd..422c29b66cf 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1588.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1588.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![allow(clippy::all)]
+#![expect(clippy::no_effect)]
 
 // Test for https://github.com/rust-lang/rust-clippy/issues/1588
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
index 4a1886c08af..776b0a93bf7 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![allow(dead_code, unused_variables, invalid_null_arguments)]
+#![allow(dead_code, unused_variables, invalid_null_arguments, unnecessary_transmutes)]
 #![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)]
 
 /// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1969.rs b/src/tools/clippy/tests/ui/crashes/ice-1969.rs
index 34ff725d711..813972a046f 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1969.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1969.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![allow(clippy::all)]
-
 // Test for https://github.com/rust-lang/rust-clippy/issues/1969
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3462.rs b/src/tools/clippy/tests/ui/crashes/ice-3462.rs
index 4ce484917ae..e06eccdf142 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3462.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3462.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 
-#![warn(clippy::all)]
-#![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)]
-#![allow(unused)]
+#![expect(clippy::disallowed_names)]
 
 // Test for https://github.com/rust-lang/rust-clippy/issues/3462
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-700.rs b/src/tools/clippy/tests/ui/crashes/ice-700.rs
index aa3bf493c20..ca82f638b0b 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-700.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-700.rs
@@ -1,7 +1,5 @@
 //@ check-pass
 
-#![deny(clippy::all)]
-
 // Test for https://github.com/rust-lang/rust-clippy/issues/700
 
 fn core() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7012.rs b/src/tools/clippy/tests/ui/crashes/ice-7012.rs
index d76995adadf..48c1c5a98d4 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7012.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7012.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![allow(clippy::all)]
+#![expect(clippy::single_match)]
 
 enum _MyOption {
     None,
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7423.rs b/src/tools/clippy/tests/ui/crashes/ice-7423.rs
index a03981842fc..fbf5d6520ed 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7423.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7423.rs
@@ -6,7 +6,7 @@ pub trait Trait {
 
 impl Trait for usize {
     fn f() {
-        extern "C" {
+        unsafe extern "C" {
             fn g() -> usize;
         }
     }
diff --git a/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs b/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
index cb4685e78e2..0aa55cd0fac 100644
--- a/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
@@ -1,10 +1,7 @@
 //@ check-pass
 
-#![deny(clippy::all)]
-
 // Test for https://github.com/rust-lang/rust-clippy/issues/1336
 
-#[allow(dead_code)]
 struct Foo;
 
 impl Iterator for Foo {
diff --git a/src/tools/clippy/tests/ui/crashes/needless_borrow_fp.rs b/src/tools/clippy/tests/ui/crashes/needless_borrow_fp.rs
index 68e39531682..1b3b0290d90 100644
--- a/src/tools/clippy/tests/ui/crashes/needless_borrow_fp.rs
+++ b/src/tools/clippy/tests/ui/crashes/needless_borrow_fp.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 
-#[deny(clippy::all)]
 #[derive(Debug)]
 pub enum Error {
     Type(&'static str),
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed
index e09a913ef06..9d977e9eddc 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed
@@ -3,7 +3,6 @@
 
 use core::panic::PanicInfo;
 
-#[warn(clippy::all)]
 pub fn main() {
     let mut a = 42;
     let mut b = 1337;
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs
index 66ca97690c1..0967efe2ed8 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs
@@ -3,7 +3,6 @@
 
 use core::panic::PanicInfo;
 
-#[warn(clippy::all)]
 pub fn main() {
     let mut a = 42;
     let mut b = 1337;
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
index 3e37bd95ef3..e16b53b51a8 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
@@ -1,5 +1,5 @@
 error: this looks like you are trying to swap `a` and `b`
-  --> tests/ui/crate_level_checks/no_std_swap.rs:11:5
+  --> tests/ui/crate_level_checks/no_std_swap.rs:10:5
    |
 LL | /     a = b;
 ...  |
@@ -7,8 +7,7 @@ LL | |     b = a;
    | |_________^ help: try: `core::mem::swap(&mut a, &mut b)`
    |
    = note: or maybe you should use `core::mem::replace`?
-   = note: `-D clippy::almost-swapped` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::almost_swapped)]`
+   = note: `#[deny(clippy::almost_swapped)]` on by default
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
index fd1a0d8934b..3b9dee81898 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
@@ -1,5 +1,10 @@
+#![allow(
+    clippy::no_effect,
+    clippy::uninlined_format_args,
+    clippy::unit_arg,
+    clippy::unnecessary_operation
+)]
 #![warn(clippy::dbg_macro)]
-#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)]
 
 fn foo(n: u32) -> u32 {
     if let Some(n) = n.checked_sub(4) { n } else { n }
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
index c96e2c7251c..1dbbc6fe984 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
@@ -1,5 +1,10 @@
+#![allow(
+    clippy::no_effect,
+    clippy::uninlined_format_args,
+    clippy::unit_arg,
+    clippy::unnecessary_operation
+)]
 #![warn(clippy::dbg_macro)]
-#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)]
 
 fn foo(n: u32) -> u32 {
     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
index cd6dce584a2..f1412023cc8 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
@@ -1,5 +1,5 @@
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:5:22
+  --> tests/ui/dbg_macro/dbg_macro.rs:10:22
    |
 LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
    |                      ^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL +     if let Some(n) = n.checked_sub(4) { n } else { n }
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:11:8
+  --> tests/ui/dbg_macro/dbg_macro.rs:16:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL +     if n <= 1 {
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:14:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:19:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -37,7 +37,7 @@ LL +         1
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:17:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:22:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL +         n * factorial(n - 1)
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:23:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:28:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -61,7 +61,7 @@ LL +     42;
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:26:14
+  --> tests/ui/dbg_macro/dbg_macro.rs:31:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL +     foo(3) + factorial(4);
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:29:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:34:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -85,7 +85,7 @@ LL +     (1, 2, 3, 4, 5);
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:51:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:56:5
    |
 LL |     dbg!();
    |     ^^^^^^
@@ -96,7 +96,7 @@ LL -     dbg!();
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:55:13
+  --> tests/ui/dbg_macro/dbg_macro.rs:60:13
    |
 LL |     let _ = dbg!();
    |             ^^^^^^
@@ -108,7 +108,7 @@ LL +     let _ = ();
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:58:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:63:9
    |
 LL |     bar(dbg!());
    |         ^^^^^^
@@ -120,7 +120,7 @@ LL +     bar(());
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:61:10
+  --> tests/ui/dbg_macro/dbg_macro.rs:66:10
    |
 LL |     foo!(dbg!());
    |          ^^^^^^
@@ -132,7 +132,7 @@ LL +     foo!(());
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:64:16
+  --> tests/ui/dbg_macro/dbg_macro.rs:69:16
    |
 LL |     foo2!(foo!(dbg!()));
    |                ^^^^^^
@@ -144,7 +144,7 @@ LL +     foo2!(foo!(()));
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:46:13
+  --> tests/ui/dbg_macro/dbg_macro.rs:51:13
    |
 LL |             dbg!();
    |             ^^^^^^
@@ -159,7 +159,7 @@ LL -             dbg!();
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:87:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:92:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
@@ -171,7 +171,7 @@ LL +         2;
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:94:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:99:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -183,7 +183,7 @@ LL +     1;
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:100:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:105:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -195,7 +195,7 @@ LL +     1;
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:107:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:112:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
@@ -207,7 +207,7 @@ LL +         1;
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:114:31
+  --> tests/ui/dbg_macro/dbg_macro.rs:119:31
    |
 LL |         println!("dbg: {:?}", dbg!(s));
    |                               ^^^^^^^
@@ -219,7 +219,7 @@ LL +         println!("dbg: {:?}", s);
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:117:22
+  --> tests/ui/dbg_macro/dbg_macro.rs:122:22
    |
 LL |         print!("{}", dbg!(s));
    |                      ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index 03f5ca31f5f..40f40f7ea09 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -5,7 +5,7 @@
 #![allow(clippy::missing_safety_doc)]
 
 #[link(name = "c")]
-extern "C" {}
+unsafe extern "C" {}
 
 #[lang = "sized"]
 pub trait Sized {}
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
index fa4d5517782..1ca9be0cedd 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
@@ -161,3 +161,17 @@ fn main() {
 
     let _ = <struct_from_macro!()>::default();
 }
+
+fn issue12654() {
+    #[derive(Default)]
+    struct G;
+
+    fn f(_g: G) {}
+
+    f(<_>::default());
+    f(G);
+    //~^ default_constructed_unit_structs
+
+    // No lint because `as Default` hides the singleton
+    f(<G as Default>::default());
+}
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
index 291cd89da0b..99eb8913fc3 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
@@ -161,3 +161,17 @@ fn main() {
 
     let _ = <struct_from_macro!()>::default();
 }
+
+fn issue12654() {
+    #[derive(Default)]
+    struct G;
+
+    fn f(_g: G) {}
+
+    f(<_>::default());
+    f(<G>::default());
+    //~^ default_constructed_unit_structs
+
+    // No lint because `as Default` hides the singleton
+    f(<G as Default>::default());
+}
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
index 6d4e1bdc2cc..97fad792e4f 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
@@ -1,41 +1,65 @@
 error: use of `default` to create a unit struct
-  --> tests/ui/default_constructed_unit_structs.rs:11:13
+  --> tests/ui/default_constructed_unit_structs.rs:11:9
    |
 LL |         Self::default()
-   |             ^^^^^^^^^^^ help: remove this call to `default`
+   |         ^^^^-----------
+   |             |
+   |             help: remove this call to `default`
    |
    = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::default_constructed_unit_structs)]`
 
 error: use of `default` to create a unit struct
-  --> tests/ui/default_constructed_unit_structs.rs:54:31
+  --> tests/ui/default_constructed_unit_structs.rs:54:20
    |
 LL |             inner: PhantomData::default(),
-   |                               ^^^^^^^^^^^ help: remove this call to `default`
+   |                    ^^^^^^^^^^^-----------
+   |                               |
+   |                               help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> tests/ui/default_constructed_unit_structs.rs:128:33
+  --> tests/ui/default_constructed_unit_structs.rs:128:13
    |
 LL |     let _ = PhantomData::<usize>::default();
-   |                                 ^^^^^^^^^^^ help: remove this call to `default`
+   |             ^^^^^^^^^^^^^^^^^^^^-----------
+   |                                 |
+   |                                 help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> tests/ui/default_constructed_unit_structs.rs:130:42
+  --> tests/ui/default_constructed_unit_structs.rs:130:31
    |
 LL |     let _: PhantomData<i32> = PhantomData::default();
-   |                                          ^^^^^^^^^^^ help: remove this call to `default`
+   |                               ^^^^^^^^^^^-----------
+   |                                          |
+   |                                          help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> tests/ui/default_constructed_unit_structs.rs:132:55
+  --> tests/ui/default_constructed_unit_structs.rs:132:31
    |
 LL |     let _: PhantomData<i32> = std::marker::PhantomData::default();
-   |                                                       ^^^^^^^^^^^ help: remove this call to `default`
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^-----------
+   |                                                       |
+   |                                                       help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> tests/ui/default_constructed_unit_structs.rs:134:23
+  --> tests/ui/default_constructed_unit_structs.rs:134:13
    |
 LL |     let _ = UnitStruct::default();
-   |                       ^^^^^^^^^^^ help: remove this call to `default`
+   |             ^^^^^^^^^^-----------
+   |                       |
+   |                       help: remove this call to `default`
 
-error: aborting due to 6 previous errors
+error: use of `default` to create a unit struct
+  --> tests/ui/default_constructed_unit_structs.rs:172:7
+   |
+LL |     f(<G>::default());
+   |       ^^^^^^^^^^^^^^
+   |
+help: remove this call to `default`
+   |
+LL -     f(<G>::default());
+LL +     f(G);
+   |
+
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index 35646e1c239..2787f6406fe 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -16,5 +16,6 @@
 #![warn(clippy::pub_enum_variant_names)] //~ ERROR: lint `clippy::pub_enum_variant_names`
 #![warn(clippy::wrong_pub_self_convention)] //~ ERROR: lint `clippy::wrong_pub_self_convention`
 #![warn(clippy::option_map_or_err_ok)] //~ ERROR: lint `clippy::option_map_or_err_ok`
+#![warn(clippy::match_on_vec_items)] //~ ERROR: lint `clippy::match_on_vec_items`
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index d7be1e583b0..604732405c3 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -85,5 +85,11 @@ error: lint `clippy::option_map_or_err_ok` has been removed: `clippy::manual_ok_
 LL | #![warn(clippy::option_map_or_err_ok)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: lint `clippy::match_on_vec_items` has been removed: `clippy::indexing_slicing` covers indexing and slicing on `Vec<_>`
+  --> tests/ui/deprecated.rs:19:9
+   |
+LL | #![warn(clippy::match_on_vec_items)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/derive.rs b/src/tools/clippy/tests/ui/derive.rs
index 707a9ff0585..e334203c7b2 100644
--- a/src/tools/clippy/tests/ui/derive.rs
+++ b/src/tools/clippy/tests/ui/derive.rs
@@ -6,6 +6,8 @@
     dead_code
 )]
 #![warn(clippy::expl_impl_clone_on_copy)]
+#![expect(incomplete_features)] // `unsafe_fields` is incomplete for the time being
+#![feature(unsafe_fields)] // `clone()` cannot be derived automatically on unsafe fields
 
 
 #[derive(Copy)]
@@ -113,4 +115,19 @@ impl<T: Copy> Clone for Packed<T> {
     }
 }
 
+fn issue14558() {
+    pub struct Valid {
+        pub unsafe actual: (),
+    }
+
+    unsafe impl Copy for Valid {}
+
+    impl Clone for Valid {
+        #[inline]
+        fn clone(&self) -> Self {
+            *self
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive.stderr b/src/tools/clippy/tests/ui/derive.stderr
index 20278d4f4e4..9004ced6849 100644
--- a/src/tools/clippy/tests/ui/derive.stderr
+++ b/src/tools/clippy/tests/ui/derive.stderr
@@ -1,5 +1,5 @@
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> tests/ui/derive.rs:14:1
+  --> tests/ui/derive.rs:16:1
    |
 LL | / impl Clone for Qux {
 LL | |
@@ -10,7 +10,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> tests/ui/derive.rs:14:1
+  --> tests/ui/derive.rs:16:1
    |
 LL | / impl Clone for Qux {
 LL | |
@@ -23,7 +23,7 @@ LL | | }
    = help: to override `-D warnings` add `#[allow(clippy::expl_impl_clone_on_copy)]`
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> tests/ui/derive.rs:40:1
+  --> tests/ui/derive.rs:42:1
    |
 LL | / impl<'a> Clone for Lt<'a> {
 LL | |
@@ -34,7 +34,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> tests/ui/derive.rs:40:1
+  --> tests/ui/derive.rs:42:1
    |
 LL | / impl<'a> Clone for Lt<'a> {
 LL | |
@@ -45,7 +45,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> tests/ui/derive.rs:53:1
+  --> tests/ui/derive.rs:55:1
    |
 LL | / impl Clone for BigArray {
 LL | |
@@ -56,7 +56,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> tests/ui/derive.rs:53:1
+  --> tests/ui/derive.rs:55:1
    |
 LL | / impl Clone for BigArray {
 LL | |
@@ -67,7 +67,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> tests/ui/derive.rs:66:1
+  --> tests/ui/derive.rs:68:1
    |
 LL | / impl Clone for FnPtr {
 LL | |
@@ -78,7 +78,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> tests/ui/derive.rs:66:1
+  --> tests/ui/derive.rs:68:1
    |
 LL | / impl Clone for FnPtr {
 LL | |
@@ -89,7 +89,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> tests/ui/derive.rs:88:1
+  --> tests/ui/derive.rs:90:1
    |
 LL | / impl<T: Clone> Clone for Generic2<T> {
 LL | |
@@ -100,7 +100,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> tests/ui/derive.rs:88:1
+  --> tests/ui/derive.rs:90:1
    |
 LL | / impl<T: Clone> Clone for Generic2<T> {
 LL | |
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index 5f2b697f88b..8cf20d8b1a1 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -1,4 +1,3 @@
-
 //! This file tests for the `DOC_MARKDOWN` lint.
 
 #![allow(dead_code, incomplete_features)]
@@ -272,7 +271,7 @@ fn parenthesized_word() {}
 /// UXes
 fn plural_acronym_test() {}
 
-extern "C" {
+unsafe extern "C" {
     /// `foo()`
     //~^ doc_markdown
     fn in_extern();
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index ed3925694c6..5b6f2bd8330 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -1,4 +1,3 @@
-
 //! This file tests for the `DOC_MARKDOWN` lint.
 
 #![allow(dead_code, incomplete_features)]
@@ -272,7 +271,7 @@ fn parenthesized_word() {}
 /// UXes
 fn plural_acronym_test() {}
 
-extern "C" {
+unsafe extern "C" {
     /// foo()
     //~^ doc_markdown
     fn in_extern();
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
index d67da75a230..98c26e6bec2 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -1,5 +1,5 @@
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:9:9
+  --> tests/ui/doc/doc-fixable.rs:8:9
    |
 LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
    |         ^^^^^^^
@@ -13,7 +13,7 @@ LL + /// The `foo_bar` function does _nothing_. See also foo::bar. (note the dot
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:9:51
+  --> tests/ui/doc/doc-fixable.rs:8:51
    |
 LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
    |                                                   ^^^^^^^^
@@ -25,7 +25,7 @@ LL + /// The foo_bar function does _nothing_. See also `foo::bar`. (note the dot
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:12:83
+  --> tests/ui/doc/doc-fixable.rs:11:83
    |
 LL | /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
    |                                                                                   ^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL + /// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. B
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:15:13
+  --> tests/ui/doc/doc-fixable.rs:14:13
    |
 LL | /// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
    |             ^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL + /// Here be `::a::global:path`, and _::another::global::path_.  :: is not a
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:15:36
+  --> tests/ui/doc/doc-fixable.rs:14:36
    |
 LL | /// Here be ::a::global:path, and _::another::global::path_.  :: is not a path though.
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL + /// Here be ::a::global:path, and _`::another::global::path`_.  :: is not a
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:18:25
+  --> tests/ui/doc/doc-fixable.rs:17:25
    |
 LL | /// Import an item from ::awesome::global::blob:: (Intended postfix)
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL + /// Import an item from `::awesome::global::blob::` (Intended postfix)
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:20:31
+  --> tests/ui/doc/doc-fixable.rs:19:31
    |
 LL | /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
    |                               ^^^^^
@@ -85,7 +85,7 @@ LL + /// These are the options for `::Cat`: (Intended trailing single colon, sho
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:22:22
+  --> tests/ui/doc/doc-fixable.rs:21:22
    |
 LL | /// That's not code ~NotInCodeBlock~.
    |                      ^^^^^^^^^^^^^^
@@ -97,7 +97,7 @@ LL + /// That's not code ~`NotInCodeBlock`~.
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:24:5
+  --> tests/ui/doc/doc-fixable.rs:23:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -109,7 +109,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:39:5
+  --> tests/ui/doc/doc-fixable.rs:38:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -121,7 +121,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:47:5
+  --> tests/ui/doc/doc-fixable.rs:46:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -133,7 +133,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:62:5
+  --> tests/ui/doc/doc-fixable.rs:61:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:91:5
+  --> tests/ui/doc/doc-fixable.rs:90:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:109:5
+  --> tests/ui/doc/doc-fixable.rs:108:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -169,7 +169,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:118:8
+  --> tests/ui/doc/doc-fixable.rs:117:8
    |
 LL | /// ## CamelCaseThing
    |        ^^^^^^^^^^^^^^
@@ -181,7 +181,7 @@ LL + /// ## `CamelCaseThing`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:122:7
+  --> tests/ui/doc/doc-fixable.rs:121:7
    |
 LL | /// # CamelCaseThing
    |       ^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@ LL + /// # `CamelCaseThing`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:125:22
+  --> tests/ui/doc/doc-fixable.rs:124:22
    |
 LL | /// Not a title #897 CamelCaseThing
    |                      ^^^^^^^^^^^^^^
@@ -205,7 +205,7 @@ LL + /// Not a title #897 `CamelCaseThing`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:127:5
+  --> tests/ui/doc/doc-fixable.rs:126:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -217,7 +217,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:135:5
+  --> tests/ui/doc/doc-fixable.rs:134:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +229,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:149:5
+  --> tests/ui/doc/doc-fixable.rs:148:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -241,7 +241,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:161:43
+  --> tests/ui/doc/doc-fixable.rs:160:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -253,7 +253,7 @@ LL + /** E.g., serialization of an empty list: `FooBar`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:166:5
+  --> tests/ui/doc/doc-fixable.rs:165:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -265,7 +265,7 @@ LL + And `BarQuz` too.
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:167:1
+  --> tests/ui/doc/doc-fixable.rs:166:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -277,7 +277,7 @@ LL + `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:175:43
+  --> tests/ui/doc/doc-fixable.rs:174:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -289,7 +289,7 @@ LL + /** E.g., serialization of an empty list: `FooBar`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:180:5
+  --> tests/ui/doc/doc-fixable.rs:179:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -301,7 +301,7 @@ LL + And `BarQuz` too.
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:181:1
+  --> tests/ui/doc/doc-fixable.rs:180:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -313,7 +313,7 @@ LL + `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:195:5
+  --> tests/ui/doc/doc-fixable.rs:194:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -325,7 +325,7 @@ LL + /// `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:215:22
+  --> tests/ui/doc/doc-fixable.rs:214:22
    |
 LL | /// An iterator over mycrate::Collection's values.
    |                      ^^^^^^^^^^^^^^^^^^^
@@ -337,7 +337,7 @@ LL + /// An iterator over `mycrate::Collection`'s values.
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:240:34
+  --> tests/ui/doc/doc-fixable.rs:239:34
    |
 LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint
    |                                  ^^^^^^^^^^^^^^^
@@ -349,7 +349,7 @@ LL + /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:264:22
+  --> tests/ui/doc/doc-fixable.rs:263:22
    |
 LL | /// There is no try (do() or do_not()).
    |                      ^^^^
@@ -361,7 +361,7 @@ LL + /// There is no try (`do()` or do_not()).
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:264:30
+  --> tests/ui/doc/doc-fixable.rs:263:30
    |
 LL | /// There is no try (do() or do_not()).
    |                              ^^^^^^^^
@@ -373,7 +373,7 @@ LL + /// There is no try (do() or `do_not()`).
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:269:5
+  --> tests/ui/doc/doc-fixable.rs:268:5
    |
 LL | /// ABes
    |     ^^^^
@@ -385,7 +385,7 @@ LL + /// `ABes`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:276:9
+  --> tests/ui/doc/doc-fixable.rs:275:9
    |
 LL |     /// foo()
    |         ^^^^^
@@ -397,7 +397,7 @@ LL +     /// `foo()`
    |
 
 error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> tests/ui/doc/doc-fixable.rs:281:5
+  --> tests/ui/doc/doc-fixable.rs:280:5
    |
 LL | /// https://github.com/rust-lang/rust-clippy/pull/12836
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<https://github.com/rust-lang/rust-clippy/pull/12836>`
diff --git a/src/tools/clippy/tests/ui/doc_unsafe.rs b/src/tools/clippy/tests/ui/doc_unsafe.rs
index 1bdf01e4e22..7146fd7941a 100644
--- a/src/tools/clippy/tests/ui/doc_unsafe.rs
+++ b/src/tools/clippy/tests/ui/doc_unsafe.rs
@@ -103,7 +103,7 @@ macro_rules! very_unsafe {
         ///
         /// Please keep the seat belt fastened
         pub unsafe fn drive() {
-            whee()
+            unsafe { whee() }
         }
     };
 }
diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed b/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed
index 17d0d71a885..2ce0c04c301 100644
--- a/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed
+++ b/src/tools/clippy/tests/ui/double_ended_iterator_last.fixed
@@ -52,28 +52,35 @@ fn main() {
     let _ = CustomLast.last();
 }
 
+// Should not be linted because applying the lint would move the original iterator. This can only be
+// linted if the iterator is used thereafter.
 fn issue_14139() {
     let mut index = [true, true, false, false, false, true].iter();
-    let mut subindex = index.by_ref().take(3);
-    let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let subindex = index.by_ref().take(3);
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let mut subindex = index.by_ref().take(3);
-    let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let mut subindex = index.by_ref().take(3);
     let subindex = &mut subindex;
-    let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let mut subindex = index.by_ref().take(3);
     let subindex = &mut subindex;
-    let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
-    let (mut subindex, _) = (index.by_ref().take(3), 42);
-    let _ = subindex.next_back(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let (subindex, _) = (index.by_ref().take(3), 42);
+    let _ = subindex.last();
+    let _ = index.next();
 }
 
 fn drop_order() {
@@ -90,3 +97,14 @@ fn drop_order() {
     //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
     println!("Done");
 }
+
+fn issue_14444() {
+    let mut squares = vec![];
+    let last_square = [1, 2, 3]
+        .into_iter()
+        .map(|x| {
+            squares.push(x * x);
+            Some(x * x)
+        })
+        .last();
+}
diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last.rs b/src/tools/clippy/tests/ui/double_ended_iterator_last.rs
index 41bc669b171..a4eb9b3337b 100644
--- a/src/tools/clippy/tests/ui/double_ended_iterator_last.rs
+++ b/src/tools/clippy/tests/ui/double_ended_iterator_last.rs
@@ -52,28 +52,35 @@ fn main() {
     let _ = CustomLast.last();
 }
 
+// Should not be linted because applying the lint would move the original iterator. This can only be
+// linted if the iterator is used thereafter.
 fn issue_14139() {
     let mut index = [true, true, false, false, false, true].iter();
     let subindex = index.by_ref().take(3);
-    let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let mut subindex = index.by_ref().take(3);
-    let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let mut subindex = index.by_ref().take(3);
     let subindex = &mut subindex;
-    let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let mut subindex = index.by_ref().take(3);
     let subindex = &mut subindex;
-    let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 
     let mut index = [true, true, false, false, false, true].iter();
     let (subindex, _) = (index.by_ref().take(3), 42);
-    let _ = subindex.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.last();
+    let _ = index.next();
 }
 
 fn drop_order() {
@@ -90,3 +97,14 @@ fn drop_order() {
     //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
     println!("Done");
 }
+
+fn issue_14444() {
+    let mut squares = vec![];
+    let last_square = [1, 2, 3]
+        .into_iter()
+        .map(|x| {
+            squares.push(x * x);
+            Some(x * x)
+        })
+        .last();
+}
diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr b/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr
index 1702a24d7a0..fe8cf2dcb25 100644
--- a/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr
+++ b/src/tools/clippy/tests/ui/double_ended_iterator_last.stderr
@@ -18,55 +18,7 @@ LL |     let _ = DeIterator.last();
    |                        help: try: `next_back()`
 
 error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last.rs:58:13
-   |
-LL |     let _ = subindex.last();
-   |             ^^^^^^^^^^^^^^^
-   |
-help: try
-   |
-LL ~     let mut subindex = index.by_ref().take(3);
-LL ~     let _ = subindex.next_back();
-   |
-
-error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last.rs:62:13
-   |
-LL |     let _ = subindex.last();
-   |             ^^^^^^^^^------
-   |                      |
-   |                      help: try: `next_back()`
-
-error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last.rs:67:13
-   |
-LL |     let _ = subindex.last();
-   |             ^^^^^^^^^------
-   |                      |
-   |                      help: try: `next_back()`
-
-error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last.rs:72:13
-   |
-LL |     let _ = subindex.last();
-   |             ^^^^^^^^^------
-   |                      |
-   |                      help: try: `next_back()`
-
-error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last.rs:76:13
-   |
-LL |     let _ = subindex.last();
-   |             ^^^^^^^^^^^^^^^
-   |
-help: try
-   |
-LL ~     let (mut subindex, _) = (index.by_ref().take(3), 42);
-LL ~     let _ = subindex.next_back();
-   |
-
-error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last.rs:89:36
+  --> tests/ui/double_ended_iterator_last.rs:96:36
    |
 LL |     println!("Last element is {}", v.last().unwrap().0);
    |                                    ^^^^^^^^
@@ -78,5 +30,5 @@ LL ~     let mut v = v.into_iter();
 LL ~     println!("Last element is {}", v.next_back().unwrap().0);
    |
 
-error: aborting due to 8 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs
index 3f125c7f20c..7c5de8832d6 100644
--- a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs
+++ b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.rs
@@ -1,10 +1,13 @@
 //@no-rustfix
 #![warn(clippy::double_ended_iterator_last)]
 
+// Should not be linted because applying the lint would move the original iterator. This can only be
+// linted if the iterator is used thereafter.
 fn main() {
     let mut index = [true, true, false, false, false, true].iter();
     let subindex = (index.by_ref().take(3), 42);
-    let _ = subindex.0.last(); //~ ERROR: called `Iterator::last` on a `DoubleEndedIterator`
+    let _ = subindex.0.last();
+    let _ = index.next();
 }
 
 fn drop_order() {
diff --git a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr
index f4be757d00d..845afc11f04 100644
--- a/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/double_ended_iterator_last_unfixable.stderr
@@ -1,21 +1,5 @@
 error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last_unfixable.rs:7:13
-   |
-LL |     let _ = subindex.0.last();
-   |             ^^^^^^^^^^^------
-   |                        |
-   |                        help: try: `next_back()`
-   |
-note: this must be made mutable to use `.next_back()`
-  --> tests/ui/double_ended_iterator_last_unfixable.rs:7:13
-   |
-LL |     let _ = subindex.0.last();
-   |             ^^^^^^^^^^
-   = note: `-D clippy::double-ended-iterator-last` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::double_ended_iterator_last)]`
-
-error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator
-  --> tests/ui/double_ended_iterator_last_unfixable.rs:20:36
+  --> tests/ui/double_ended_iterator_last_unfixable.rs:23:36
    |
 LL |     println!("Last element is {}", v.0.last().unwrap().0);
    |                                    ^^^^------
@@ -24,10 +8,12 @@ LL |     println!("Last element is {}", v.0.last().unwrap().0);
    |
    = note: this change will alter drop order which may be undesirable
 note: this must be made mutable to use `.next_back()`
-  --> tests/ui/double_ended_iterator_last_unfixable.rs:20:36
+  --> tests/ui/double_ended_iterator_last_unfixable.rs:23:36
    |
 LL |     println!("Last element is {}", v.0.last().unwrap().0);
    |                                    ^^^
+   = note: `-D clippy::double-ended-iterator-last` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::double_ended_iterator_last)]`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/src/tools/clippy/tests/ui/eager_transmute.fixed b/src/tools/clippy/tests/ui/eager_transmute.fixed
index 14cbb6113e6..47a32ec836c 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.fixed
+++ b/src/tools/clippy/tests/ui/eager_transmute.fixed
@@ -71,8 +71,10 @@ fn f(op: u8, op2: Data, unrelated: u8) {
 }
 
 unsafe fn f2(op: u8) {
-    (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
-    //~^ eager_transmute
+    unsafe {
+        (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
+        //~^ eager_transmute
+    }
 }
 
 #[rustc_layout_scalar_valid_range_end(254)]
diff --git a/src/tools/clippy/tests/ui/eager_transmute.rs b/src/tools/clippy/tests/ui/eager_transmute.rs
index 48d7d50cdae..906cd7bccc8 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.rs
+++ b/src/tools/clippy/tests/ui/eager_transmute.rs
@@ -71,8 +71,10 @@ fn f(op: u8, op2: Data, unrelated: u8) {
 }
 
 unsafe fn f2(op: u8) {
-    (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
-    //~^ eager_transmute
+    unsafe {
+        (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
+        //~^ eager_transmute
+    }
 }
 
 #[rustc_layout_scalar_valid_range_end(254)]
diff --git a/src/tools/clippy/tests/ui/eager_transmute.stderr b/src/tools/clippy/tests/ui/eager_transmute.stderr
index 54850d110eb..c719ca8adc1 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.stderr
+++ b/src/tools/clippy/tests/ui/eager_transmute.stderr
@@ -157,19 +157,19 @@ LL +     let _: Option<Opcode> = (..=3).contains(&op).then(|| unsafe { std::mem:
    |
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> tests/ui/eager_transmute.rs:74:24
+  --> tests/ui/eager_transmute.rs:75:28
    |
-LL |     (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider using `bool::then` to only transmute if the condition holds
    |
-LL -     (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
-LL +     (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
+LL -         (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
+LL +         (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
    |
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> tests/ui/eager_transmute.rs:104:62
+  --> tests/ui/eager_transmute.rs:106:62
    |
 LL |     let _: Option<NonZero<u8>> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
    |                                                              ^^^^^^^^^^^^^^^^^^^^^^^
@@ -181,7 +181,7 @@ LL +     let _: Option<NonZero<u8>> = (v1 > 0).then(|| unsafe { std::mem::transm
    |
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> tests/ui/eager_transmute.rs:111:86
+  --> tests/ui/eager_transmute.rs:113:86
    |
 LL |     let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@ LL +     let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| u
    |
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> tests/ui/eager_transmute.rs:118:93
+  --> tests/ui/eager_transmute.rs:120:93
    |
 LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
    |                                                                                             ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/empty_docs.rs b/src/tools/clippy/tests/ui/empty_docs.rs
index d7768e07901..57f8976cd6a 100644
--- a/src/tools/clippy/tests/ui/empty_docs.rs
+++ b/src/tools/clippy/tests/ui/empty_docs.rs
@@ -84,7 +84,7 @@ mod issue_12377 {
     use proc_macro_attr::with_empty_docs;
 
     #[with_empty_docs]
-    extern "C" {
+    unsafe extern "C" {
         type Test;
     }
 
diff --git a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed
index 885f6a50025..abdf6ca5cb6 100644
--- a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed
+++ b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed
@@ -6,8 +6,7 @@ pub enum PublicTestEnum {
     NonEmptyParentheses(i32, i32),     // No error
     EmptyBraces,
     //~^ empty_enum_variants_with_brackets
-    EmptyParentheses,
-    //~^ empty_enum_variants_with_brackets
+    EmptyParentheses(), // No error as enum is pub
 }
 
 enum TestEnum {
@@ -20,6 +19,67 @@ enum TestEnum {
     AnotherEnum, // No error
 }
 
+mod issue12551 {
+    enum EvenOdd {
+        // Used as functions -> no error
+        Even(),
+        Odd(),
+        // Not used as a function
+        Unknown,
+        //~^ empty_enum_variants_with_brackets
+    }
+
+    fn even_odd(x: i32) -> EvenOdd {
+        (x % 2 == 0).then(EvenOdd::Even).unwrap_or_else(EvenOdd::Odd)
+    }
+
+    fn natural_number(x: i32) -> NaturalOrNot {
+        (x > 0)
+            .then(NaturalOrNot::Natural)
+            .unwrap_or_else(NaturalOrNot::NotNatural)
+    }
+
+    enum NaturalOrNot {
+        // Used as functions -> no error
+        Natural(),
+        NotNatural(),
+        // Not used as a function
+        Unknown,
+        //~^ empty_enum_variants_with_brackets
+    }
+
+    enum RedundantParenthesesFunctionCall {
+        // Used as a function call but with redundant parentheses
+        Parentheses,
+        //~^ empty_enum_variants_with_brackets
+        // Not used as a function
+        NoParentheses,
+    }
+
+    #[allow(clippy::no_effect)]
+    fn redundant_parentheses_function_call() {
+        // The parentheses in the below line are redundant.
+        RedundantParenthesesFunctionCall::Parentheses;
+        RedundantParenthesesFunctionCall::NoParentheses;
+    }
+
+    // Same test as above but with usage of the enum occurring before the definition.
+    #[allow(clippy::no_effect)]
+    fn redundant_parentheses_function_call_2() {
+        // The parentheses in the below line are redundant.
+        RedundantParenthesesFunctionCall2::Parentheses;
+        RedundantParenthesesFunctionCall2::NoParentheses;
+    }
+
+    enum RedundantParenthesesFunctionCall2 {
+        // Used as a function call but with redundant parentheses
+        Parentheses,
+        //~^ empty_enum_variants_with_brackets
+        // Not used as a function
+        NoParentheses,
+    }
+}
+
 enum TestEnumWithFeatures {
     NonEmptyBraces {
         #[cfg(feature = "thisisneverenabled")]
@@ -28,4 +88,18 @@ enum TestEnumWithFeatures {
     NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32), // No error
 }
 
+#[derive(Clone)]
+enum Foo {
+    Variant1(i32),
+    Variant2,
+    Variant3, //~ ERROR: enum variant has empty brackets
+}
+
+#[derive(Clone)]
+pub enum PubFoo {
+    Variant1(i32),
+    Variant2,
+    Variant3(),
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs
index 092712ee2ea..63a5a8e9143 100644
--- a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs
+++ b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs
@@ -6,8 +6,7 @@ pub enum PublicTestEnum {
     NonEmptyParentheses(i32, i32),     // No error
     EmptyBraces {},
     //~^ empty_enum_variants_with_brackets
-    EmptyParentheses(),
-    //~^ empty_enum_variants_with_brackets
+    EmptyParentheses(), // No error as enum is pub
 }
 
 enum TestEnum {
@@ -20,6 +19,67 @@ enum TestEnum {
     AnotherEnum, // No error
 }
 
+mod issue12551 {
+    enum EvenOdd {
+        // Used as functions -> no error
+        Even(),
+        Odd(),
+        // Not used as a function
+        Unknown(),
+        //~^ empty_enum_variants_with_brackets
+    }
+
+    fn even_odd(x: i32) -> EvenOdd {
+        (x % 2 == 0).then(EvenOdd::Even).unwrap_or_else(EvenOdd::Odd)
+    }
+
+    fn natural_number(x: i32) -> NaturalOrNot {
+        (x > 0)
+            .then(NaturalOrNot::Natural)
+            .unwrap_or_else(NaturalOrNot::NotNatural)
+    }
+
+    enum NaturalOrNot {
+        // Used as functions -> no error
+        Natural(),
+        NotNatural(),
+        // Not used as a function
+        Unknown(),
+        //~^ empty_enum_variants_with_brackets
+    }
+
+    enum RedundantParenthesesFunctionCall {
+        // Used as a function call but with redundant parentheses
+        Parentheses(),
+        //~^ empty_enum_variants_with_brackets
+        // Not used as a function
+        NoParentheses,
+    }
+
+    #[allow(clippy::no_effect)]
+    fn redundant_parentheses_function_call() {
+        // The parentheses in the below line are redundant.
+        RedundantParenthesesFunctionCall::Parentheses();
+        RedundantParenthesesFunctionCall::NoParentheses;
+    }
+
+    // Same test as above but with usage of the enum occurring before the definition.
+    #[allow(clippy::no_effect)]
+    fn redundant_parentheses_function_call_2() {
+        // The parentheses in the below line are redundant.
+        RedundantParenthesesFunctionCall2::Parentheses();
+        RedundantParenthesesFunctionCall2::NoParentheses;
+    }
+
+    enum RedundantParenthesesFunctionCall2 {
+        // Used as a function call but with redundant parentheses
+        Parentheses(),
+        //~^ empty_enum_variants_with_brackets
+        // Not used as a function
+        NoParentheses,
+    }
+}
+
 enum TestEnumWithFeatures {
     NonEmptyBraces {
         #[cfg(feature = "thisisneverenabled")]
@@ -28,4 +88,18 @@ enum TestEnumWithFeatures {
     NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32), // No error
 }
 
+#[derive(Clone)]
+enum Foo {
+    Variant1(i32),
+    Variant2,
+    Variant3(), //~ ERROR: enum variant has empty brackets
+}
+
+#[derive(Clone)]
+pub enum PubFoo {
+    Variant1(i32),
+    Variant2,
+    Variant3(),
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr
index a9ae3b476dd..7fe85e829a3 100644
--- a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr
+++ b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr
@@ -9,7 +9,15 @@ LL |     EmptyBraces {},
    = help: remove the brackets
 
 error: enum variant has empty brackets
-  --> tests/ui/empty_enum_variants_with_brackets.rs:9:21
+  --> tests/ui/empty_enum_variants_with_brackets.rs:15:16
+   |
+LL |     EmptyBraces {},
+   |                ^^^
+   |
+   = help: remove the brackets
+
+error: enum variant has empty brackets
+  --> tests/ui/empty_enum_variants_with_brackets.rs:17:21
    |
 LL |     EmptyParentheses(),
    |                     ^^
@@ -17,20 +25,58 @@ LL |     EmptyParentheses(),
    = help: remove the brackets
 
 error: enum variant has empty brackets
-  --> tests/ui/empty_enum_variants_with_brackets.rs:16:16
+  --> tests/ui/empty_enum_variants_with_brackets.rs:28:16
    |
-LL |     EmptyBraces {},
-   |                ^^^
+LL |         Unknown(),
+   |                ^^
    |
    = help: remove the brackets
 
 error: enum variant has empty brackets
-  --> tests/ui/empty_enum_variants_with_brackets.rs:18:21
+  --> tests/ui/empty_enum_variants_with_brackets.rs:47:16
    |
-LL |     EmptyParentheses(),
-   |                     ^^
+LL |         Unknown(),
+   |                ^^
+   |
+   = help: remove the brackets
+
+error: enum variant has empty brackets
+  --> tests/ui/empty_enum_variants_with_brackets.rs:53:20
+   |
+LL |         Parentheses(),
+   |                    ^^
+   |
+help: remove the brackets
+   |
+LL ~         Parentheses,
+LL |
+...
+LL |         // The parentheses in the below line are redundant.
+LL ~         RedundantParenthesesFunctionCall::Parentheses;
+   |
+
+error: enum variant has empty brackets
+  --> tests/ui/empty_enum_variants_with_brackets.rs:76:20
+   |
+LL |         Parentheses(),
+   |                    ^^
+   |
+help: remove the brackets
+   |
+LL ~         RedundantParenthesesFunctionCall2::Parentheses;
+LL |         RedundantParenthesesFunctionCall2::NoParentheses;
+...
+LL |         // Used as a function call but with redundant parentheses
+LL ~         Parentheses,
+   |
+
+error: enum variant has empty brackets
+  --> tests/ui/empty_enum_variants_with_brackets.rs:95:13
+   |
+LL |     Variant3(),
+   |             ^^
    |
    = help: remove the brackets
 
-error: aborting due to 4 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed
index e4ba09ea1d4..70ab235b694 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed
@@ -142,4 +142,9 @@ impl Foo for LineComment {
     fn bar() {}
 }
 
+//~v empty_line_after_doc_comments
+/// Docs for this item.
+// fn some_item() {}
+impl LineComment {} // or any other nameless item kind
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed
index a20f9bc20eb..87c636c6ad2 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed
@@ -152,4 +152,10 @@ impl Foo for LineComment {
     fn bar() {}
 }
 
+//~v empty_line_after_doc_comments
+// /// Docs for this item.
+// fn some_item() {}
+
+impl LineComment {} // or any other nameless item kind
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs
index 9e3ddfd5abe..91e9c1ac0b6 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs
@@ -155,4 +155,10 @@ impl Foo for LineComment {
     fn bar() {}
 }
 
+//~v empty_line_after_doc_comments
+/// Docs for this item.
+// fn some_item() {}
+
+impl LineComment {} // or any other nameless item kind
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
index fe25ba9afcb..ae8cb91ba12 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
@@ -87,7 +87,7 @@ LL |       fn new_code() {}
    |       ----------- the comment documents this function
    |
    = help: if the empty line is unintentional, remove it
-help: if the doc comment should not document `new_code` comment it out
+help: if the doc comment should not document function `new_code` then comment it out
    |
 LL |     // /// docs for `old_code`
    |     ++
@@ -107,7 +107,7 @@ LL |       struct Multiple;
    |       --------------- the comment documents this struct
    |
    = help: if the empty lines are unintentional, remove them
-help: if the doc comment should not document `Multiple` comment it out
+help: if the doc comment should not document struct `Multiple` then comment it out
    |
 LL ~     // /// Docs
 LL ~     // /// for OldA
@@ -149,7 +149,7 @@ LL |       fn new_code() {}
    |       ----------- the comment documents this function
    |
    = help: if the empty line is unintentional, remove it
-help: if the doc comment should not document `new_code` comment it out
+help: if the doc comment should not document function `new_code` then comment it out
    |
 LL -     /**
 LL +     /*
@@ -167,7 +167,7 @@ LL |       fn new_code2() {}
    |       ------------ the comment documents this function
    |
    = help: if the empty line is unintentional, remove it
-help: if the doc comment should not document `new_code2` comment it out
+help: if the doc comment should not document function `new_code2` then comment it out
    |
 LL |     // /// Docs for `old_code2`
    |     ++
@@ -183,10 +183,26 @@ LL |       fn bar() {}
    |       ------ the comment documents this function
    |
    = help: if the empty line is unintentional, remove it
-help: if the doc comment should not document `bar` comment it out
+help: if the doc comment should not document function `bar` then comment it out
    |
 LL |     // /// comment on assoc item
    |     ++
 
-error: aborting due to 11 previous errors
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:159:1
+   |
+LL | / /// Docs for this item.
+LL | | // fn some_item() {}
+LL | |
+   | |_^
+LL |   impl LineComment {} // or any other nameless item kind
+   |   - the comment documents this implementation
+   |
+   = help: if the empty line is unintentional, remove it
+help: if the doc comment should not document the following item then comment it out
+   |
+LL | // /// Docs for this item.
+   | ++
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index 69452a8d9a6..f2df9f0204e 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -226,4 +226,26 @@ fn issue11976() {
     }
 }
 
+mod issue14449 {
+    use std::collections::BTreeMap;
+
+    pub struct Meow {
+        map: BTreeMap<String, String>,
+    }
+
+    impl Meow {
+        fn pet(&self, _key: &str, _v: u32) -> u32 {
+            42
+        }
+    }
+
+    pub fn f(meow: &Meow, x: String) {
+        if meow.map.contains_key(&x) {
+            let _ = meow.pet(&x, 1);
+        } else {
+            let _ = meow.pet(&x, 0);
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index 3578324f01c..166eea417ac 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -232,4 +232,26 @@ fn issue11976() {
     }
 }
 
+mod issue14449 {
+    use std::collections::BTreeMap;
+
+    pub struct Meow {
+        map: BTreeMap<String, String>,
+    }
+
+    impl Meow {
+        fn pet(&self, _key: &str, _v: u32) -> u32 {
+            42
+        }
+    }
+
+    pub fn f(meow: &Meow, x: String) {
+        if meow.map.contains_key(&x) {
+            let _ = meow.pet(&x, 1);
+        } else {
+            let _ = meow.pet(&x, 0);
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
index 7235f7d5b82..ec6bed152e7 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
@@ -59,7 +59,7 @@ fn f_str_t<T>(_: &str, _: T) {}
 
 fn f_box_t<T>(_: &Box<T>) {}
 
-extern "C" {
+unsafe extern "C" {
     fn var(_: u32, ...);
 }
 
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
index c4d2b28ff4b..ca58c650d9c 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.rs
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
@@ -59,7 +59,7 @@ fn f_str_t<T>(_: &str, _: T) {}
 
 fn f_box_t<T>(_: &Box<T>) {}
 
-extern "C" {
+unsafe extern "C" {
     fn var(_: u32, ...);
 }
 
diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.rs b/src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.rs
new file mode 100644
index 00000000000..68294292502
--- /dev/null
+++ b/src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.rs
@@ -0,0 +1,63 @@
+#![allow(clippy::question_mark, unused)]
+#![warn(clippy::filter_map_bool_then)]
+//@no-rustfix
+
+fn issue11617() {
+    let mut x: Vec<usize> = vec![0; 10];
+    let _ = (0..x.len()).zip(x.clone().iter()).filter_map(|(i, v)| {
+        //~^ filter_map_bool_then
+        (x[i] != *v).then(|| {
+            x[i] = i;
+            i
+        })
+    });
+}
+
+mod issue14368 {
+
+    fn do_something(_: ()) -> bool {
+        true
+    }
+
+    fn option_with_early_return(x: &[Option<bool>]) {
+        let _ = x.iter().filter_map(|&x| x?.then(|| do_something(())));
+        //~^ filter_map_bool_then
+        let _ = x
+            .iter()
+            .filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(())));
+        //~^ filter_map_bool_then
+        let _ = x.iter().filter_map(|&x| {
+            //~^ filter_map_bool_then
+            match x {
+                Some(x) => x,
+                None => return None,
+            }
+            .then(|| do_something(()))
+        });
+    }
+
+    #[derive(Copy, Clone)]
+    enum Foo {
+        One(bool),
+        Two,
+        Three(Option<i32>),
+    }
+
+    fn nested_type_with_early_return(x: &[Foo]) {
+        let _ = x.iter().filter_map(|&x| {
+            //~^ filter_map_bool_then
+            match x {
+                Foo::One(x) => x,
+                Foo::Two => return None,
+                Foo::Three(inner) => {
+                    if inner? == 0 {
+                        return Some(false);
+                    } else {
+                        true
+                    }
+                },
+            }
+            .then(|| do_something(()))
+        });
+    }
+}
diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.stderr b/src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.stderr
new file mode 100644
index 00000000000..2025958136b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/filter_map_bool_then_unfixable.stderr
@@ -0,0 +1,65 @@
+error: usage of `bool::then` in `filter_map`
+  --> tests/ui/filter_map_bool_then_unfixable.rs:7:48
+   |
+LL |       let _ = (0..x.len()).zip(x.clone().iter()).filter_map(|(i, v)| {
+   |  ________________________________________________^
+LL | |
+LL | |         (x[i] != *v).then(|| {
+LL | |             x[i] = i;
+LL | |             i
+LL | |         })
+LL | |     });
+   | |______^
+   |
+   = help: consider using `filter` then `map` instead
+   = note: `-D clippy::filter-map-bool-then` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::filter_map_bool_then)]`
+
+error: usage of `bool::then` in `filter_map`
+  --> tests/ui/filter_map_bool_then_unfixable.rs:23:26
+   |
+LL |         let _ = x.iter().filter_map(|&x| x?.then(|| do_something(())));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using `filter` then `map` instead
+
+error: usage of `bool::then` in `filter_map`
+  --> tests/ui/filter_map_bool_then_unfixable.rs:27:14
+   |
+LL |             .filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(())));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using `filter` then `map` instead
+
+error: usage of `bool::then` in `filter_map`
+  --> tests/ui/filter_map_bool_then_unfixable.rs:29:26
+   |
+LL |           let _ = x.iter().filter_map(|&x| {
+   |  __________________________^
+LL | |
+LL | |             match x {
+LL | |                 Some(x) => x,
+...  |
+LL | |             .then(|| do_something(()))
+LL | |         });
+   | |__________^
+   |
+   = help: consider using `filter` then `map` instead
+
+error: usage of `bool::then` in `filter_map`
+  --> tests/ui/filter_map_bool_then_unfixable.rs:47:26
+   |
+LL |           let _ = x.iter().filter_map(|&x| {
+   |  __________________________^
+LL | |
+LL | |             match x {
+LL | |                 Foo::One(x) => x,
+...  |
+LL | |             .then(|| do_something(()))
+LL | |         });
+   | |__________^
+   |
+   = help: consider using `filter` then `map` instead
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/filter_map_next.rs b/src/tools/clippy/tests/ui/filter_map_next.rs
index 2a2237ed16c..5414e01c870 100644
--- a/src/tools/clippy/tests/ui/filter_map_next.rs
+++ b/src/tools/clippy/tests/ui/filter_map_next.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::all, clippy::pedantic)]
+#![warn(clippy::filter_map_next)]
 
 fn main() {
     let a = ["1", "lol", "3", "NaN", "5"];
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed b/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
index 285863ef340..09c416041a4 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
@@ -1,5 +1,4 @@
-#![warn(clippy::all, clippy::pedantic)]
-#![allow(unused)]
+#![warn(clippy::filter_map_next)]
 
 fn main() {
     let a = ["1", "lol", "3", "NaN", "5"];
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.rs b/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
index af911689b7c..3d686ef41d9 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
@@ -1,5 +1,4 @@
-#![warn(clippy::all, clippy::pedantic)]
-#![allow(unused)]
+#![warn(clippy::filter_map_next)]
 
 fn main() {
     let a = ["1", "lol", "3", "NaN", "5"];
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr b/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr
index 707dec8687b..1002837732b 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead
-  --> tests/ui/filter_map_next_fixable.rs:7:32
+  --> tests/ui/filter_map_next_fixable.rs:6:32
    |
 LL |     let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())`
@@ -8,7 +8,7 @@ LL |     let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next
    = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]`
 
 error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead
-  --> tests/ui/filter_map_next_fixable.rs:21:26
+  --> tests/ui/filter_map_next_fixable.rs:20:26
    |
 LL |     let _: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())`
diff --git a/src/tools/clippy/tests/ui/find_map.rs b/src/tools/clippy/tests/ui/find_map.rs
index aba1f2cbe58..a9a8508d5b7 100644
--- a/src/tools/clippy/tests/ui/find_map.rs
+++ b/src/tools/clippy/tests/ui/find_map.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 
-#![warn(clippy::all, clippy::pedantic)]
 #![allow(clippy::useless_vec)]
 
 #[derive(Debug, Copy, Clone)]
diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
index cc18708d25f..25d25663d1e 100644
--- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
+++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
@@ -1,7 +1,7 @@
 #![warn(clippy::fn_params_excessive_bools)]
 #![allow(clippy::too_many_arguments)]
 
-extern "C" {
+unsafe extern "C" {
     // Should not lint, most of the time users have no control over extern function signatures
     fn f(_: bool, _: bool, _: bool, _: bool);
 }
@@ -14,8 +14,8 @@ macro_rules! foo {
 
 foo!();
 
-#[no_mangle]
-extern "C" fn k(_: bool, _: bool, _: bool, _: bool) {}
+#[unsafe(no_mangle)]
+unsafe extern "C" fn k(_: bool, _: bool, _: bool, _: bool) {}
 fn g(_: bool, _: bool, _: bool, _: bool) {}
 //~^ ERROR: more than 3 bools in function parameters
 fn h(_: bool, _: bool, _: bool) {}
@@ -39,8 +39,8 @@ impl S {
     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
     //~^ ERROR: more than 3 bools in function parameters
     fn g(&self, _: bool, _: bool, _: bool) {}
-    #[no_mangle]
-    extern "C" fn h(_: bool, _: bool, _: bool, _: bool) {}
+    #[unsafe(no_mangle)]
+    unsafe extern "C" fn h(_: bool, _: bool, _: bool, _: bool) {}
 }
 
 impl Trait for S {
diff --git a/src/tools/clippy/tests/ui/formatting.rs b/src/tools/clippy/tests/ui/formatting.rs
index 4e84dcf7d5b..009815633d7 100644
--- a/src/tools/clippy/tests/ui/formatting.rs
+++ b/src/tools/clippy/tests/ui/formatting.rs
@@ -1,6 +1,3 @@
-#![warn(clippy::all)]
-#![allow(unused_variables)]
-#![allow(unused_assignments)]
 #![allow(clippy::if_same_then_else)]
 #![allow(clippy::deref_addrof)]
 #![allow(clippy::nonminimal_bool)]
diff --git a/src/tools/clippy/tests/ui/formatting.stderr b/src/tools/clippy/tests/ui/formatting.stderr
index 972bd3a6a2e..d9dc2a55f5b 100644
--- a/src/tools/clippy/tests/ui/formatting.stderr
+++ b/src/tools/clippy/tests/ui/formatting.stderr
@@ -1,5 +1,5 @@
 error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)`
-  --> tests/ui/formatting.rs:16:6
+  --> tests/ui/formatting.rs:13:6
    |
 LL |     a =- 35;
    |      ^^^^
@@ -9,7 +9,7 @@ LL |     a =- 35;
    = help: to override `-D warnings` add `#[allow(clippy::suspicious_assignment_formatting)]`
 
 error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)`
-  --> tests/ui/formatting.rs:20:6
+  --> tests/ui/formatting.rs:17:6
    |
 LL |     a =* &191;
    |      ^^^^
@@ -17,7 +17,7 @@ LL |     a =* &191;
    = note: to remove this lint, use either `*=` or `= *`
 
 error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)`
-  --> tests/ui/formatting.rs:26:6
+  --> tests/ui/formatting.rs:23:6
    |
 LL |     b =! false;
    |      ^^^^
@@ -25,17 +25,16 @@ LL |     b =! false;
    = note: to remove this lint, use either `!=` or `= !`
 
 error: possibly missing a comma here
-  --> tests/ui/formatting.rs:38:19
+  --> tests/ui/formatting.rs:35:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
    |
    = note: to remove this lint, add a comma or write the expr in a single line
-   = note: `-D clippy::possible-missing-comma` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::possible_missing_comma)]`
+   = note: `#[deny(clippy::possible_missing_comma)]` on by default
 
 error: possibly missing a comma here
-  --> tests/ui/formatting.rs:45:19
+  --> tests/ui/formatting.rs:42:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -43,7 +42,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> tests/ui/formatting.rs:85:11
+  --> tests/ui/formatting.rs:82:11
    |
 LL |         -1
    |           ^
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
index 8618004efb8..be98b227795 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
@@ -73,3 +73,46 @@ fn main() {
     for _i in [1, 2, 3].iter().collect::<Vec<&i32>>() {}
     //~^ from_iter_instead_of_collect
 }
+
+fn issue14581() {
+    let nums = [0, 1, 2];
+    let _ = &nums.iter().map(|&num| char::from_u32(num).unwrap()).collect::<String>();
+    //~^ from_iter_instead_of_collect
+}
+
+fn test_implicit_generic_args(iter: impl Iterator<Item = &'static i32> + Copy) {
+    struct S<'l, T = i32, const A: usize = 3, const B: usize = 3> {
+        a: [&'l T; A],
+        b: [&'l T; B],
+    }
+
+    impl<'l, T, const A: usize, const B: usize> FromIterator<&'l T> for S<'l, T, A, B> {
+        fn from_iter<I: IntoIterator<Item = &'l T>>(_: I) -> Self {
+            todo!()
+        }
+    }
+
+    let _ = iter.collect::<S<'static, i32, 7>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S<'static, i32>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S<'static, _, 7>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S<'static, _, 7, 8>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S<_, 7, 8>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S<i32>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S<i32>>();
+    //~^ from_iter_instead_of_collect
+
+    let _ = iter.collect::<S>();
+    //~^ from_iter_instead_of_collect
+}
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
index c46397e8ff5..ce20fef2ac3 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
@@ -73,3 +73,46 @@ fn main() {
     for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {}
     //~^ from_iter_instead_of_collect
 }
+
+fn issue14581() {
+    let nums = [0, 1, 2];
+    let _ = &String::from_iter(nums.iter().map(|&num| char::from_u32(num).unwrap()));
+    //~^ from_iter_instead_of_collect
+}
+
+fn test_implicit_generic_args(iter: impl Iterator<Item = &'static i32> + Copy) {
+    struct S<'l, T = i32, const A: usize = 3, const B: usize = 3> {
+        a: [&'l T; A],
+        b: [&'l T; B],
+    }
+
+    impl<'l, T, const A: usize, const B: usize> FromIterator<&'l T> for S<'l, T, A, B> {
+        fn from_iter<I: IntoIterator<Item = &'l T>>(_: I) -> Self {
+            todo!()
+        }
+    }
+
+    let _ = <S<'static, i32, 7>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S<'static, i32>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S<'static, _, 7>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S<'static, _, 7, 8>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S<'_, _, 7, 8>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S<i32>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S<'_, i32>>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+
+    let _ = <S>::from_iter(iter);
+    //~^ from_iter_instead_of_collect
+}
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
index b46d97af152..ec11a375c0d 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
@@ -91,5 +91,59 @@ error: usage of `FromIterator::from_iter`
 LL |     for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<&i32>>()`
 
-error: aborting due to 15 previous errors
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:79:14
+   |
+LL |     let _ = &String::from_iter(nums.iter().map(|&num| char::from_u32(num).unwrap()));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `nums.iter().map(|&num| char::from_u32(num).unwrap()).collect::<String>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:95:13
+   |
+LL |     let _ = <S<'static, i32, 7>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<'static, i32, 7>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:98:13
+   |
+LL |     let _ = <S<'static, i32>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<'static, i32>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:101:13
+   |
+LL |     let _ = <S<'static, _, 7>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<'static, _, 7>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:104:13
+   |
+LL |     let _ = <S<'static, _, 7, 8>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<'static, _, 7, 8>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:107:13
+   |
+LL |     let _ = <S<'_, _, 7, 8>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<_, 7, 8>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:110:13
+   |
+LL |     let _ = <S<i32>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<i32>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:113:13
+   |
+LL |     let _ = <S<'_, i32>>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S<i32>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> tests/ui/from_iter_instead_of_collect.rs:116:13
+   |
+LL |     let _ = <S>::from_iter(iter);
+   |             ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.collect::<S>()`
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/functions.rs b/src/tools/clippy/tests/ui/functions.rs
index 9c1ca8bf930..ceaba392dc2 100644
--- a/src/tools/clippy/tests/ui/functions.rs
+++ b/src/tools/clippy/tests/ui/functions.rs
@@ -1,5 +1,3 @@
-#![warn(clippy::all)]
-#![allow(dead_code, unused_unsafe)]
 #![allow(clippy::missing_safety_doc, clippy::uninlined_format_args)]
 
 // TOO_MANY_ARGUMENTS
diff --git a/src/tools/clippy/tests/ui/functions.stderr b/src/tools/clippy/tests/ui/functions.stderr
index c8770023f77..65cc627cc44 100644
--- a/src/tools/clippy/tests/ui/functions.stderr
+++ b/src/tools/clippy/tests/ui/functions.stderr
@@ -1,5 +1,5 @@
 error: this function has too many arguments (8/7)
-  --> tests/ui/functions.rs:8:1
+  --> tests/ui/functions.rs:6:1
    |
 LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f
    = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]`
 
 error: this function has too many arguments (8/7)
-  --> tests/ui/functions.rs:12:1
+  --> tests/ui/functions.rs:10:1
    |
 LL | / fn bad_multiline(
 LL | |
@@ -20,88 +20,87 @@ LL | | ) {
    | |_^
 
 error: this function has too many arguments (8/7)
-  --> tests/ui/functions.rs:48:5
+  --> tests/ui/functions.rs:46:5
    |
 LL |     fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this function has too many arguments (8/7)
-  --> tests/ui/functions.rs:58:5
+  --> tests/ui/functions.rs:56:5
    |
 LL |     fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:68:34
+  --> tests/ui/functions.rs:66:34
    |
 LL |         println!("{}", unsafe { *p });
    |                                  ^
    |
-   = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::not_unsafe_ptr_arg_deref)]`
+   = note: `#[deny(clippy::not_unsafe_ptr_arg_deref)]` on by default
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:71:35
+  --> tests/ui/functions.rs:69:35
    |
 LL |         println!("{:?}", unsafe { p.as_ref() });
    |                                   ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:74:33
+  --> tests/ui/functions.rs:72:33
    |
 LL |         unsafe { std::ptr::read(p) };
    |                                 ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:86:30
+  --> tests/ui/functions.rs:84:30
    |
 LL |     println!("{}", unsafe { *p });
    |                              ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:89:31
+  --> tests/ui/functions.rs:87:31
    |
 LL |     println!("{:?}", unsafe { p.as_ref() });
    |                               ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:92:29
+  --> tests/ui/functions.rs:90:29
    |
 LL |     unsafe { std::ptr::read(p) };
    |                             ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:99:30
+  --> tests/ui/functions.rs:97:30
    |
 LL |     println!("{}", unsafe { *p });
    |                              ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:102:31
+  --> tests/ui/functions.rs:100:31
    |
 LL |     println!("{:?}", unsafe { p.as_ref() });
    |                               ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:105:29
+  --> tests/ui/functions.rs:103:29
    |
 LL |     unsafe { std::ptr::read(p) };
    |                             ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:115:34
+  --> tests/ui/functions.rs:113:34
    |
 LL |         println!("{}", unsafe { *p });
    |                                  ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:118:35
+  --> tests/ui/functions.rs:116:35
    |
 LL |         println!("{:?}", unsafe { p.as_ref() });
    |                                   ^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
-  --> tests/ui/functions.rs:121:33
+  --> tests/ui/functions.rs:119:33
    |
 LL |         unsafe { std::ptr::read(p) };
    |                                 ^
diff --git a/src/tools/clippy/tests/ui/if_not_else.fixed b/src/tools/clippy/tests/ui/if_not_else.fixed
index d26a15156cd..4e6f43e5671 100644
--- a/src/tools/clippy/tests/ui/if_not_else.fixed
+++ b/src/tools/clippy/tests/ui/if_not_else.fixed
@@ -1,4 +1,3 @@
-#![warn(clippy::all)]
 #![warn(clippy::if_not_else)]
 
 fn foo() -> bool {
diff --git a/src/tools/clippy/tests/ui/if_not_else.rs b/src/tools/clippy/tests/ui/if_not_else.rs
index 6171cf11649..6cd2e3bd63f 100644
--- a/src/tools/clippy/tests/ui/if_not_else.rs
+++ b/src/tools/clippy/tests/ui/if_not_else.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all)]
 #![warn(clippy::if_not_else)]
 
 fn foo() -> bool {
diff --git a/src/tools/clippy/tests/ui/if_not_else.stderr b/src/tools/clippy/tests/ui/if_not_else.stderr
index f44dd0aabc8..824837bd52b 100644
--- a/src/tools/clippy/tests/ui/if_not_else.stderr
+++ b/src/tools/clippy/tests/ui/if_not_else.stderr
@@ -1,5 +1,5 @@
 error: unnecessary boolean `not` operation
-  --> tests/ui/if_not_else.rs:12:5
+  --> tests/ui/if_not_else.rs:11:5
    |
 LL | /     if !bla() {
 LL | |
@@ -24,7 +24,7 @@ LL +     }
    |
 
 error: unnecessary `!=` operation
-  --> tests/ui/if_not_else.rs:19:5
+  --> tests/ui/if_not_else.rs:18:5
    |
 LL | /     if 4 != 5 {
 LL | |
@@ -47,7 +47,7 @@ LL +     }
    |
 
 error: unnecessary boolean `not` operation
-  --> tests/ui/if_not_else.rs:34:5
+  --> tests/ui/if_not_else.rs:33:5
    |
 LL | /     if !(foo() && bla()) {
 LL | |
@@ -79,7 +79,7 @@ LL +     }
    |
 
 error: unnecessary boolean `not` operation
-  --> tests/ui/if_not_else.rs:53:5
+  --> tests/ui/if_not_else.rs:52:5
    |
 LL | /     if !foo() {
 LL | |
@@ -102,7 +102,7 @@ LL +     }
    |
 
 error: unnecessary boolean `not` operation
-  --> tests/ui/if_not_else.rs:61:5
+  --> tests/ui/if_not_else.rs:60:5
    |
 LL | /     if !bla() {
 LL | |
@@ -125,7 +125,7 @@ LL +     }
    |
 
 error: unnecessary boolean `not` operation
-  --> tests/ui/if_not_else.rs:72:5
+  --> tests/ui/if_not_else.rs:71:5
    |
 LL | /     if !foo() {
 LL | |
diff --git a/src/tools/clippy/tests/ui/ignore_without_reason.rs b/src/tools/clippy/tests/ui/ignore_without_reason.rs
new file mode 100644
index 00000000000..53ac34c2724
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ignore_without_reason.rs
@@ -0,0 +1,14 @@
+#![warn(clippy::ignore_without_reason)]
+
+fn main() {}
+
+#[test]
+fn unignored_test() {}
+
+#[test]
+#[ignore = "Some good reason"]
+fn ignored_with_reason() {}
+
+#[test]
+#[ignore] //~ ignore_without_reason
+fn ignored_without_reason() {}
diff --git a/src/tools/clippy/tests/ui/ignore_without_reason.stderr b/src/tools/clippy/tests/ui/ignore_without_reason.stderr
new file mode 100644
index 00000000000..4c0210c2bbc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ignore_without_reason.stderr
@@ -0,0 +1,12 @@
+error: `#[ignore]` without reason
+  --> tests/ui/ignore_without_reason.rs:13:1
+   |
+LL | #[ignore]
+   | ^^^^^^^^^
+   |
+   = help: add a reason with `= ".."`
+   = note: `-D clippy::ignore-without-reason` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::ignore_without_reason)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/implicit_return.fixed b/src/tools/clippy/tests/ui/implicit_return.fixed
index 1cb639b60a9..728c6e015c1 100644
--- a/src/tools/clippy/tests/ui/implicit_return.fixed
+++ b/src/tools/clippy/tests/ui/implicit_return.fixed
@@ -165,3 +165,46 @@ with_span!(
         x
     }
 );
+
+fn desugared_closure_14446() {
+    let _ = async || return 0;
+    //~^ implicit_return
+    #[rustfmt::skip]
+    let _ = async || -> i32 { return 0 };
+    //~^ implicit_return
+    let _ = async |a: i32| return a;
+    //~^ implicit_return
+    #[rustfmt::skip]
+    let _ = async |a: i32| { return a };
+    //~^ implicit_return
+
+    let _ = async || return 0;
+    let _ = async || -> i32 { return 0 };
+    let _ = async |a: i32| return a;
+    #[rustfmt::skip]
+    let _ = async |a: i32| { return a; };
+
+    let _ = async || return foo().await;
+    //~^ implicit_return
+    let _ = async || {
+        foo().await;
+        return foo().await
+    };
+    //~^^ implicit_return
+    #[rustfmt::skip]
+    let _ = async || { return foo().await };
+    //~^ implicit_return
+    let _ = async || -> bool { return foo().await };
+    //~^ implicit_return
+
+    let _ = async || return foo().await;
+    let _ = async || {
+        foo().await;
+        return foo().await;
+    };
+    #[rustfmt::skip]
+    let _ = async || { return foo().await; };
+    let _ = async || -> bool {
+        return foo().await;
+    };
+}
diff --git a/src/tools/clippy/tests/ui/implicit_return.rs b/src/tools/clippy/tests/ui/implicit_return.rs
index 99d75e4987e..3381fffb6e4 100644
--- a/src/tools/clippy/tests/ui/implicit_return.rs
+++ b/src/tools/clippy/tests/ui/implicit_return.rs
@@ -165,3 +165,46 @@ with_span!(
         x
     }
 );
+
+fn desugared_closure_14446() {
+    let _ = async || 0;
+    //~^ implicit_return
+    #[rustfmt::skip]
+    let _ = async || -> i32 { 0 };
+    //~^ implicit_return
+    let _ = async |a: i32| a;
+    //~^ implicit_return
+    #[rustfmt::skip]
+    let _ = async |a: i32| { a };
+    //~^ implicit_return
+
+    let _ = async || return 0;
+    let _ = async || -> i32 { return 0 };
+    let _ = async |a: i32| return a;
+    #[rustfmt::skip]
+    let _ = async |a: i32| { return a; };
+
+    let _ = async || foo().await;
+    //~^ implicit_return
+    let _ = async || {
+        foo().await;
+        foo().await
+    };
+    //~^^ implicit_return
+    #[rustfmt::skip]
+    let _ = async || { foo().await };
+    //~^ implicit_return
+    let _ = async || -> bool { foo().await };
+    //~^ implicit_return
+
+    let _ = async || return foo().await;
+    let _ = async || {
+        foo().await;
+        return foo().await;
+    };
+    #[rustfmt::skip]
+    let _ = async || { return foo().await; };
+    let _ = async || -> bool {
+        return foo().await;
+    };
+}
diff --git a/src/tools/clippy/tests/ui/implicit_return.stderr b/src/tools/clippy/tests/ui/implicit_return.stderr
index 02044df47ac..05cd7f62583 100644
--- a/src/tools/clippy/tests/ui/implicit_return.stderr
+++ b/src/tools/clippy/tests/ui/implicit_return.stderr
@@ -183,5 +183,93 @@ help: add `return` as shown
 LL |     return true
    |     ++++++
 
-error: aborting due to 16 previous errors
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:170:22
+   |
+LL |     let _ = async || 0;
+   |                      ^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async || return 0;
+   |                      ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:173:31
+   |
+LL |     let _ = async || -> i32 { 0 };
+   |                               ^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async || -> i32 { return 0 };
+   |                               ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:175:28
+   |
+LL |     let _ = async |a: i32| a;
+   |                            ^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async |a: i32| return a;
+   |                            ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:178:30
+   |
+LL |     let _ = async |a: i32| { a };
+   |                              ^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async |a: i32| { return a };
+   |                              ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:187:22
+   |
+LL |     let _ = async || foo().await;
+   |                      ^^^^^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async || return foo().await;
+   |                      ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:191:9
+   |
+LL |         foo().await
+   |         ^^^^^
+   |
+help: add `return` as shown
+   |
+LL |         return foo().await
+   |         ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:195:24
+   |
+LL |     let _ = async || { foo().await };
+   |                        ^^^^^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async || { return foo().await };
+   |                        ++++++
+
+error: missing `return` statement
+  --> tests/ui/implicit_return.rs:197:32
+   |
+LL |     let _ = async || -> bool { foo().await };
+   |                                ^^^^^
+   |
+help: add `return` as shown
+   |
+LL |     let _ = async || -> bool { return foo().await };
+   |                                ++++++
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed b/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed
index f036b368a66..c00d6440f1c 100644
--- a/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed
+++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.fixed
@@ -1,4 +1,3 @@
-#![allow(unused)]
 #![warn(clippy::items_after_test_module)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs b/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs
index de0cbb12033..23d191e3b13 100644
--- a/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs
+++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.rs
@@ -1,4 +1,3 @@
-#![allow(unused)]
 #![warn(clippy::items_after_test_module)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr
index bed8d4bd5a0..952489ff5ef 100644
--- a/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr
+++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr
@@ -1,5 +1,5 @@
 error: items after a test module
-  --> tests/ui/items_after_test_module/root_module.rs:12:1
+  --> tests/ui/items_after_test_module/root_module.rs:11:1
    |
 LL | mod tests {
    | ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
index e9fb44e8959..231fac7cdde 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
@@ -29,3 +29,30 @@ fn main() {
     let _: Vec<isize> = v.to_vec();
     //~^ iter_cloned_collect
 }
+
+mod issue9119 {
+
+    use std::iter;
+
+    #[derive(Clone)]
+    struct Example(u16);
+
+    impl iter::FromIterator<Example> for Vec<u8> {
+        fn from_iter<T>(iter: T) -> Self
+        where
+            T: IntoIterator<Item = Example>,
+        {
+            iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect()
+        }
+    }
+
+    fn foo() {
+        let examples = [Example(1), Example(0x1234)];
+        let encoded: Vec<u8> = examples.iter().cloned().collect();
+        assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]);
+
+        let a = [&&String::new()];
+        let v: Vec<&&String> = a.to_vec();
+        //~^ iter_cloned_collect
+    }
+}
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.rs b/src/tools/clippy/tests/ui/iter_cloned_collect.rs
index c9b8abcc9a0..e73b6ecae80 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.rs
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.rs
@@ -33,3 +33,30 @@ fn main() {
     let _: Vec<isize> = v.iter().copied().collect();
     //~^ iter_cloned_collect
 }
+
+mod issue9119 {
+
+    use std::iter;
+
+    #[derive(Clone)]
+    struct Example(u16);
+
+    impl iter::FromIterator<Example> for Vec<u8> {
+        fn from_iter<T>(iter: T) -> Self
+        where
+            T: IntoIterator<Item = Example>,
+        {
+            iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect()
+        }
+    }
+
+    fn foo() {
+        let examples = [Example(1), Example(0x1234)];
+        let encoded: Vec<u8> = examples.iter().cloned().collect();
+        assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]);
+
+        let a = [&&String::new()];
+        let v: Vec<&&String> = a.iter().cloned().collect();
+        //~^ iter_cloned_collect
+    }
+}
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.stderr b/src/tools/clippy/tests/ui/iter_cloned_collect.stderr
index 119698cb463..f8a50794327 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.stderr
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.stderr
@@ -36,5 +36,11 @@ error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling
 LL |     let _: Vec<isize> = v.iter().copied().collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
 
-error: aborting due to 5 previous errors
+error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
+  --> tests/ui/iter_cloned_collect.rs:59:33
+   |
+LL |         let v: Vec<&&String> = a.iter().cloned().collect();
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.fixed b/src/tools/clippy/tests/ui/iter_kv_map.fixed
index 7fcab6592e2..874f749b33d 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.fixed
+++ b/src/tools/clippy/tests/ui/iter_kv_map.fixed
@@ -166,3 +166,18 @@ fn msrv_1_54() {
     let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
     //~^ iter_kv_map
 }
+
+fn issue14595() {
+    pub struct Foo(BTreeMap<String, i32>);
+
+    impl AsRef<BTreeMap<String, i32>> for Foo {
+        fn as_ref(&self) -> &BTreeMap<String, i32> {
+            &self.0
+        }
+    }
+
+    let map = Foo(BTreeMap::default());
+
+    let _ = map.as_ref().values().copied().collect::<Vec<_>>();
+    //~^ iter_kv_map
+}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.rs b/src/tools/clippy/tests/ui/iter_kv_map.rs
index b590aef7b80..f570e3c32cb 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.rs
+++ b/src/tools/clippy/tests/ui/iter_kv_map.rs
@@ -170,3 +170,18 @@ fn msrv_1_54() {
     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
     //~^ iter_kv_map
 }
+
+fn issue14595() {
+    pub struct Foo(BTreeMap<String, i32>);
+
+    impl AsRef<BTreeMap<String, i32>> for Foo {
+        fn as_ref(&self) -> &BTreeMap<String, i32> {
+            &self.0
+        }
+    }
+
+    let map = Foo(BTreeMap::default());
+
+    let _ = map.as_ref().iter().map(|(_, v)| v).copied().collect::<Vec<_>>();
+    //~^ iter_kv_map
+}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.stderr b/src/tools/clippy/tests/ui/iter_kv_map.stderr
index 00d566ed14a..31ee76c25b7 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.stderr
+++ b/src/tools/clippy/tests/ui/iter_kv_map.stderr
@@ -263,5 +263,11 @@ error: iterating on a map's values
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
-error: aborting due to 38 previous errors
+error: iterating on a map's values
+  --> tests/ui/iter_kv_map.rs:185:13
+   |
+LL |     let _ = map.as_ref().iter().map(|(_, v)| v).copied().collect::<Vec<_>>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.as_ref().values()`
+
+error: aborting due to 39 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
index 99991269029..b0e548f1790 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
@@ -59,7 +59,7 @@ fn main() {
         iter: impl Iterator<Item = &'a (&'a u32, String)> + 'a,
         target: String,
     ) -> impl Iterator<Item = (&'a u32, String)> + 'a {
-        iter.filter(move |&(&a, b)| a == 1 && b == &target).cloned()
+        iter.filter(move |&&(&a, ref b)| a == 1 && b == &target).cloned()
         //~^ iter_overeager_cloned
     }
 
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
index 6a860dad5af..cedf62a6b47 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
@@ -60,7 +60,7 @@ fn main() {
         iter: impl Iterator<Item = &'a (&'a u32, String)> + 'a,
         target: String,
     ) -> impl Iterator<Item = (&'a u32, String)> + 'a {
-        iter.cloned().filter(move |(&a, b)| a == 1 && b == &target)
+        iter.cloned().filter(move |&(&a, ref b)| a == 1 && b == &target)
         //~^ iter_overeager_cloned
     }
 
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr b/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr
index f3239b59582..1616dec95b7 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.stderr
@@ -120,10 +120,10 @@ LL |         let _ = vec.iter().cloned().find(f);
 error: unnecessarily eager cloning of iterator items
   --> tests/ui/iter_overeager_cloned.rs:63:9
    |
-LL |         iter.cloned().filter(move |(&a, b)| a == 1 && b == &target)
-   |         ^^^^-------------------------------------------------------
+LL |         iter.cloned().filter(move |&(&a, ref b)| a == 1 && b == &target)
+   |         ^^^^------------------------------------------------------------
    |             |
-   |             help: try: `.filter(move |&(&a, b)| a == 1 && b == &target).cloned()`
+   |             help: try: `.filter(move |&&(&a, ref b)| a == 1 && b == &target).cloned()`
 
 error: unnecessarily eager cloning of iterator items
   --> tests/ui/iter_overeager_cloned.rs:75:13
diff --git a/src/tools/clippy/tests/ui/large_futures.fixed b/src/tools/clippy/tests/ui/large_futures.fixed
index c2159c58de1..4c7215f0abe 100644
--- a/src/tools/clippy/tests/ui/large_futures.fixed
+++ b/src/tools/clippy/tests/ui/large_futures.fixed
@@ -1,7 +1,10 @@
+#![allow(
+    clippy::future_not_send,
+    clippy::manual_async_fn,
+    clippy::never_loop,
+    clippy::uninlined_format_args
+)]
 #![warn(clippy::large_futures)]
-#![allow(clippy::never_loop)]
-#![allow(clippy::future_not_send)]
-#![allow(clippy::manual_async_fn)]
 
 async fn big_fut(_arg: [u8; 1024 * 16]) {}
 
diff --git a/src/tools/clippy/tests/ui/large_futures.rs b/src/tools/clippy/tests/ui/large_futures.rs
index 567f6344afe..2b5860583f5 100644
--- a/src/tools/clippy/tests/ui/large_futures.rs
+++ b/src/tools/clippy/tests/ui/large_futures.rs
@@ -1,7 +1,10 @@
+#![allow(
+    clippy::future_not_send,
+    clippy::manual_async_fn,
+    clippy::never_loop,
+    clippy::uninlined_format_args
+)]
 #![warn(clippy::large_futures)]
-#![allow(clippy::never_loop)]
-#![allow(clippy::future_not_send)]
-#![allow(clippy::manual_async_fn)]
 
 async fn big_fut(_arg: [u8; 1024 * 16]) {}
 
diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr
index fd6ba4e3563..4280c9e2af2 100644
--- a/src/tools/clippy/tests/ui/large_futures.stderr
+++ b/src/tools/clippy/tests/ui/large_futures.stderr
@@ -1,5 +1,5 @@
 error: large future with a size of 16385 bytes
-  --> tests/ui/large_futures.rs:10:9
+  --> tests/ui/large_futures.rs:13:9
    |
 LL |         big_fut([0u8; 1024 * 16]).await;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
@@ -8,37 +8,37 @@ LL |         big_fut([0u8; 1024 * 16]).await;
    = help: to override `-D warnings` add `#[allow(clippy::large_futures)]`
 
 error: large future with a size of 16386 bytes
-  --> tests/ui/large_futures.rs:13:5
+  --> tests/ui/large_futures.rs:16:5
    |
 LL |     f.await
    |     ^ help: consider `Box::pin` on it: `Box::pin(f)`
 
 error: large future with a size of 16387 bytes
-  --> tests/ui/large_futures.rs:18:9
+  --> tests/ui/large_futures.rs:21:9
    |
 LL |         wait().await;
    |         ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 16387 bytes
-  --> tests/ui/large_futures.rs:24:13
+  --> tests/ui/large_futures.rs:27:13
    |
 LL |             wait().await;
    |             ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:32:5
+  --> tests/ui/large_futures.rs:35:5
    |
 LL |     foo().await;
    |     ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
 
 error: large future with a size of 49159 bytes
-  --> tests/ui/large_futures.rs:35:5
+  --> tests/ui/large_futures.rs:38:5
    |
 LL |     calls_fut(fut).await;
    |     ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:48:5
+  --> tests/ui/large_futures.rs:51:5
    |
 LL | /     async {
 LL | |
@@ -61,7 +61,7 @@ LL +     })
    |
 
 error: large future with a size of 65540 bytes
-  --> tests/ui/large_futures.rs:61:13
+  --> tests/ui/large_futures.rs:64:13
    |
 LL | /             async {
 LL | |
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty_expect.rs b/src/tools/clippy/tests/ui/len_without_is_empty_expect.rs
new file mode 100644
index 00000000000..9d1245e2d02
--- /dev/null
+++ b/src/tools/clippy/tests/ui/len_without_is_empty_expect.rs
@@ -0,0 +1,28 @@
+//@no-rustfix
+#![allow(clippy::len_without_is_empty)]
+
+// Check that the lint expectation is fulfilled even if the lint is allowed at the type level.
+pub struct Empty;
+
+impl Empty {
+    #[expect(clippy::len_without_is_empty)]
+    pub fn len(&self) -> usize {
+        0
+    }
+}
+
+// Check that the lint expectation is not triggered if it should not
+pub struct Empty2;
+
+impl Empty2 {
+    #[expect(clippy::len_without_is_empty)] //~ ERROR: this lint expectation is unfulfilled
+    pub fn len(&self) -> usize {
+        0
+    }
+
+    pub fn is_empty(&self) -> bool {
+        false
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty_expect.stderr b/src/tools/clippy/tests/ui/len_without_is_empty_expect.stderr
new file mode 100644
index 00000000000..e96870f054e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/len_without_is_empty_expect.stderr
@@ -0,0 +1,11 @@
+error: this lint expectation is unfulfilled
+  --> tests/ui/len_without_is_empty_expect.rs:18:14
+   |
+LL |     #[expect(clippy::len_without_is_empty)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D unfulfilled-lint-expectations` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/manual_abs_diff.fixed b/src/tools/clippy/tests/ui/manual_abs_diff.fixed
new file mode 100644
index 00000000000..f1b1278ea6d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_abs_diff.fixed
@@ -0,0 +1,106 @@
+#![warn(clippy::manual_abs_diff)]
+
+use std::time::Duration;
+
+fn main() {
+    let a: usize = 5;
+    let b: usize = 3;
+    let c: usize = 8;
+    let d: usize = 11;
+
+    let _ = a.abs_diff(b);
+    //~^ manual_abs_diff
+    let _ = b.abs_diff(a);
+    //~^ manual_abs_diff
+
+    let _ = b.abs_diff(5);
+    //~^ manual_abs_diff
+    let _ = b.abs_diff(5);
+    //~^ manual_abs_diff
+
+    let _ = a.abs_diff(b);
+    //~^ manual_abs_diff
+    let _ = b.abs_diff(a);
+    //~^ manual_abs_diff
+
+    #[allow(arithmetic_overflow)]
+    {
+        let _ = if a > b { b - a } else { a - b };
+        let _ = if a < b { a - b } else { b - a };
+    }
+
+    let _ = (a + b).abs_diff(c + d);
+    let _ = (c + d).abs_diff(a + b);
+
+    const A: usize = 5;
+    const B: usize = 3;
+    // check const context
+    const _: usize = A.abs_diff(B);
+    //~^ manual_abs_diff
+
+    let a = Duration::from_secs(3);
+    let b = Duration::from_secs(5);
+    let _ = a.abs_diff(b);
+    //~^ manual_abs_diff
+
+    let a: i32 = 3;
+    let b: i32 = -5;
+    let _ = if a > b { a - b } else { b - a };
+    let _ = a.abs_diff(b);
+    //~^ manual_abs_diff
+}
+
+// FIXME: bunch of patterns that should be linted
+fn fixme() {
+    let a: usize = 5;
+    let b: usize = 3;
+    let c: usize = 8;
+    let d: usize = 11;
+
+    {
+        let out;
+        if a > b {
+            out = a - b;
+        } else {
+            out = b - a;
+        }
+    }
+
+    {
+        let mut out = 0;
+        if a > b {
+            out = a - b;
+        } else if a < b {
+            out = b - a;
+        }
+    }
+
+    #[allow(clippy::implicit_saturating_sub)]
+    let _ = if a > b {
+        a - b
+    } else if a < b {
+        b - a
+    } else {
+        0
+    };
+
+    let a: i32 = 3;
+    let b: i32 = 5;
+    let _: u32 = if a > b { a - b } else { b - a } as u32;
+}
+
+fn non_primitive_ty() {
+    #[derive(Eq, PartialEq, PartialOrd)]
+    struct S(i32);
+
+    impl std::ops::Sub for S {
+        type Output = S;
+
+        fn sub(self, rhs: Self) -> Self::Output {
+            Self(self.0 - rhs.0)
+        }
+    }
+
+    let (a, b) = (S(10), S(20));
+    let _ = if a < b { b - a } else { a - b };
+}
diff --git a/src/tools/clippy/tests/ui/manual_abs_diff.rs b/src/tools/clippy/tests/ui/manual_abs_diff.rs
new file mode 100644
index 00000000000..60ef819c12d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_abs_diff.rs
@@ -0,0 +1,116 @@
+#![warn(clippy::manual_abs_diff)]
+
+use std::time::Duration;
+
+fn main() {
+    let a: usize = 5;
+    let b: usize = 3;
+    let c: usize = 8;
+    let d: usize = 11;
+
+    let _ = if a > b { a - b } else { b - a };
+    //~^ manual_abs_diff
+    let _ = if a < b { b - a } else { a - b };
+    //~^ manual_abs_diff
+
+    let _ = if 5 > b { 5 - b } else { b - 5 };
+    //~^ manual_abs_diff
+    let _ = if b > 5 { b - 5 } else { 5 - b };
+    //~^ manual_abs_diff
+
+    let _ = if a >= b { a - b } else { b - a };
+    //~^ manual_abs_diff
+    let _ = if a <= b { b - a } else { a - b };
+    //~^ manual_abs_diff
+
+    #[allow(arithmetic_overflow)]
+    {
+        let _ = if a > b { b - a } else { a - b };
+        let _ = if a < b { a - b } else { b - a };
+    }
+
+    let _ = if (a + b) > (c + d) {
+        //~^ manual_abs_diff
+        (a + b) - (c + d)
+    } else {
+        (c + d) - (a + b)
+    };
+    let _ = if (a + b) < (c + d) {
+        //~^ manual_abs_diff
+        (c + d) - (a + b)
+    } else {
+        (a + b) - (c + d)
+    };
+
+    const A: usize = 5;
+    const B: usize = 3;
+    // check const context
+    const _: usize = if A > B { A - B } else { B - A };
+    //~^ manual_abs_diff
+
+    let a = Duration::from_secs(3);
+    let b = Duration::from_secs(5);
+    let _ = if a > b { a - b } else { b - a };
+    //~^ manual_abs_diff
+
+    let a: i32 = 3;
+    let b: i32 = -5;
+    let _ = if a > b { a - b } else { b - a };
+    let _ = if a > b { (a - b) as u32 } else { (b - a) as u32 };
+    //~^ manual_abs_diff
+}
+
+// FIXME: bunch of patterns that should be linted
+fn fixme() {
+    let a: usize = 5;
+    let b: usize = 3;
+    let c: usize = 8;
+    let d: usize = 11;
+
+    {
+        let out;
+        if a > b {
+            out = a - b;
+        } else {
+            out = b - a;
+        }
+    }
+
+    {
+        let mut out = 0;
+        if a > b {
+            out = a - b;
+        } else if a < b {
+            out = b - a;
+        }
+    }
+
+    #[allow(clippy::implicit_saturating_sub)]
+    let _ = if a > b {
+        a - b
+    } else if a < b {
+        b - a
+    } else {
+        0
+    };
+
+    let a: i32 = 3;
+    let b: i32 = 5;
+    let _: u32 = if a > b { a - b } else { b - a } as u32;
+}
+
+fn non_primitive_ty() {
+    #[derive(Eq, PartialEq, PartialOrd)]
+    struct S(i32);
+
+    impl std::ops::Sub for S {
+        type Output = S;
+
+        fn sub(self, rhs: Self) -> Self::Output {
+            Self(self.0 - rhs.0)
+        }
+    }
+
+    let (a, b) = (S(10), S(20));
+    let _ = if a < b { b - a } else { a - b };
+}
diff --git a/src/tools/clippy/tests/ui/manual_abs_diff.stderr b/src/tools/clippy/tests/ui/manual_abs_diff.stderr
new file mode 100644
index 00000000000..c14c1dc830f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_abs_diff.stderr
@@ -0,0 +1,83 @@
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:11:13
+   |
+LL |     let _ = if a > b { a - b } else { b - a };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `a.abs_diff(b)`
+   |
+   = note: `-D clippy::manual-abs-diff` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_abs_diff)]`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:13:13
+   |
+LL |     let _ = if a < b { b - a } else { a - b };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `b.abs_diff(a)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:16:13
+   |
+LL |     let _ = if 5 > b { 5 - b } else { b - 5 };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `b.abs_diff(5)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:18:13
+   |
+LL |     let _ = if b > 5 { b - 5 } else { 5 - b };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `b.abs_diff(5)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:21:13
+   |
+LL |     let _ = if a >= b { a - b } else { b - a };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `a.abs_diff(b)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:23:13
+   |
+LL |     let _ = if a <= b { b - a } else { a - b };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `b.abs_diff(a)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:32:13
+   |
+LL |       let _ = if (a + b) > (c + d) {
+   |  _____________^
+LL | |
+LL | |         (a + b) - (c + d)
+LL | |     } else {
+LL | |         (c + d) - (a + b)
+LL | |     };
+   | |_____^ help: replace with `abs_diff`: `(a + b).abs_diff(c + d)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:38:13
+   |
+LL |       let _ = if (a + b) < (c + d) {
+   |  _____________^
+LL | |
+LL | |         (c + d) - (a + b)
+LL | |     } else {
+LL | |         (a + b) - (c + d)
+LL | |     };
+   | |_____^ help: replace with `abs_diff`: `(c + d).abs_diff(a + b)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:48:22
+   |
+LL |     const _: usize = if A > B { A - B } else { B - A };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `A.abs_diff(B)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:53:13
+   |
+LL |     let _ = if a > b { a - b } else { b - a };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `a.abs_diff(b)`
+
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:59:13
+   |
+LL |     let _ = if a > b { (a - b) as u32 } else { (b - a) as u32 };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `a.abs_diff(b)`
+
+error: aborting due to 11 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed
index ad0266d39e9..a284ca9f625 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.fixed
+++ b/src/tools/clippy/tests/ui/manual_async_fn.fixed
@@ -75,7 +75,7 @@ impl S {
 async fn elided(_: &i32) -> i32 { 42 }
 
 // should be ignored
-fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
+fn elided_not_bound(_: &i32) -> impl Future<Output = i32> + use<> {
     async { 42 }
 }
 
@@ -84,7 +84,7 @@ async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 }
 
 // should be ignored
 #[allow(clippy::needless_lifetimes)]
-fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
+fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + use<> {
     async { 42 }
 }
 
@@ -94,7 +94,7 @@ mod issue_5765 {
 
     struct A;
     impl A {
-        fn f(&self) -> impl Future<Output = ()> {
+        fn f(&self) -> impl Future<Output = ()> + use<> {
             async {}
         }
     }
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs
index fe367b4bc7b..188f8a4982c 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.rs
+++ b/src/tools/clippy/tests/ui/manual_async_fn.rs
@@ -102,7 +102,7 @@ fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
 }
 
 // should be ignored
-fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
+fn elided_not_bound(_: &i32) -> impl Future<Output = i32> + use<> {
     async { 42 }
 }
 
@@ -114,7 +114,7 @@ fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a +
 
 // should be ignored
 #[allow(clippy::needless_lifetimes)]
-fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
+fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + use<> {
     async { 42 }
 }
 
@@ -124,7 +124,7 @@ mod issue_5765 {
 
     struct A;
     impl A {
-        fn f(&self) -> impl Future<Output = ()> {
+        fn f(&self) -> impl Future<Output = ()> + use<> {
             async {}
         }
     }
diff --git a/src/tools/clippy/tests/ui/manual_dangling_ptr.fixed b/src/tools/clippy/tests/ui/manual_dangling_ptr.fixed
new file mode 100644
index 00000000000..b6afe789890
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_dangling_ptr.fixed
@@ -0,0 +1,44 @@
+#![warn(clippy::manual_dangling_ptr)]
+use std::mem;
+
+pub fn foo(_const: *const f32, _mut: *mut i32) {}
+
+fn main() {
+    let _: *const u8 = std::ptr::dangling();
+    //~^ manual_dangling_ptr
+    let _ = std::ptr::dangling::<u32>();
+    //~^ manual_dangling_ptr
+    let _ = std::ptr::dangling_mut::<f32>();
+    //~^ manual_dangling_ptr
+
+    let _ = std::ptr::dangling::<u8>();
+    //~^ manual_dangling_ptr
+    let _ = std::ptr::dangling::<u32>();
+    //~^ manual_dangling_ptr
+    let _ = std::ptr::dangling::<usize>();
+    //~^ manual_dangling_ptr
+
+    foo(std::ptr::dangling(), std::ptr::dangling_mut());
+    //~^ manual_dangling_ptr
+    //~| manual_dangling_ptr
+}
+
+fn should_not_lint() {
+    let _ = 0x10 as *mut i32;
+    let _ = mem::align_of::<u32>() as *const u8;
+
+    foo(0 as _, 0 as _);
+}
+
+#[clippy::msrv = "1.83"]
+fn _msrv_1_83() {
+    // `{core, std}::ptr::dangling` was stabilized in 1.84. Do not lint this
+    foo(4 as *const _, 4 as *mut _);
+}
+
+#[clippy::msrv = "1.84"]
+fn _msrv_1_84() {
+    foo(std::ptr::dangling(), std::ptr::dangling_mut());
+    //~^ manual_dangling_ptr
+    //~| manual_dangling_ptr
+}
diff --git a/src/tools/clippy/tests/ui/manual_dangling_ptr.rs b/src/tools/clippy/tests/ui/manual_dangling_ptr.rs
new file mode 100644
index 00000000000..581ad50113e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_dangling_ptr.rs
@@ -0,0 +1,44 @@
+#![warn(clippy::manual_dangling_ptr)]
+use std::mem;
+
+pub fn foo(_const: *const f32, _mut: *mut i32) {}
+
+fn main() {
+    let _: *const u8 = 1 as *const _;
+    //~^ manual_dangling_ptr
+    let _ = 2 as *const u32;
+    //~^ manual_dangling_ptr
+    let _ = 4 as *mut f32;
+    //~^ manual_dangling_ptr
+
+    let _ = mem::align_of::<u8>() as *const u8;
+    //~^ manual_dangling_ptr
+    let _ = mem::align_of::<u32>() as *const u32;
+    //~^ manual_dangling_ptr
+    let _ = mem::align_of::<usize>() as *const usize;
+    //~^ manual_dangling_ptr
+
+    foo(4 as *const _, 4 as *mut _);
+    //~^ manual_dangling_ptr
+    //~| manual_dangling_ptr
+}
+
+fn should_not_lint() {
+    let _ = 0x10 as *mut i32;
+    let _ = mem::align_of::<u32>() as *const u8;
+
+    foo(0 as _, 0 as _);
+}
+
+#[clippy::msrv = "1.83"]
+fn _msrv_1_83() {
+    // `{core, std}::ptr::dangling` was stabilized in 1.84. Do not lint this
+    foo(4 as *const _, 4 as *mut _);
+}
+
+#[clippy::msrv = "1.84"]
+fn _msrv_1_84() {
+    foo(4 as *const _, 4 as *mut _);
+    //~^ manual_dangling_ptr
+    //~| manual_dangling_ptr
+}
diff --git a/src/tools/clippy/tests/ui/manual_dangling_ptr.stderr b/src/tools/clippy/tests/ui/manual_dangling_ptr.stderr
new file mode 100644
index 00000000000..e3bc9b16b0d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_dangling_ptr.stderr
@@ -0,0 +1,65 @@
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:7:24
+   |
+LL |     let _: *const u8 = 1 as *const _;
+   |                        ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()`
+   |
+   = note: `-D clippy::manual-dangling-ptr` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_dangling_ptr)]`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:9:13
+   |
+LL |     let _ = 2 as *const u32;
+   |             ^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::<u32>()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:11:13
+   |
+LL |     let _ = 4 as *mut f32;
+   |             ^^^^^^^^^^^^^ help: use: `std::ptr::dangling_mut::<f32>()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:14:13
+   |
+LL |     let _ = mem::align_of::<u8>() as *const u8;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::<u8>()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:16:13
+   |
+LL |     let _ = mem::align_of::<u32>() as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::<u32>()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:18:13
+   |
+LL |     let _ = mem::align_of::<usize>() as *const usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::<usize>()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:21:9
+   |
+LL |     foo(4 as *const _, 4 as *mut _);
+   |         ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:21:24
+   |
+LL |     foo(4 as *const _, 4 as *mut _);
+   |                        ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:41:9
+   |
+LL |     foo(4 as *const _, 4 as *mut _);
+   |         ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()`
+
+error: manual creation of a dangling pointer
+  --> tests/ui/manual_dangling_ptr.rs:41:24
+   |
+LL |     foo(4 as *const _, 4 as *mut _);
+   |                        ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_find.rs b/src/tools/clippy/tests/ui/manual_find.rs
index 20b557f21d1..7b9846cfe42 100644
--- a/src/tools/clippy/tests/ui/manual_find.rs
+++ b/src/tools/clippy/tests/ui/manual_find.rs
@@ -23,4 +23,32 @@ fn tuple(arr: Vec<(String, i32)>) -> Option<String> {
     None
 }
 
+mod issue9521 {
+    fn condition(x: u32, y: u32) -> Result<bool, ()> {
+        todo!()
+    }
+
+    fn find_with_early_return(v: Vec<u32>) -> Option<u32> {
+        for x in v {
+            if condition(x, 10).ok()? {
+                return Some(x);
+            }
+        }
+        None
+    }
+
+    fn find_with_early_break(v: Vec<u32>) -> Option<u32> {
+        for x in v {
+            if if x < 3 {
+                break;
+            } else {
+                x < 10
+            } {
+                return Some(x);
+            }
+        }
+        None
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_ignore_case_cmp.fixed b/src/tools/clippy/tests/ui/manual_ignore_case_cmp.fixed
index c1c929585cf..cd7adc20b12 100644
--- a/src/tools/clippy/tests/ui/manual_ignore_case_cmp.fixed
+++ b/src/tools/clippy/tests/ui/manual_ignore_case_cmp.fixed
@@ -1,5 +1,11 @@
-#![allow(clippy::all)]
-#![deny(clippy::manual_ignore_case_cmp)]
+#![warn(clippy::manual_ignore_case_cmp)]
+#![allow(
+    clippy::deref_addrof,
+    clippy::op_ref,
+    clippy::ptr_arg,
+    clippy::short_circuit_statement,
+    clippy::unnecessary_operation
+)]
 
 use std::ffi::{OsStr, OsString};
 
diff --git a/src/tools/clippy/tests/ui/manual_ignore_case_cmp.rs b/src/tools/clippy/tests/ui/manual_ignore_case_cmp.rs
index ca401e595fe..85f6719827c 100644
--- a/src/tools/clippy/tests/ui/manual_ignore_case_cmp.rs
+++ b/src/tools/clippy/tests/ui/manual_ignore_case_cmp.rs
@@ -1,5 +1,11 @@
-#![allow(clippy::all)]
-#![deny(clippy::manual_ignore_case_cmp)]
+#![warn(clippy::manual_ignore_case_cmp)]
+#![allow(
+    clippy::deref_addrof,
+    clippy::op_ref,
+    clippy::ptr_arg,
+    clippy::short_circuit_statement,
+    clippy::unnecessary_operation
+)]
 
 use std::ffi::{OsStr, OsString};
 
diff --git a/src/tools/clippy/tests/ui/manual_ignore_case_cmp.stderr b/src/tools/clippy/tests/ui/manual_ignore_case_cmp.stderr
index 47378a65799..fa7fadd9107 100644
--- a/src/tools/clippy/tests/ui/manual_ignore_case_cmp.stderr
+++ b/src/tools/clippy/tests/ui/manual_ignore_case_cmp.stderr
@@ -1,14 +1,11 @@
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:9:8
+  --> tests/ui/manual_ignore_case_cmp.rs:15:8
    |
 LL |     if a.to_ascii_lowercase() == b.to_ascii_lowercase() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: the lint level is defined here
-  --> tests/ui/manual_ignore_case_cmp.rs:2:9
-   |
-LL | #![deny(clippy::manual_ignore_case_cmp)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `-D clippy::manual-ignore-case-cmp` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_ignore_case_cmp)]`
 help: consider using `.eq_ignore_ascii_case()` instead
    |
 LL -     if a.to_ascii_lowercase() == b.to_ascii_lowercase() {
@@ -16,7 +13,7 @@ LL +     if a.eq_ignore_ascii_case(b) {
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:13:8
+  --> tests/ui/manual_ignore_case_cmp.rs:19:8
    |
 LL |     if a.to_ascii_uppercase() == b.to_ascii_uppercase() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +25,7 @@ LL +     if a.eq_ignore_ascii_case(b) {
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:17:13
+  --> tests/ui/manual_ignore_case_cmp.rs:23:13
    |
 LL |     let r = a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +37,7 @@ LL +     let r = a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:19:18
+  --> tests/ui/manual_ignore_case_cmp.rs:25:18
    |
 LL |     let r = r || a.to_ascii_uppercase() == b.to_ascii_uppercase();
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,7 +49,7 @@ LL +     let r = r || a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:21:10
+  --> tests/ui/manual_ignore_case_cmp.rs:27:10
    |
 LL |     r && a.to_ascii_lowercase() == b.to_uppercase().to_ascii_lowercase();
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -64,7 +61,7 @@ LL +     r && a.eq_ignore_ascii_case(&b.to_uppercase());
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:24:8
+  --> tests/ui/manual_ignore_case_cmp.rs:30:8
    |
 LL |     if a.to_ascii_lowercase() != b.to_ascii_lowercase() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,7 +73,7 @@ LL +     if !a.eq_ignore_ascii_case(b) {
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:28:8
+  --> tests/ui/manual_ignore_case_cmp.rs:34:8
    |
 LL |     if a.to_ascii_uppercase() != b.to_ascii_uppercase() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +85,7 @@ LL +     if !a.eq_ignore_ascii_case(b) {
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:32:13
+  --> tests/ui/manual_ignore_case_cmp.rs:38:13
    |
 LL |     let r = a.to_ascii_lowercase() != b.to_ascii_lowercase();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +97,7 @@ LL +     let r = !a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:34:18
+  --> tests/ui/manual_ignore_case_cmp.rs:40:18
    |
 LL |     let r = r || a.to_ascii_uppercase() != b.to_ascii_uppercase();
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +109,7 @@ LL +     let r = r || !a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:36:10
+  --> tests/ui/manual_ignore_case_cmp.rs:42:10
    |
 LL |     r && a.to_ascii_lowercase() != b.to_uppercase().to_ascii_lowercase();
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -124,7 +121,7 @@ LL +     r && !a.eq_ignore_ascii_case(&b.to_uppercase());
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:48:5
+  --> tests/ui/manual_ignore_case_cmp.rs:54:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,7 +133,7 @@ LL +     a.eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:52:5
+  --> tests/ui/manual_ignore_case_cmp.rs:58:5
    |
 LL |     a.to_ascii_lowercase() == 'a';
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +145,7 @@ LL +     a.eq_ignore_ascii_case(&'a');
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:54:5
+  --> tests/ui/manual_ignore_case_cmp.rs:60:5
    |
 LL |     'a' == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -160,7 +157,7 @@ LL +     'a'.eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:58:5
+  --> tests/ui/manual_ignore_case_cmp.rs:64:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -172,7 +169,7 @@ LL +     a.eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:60:5
+  --> tests/ui/manual_ignore_case_cmp.rs:66:5
    |
 LL |     a.to_ascii_lowercase() == b'a';
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +181,7 @@ LL +     a.eq_ignore_ascii_case(&b'a');
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:62:5
+  --> tests/ui/manual_ignore_case_cmp.rs:68:5
    |
 LL |     b'a' == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -196,7 +193,7 @@ LL +     b'a'.eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:66:5
+  --> tests/ui/manual_ignore_case_cmp.rs:72:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -208,7 +205,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:68:5
+  --> tests/ui/manual_ignore_case_cmp.rs:74:5
    |
 LL |     a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +217,7 @@ LL +     a.to_uppercase().eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:70:5
+  --> tests/ui/manual_ignore_case_cmp.rs:76:5
    |
 LL |     a.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -232,7 +229,7 @@ LL +     a.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:72:5
+  --> tests/ui/manual_ignore_case_cmp.rs:78:5
    |
 LL |     "a" == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -244,7 +241,7 @@ LL +     "a".eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:76:5
+  --> tests/ui/manual_ignore_case_cmp.rs:82:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -256,7 +253,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:78:5
+  --> tests/ui/manual_ignore_case_cmp.rs:84:5
    |
 LL |     a.to_uppercase().to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -268,7 +265,7 @@ LL +     a.to_uppercase().eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:80:5
+  --> tests/ui/manual_ignore_case_cmp.rs:86:5
    |
 LL |     a.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -280,7 +277,7 @@ LL +     a.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:82:5
+  --> tests/ui/manual_ignore_case_cmp.rs:88:5
    |
 LL |     "a" == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -292,7 +289,7 @@ LL +     "a".eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:86:5
+  --> tests/ui/manual_ignore_case_cmp.rs:92:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -304,7 +301,7 @@ LL +     a.eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:88:5
+  --> tests/ui/manual_ignore_case_cmp.rs:94:5
    |
 LL |     a.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -316,7 +313,7 @@ LL +     a.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:90:5
+  --> tests/ui/manual_ignore_case_cmp.rs:96:5
    |
 LL |     "a" == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -328,7 +325,7 @@ LL +     "a".eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:94:5
+  --> tests/ui/manual_ignore_case_cmp.rs:100:5
    |
 LL |     a.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -340,7 +337,7 @@ LL +     a.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:96:5
+  --> tests/ui/manual_ignore_case_cmp.rs:102:5
    |
 LL |     "a" == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -352,7 +349,7 @@ LL +     "a".eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:100:5
+  --> tests/ui/manual_ignore_case_cmp.rs:106:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -364,7 +361,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:102:5
+  --> tests/ui/manual_ignore_case_cmp.rs:108:5
    |
 LL |     a.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -376,7 +373,7 @@ LL +     a.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:104:5
+  --> tests/ui/manual_ignore_case_cmp.rs:110:5
    |
 LL |     "a" == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -388,7 +385,7 @@ LL +     "a".eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:107:5
+  --> tests/ui/manual_ignore_case_cmp.rs:113:5
    |
 LL |     b.to_ascii_lowercase() == a.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -400,7 +397,7 @@ LL +     b.eq_ignore_ascii_case(&a);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:109:5
+  --> tests/ui/manual_ignore_case_cmp.rs:115:5
    |
 LL |     b.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -412,7 +409,7 @@ LL +     b.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:111:5
+  --> tests/ui/manual_ignore_case_cmp.rs:117:5
    |
 LL |     "a" == a.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -424,7 +421,7 @@ LL +     "a".eq_ignore_ascii_case(&a);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:115:5
+  --> tests/ui/manual_ignore_case_cmp.rs:121:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -436,7 +433,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:117:5
+  --> tests/ui/manual_ignore_case_cmp.rs:123:5
    |
 LL |     a.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -448,7 +445,7 @@ LL +     a.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:119:5
+  --> tests/ui/manual_ignore_case_cmp.rs:125:5
    |
 LL |     "a" == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -460,7 +457,7 @@ LL +     "a".eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:122:5
+  --> tests/ui/manual_ignore_case_cmp.rs:128:5
    |
 LL |     b.to_ascii_lowercase() == a.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -472,7 +469,7 @@ LL +     b.eq_ignore_ascii_case(&a);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:124:5
+  --> tests/ui/manual_ignore_case_cmp.rs:130:5
    |
 LL |     b.to_ascii_lowercase() == "a";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -484,7 +481,7 @@ LL +     b.eq_ignore_ascii_case("a");
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:126:5
+  --> tests/ui/manual_ignore_case_cmp.rs:132:5
    |
 LL |     "a" == a.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -496,7 +493,7 @@ LL +     "a".eq_ignore_ascii_case(&a);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:130:5
+  --> tests/ui/manual_ignore_case_cmp.rs:136:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -508,7 +505,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:134:5
+  --> tests/ui/manual_ignore_case_cmp.rs:140:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -520,7 +517,7 @@ LL +     a.eq_ignore_ascii_case(&b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:138:5
+  --> tests/ui/manual_ignore_case_cmp.rs:144:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -532,7 +529,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:140:5
+  --> tests/ui/manual_ignore_case_cmp.rs:146:5
    |
 LL |     b.to_ascii_lowercase() == a.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -544,7 +541,7 @@ LL +     b.eq_ignore_ascii_case(&a);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:144:5
+  --> tests/ui/manual_ignore_case_cmp.rs:150:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -556,7 +553,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:148:5
+  --> tests/ui/manual_ignore_case_cmp.rs:154:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -568,7 +565,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:152:5
+  --> tests/ui/manual_ignore_case_cmp.rs:158:5
    |
 LL |     a.to_ascii_lowercase() == b.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -580,7 +577,7 @@ LL +     a.eq_ignore_ascii_case(b);
    |
 
 error: manual case-insensitive ASCII comparison
-  --> tests/ui/manual_ignore_case_cmp.rs:154:5
+  --> tests/ui/manual_ignore_case_cmp.rs:160:5
    |
 LL |     b.to_ascii_lowercase() == a.to_ascii_lowercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/manual_inspect.fixed b/src/tools/clippy/tests/ui/manual_inspect.fixed
index 44f15d61f85..ec87fe217ae 100644
--- a/src/tools/clippy/tests/ui/manual_inspect.fixed
+++ b/src/tools/clippy/tests/ui/manual_inspect.fixed
@@ -1,5 +1,5 @@
+#![allow(clippy::no_effect, clippy::op_ref, clippy::uninlined_format_args)]
 #![warn(clippy::manual_inspect)]
-#![allow(clippy::no_effect, clippy::op_ref)]
 
 fn main() {
     let _ = Some(0).inspect(|&x| {
@@ -107,7 +107,7 @@ fn main() {
             let _ = || {
                 let _x = x;
             };
-            return;
+            return ;
         }
         println!("test");
     });
@@ -185,3 +185,12 @@ fn main() {
         });
     }
 }
+
+#[rustfmt::skip]
+fn layout_check() {
+    if let Some(x) = Some(1).inspect(|&x| { println!("{x}"); //~ manual_inspect
+        // Do not collapse code into this comment
+         }) {
+        println!("{x}");
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_inspect.rs b/src/tools/clippy/tests/ui/manual_inspect.rs
index d34f2abce6a..e679636201e 100644
--- a/src/tools/clippy/tests/ui/manual_inspect.rs
+++ b/src/tools/clippy/tests/ui/manual_inspect.rs
@@ -1,5 +1,5 @@
+#![allow(clippy::no_effect, clippy::op_ref, clippy::uninlined_format_args)]
 #![warn(clippy::manual_inspect)]
-#![allow(clippy::no_effect, clippy::op_ref)]
 
 fn main() {
     let _ = Some(0).map(|x| {
@@ -197,3 +197,12 @@ fn main() {
         });
     }
 }
+
+#[rustfmt::skip]
+fn layout_check() {
+    if let Some(x) = Some(1).map(|x| { println!("{x}"); //~ manual_inspect
+        // Do not collapse code into this comment
+        x }) {
+        println!("{x}");
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_inspect.stderr b/src/tools/clippy/tests/ui/manual_inspect.stderr
index 510325d2baa..eb98f9f5995 100644
--- a/src/tools/clippy/tests/ui/manual_inspect.stderr
+++ b/src/tools/clippy/tests/ui/manual_inspect.stderr
@@ -98,7 +98,7 @@ LL |         if x.is_empty() {
 LL |             let _ = || {
 LL ~                 let _x = x;
 LL |             };
-LL ~             return;
+LL ~             return ;
 LL |         }
 LL ~         println!("test");
    |
@@ -187,5 +187,18 @@ LL |
 LL ~             println!("{}", x);
    |
 
-error: aborting due to 13 previous errors
+error: using `map` over `inspect`
+  --> tests/ui/manual_inspect.rs:203:30
+   |
+LL |     if let Some(x) = Some(1).map(|x| { println!("{x}");
+   |                              ^^^
+   |
+help: try
+   |
+LL ~     if let Some(x) = Some(1).inspect(|&x| { println!("{x}");
+LL |         // Do not collapse code into this comment
+LL ~          }) {
+   |
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed b/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed
index 6f29d76bd21..8a1ab785dfb 100644
--- a/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed
+++ b/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed
@@ -1,4 +1,17 @@
 #![warn(clippy::manual_is_power_of_two)]
+#![allow(clippy::precedence)]
+
+macro_rules! binop {
+    ($a: expr, equal, $b: expr) => {
+        $a == $b
+    };
+    ($a: expr, and, $b: expr) => {
+        $a & $b
+    };
+    ($a: expr, minus, $b: expr) => {
+        $a - $b
+    };
+}
 
 fn main() {
     let a = 16_u64;
@@ -7,6 +20,8 @@ fn main() {
     //~^ manual_is_power_of_two
     let _ = a.is_power_of_two();
     //~^ manual_is_power_of_two
+    let _ = a.is_power_of_two();
+    //~^ manual_is_power_of_two
 
     // Test different orders of expression
     let _ = a.is_power_of_two();
@@ -23,4 +38,23 @@ fn main() {
     // is_power_of_two only works for unsigned integers
     let _ = b.count_ones() == 1;
     let _ = b & (b - 1) == 0;
+
+    let i: i32 = 3;
+    let _ = (i as u32).is_power_of_two();
+    //~^ manual_is_power_of_two
+
+    let _ = binop!(a.count_ones(), equal, 1);
+    let _ = binop!(a, and, a - 1) == 0;
+    let _ = a & binop!(a, minus, 1) == 0;
+}
+
+#[clippy::msrv = "1.31"]
+const fn low_msrv(a: u32) -> bool {
+    a & (a - 1) == 0
+}
+
+#[clippy::msrv = "1.32"]
+const fn high_msrv(a: u32) -> bool {
+    a.is_power_of_two()
+    //~^ manual_is_power_of_two
 }
diff --git a/src/tools/clippy/tests/ui/manual_is_power_of_two.rs b/src/tools/clippy/tests/ui/manual_is_power_of_two.rs
index 0c44d7a660b..57a3b05e033 100644
--- a/src/tools/clippy/tests/ui/manual_is_power_of_two.rs
+++ b/src/tools/clippy/tests/ui/manual_is_power_of_two.rs
@@ -1,10 +1,25 @@
 #![warn(clippy::manual_is_power_of_two)]
+#![allow(clippy::precedence)]
+
+macro_rules! binop {
+    ($a: expr, equal, $b: expr) => {
+        $a == $b
+    };
+    ($a: expr, and, $b: expr) => {
+        $a & $b
+    };
+    ($a: expr, minus, $b: expr) => {
+        $a - $b
+    };
+}
 
 fn main() {
     let a = 16_u64;
 
     let _ = a.count_ones() == 1;
     //~^ manual_is_power_of_two
+    let _ = u64::count_ones(a) == 1;
+    //~^ manual_is_power_of_two
     let _ = a & (a - 1) == 0;
     //~^ manual_is_power_of_two
 
@@ -23,4 +38,23 @@ fn main() {
     // is_power_of_two only works for unsigned integers
     let _ = b.count_ones() == 1;
     let _ = b & (b - 1) == 0;
+
+    let i: i32 = 3;
+    let _ = i as u32 & (i as u32 - 1) == 0;
+    //~^ manual_is_power_of_two
+
+    let _ = binop!(a.count_ones(), equal, 1);
+    let _ = binop!(a, and, a - 1) == 0;
+    let _ = a & binop!(a, minus, 1) == 0;
+}
+
+#[clippy::msrv = "1.31"]
+const fn low_msrv(a: u32) -> bool {
+    a & (a - 1) == 0
+}
+
+#[clippy::msrv = "1.32"]
+const fn high_msrv(a: u32) -> bool {
+    a & (a - 1) == 0
+    //~^ manual_is_power_of_two
 }
diff --git a/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr b/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr
index ad12ee10565..5781a093d5f 100644
--- a/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr
+++ b/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr
@@ -1,5 +1,5 @@
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:6:13
+  --> tests/ui/manual_is_power_of_two.rs:19:13
    |
 LL |     let _ = a.count_ones() == 1;
    |             ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
@@ -8,34 +8,52 @@ LL |     let _ = a.count_ones() == 1;
    = help: to override `-D warnings` add `#[allow(clippy::manual_is_power_of_two)]`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:8:13
+  --> tests/ui/manual_is_power_of_two.rs:21:13
+   |
+LL |     let _ = u64::count_ones(a) == 1;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:23:13
    |
 LL |     let _ = a & (a - 1) == 0;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:12:13
+  --> tests/ui/manual_is_power_of_two.rs:27:13
    |
 LL |     let _ = 1 == a.count_ones();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:14:13
+  --> tests/ui/manual_is_power_of_two.rs:29:13
    |
 LL |     let _ = (a - 1) & a == 0;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:16:13
+  --> tests/ui/manual_is_power_of_two.rs:31:13
    |
 LL |     let _ = 0 == a & (a - 1);
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
 error: manually reimplementing `is_power_of_two`
-  --> tests/ui/manual_is_power_of_two.rs:18:13
+  --> tests/ui/manual_is_power_of_two.rs:33:13
    |
 LL |     let _ = 0 == (a - 1) & a;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
-error: aborting due to 6 previous errors
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:43:13
+   |
+LL |     let _ = i as u32 & (i as u32 - 1) == 0;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `(i as u32).is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:58:5
+   |
+LL |     a & (a - 1) == 0
+   |     ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs
index 9477d0d795d..40133748d45 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option.rs
@@ -101,7 +101,7 @@ fn main() {
 
     match &mut Some(String::new()) {
         //~^ manual_map
-        Some(ref x) => Some(x.len()),
+        &mut Some(ref x) => Some(x.len()),
         None => None,
     };
 
diff --git a/src/tools/clippy/tests/ui/manual_map_option.stderr b/src/tools/clippy/tests/ui/manual_map_option.stderr
index 8f9bce4c265..486379c1e5f 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.stderr
+++ b/src/tools/clippy/tests/ui/manual_map_option.stderr
@@ -127,7 +127,7 @@ error: manual implementation of `Option::map`
    |
 LL | /     match &mut Some(String::new()) {
 LL | |
-LL | |         Some(ref x) => Some(x.len()),
+LL | |         &mut Some(ref x) => Some(x.len()),
 LL | |         None => None,
 LL | |     };
    | |_____^ help: try: `Some(String::new()).as_ref().map(|x| x.len())`
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.fixed b/src/tools/clippy/tests/ui/manual_map_option_2.fixed
index d698cc74ea6..206c6d5d077 100644
--- a/src/tools/clippy/tests/ui/manual_map_option_2.fixed
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.fixed
@@ -115,7 +115,7 @@ mod with_type_coercion {
     fn with_fn_ret(s: &Option<String>) -> Option<(String, &str)> {
         // Don't lint, `map` doesn't work as the return type is adjusted.
         match s {
-            Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
+            Some(x) => Some({ if let Some(s) = s { (x.clone(), s) } else { panic!() } }),
             None => None,
         }
     }
@@ -124,7 +124,7 @@ mod with_type_coercion {
         if true {
             // Don't lint, `map` doesn't work as the return type is adjusted.
             return match s {
-                Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
+                Some(x) => Some({ if let Some(s) = s { (x.clone(), s) } else { panic!() } }),
                 None => None,
             };
         }
@@ -136,7 +136,7 @@ mod with_type_coercion {
         let x: Option<(String, &'a str)>;
         x = {
             match s {
-                Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
+                Some(x) => Some({ if let Some(s) = s { (x.clone(), s) } else { panic!() } }),
                 None => None,
             }
         };
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.rs b/src/tools/clippy/tests/ui/manual_map_option_2.rs
index 069c2381f6d..a47dc950760 100644
--- a/src/tools/clippy/tests/ui/manual_map_option_2.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.rs
@@ -143,7 +143,7 @@ mod with_type_coercion {
     fn with_fn_ret(s: &Option<String>) -> Option<(String, &str)> {
         // Don't lint, `map` doesn't work as the return type is adjusted.
         match s {
-            Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
+            Some(x) => Some({ if let Some(s) = s { (x.clone(), s) } else { panic!() } }),
             None => None,
         }
     }
@@ -152,7 +152,7 @@ mod with_type_coercion {
         if true {
             // Don't lint, `map` doesn't work as the return type is adjusted.
             return match s {
-                Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
+                Some(x) => Some({ if let Some(s) = s { (x.clone(), s) } else { panic!() } }),
                 None => None,
             };
         }
@@ -164,7 +164,7 @@ mod with_type_coercion {
         let x: Option<(String, &'a str)>;
         x = {
             match s {
-                Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
+                Some(x) => Some({ if let Some(s) = s { (x.clone(), s) } else { panic!() } }),
                 None => None,
             }
         };
diff --git a/src/tools/clippy/tests/ui/manual_ok_err.fixed b/src/tools/clippy/tests/ui/manual_ok_err.fixed
index bc169b64be9..e6f799aa58d 100644
--- a/src/tools/clippy/tests/ui/manual_ok_err.fixed
+++ b/src/tools/clippy/tests/ui/manual_ok_err.fixed
@@ -80,6 +80,11 @@ fn no_lint() {
         Ok(3) => None,
         Ok(v) => Some(v),
     };
+
+    let _ = match funcall() {
+        Ok(v @ 1..) => Some(v),
+        _ => None,
+    };
 }
 
 const fn cf(x: Result<u32, &'static str>) -> Option<u32> {
diff --git a/src/tools/clippy/tests/ui/manual_ok_err.rs b/src/tools/clippy/tests/ui/manual_ok_err.rs
index 03c730d4b4e..972b2c41ee7 100644
--- a/src/tools/clippy/tests/ui/manual_ok_err.rs
+++ b/src/tools/clippy/tests/ui/manual_ok_err.rs
@@ -116,6 +116,11 @@ fn no_lint() {
         Ok(3) => None,
         Ok(v) => Some(v),
     };
+
+    let _ = match funcall() {
+        Ok(v @ 1..) => Some(v),
+        _ => None,
+    };
 }
 
 const fn cf(x: Result<u32, &'static str>) -> Option<u32> {
diff --git a/src/tools/clippy/tests/ui/manual_ok_err.stderr b/src/tools/clippy/tests/ui/manual_ok_err.stderr
index 13fceacda10..040e170f397 100644
--- a/src/tools/clippy/tests/ui/manual_ok_err.stderr
+++ b/src/tools/clippy/tests/ui/manual_ok_err.stderr
@@ -94,7 +94,7 @@ LL | |     };
    | |_____^ help: replace with: `(-S).ok()`
 
 error: manual implementation of `ok`
-  --> tests/ui/manual_ok_err.rs:132:12
+  --> tests/ui/manual_ok_err.rs:137:12
    |
 LL |       } else if let Ok(n) = "1".parse::<u8>() {
    |  ____________^
diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed
index ca8491131c0..016f520e216 100644
--- a/src/tools/clippy/tests/ui/manual_retain.fixed
+++ b/src/tools/clippy/tests/ui/manual_retain.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::manual_retain)]
-#![allow(unused, clippy::redundant_clone)]
+#![allow(unused, clippy::needless_borrowed_reference, clippy::redundant_clone)]
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
 
 fn main() {
@@ -31,7 +31,7 @@ fn binary_heap_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]);
-    tuples.retain(|(ref x, ref y)| *x == 0);
+    tuples.retain(|&(ref x, ref y)| *x == 0);
     //~^ manual_retain
     tuples.retain(|(x, y)| *x == 0);
     //~^ manual_retain
@@ -99,7 +99,7 @@ fn btree_set_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]);
-    tuples.retain(|(ref x, ref y)| *x == 0);
+    tuples.retain(|&(ref x, ref y)| *x == 0);
     //~^ manual_retain
     tuples.retain(|(x, y)| *x == 0);
     //~^ manual_retain
@@ -166,7 +166,7 @@ fn hash_set_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]);
-    tuples.retain(|(ref x, ref y)| *x == 0);
+    tuples.retain(|&(ref x, ref y)| *x == 0);
     //~^ manual_retain
     tuples.retain(|(x, y)| *x == 0);
     //~^ manual_retain
@@ -220,7 +220,7 @@ fn vec_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = vec![(0, 1), (1, 2), (2, 3)];
-    tuples.retain(|(ref x, ref y)| *x == 0);
+    tuples.retain(|&(ref x, ref y)| *x == 0);
     //~^ manual_retain
     tuples.retain(|(x, y)| *x == 0);
     //~^ manual_retain
diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs
index cd05a41f3f2..62f9b7b0595 100644
--- a/src/tools/clippy/tests/ui/manual_retain.rs
+++ b/src/tools/clippy/tests/ui/manual_retain.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::manual_retain)]
-#![allow(unused, clippy::redundant_clone)]
+#![allow(unused, clippy::needless_borrowed_reference, clippy::redundant_clone)]
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
 
 fn main() {
@@ -31,7 +31,7 @@ fn binary_heap_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]);
-    tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
+    tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
     //~^ manual_retain
     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
     //~^ manual_retain
@@ -103,7 +103,7 @@ fn btree_set_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]);
-    tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
+    tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
     //~^ manual_retain
     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
     //~^ manual_retain
@@ -174,7 +174,7 @@ fn hash_set_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]);
-    tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
+    tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
     //~^ manual_retain
     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
     //~^ manual_retain
@@ -228,7 +228,7 @@ fn vec_retain() {
 
     // Do lint, because we use pattern matching
     let mut tuples = vec![(0, 1), (1, 2), (2, 3)];
-    tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
+    tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
     //~^ manual_retain
     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
     //~^ manual_retain
diff --git a/src/tools/clippy/tests/ui/manual_retain.stderr b/src/tools/clippy/tests/ui/manual_retain.stderr
index 2f81647dd8b..e7d3e34b5d7 100644
--- a/src/tools/clippy/tests/ui/manual_retain.stderr
+++ b/src/tools/clippy/tests/ui/manual_retain.stderr
@@ -22,8 +22,8 @@ LL |     binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().colle
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:34:5
    |
-LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
+LL |     tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:36:5
@@ -74,8 +74,8 @@ LL |     btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:106:5
    |
-LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
+LL |     tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:108:5
@@ -126,8 +126,8 @@ LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:177:5
    |
-LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
+LL |     tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:179:5
@@ -162,8 +162,8 @@ LL |     vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:231:5
    |
-LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
+LL |     tuples = tuples.iter().filter(|&&(ref x, ref y)| *x == 0).copied().collect();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|&(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
   --> tests/ui/manual_retain.rs:233:5
diff --git a/src/tools/clippy/tests/ui/manual_strip_fixable.fixed b/src/tools/clippy/tests/ui/manual_strip_fixable.fixed
index 75a3f1645de..b59e3719d95 100644
--- a/src/tools/clippy/tests/ui/manual_strip_fixable.fixed
+++ b/src/tools/clippy/tests/ui/manual_strip_fixable.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::manual_strip)]
+#![allow(clippy::uninlined_format_args)]
 
 fn main() {
     let s = "abc";
diff --git a/src/tools/clippy/tests/ui/manual_strip_fixable.rs b/src/tools/clippy/tests/ui/manual_strip_fixable.rs
index 5080068449e..4fb3a9bf007 100644
--- a/src/tools/clippy/tests/ui/manual_strip_fixable.rs
+++ b/src/tools/clippy/tests/ui/manual_strip_fixable.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::manual_strip)]
+#![allow(clippy::uninlined_format_args)]
 
 fn main() {
     let s = "abc";
diff --git a/src/tools/clippy/tests/ui/manual_strip_fixable.stderr b/src/tools/clippy/tests/ui/manual_strip_fixable.stderr
index 1c276e5d8fd..da8b0cd08f8 100644
--- a/src/tools/clippy/tests/ui/manual_strip_fixable.stderr
+++ b/src/tools/clippy/tests/ui/manual_strip_fixable.stderr
@@ -1,11 +1,11 @@
 error: stripping a prefix manually
-  --> tests/ui/manual_strip_fixable.rs:7:24
+  --> tests/ui/manual_strip_fixable.rs:8:24
    |
 LL |         let stripped = &s["ab".len()..];
    |                        ^^^^^^^^^^^^^^^^
    |
 note: the prefix was tested here
-  --> tests/ui/manual_strip_fixable.rs:6:5
+  --> tests/ui/manual_strip_fixable.rs:7:5
    |
 LL |     if s.starts_with("ab") {
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -19,13 +19,13 @@ LL ~         println!("{stripped}{}", stripped);
    |
 
 error: stripping a suffix manually
-  --> tests/ui/manual_strip_fixable.rs:13:24
+  --> tests/ui/manual_strip_fixable.rs:14:24
    |
 LL |         let stripped = &s[..s.len() - "bc".len()];
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the suffix was tested here
-  --> tests/ui/manual_strip_fixable.rs:12:5
+  --> tests/ui/manual_strip_fixable.rs:13:5
    |
 LL |     if s.ends_with("bc") {
    |     ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
index 07e4bdd483a..e12287a7093 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
@@ -18,11 +18,9 @@ fn option_unwrap_or() {
 
     // multiline case
     #[rustfmt::skip]
-    Some(1).unwrap_or({
-        42 + 42
-            + 42 + 42 + 42
-            + 42 + 42 + 42
-    });
+    Some(1).unwrap_or(42 + 42
+    + 42 + 42 + 42
+    + 42 + 42 + 42);
 
     // string case
     Some("Bob").unwrap_or("Alice");
@@ -125,11 +123,9 @@ fn result_unwrap_or() {
 
     // multiline case
     #[rustfmt::skip]
-    Ok::<i32, &str>(1).unwrap_or({
-        42 + 42
-            + 42 + 42 + 42
-            + 42 + 42 + 42
-    });
+    Ok::<i32, &str>(1).unwrap_or(42 + 42
+    + 42 + 42 + 42
+    + 42 + 42 + 42);
 
     // string case
     Ok::<&str, &str>("Bob").unwrap_or("Alice");
@@ -159,11 +155,7 @@ fn result_unwrap_or() {
         Ok(s) => s,
         Err(s) => s,
     };
-    // could lint, but unused_variables takes care of it
-    match Ok::<&str, &str>("Alice") {
-        Ok(s) => s,
-        Err(s) => "Bob",
-    };
+    Ok::<&str, &str>("Alice").unwrap_or("Bob");
 
     Ok::<i32, i32>(1).unwrap_or(42);
 
@@ -250,4 +242,12 @@ mod issue_13018 {
     }
 }
 
+fn implicit_deref(v: Vec<String>) {
+    let _ = if let Some(s) = v.first() { s } else { "" };
+}
+
+fn allowed_manual_unwrap_or_zero() -> u32 {
+    Some(42).unwrap_or(0)
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
index c88b6f95da6..53cffcab5b5 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
@@ -216,8 +216,8 @@ fn result_unwrap_or() {
         Ok(s) => s,
         Err(s) => s,
     };
-    // could lint, but unused_variables takes care of it
     match Ok::<&str, &str>("Alice") {
+        //~^ manual_unwrap_or
         Ok(s) => s,
         Err(s) => "Bob",
     };
@@ -316,4 +316,17 @@ mod issue_13018 {
     }
 }
 
+fn implicit_deref(v: Vec<String>) {
+    let _ = if let Some(s) = v.first() { s } else { "" };
+}
+
+fn allowed_manual_unwrap_or_zero() -> u32 {
+    if let Some(x) = Some(42) {
+        //~^ manual_unwrap_or
+        x
+    } else {
+        0
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
index a5deb55786e..320e895fb82 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
@@ -44,11 +44,9 @@ LL | |     };
    |
 help: replace with
    |
-LL ~     Some(1).unwrap_or({
-LL +         42 + 42
-LL +             + 42 + 42 + 42
-LL +             + 42 + 42 + 42
-LL ~     });
+LL ~     Some(1).unwrap_or(42 + 42
+LL +     + 42 + 42 + 42
+LL ~     + 42 + 42 + 42);
    |
 
 error: this pattern reimplements `Option::unwrap_or`
@@ -145,11 +143,9 @@ LL | |     };
    |
 help: replace with
    |
-LL ~     Ok::<i32, &str>(1).unwrap_or({
-LL +         42 + 42
-LL +             + 42 + 42 + 42
-LL +             + 42 + 42 + 42
-LL ~     });
+LL ~     Ok::<i32, &str>(1).unwrap_or(42 + 42
+LL +     + 42 + 42 + 42
+LL ~     + 42 + 42 + 42);
    |
 
 error: this pattern reimplements `Result::unwrap_or`
@@ -163,6 +159,16 @@ LL | |     };
    | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")`
 
 error: this pattern reimplements `Result::unwrap_or`
+  --> tests/ui/manual_unwrap_or.rs:219:5
+   |
+LL | /     match Ok::<&str, &str>("Alice") {
+LL | |
+LL | |         Ok(s) => s,
+LL | |         Err(s) => "Bob",
+LL | |     };
+   | |_____^ help: replace with: `Ok::<&str, &str>("Alice").unwrap_or("Bob")`
+
+error: this pattern reimplements `Result::unwrap_or`
   --> tests/ui/manual_unwrap_or.rs:225:5
    |
 LL | /     if let Ok(x) = Ok::<i32, i32>(1) {
@@ -184,5 +190,16 @@ LL | |             None => 0,
 LL | |         };
    | |_________^ help: replace with: `some_macro!().unwrap_or(0)`
 
-error: aborting due to 16 previous errors
+error: this pattern reimplements `Option::unwrap_or`
+  --> tests/ui/manual_unwrap_or.rs:324:5
+   |
+LL | /     if let Some(x) = Some(42) {
+LL | |
+LL | |         x
+LL | |     } else {
+LL | |         0
+LL | |     }
+   | |_____^ help: replace with: `Some(42).unwrap_or(0)`
+
+error: aborting due to 18 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 832376fa5af..9dae9fcae07 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::manual_unwrap_or_default)]
-#![allow(clippy::unnecessary_literal_unwrap, clippy::manual_unwrap_or)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
     let x: Option<Vec<String>> = None;
@@ -36,10 +36,12 @@ fn main() {
 
 // Issue #12531
 unsafe fn no_deref_ptr(a: Option<i32>, b: *const Option<i32>) -> i32 {
-    match a {
-        // `*b` being correct depends on `a == Some(_)`
-        Some(_) => (*b).unwrap_or_default(),
-        _ => 0,
+    unsafe {
+        match a {
+            // `*b` being correct depends on `a == Some(_)`
+            Some(_) => (*b).unwrap_or_default(),
+            _ => 0,
+        }
     }
 }
 
@@ -99,3 +101,8 @@ fn issue_12928() {
     let y = if let Some(Y(a, _)) = x { a } else { 0 };
     let y = if let Some(Y(a, ..)) = x { a } else { 0 };
 }
+
+// For symetry with `manual_unwrap_or` test
+fn allowed_manual_unwrap_or_zero() -> u32 {
+    Some(42).unwrap_or_default()
+}
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 bedb3f0af0f..539d7a8bbae 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::manual_unwrap_or_default)]
-#![allow(clippy::unnecessary_literal_unwrap, clippy::manual_unwrap_or)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
     let x: Option<Vec<String>> = None;
@@ -68,14 +68,16 @@ fn main() {
 
 // Issue #12531
 unsafe fn no_deref_ptr(a: Option<i32>, b: *const Option<i32>) -> i32 {
-    match a {
-        // `*b` being correct depends on `a == Some(_)`
-        Some(_) => match *b {
-            //~^ manual_unwrap_or_default
-            Some(v) => v,
+    unsafe {
+        match a {
+            // `*b` being correct depends on `a == Some(_)`
+            Some(_) => match *b {
+                //~^ manual_unwrap_or_default
+                Some(v) => v,
+                _ => 0,
+            },
             _ => 0,
-        },
-        _ => 0,
+        }
     }
 }
 
@@ -135,3 +137,13 @@ fn issue_12928() {
     let y = if let Some(Y(a, _)) = x { a } else { 0 };
     let y = if let Some(Y(a, ..)) = x { a } else { 0 };
 }
+
+// For symetry with `manual_unwrap_or` test
+fn allowed_manual_unwrap_or_zero() -> u32 {
+    if let Some(x) = Some(42) {
+        //~^ manual_unwrap_or_default
+        x
+    } else {
+        0
+    }
+}
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 ca9aa159152..e8f38a2e389 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
@@ -76,15 +76,26 @@ 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:73:20
+  --> tests/ui/manual_unwrap_or_default.rs:74:24
    |
-LL |           Some(_) => match *b {
-   |  ____________________^
+LL |               Some(_) => match *b {
+   |  ________________________^
 LL | |
-LL | |             Some(v) => v,
-LL | |             _ => 0,
-LL | |         },
-   | |_________^ help: replace it with: `(*b).unwrap_or_default()`
+LL | |                 Some(v) => v,
+LL | |                 _ => 0,
+LL | |             },
+   | |_____________^ help: replace it with: `(*b).unwrap_or_default()`
 
-error: aborting due to 8 previous errors
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:143:5
+   |
+LL | /     if let Some(x) = Some(42) {
+LL | |
+LL | |         x
+LL | |     } else {
+LL | |         0
+LL | |     }
+   | |_____^ help: replace it with: `Some(42).unwrap_or_default()`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index 948fec970d8..f8379ed23c5 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -1,10 +1,11 @@
-#![warn(clippy::all, clippy::pedantic)]
-#![allow(clippy::let_underscore_untyped)]
-#![allow(clippy::missing_docs_in_private_items)]
-#![allow(clippy::map_identity)]
-#![allow(clippy::redundant_closure)]
-#![allow(clippy::unnecessary_wraps)]
 #![feature(result_flattening)]
+#![allow(
+    clippy::let_underscore_untyped,
+    clippy::missing_docs_in_private_items,
+    clippy::map_identity,
+    clippy::redundant_closure,
+    clippy::unnecessary_wraps
+)]
 
 fn main() {
     // mapping to Option on Iterator
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.rs b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
index 67a91ab9414..040a9ca85f6 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
@@ -1,10 +1,11 @@
-#![warn(clippy::all, clippy::pedantic)]
-#![allow(clippy::let_underscore_untyped)]
-#![allow(clippy::missing_docs_in_private_items)]
-#![allow(clippy::map_identity)]
-#![allow(clippy::redundant_closure)]
-#![allow(clippy::unnecessary_wraps)]
 #![feature(result_flattening)]
+#![allow(
+    clippy::let_underscore_untyped,
+    clippy::missing_docs_in_private_items,
+    clippy::map_identity,
+    clippy::redundant_closure,
+    clippy::unnecessary_wraps
+)]
 
 fn main() {
     // mapping to Option on Iterator
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index 05d4d9a6ad8..fe68eb7e4ab 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:16:47
+  --> tests/ui/map_flatten_fixable.rs:17:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -8,43 +8,43 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = help: to override `-D warnings` add `#[allow(clippy::map_flatten)]`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:18:47
+  --> tests/ui/map_flatten_fixable.rs:19:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:20:47
+  --> tests/ui/map_flatten_fixable.rs:21:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:22:47
+  --> tests/ui/map_flatten_fixable.rs:23:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:26:47
+  --> tests/ui/map_flatten_fixable.rs:27:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
-  --> tests/ui/map_flatten_fixable.rs:30:40
+  --> tests/ui/map_flatten_fixable.rs:31:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
-  --> tests/ui/map_flatten_fixable.rs:34:42
+  --> tests/ui/map_flatten_fixable.rs:35:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
    |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:44:10
+  --> tests/ui/map_flatten_fixable.rs:45:10
    |
 LL |           .map(|n| match n {
    |  __________^
@@ -74,7 +74,7 @@ LL ~         });
    |
 
 error: called `map(..).flatten()` on `Option`
-  --> tests/ui/map_flatten_fixable.rs:65:10
+  --> tests/ui/map_flatten_fixable.rs:66:10
    |
 LL |           .map(|_| {
    |  __________^
diff --git a/src/tools/clippy/tests/ui/match_on_vec_items.rs b/src/tools/clippy/tests/ui/match_on_vec_items.rs
deleted file mode 100644
index f3174ec9734..00000000000
--- a/src/tools/clippy/tests/ui/match_on_vec_items.rs
+++ /dev/null
@@ -1,161 +0,0 @@
-#![warn(clippy::match_on_vec_items)]
-#![allow(clippy::redundant_at_rest_pattern, clippy::useless_vec)]
-//@no-rustfix
-fn match_with_wildcard() {
-    let arr = vec![0, 1, 2, 3];
-    let range = 1..3;
-    let idx = 1;
-
-    // Lint, may panic
-    match arr[idx] {
-        //~^ match_on_vec_items
-        0 => println!("0"),
-        1 => println!("1"),
-        _ => {},
-    }
-
-    // Lint, may panic
-    match arr[range] {
-        //~^ match_on_vec_items
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        _ => {},
-    }
-}
-
-fn match_without_wildcard() {
-    let arr = vec![0, 1, 2, 3];
-    let range = 1..3;
-    let idx = 2;
-
-    // Lint, may panic
-    match arr[idx] {
-        //~^ match_on_vec_items
-        0 => println!("0"),
-        1 => println!("1"),
-        num => {},
-    }
-
-    // Lint, may panic
-    match arr[range] {
-        //~^ match_on_vec_items
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        [ref sub @ ..] => {},
-    }
-}
-
-fn match_wildcard_and_action() {
-    let arr = vec![0, 1, 2, 3];
-    let range = 1..3;
-    let idx = 3;
-
-    // Lint, may panic
-    match arr[idx] {
-        //~^ match_on_vec_items
-        0 => println!("0"),
-        1 => println!("1"),
-        _ => println!("Hello, World!"),
-    }
-
-    // Lint, may panic
-    match arr[range] {
-        //~^ match_on_vec_items
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        _ => println!("Hello, World!"),
-    }
-}
-
-fn match_vec_ref() {
-    let arr = &vec![0, 1, 2, 3];
-    let range = 1..3;
-    let idx = 3;
-
-    // Lint, may panic
-    match arr[idx] {
-        //~^ match_on_vec_items
-        0 => println!("0"),
-        1 => println!("1"),
-        _ => {},
-    }
-
-    // Lint, may panic
-    match arr[range] {
-        //~^ match_on_vec_items
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        _ => {},
-    }
-}
-
-fn match_with_get() {
-    let arr = vec![0, 1, 2, 3];
-    let range = 1..3;
-    let idx = 3;
-
-    // Ok
-    match arr.get(idx) {
-        Some(0) => println!("0"),
-        Some(1) => println!("1"),
-        _ => {},
-    }
-
-    // Ok
-    match arr.get(range) {
-        Some(&[0, 1]) => println!("0 1"),
-        Some(&[1, 2]) => println!("1 2"),
-        _ => {},
-    }
-}
-
-fn match_with_array() {
-    let arr = [0, 1, 2, 3];
-    let range = 1..3;
-    let idx = 3;
-
-    // Ok
-    match arr[idx] {
-        0 => println!("0"),
-        1 => println!("1"),
-        _ => {},
-    }
-
-    // Ok
-    match arr[range] {
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        _ => {},
-    }
-}
-
-fn match_with_endless_range() {
-    let arr = vec![0, 1, 2, 3];
-    let range = ..;
-
-    // Ok
-    match arr[range] {
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        [0, 1, 2, 3] => println!("0, 1, 2, 3"),
-        _ => {},
-    }
-
-    // Ok
-    match arr[..] {
-        [0, 1] => println!("0 1"),
-        [1, 2] => println!("1 2"),
-        [0, 1, 2, 3] => println!("0, 1, 2, 3"),
-        _ => {},
-    }
-}
-
-fn main() {
-    match_with_wildcard();
-    match_without_wildcard();
-    match_wildcard_and_action();
-    match_vec_ref();
-    match_with_get();
-    match_with_array();
-    match_with_endless_range();
-}
diff --git a/src/tools/clippy/tests/ui/match_on_vec_items.stderr b/src/tools/clippy/tests/ui/match_on_vec_items.stderr
deleted file mode 100644
index ae79e1305f7..00000000000
--- a/src/tools/clippy/tests/ui/match_on_vec_items.stderr
+++ /dev/null
@@ -1,53 +0,0 @@
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:10:11
-   |
-LL |     match arr[idx] {
-   |           ^^^^^^^^ help: try: `arr.get(idx)`
-   |
-   = note: `-D clippy::match-on-vec-items` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::match_on_vec_items)]`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:18:11
-   |
-LL |     match arr[range] {
-   |           ^^^^^^^^^^ help: try: `arr.get(range)`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:32:11
-   |
-LL |     match arr[idx] {
-   |           ^^^^^^^^ help: try: `arr.get(idx)`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:40:11
-   |
-LL |     match arr[range] {
-   |           ^^^^^^^^^^ help: try: `arr.get(range)`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:54:11
-   |
-LL |     match arr[idx] {
-   |           ^^^^^^^^ help: try: `arr.get(idx)`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:62:11
-   |
-LL |     match arr[range] {
-   |           ^^^^^^^^^^ help: try: `arr.get(range)`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:76:11
-   |
-LL |     match arr[idx] {
-   |           ^^^^^^^^ help: try: `arr.get(idx)`
-
-error: indexing into a vector may panic
-  --> tests/ui/match_on_vec_items.rs:84:11
-   |
-LL |     match arr[range] {
-   |           ^^^^^^^^^^ help: try: `arr.get(range)`
-
-error: aborting due to 8 previous errors
-
diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed
index 3a3eee4c958..bdf39796ebf 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding.fixed
@@ -171,3 +171,20 @@ fn issue_10447() -> usize {
 
     2
 }
+
+fn issue14634() {
+    macro_rules! id {
+        ($i:ident) => {
+            $i
+        };
+    }
+    dbg!(3);
+    println!("here");
+    //~^^^ match_single_binding
+    let id!(a) = dbg!(3);
+    println!("found {a}");
+    //~^^^ match_single_binding
+    let id!(b) = dbg!(3);
+    let id!(_a) = dbg!(b + 1);
+    //~^^^ match_single_binding
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs
index ada51254c6c..419ff95d873 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding.rs
@@ -229,3 +229,23 @@ fn issue_10447() -> usize {
 
     2
 }
+
+fn issue14634() {
+    macro_rules! id {
+        ($i:ident) => {
+            $i
+        };
+    }
+    match dbg!(3) {
+        _ => println!("here"),
+    }
+    //~^^^ match_single_binding
+    match dbg!(3) {
+        id!(a) => println!("found {a}"),
+    }
+    //~^^^ match_single_binding
+    let id!(_a) = match dbg!(3) {
+        id!(b) => dbg!(b + 1),
+    };
+    //~^^^ match_single_binding
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr
index 7e1ec32dac2..bdd0134a5f1 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.stderr
+++ b/src/tools/clippy/tests/ui/match_single_binding.stderr
@@ -336,5 +336,47 @@ LL | |             _ => println!("1"),
 LL | |         },
    | |_________^ help: consider using the match body instead: `println!("1")`
 
-error: aborting due to 24 previous errors
+error: this match could be replaced by its scrutinee and body
+  --> tests/ui/match_single_binding.rs:239:5
+   |
+LL | /     match dbg!(3) {
+LL | |         _ => println!("here"),
+LL | |     }
+   | |_____^
+   |
+help: consider using the scrutinee and body instead
+   |
+LL ~     dbg!(3);
+LL +     println!("here");
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:243:5
+   |
+LL | /     match dbg!(3) {
+LL | |         id!(a) => println!("found {a}"),
+LL | |     }
+   | |_____^
+   |
+help: consider using a `let` statement
+   |
+LL ~     let id!(a) = dbg!(3);
+LL +     println!("found {a}");
+   |
+
+error: this match could be written as a `let` statement
+  --> tests/ui/match_single_binding.rs:247:5
+   |
+LL | /     let id!(_a) = match dbg!(3) {
+LL | |         id!(b) => dbg!(b + 1),
+LL | |     };
+   | |______^
+   |
+help: consider using a `let` statement
+   |
+LL ~     let id!(b) = dbg!(3);
+LL +     let id!(_a) = dbg!(b + 1);
+   |
+
+error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index 76b0d131dd4..2f4004181f6 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -1,6 +1,5 @@
 //@aux-build:option_helpers.rs
 
-#![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::disallowed_names,
     clippy::default_trait_access,
@@ -19,8 +18,7 @@
     clippy::wrong_self_convention,
     clippy::unused_async,
     clippy::unused_self,
-    clippy::useless_vec,
-    unused
+    clippy::useless_vec
 )]
 
 #[macro_use]
diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr
index 353b999d7da..b226ce7c65d 100644
--- a/src/tools/clippy/tests/ui/methods.stderr
+++ b/src/tools/clippy/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> tests/ui/methods.rs:104:5
+  --> tests/ui/methods.rs:102:5
    |
 LL | /     fn new() -> i32 {
 LL | |
@@ -11,7 +11,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::new_ret_no_self)]`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> tests/ui/methods.rs:126:13
+  --> tests/ui/methods.rs:124:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/min_max.rs b/src/tools/clippy/tests/ui/min_max.rs
index f3eeb85f20e..ee19d3ff714 100644
--- a/src/tools/clippy/tests/ui/min_max.rs
+++ b/src/tools/clippy/tests/ui/min_max.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all)]
 #![allow(clippy::manual_clamp)]
 
 use std::cmp::{max as my_max, max, min as my_min, min};
diff --git a/src/tools/clippy/tests/ui/min_max.stderr b/src/tools/clippy/tests/ui/min_max.stderr
index 84b4d375455..87510a465a0 100644
--- a/src/tools/clippy/tests/ui/min_max.stderr
+++ b/src/tools/clippy/tests/ui/min_max.stderr
@@ -1,80 +1,79 @@
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:22:5
+  --> tests/ui/min_max.rs:21:5
    |
 LL |     min(1, max(3, x));
    |     ^^^^^^^^^^^^^^^^^
    |
-   = note: `-D clippy::min-max` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::min_max)]`
+   = note: `#[deny(clippy::min_max)]` on by default
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:25:5
+  --> tests/ui/min_max.rs:24:5
    |
 LL |     min(max(3, x), 1);
    |     ^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:28:5
+  --> tests/ui/min_max.rs:27:5
    |
 LL |     max(min(x, 1), 3);
    |     ^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:31:5
+  --> tests/ui/min_max.rs:30:5
    |
 LL |     max(3, min(x, 1));
    |     ^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:34:5
+  --> tests/ui/min_max.rs:33:5
    |
 LL |     my_max(3, my_min(x, 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:45:5
+  --> tests/ui/min_max.rs:44:5
    |
 LL |     min("Apple", max("Zoo", s));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:48:5
+  --> tests/ui/min_max.rs:47:5
    |
 LL |     max(min(s, "Apple"), "Zoo");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:54:5
+  --> tests/ui/min_max.rs:53:5
    |
 LL |     x.min(1).max(3);
    |     ^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:57:5
+  --> tests/ui/min_max.rs:56:5
    |
 LL |     x.max(3).min(1);
    |     ^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:60:5
+  --> tests/ui/min_max.rs:59:5
    |
 LL |     f.max(3f32).min(1f32);
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:67:5
+  --> tests/ui/min_max.rs:66:5
    |
 LL |     max(x.min(1), 3);
    |     ^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:72:5
+  --> tests/ui/min_max.rs:71:5
    |
 LL |     s.max("Zoo").min("Apple");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this `min`/`max` combination leads to constant result
-  --> tests/ui/min_max.rs:75:5
+  --> tests/ui/min_max.rs:74:5
    |
 LL |     s.min("Apple").max("Zoo");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/misnamed_getters.fixed b/src/tools/clippy/tests/ui/misnamed_getters.fixed
index cada5307b1c..bc123d1a40b 100644
--- a/src/tools/clippy/tests/ui/misnamed_getters.fixed
+++ b/src/tools/clippy/tests/ui/misnamed_getters.fixed
@@ -54,63 +54,63 @@ impl B {
     unsafe fn a(&self) -> &u8 {
         //~^ misnamed_getters
 
-        &self.a
+        unsafe { &self.a }
     }
     unsafe fn a_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.a
+        unsafe { &mut self.a }
     }
 
     unsafe fn b(self) -> u8 {
         //~^ misnamed_getters
 
-        self.b
+        unsafe { self.b }
     }
 
     unsafe fn b_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.b
+        unsafe { &mut self.b }
     }
 
     unsafe fn c(&self) -> &u8 {
-        &self.b
+        unsafe { &self.b }
     }
 
     unsafe fn c_mut(&mut self) -> &mut u8 {
-        &mut self.a
+        unsafe { &mut self.a }
     }
 
     unsafe fn a_unchecked(&self) -> &u8 {
         //~^ misnamed_getters
 
-        &self.a
+        unsafe { &self.a }
     }
     unsafe fn a_unchecked_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.a
+        unsafe { &mut self.a }
     }
 
     unsafe fn b_unchecked(self) -> u8 {
         //~^ misnamed_getters
 
-        self.b
+        unsafe { self.b }
     }
 
     unsafe fn b_unchecked_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.b
+        unsafe { &mut self.b }
     }
 
     unsafe fn c_unchecked(&self) -> &u8 {
-        &self.b
+        unsafe { &self.b }
     }
 
     unsafe fn c_unchecked_mut(&mut self) -> &mut u8 {
-        &mut self.a
+        unsafe { &mut self.a }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/misnamed_getters.rs b/src/tools/clippy/tests/ui/misnamed_getters.rs
index f529c56b471..6590101157c 100644
--- a/src/tools/clippy/tests/ui/misnamed_getters.rs
+++ b/src/tools/clippy/tests/ui/misnamed_getters.rs
@@ -54,63 +54,63 @@ impl B {
     unsafe fn a(&self) -> &u8 {
         //~^ misnamed_getters
 
-        &self.b
+        unsafe { &self.b }
     }
     unsafe fn a_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.b
+        unsafe { &mut self.b }
     }
 
     unsafe fn b(self) -> u8 {
         //~^ misnamed_getters
 
-        self.a
+        unsafe { self.a }
     }
 
     unsafe fn b_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.a
+        unsafe { &mut self.a }
     }
 
     unsafe fn c(&self) -> &u8 {
-        &self.b
+        unsafe { &self.b }
     }
 
     unsafe fn c_mut(&mut self) -> &mut u8 {
-        &mut self.a
+        unsafe { &mut self.a }
     }
 
     unsafe fn a_unchecked(&self) -> &u8 {
         //~^ misnamed_getters
 
-        &self.b
+        unsafe { &self.b }
     }
     unsafe fn a_unchecked_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.b
+        unsafe { &mut self.b }
     }
 
     unsafe fn b_unchecked(self) -> u8 {
         //~^ misnamed_getters
 
-        self.a
+        unsafe { self.a }
     }
 
     unsafe fn b_unchecked_mut(&mut self) -> &mut u8 {
         //~^ misnamed_getters
 
-        &mut self.a
+        unsafe { &mut self.a }
     }
 
     unsafe fn c_unchecked(&self) -> &u8 {
-        &self.b
+        unsafe { &self.b }
     }
 
     unsafe fn c_unchecked_mut(&mut self) -> &mut u8 {
-        &mut self.a
+        unsafe { &mut self.a }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/misnamed_getters.stderr b/src/tools/clippy/tests/ui/misnamed_getters.stderr
index 5dd1d75bcf6..aaf21cecb92 100644
--- a/src/tools/clippy/tests/ui/misnamed_getters.stderr
+++ b/src/tools/clippy/tests/ui/misnamed_getters.stderr
@@ -73,8 +73,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn a(&self) -> &u8 {
 LL | |
 LL | |
-LL | |         &self.b
-   | |         ------- help: consider using: `&self.a`
+LL | |         unsafe { &self.b }
+   | |                  ------- help: consider using: `&self.a`
 LL | |     }
    | |_____^
 
@@ -84,8 +84,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn a_mut(&mut self) -> &mut u8 {
 LL | |
 LL | |
-LL | |         &mut self.b
-   | |         ----------- help: consider using: `&mut self.a`
+LL | |         unsafe { &mut self.b }
+   | |                  ----------- help: consider using: `&mut self.a`
 LL | |     }
    | |_____^
 
@@ -95,8 +95,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn b(self) -> u8 {
 LL | |
 LL | |
-LL | |         self.a
-   | |         ------ help: consider using: `self.b`
+LL | |         unsafe { self.a }
+   | |                  ------ help: consider using: `self.b`
 LL | |     }
    | |_____^
 
@@ -106,8 +106,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn b_mut(&mut self) -> &mut u8 {
 LL | |
 LL | |
-LL | |         &mut self.a
-   | |         ----------- help: consider using: `&mut self.b`
+LL | |         unsafe { &mut self.a }
+   | |                  ----------- help: consider using: `&mut self.b`
 LL | |     }
    | |_____^
 
@@ -117,8 +117,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn a_unchecked(&self) -> &u8 {
 LL | |
 LL | |
-LL | |         &self.b
-   | |         ------- help: consider using: `&self.a`
+LL | |         unsafe { &self.b }
+   | |                  ------- help: consider using: `&self.a`
 LL | |     }
    | |_____^
 
@@ -128,8 +128,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn a_unchecked_mut(&mut self) -> &mut u8 {
 LL | |
 LL | |
-LL | |         &mut self.b
-   | |         ----------- help: consider using: `&mut self.a`
+LL | |         unsafe { &mut self.b }
+   | |                  ----------- help: consider using: `&mut self.a`
 LL | |     }
    | |_____^
 
@@ -139,8 +139,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn b_unchecked(self) -> u8 {
 LL | |
 LL | |
-LL | |         self.a
-   | |         ------ help: consider using: `self.b`
+LL | |         unsafe { self.a }
+   | |                  ------ help: consider using: `self.b`
 LL | |     }
    | |_____^
 
@@ -150,8 +150,8 @@ error: getter function appears to return the wrong field
 LL | /     unsafe fn b_unchecked_mut(&mut self) -> &mut u8 {
 LL | |
 LL | |
-LL | |         &mut self.a
-   | |         ----------- help: consider using: `&mut self.b`
+LL | |         unsafe { &mut self.a }
+   | |                  ----------- help: consider using: `&mut self.b`
 LL | |     }
    | |_____^
 
diff --git a/src/tools/clippy/tests/ui/misnamed_getters_2021.fixed b/src/tools/clippy/tests/ui/misnamed_getters_2021.fixed
new file mode 100644
index 00000000000..7112719a9f2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/misnamed_getters_2021.fixed
@@ -0,0 +1,24 @@
+//@edition: 2021
+#![allow(unused)]
+#![allow(clippy::struct_field_names)]
+#![warn(clippy::misnamed_getters)]
+
+// Edition 2021 specific check, where `unsafe` blocks are not required
+// inside `unsafe fn`.
+
+union B {
+    a: u8,
+    b: u8,
+}
+
+impl B {
+    unsafe fn a(&self) -> &u8 {
+        //~^ misnamed_getters
+
+        &self.a
+    }
+}
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/misnamed_getters_2021.rs b/src/tools/clippy/tests/ui/misnamed_getters_2021.rs
new file mode 100644
index 00000000000..19b5d086041
--- /dev/null
+++ b/src/tools/clippy/tests/ui/misnamed_getters_2021.rs
@@ -0,0 +1,24 @@
+//@edition: 2021
+#![allow(unused)]
+#![allow(clippy::struct_field_names)]
+#![warn(clippy::misnamed_getters)]
+
+// Edition 2021 specific check, where `unsafe` blocks are not required
+// inside `unsafe fn`.
+
+union B {
+    a: u8,
+    b: u8,
+}
+
+impl B {
+    unsafe fn a(&self) -> &u8 {
+        //~^ misnamed_getters
+
+        &self.b
+    }
+}
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/misnamed_getters_2021.stderr b/src/tools/clippy/tests/ui/misnamed_getters_2021.stderr
new file mode 100644
index 00000000000..5495e2e3733
--- /dev/null
+++ b/src/tools/clippy/tests/ui/misnamed_getters_2021.stderr
@@ -0,0 +1,16 @@
+error: getter function appears to return the wrong field
+  --> tests/ui/misnamed_getters_2021.rs:15:5
+   |
+LL | /     unsafe fn a(&self) -> &u8 {
+LL | |
+LL | |
+LL | |         &self.b
+   | |         ------- help: consider using: `&self.a`
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::misnamed-getters` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::misnamed_getters)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.fixed b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.fixed
index 3bbafe0bba3..9018f38100e 100644
--- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.fixed
+++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.fixed
@@ -139,4 +139,31 @@ fn issue11835(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) {
     let _ = v4[0] + v4[1] + v4[2];
 }
 
+// ok
+fn same_index_multiple_times(v1: &[u8]) {
+    let _ = v1[0] + v1[0];
+}
+
+// ok
+fn highest_index_first(v1: &[u8]) {
+    let _ = v1[2] + v1[1] + v1[0];
+}
+
+fn issue14255(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) {
+    assert!(v1.len() == 3);
+    assert_eq!(v2.len(), 4);
+    assert!(v3.len() == 3);
+    assert_eq!(4, v4.len());
+
+    let _ = v1[0] + v1[1] + v1[2];
+    //~^ missing_asserts_for_indexing
+
+    let _ = v2[0] + v2[1] + v2[2];
+
+    let _ = v3[0] + v3[1] + v3[2];
+    //~^ missing_asserts_for_indexing
+
+    let _ = v4[0] + v4[1] + v4[2];
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.rs b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.rs
index f8ea0173c13..44c5eddf3d8 100644
--- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.rs
+++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.rs
@@ -139,4 +139,31 @@ fn issue11835(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) {
     let _ = v4[0] + v4[1] + v4[2];
 }
 
+// ok
+fn same_index_multiple_times(v1: &[u8]) {
+    let _ = v1[0] + v1[0];
+}
+
+// ok
+fn highest_index_first(v1: &[u8]) {
+    let _ = v1[2] + v1[1] + v1[0];
+}
+
+fn issue14255(v1: &[u8], v2: &[u8], v3: &[u8], v4: &[u8]) {
+    assert_eq!(v1.len(), 2);
+    assert_eq!(v2.len(), 4);
+    assert_eq!(2, v3.len());
+    assert_eq!(4, v4.len());
+
+    let _ = v1[0] + v1[1] + v1[2];
+    //~^ missing_asserts_for_indexing
+
+    let _ = v2[0] + v2[1] + v2[2];
+
+    let _ = v3[0] + v3[1] + v3[2];
+    //~^ missing_asserts_for_indexing
+
+    let _ = v4[0] + v4[1] + v4[2];
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr
index 5d30920ccf5..b610de94b53 100644
--- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr
+++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr
@@ -301,5 +301,57 @@ LL |     let _ = v3[0] + v3[1] + v3[2];
    |                             ^^^^^
    = note: asserting the length before indexing will elide bounds checks
 
-error: aborting due to 11 previous errors
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> tests/ui/missing_asserts_for_indexing.rs:158:13
+   |
+LL |     assert_eq!(v1.len(), 2);
+   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() == 3)`
+...
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing.rs:158:13
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |             ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing.rs:158:21
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |                     ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing.rs:158:29
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |                             ^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+  --> tests/ui/missing_asserts_for_indexing.rs:163:13
+   |
+LL |     assert_eq!(2, v3.len());
+   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v3.len() == 3)`
+...
+LL |     let _ = v3[0] + v3[1] + v3[2];
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing.rs:163:13
+   |
+LL |     let _ = v3[0] + v3[1] + v3[2];
+   |             ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing.rs:163:21
+   |
+LL |     let _ = v3[0] + v3[1] + v3[2];
+   |                     ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing.rs:163:29
+   |
+LL |     let _ = v3[0] + v3[1] + v3[2];
+   |                             ^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs
index a520151a2dd..eb98969efa4 100644
--- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs
+++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs
@@ -73,4 +73,17 @@ pub fn issue11856(values: &[i32]) -> usize {
     ascending.len()
 }
 
+fn assert_after_indexing(v1: &[u8]) {
+    let _ = v1[1] + v1[2];
+    //~^ ERROR: indexing into a slice multiple times without an `assert`
+    assert!(v1.len() > 2);
+}
+
+fn issue14255(v1: &[u8]) {
+    assert_ne!(v1.len(), 2);
+
+    let _ = v1[0] + v1[1] + v1[2];
+    //~^ missing_asserts_for_indexing
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr
index 24109b052a8..a17ad023213 100644
--- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr
@@ -180,5 +180,48 @@ LL |     let _ = x[0] + x[1];
    |                    ^^^^
    = note: asserting the length before indexing will elide bounds checks
 
-error: aborting due to 8 previous errors
+error: indexing into a slice multiple times without an `assert`
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:77:13
+   |
+LL |     let _ = v1[1] + v1[2];
+   |             ^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 2);`
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:77:13
+   |
+LL |     let _ = v1[1] + v1[2];
+   |             ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:77:21
+   |
+LL |     let _ = v1[1] + v1[2];
+   |                     ^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: indexing into a slice multiple times without an `assert`
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:85:13
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 2);`
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:85:13
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |             ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:85:21
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |                     ^^^^^
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:85:29
+   |
+LL |     let _ = v1[0] + v1[1] + v1[2];
+   |                             ^^^^^
+   = note: asserting the length before indexing will elide bounds checks
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
index 10df44e73b8..65eb2d5938b 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -144,7 +144,7 @@ mod msrv {
 
     #[clippy::msrv = "1.62"]
     mod with_extern {
-        const extern "C" fn c() {}
+        const unsafe extern "C" fn c() {}
         //~^ missing_const_for_fn
 
         #[rustfmt::skip]
@@ -153,7 +153,7 @@ mod msrv {
         //~^ missing_const_for_fn
 
         // any item functions in extern block won't trigger this lint
-        extern "C" {
+        unsafe extern "C" {
             fn c_in_block();
         }
     }
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 bc44b34daef..3690d2f799f 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
@@ -144,7 +144,7 @@ mod msrv {
 
     #[clippy::msrv = "1.62"]
     mod with_extern {
-        extern "C" fn c() {}
+        unsafe extern "C" fn c() {}
         //~^ missing_const_for_fn
 
         #[rustfmt::skip]
@@ -153,7 +153,7 @@ mod msrv {
         //~^ missing_const_for_fn
 
         // any item functions in extern block won't trigger this lint
-        extern "C" {
+        unsafe extern "C" {
             fn c_in_block();
         }
     }
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 5df5a54ff52..10e07d12f5a 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
@@ -212,12 +212,12 @@ LL |     const fn union_access_can_be_const() {
 error: this could be a `const fn`
   --> tests/ui/missing_const_for_fn/could_be_const.rs:147:9
    |
-LL |         extern "C" fn c() {}
-   |         ^^^^^^^^^^^^^^^^^^^^
+LL |         unsafe extern "C" fn c() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: make the function `const`
    |
-LL |         const extern "C" fn c() {}
+LL |         const unsafe extern "C" fn c() {}
    |         +++++
 
 error: this could be a `const fn`
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.rs b/src/tools/clippy/tests/ui/missing_panics_doc.rs
index 95e361c5d55..ffdae8504f7 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.rs
@@ -151,6 +151,45 @@ pub fn debug_assertions() {
     debug_assert_ne!(1, 2);
 }
 
+pub fn partially_const<const N: usize>(n: usize) {
+    //~^ missing_panics_doc
+
+    const {
+        assert!(N > 5);
+    }
+
+    assert!(N > n);
+}
+
+pub fn expect_allow(i: Option<isize>) {
+    #[expect(clippy::missing_panics_doc)]
+    i.unwrap();
+
+    #[allow(clippy::missing_panics_doc)]
+    i.unwrap();
+}
+
+pub fn expect_allow_with_error(i: Option<isize>) {
+    //~^ missing_panics_doc
+
+    #[expect(clippy::missing_panics_doc)]
+    i.unwrap();
+
+    #[allow(clippy::missing_panics_doc)]
+    i.unwrap();
+
+    i.unwrap();
+}
+
+pub fn expect_after_error(x: Option<u32>, y: Option<u32>) {
+    //~^ missing_panics_doc
+
+    let x = x.unwrap();
+
+    #[expect(clippy::missing_panics_doc)]
+    let y = y.unwrap();
+}
+
 // all function must be triggered the lint.
 // `pub` is required, because the lint does not consider unreachable items
 pub mod issue10240 {
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
index a83e2fa367d..7f0acf8de9b 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
@@ -73,76 +73,112 @@ LL |     assert_ne!(x, 0);
    |     ^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> tests/ui/missing_panics_doc.rs:157:5
+  --> tests/ui/missing_panics_doc.rs:154:1
+   |
+LL | pub fn partially_const<const N: usize>(n: usize) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> tests/ui/missing_panics_doc.rs:161:5
+   |
+LL |     assert!(N > n);
+   |     ^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> tests/ui/missing_panics_doc.rs:172:1
+   |
+LL | pub fn expect_allow_with_error(i: Option<isize>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> tests/ui/missing_panics_doc.rs:181:5
+   |
+LL |     i.unwrap();
+   |     ^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> tests/ui/missing_panics_doc.rs:184:1
+   |
+LL | pub fn expect_after_error(x: Option<u32>, y: Option<u32>) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> tests/ui/missing_panics_doc.rs:187:13
+   |
+LL |     let x = x.unwrap();
+   |             ^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> tests/ui/missing_panics_doc.rs:196:5
    |
 LL |     pub fn option_unwrap<T>(v: &[T]) -> &T {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> tests/ui/missing_panics_doc.rs:160:9
+  --> tests/ui/missing_panics_doc.rs:199:9
    |
 LL |         o.unwrap()
    |         ^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> tests/ui/missing_panics_doc.rs:163:5
+  --> tests/ui/missing_panics_doc.rs:202:5
    |
 LL |     pub fn option_expect<T>(v: &[T]) -> &T {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> tests/ui/missing_panics_doc.rs:166:9
+  --> tests/ui/missing_panics_doc.rs:205:9
    |
 LL |         o.expect("passed an empty thing")
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> tests/ui/missing_panics_doc.rs:169:5
+  --> tests/ui/missing_panics_doc.rs:208:5
    |
 LL |     pub fn result_unwrap<T>(v: &[T]) -> &T {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> tests/ui/missing_panics_doc.rs:172:9
+  --> tests/ui/missing_panics_doc.rs:211:9
    |
 LL |         res.unwrap()
    |         ^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> tests/ui/missing_panics_doc.rs:175:5
+  --> tests/ui/missing_panics_doc.rs:214:5
    |
 LL |     pub fn result_expect<T>(v: &[T]) -> &T {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> tests/ui/missing_panics_doc.rs:178:9
+  --> tests/ui/missing_panics_doc.rs:217:9
    |
 LL |         res.expect("passed an empty thing")
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> tests/ui/missing_panics_doc.rs:181:5
+  --> tests/ui/missing_panics_doc.rs:220:5
    |
 LL |     pub fn last_unwrap(v: &[u32]) -> u32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> tests/ui/missing_panics_doc.rs:183:10
+  --> tests/ui/missing_panics_doc.rs:222:10
    |
 LL |         *v.last().unwrap()
    |          ^^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> tests/ui/missing_panics_doc.rs:186:5
+  --> tests/ui/missing_panics_doc.rs:225:5
    |
 LL |     pub fn last_expect(v: &[u32]) -> u32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> tests/ui/missing_panics_doc.rs:188:10
+  --> tests/ui/missing_panics_doc.rs:227:10
    |
 LL |         *v.last().expect("passed an empty thing")
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_transmute_annotations.fixed b/src/tools/clippy/tests/ui/missing_transmute_annotations.fixed
index a3c94ab139e..58faeaee09d 100644
--- a/src/tools/clippy/tests/ui/missing_transmute_annotations.fixed
+++ b/src/tools/clippy/tests/ui/missing_transmute_annotations.fixed
@@ -18,8 +18,10 @@ fn bar(x: i32) -> i32 {
 }
 
 unsafe fn foo1() -> i32 {
-    // Should not warn!
-    std::mem::transmute([1u16, 2u16])
+    unsafe {
+        // Should not warn!
+        std::mem::transmute([1u16, 2u16])
+    }
 }
 
 // Should not warn!
@@ -31,33 +33,35 @@ enum Foo {
 }
 
 unsafe fn foo2() -> i32 {
-    let mut i: i32 = 0;
-    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
-    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
-    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
-    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
+    unsafe {
+        let mut i: i32 = 0;
+        i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
 
-    let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
-    //~^ ERROR: transmute used without annotations
-    bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
-    //~^ ERROR: transmute used without annotations
+        let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
+        //~^ ERROR: transmute used without annotations
+        bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
+        //~^ ERROR: transmute used without annotations
 
-    i = local_bad_transmute!([1u16, 2u16]);
+        i = local_bad_transmute!([1u16, 2u16]);
 
-    // Should not warn.
-    i = bad_transmute!([1u16, 2u16]);
+        // Should not warn.
+        i = bad_transmute!([1u16, 2u16]);
 
-    i = std::mem::transmute::<[i16; 2], i32>([0i16, 0i16]);
-    //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<[i16; 2], i32>([0i16, 0i16]);
+        //~^ ERROR: transmute used without annotations
 
-    i = std::mem::transmute::<Foo, i32>(Foo::A);
-    //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<Foo, i32>(Foo::A);
+        //~^ ERROR: transmute used without annotations
 
-    i
+        i
+    }
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/missing_transmute_annotations.rs b/src/tools/clippy/tests/ui/missing_transmute_annotations.rs
index c12e1b0f8d2..c9a4c5fa83b 100644
--- a/src/tools/clippy/tests/ui/missing_transmute_annotations.rs
+++ b/src/tools/clippy/tests/ui/missing_transmute_annotations.rs
@@ -18,8 +18,10 @@ fn bar(x: i32) -> i32 {
 }
 
 unsafe fn foo1() -> i32 {
-    // Should not warn!
-    std::mem::transmute([1u16, 2u16])
+    unsafe {
+        // Should not warn!
+        std::mem::transmute([1u16, 2u16])
+    }
 }
 
 // Should not warn!
@@ -31,33 +33,35 @@ enum Foo {
 }
 
 unsafe fn foo2() -> i32 {
-    let mut i: i32 = 0;
-    i = std::mem::transmute([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
-    i = std::mem::transmute::<_, _>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
-    i = std::mem::transmute::<_, i32>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
-    i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
-    //~^ ERROR: transmute used without annotations
+    unsafe {
+        let mut i: i32 = 0;
+        i = std::mem::transmute([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<_, _>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<_, i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
 
-    let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
-    //~^ ERROR: transmute used without annotations
-    bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
-    //~^ ERROR: transmute used without annotations
+        let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+        //~^ ERROR: transmute used without annotations
+        bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+        //~^ ERROR: transmute used without annotations
 
-    i = local_bad_transmute!([1u16, 2u16]);
+        i = local_bad_transmute!([1u16, 2u16]);
 
-    // Should not warn.
-    i = bad_transmute!([1u16, 2u16]);
+        // Should not warn.
+        i = bad_transmute!([1u16, 2u16]);
 
-    i = std::mem::transmute([0i16, 0i16]);
-    //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute([0i16, 0i16]);
+        //~^ ERROR: transmute used without annotations
 
-    i = std::mem::transmute(Foo::A);
-    //~^ ERROR: transmute used without annotations
+        i = std::mem::transmute(Foo::A);
+        //~^ ERROR: transmute used without annotations
 
-    i
+        i
+    }
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr b/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr
index 5903ed488ef..63f7e28ee7d 100644
--- a/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr
+++ b/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr
@@ -1,41 +1,41 @@
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:35:19
+  --> tests/ui/missing_transmute_annotations.rs:38:23
    |
-LL |     i = std::mem::transmute([1u16, 2u16]);
-   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |         i = std::mem::transmute([1u16, 2u16]);
+   |                       ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
    |
    = note: `-D clippy::missing-transmute-annotations` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:37:19
+  --> tests/ui/missing_transmute_annotations.rs:40:23
    |
-LL |     i = std::mem::transmute::<_, _>([1u16, 2u16]);
-   |                   ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |         i = std::mem::transmute::<_, _>([1u16, 2u16]);
+   |                       ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:39:19
+  --> tests/ui/missing_transmute_annotations.rs:42:23
    |
-LL |     i = std::mem::transmute::<_, i32>([1u16, 2u16]);
-   |                   ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |         i = std::mem::transmute::<_, i32>([1u16, 2u16]);
+   |                       ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:41:19
+  --> tests/ui/missing_transmute_annotations.rs:44:23
    |
-LL |     i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |         i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:44:32
+  --> tests/ui/missing_transmute_annotations.rs:47:36
    |
-LL |     let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |         let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:46:19
+  --> tests/ui/missing_transmute_annotations.rs:49:23
    |
-LL |     bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |         bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
   --> tests/ui/missing_transmute_annotations.rs:11:19
@@ -43,31 +43,31 @@ error: transmute used without annotations
 LL |         std::mem::transmute($e)
    |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 ...
-LL |     i = local_bad_transmute!([1u16, 2u16]);
-   |         ---------------------------------- in this macro invocation
+LL |         i = local_bad_transmute!([1u16, 2u16]);
+   |             ---------------------------------- in this macro invocation
    |
    = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:54:19
+  --> tests/ui/missing_transmute_annotations.rs:57:23
    |
-LL |     i = std::mem::transmute([0i16, 0i16]);
-   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[i16; 2], i32>`
+LL |         i = std::mem::transmute([0i16, 0i16]);
+   |                       ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[i16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:57:19
+  --> tests/ui/missing_transmute_annotations.rs:60:23
    |
-LL |     i = std::mem::transmute(Foo::A);
-   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<Foo, i32>`
+LL |         i = std::mem::transmute(Foo::A);
+   |                       ^^^^^^^^^ help: consider adding missing annotations: `transmute::<Foo, i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:64:35
+  --> tests/ui/missing_transmute_annotations.rs:68:35
    |
 LL |     let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) };
    |                                   ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:67:30
+  --> tests/ui/missing_transmute_annotations.rs:71:30
    |
 LL |         let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]);
    |                              ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index b5d356a5021..4c1d6b1ccb5 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -88,11 +88,13 @@ static mut COUNTER: usize = 0;
 ///
 /// Don't ever call this from multiple threads
 pub unsafe fn mutates_static() -> usize {
-    COUNTER += 1;
-    COUNTER
+    unsafe {
+        COUNTER += 1;
+        COUNTER
+    }
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub extern "C" fn unmangled(i: bool) -> bool {
     !i
 }
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index 14ea16662fd..71d546718ae 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -88,11 +88,13 @@ static mut COUNTER: usize = 0;
 ///
 /// Don't ever call this from multiple threads
 pub unsafe fn mutates_static() -> usize {
-    COUNTER += 1;
-    COUNTER
+    unsafe {
+        COUNTER += 1;
+        COUNTER
+    }
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub extern "C" fn unmangled(i: bool) -> bool {
     !i
 }
diff --git a/src/tools/clippy/tests/ui/mut_from_ref.rs b/src/tools/clippy/tests/ui/mut_from_ref.rs
index b8c10f3eeb8..1b0b351518c 100644
--- a/src/tools/clippy/tests/ui/mut_from_ref.rs
+++ b/src/tools/clippy/tests/ui/mut_from_ref.rs
@@ -1,4 +1,10 @@
-#![allow(unused, clippy::needless_lifetimes, clippy::needless_pass_by_ref_mut)]
+#![allow(
+    unused,
+    clippy::needless_lifetimes,
+    clippy::needless_pass_by_ref_mut,
+    clippy::redundant_allocation,
+    clippy::boxed_local
+)]
 #![warn(clippy::mut_from_ref)]
 
 struct Foo;
@@ -40,6 +46,18 @@ fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 {
     unsafe { unimplemented!() }
 }
 
+fn fail_tuples<'a>(x: (&'a u32, &'a u32)) -> &'a mut u32 {
+    //~^ mut_from_ref
+
+    unsafe { unimplemented!() }
+}
+
+fn fail_box<'a>(x: Box<&'a u32>) -> &'a mut u32 {
+    //~^ mut_from_ref
+
+    unsafe { unimplemented!() }
+}
+
 // this is OK, because the result borrows y
 fn works<'a>(x: &u32, y: &'a mut u32) -> &'a mut u32 {
     unsafe { unimplemented!() }
@@ -50,6 +68,20 @@ fn also_works<'a>(x: &'a u32, y: &'a mut u32) -> &'a mut u32 {
     unsafe { unimplemented!() }
 }
 
+fn works_tuples<'a>(x: (&'a u32, &'a mut u32)) -> &'a mut u32 {
+    unsafe { unimplemented!() }
+}
+
+fn works_box<'a>(x: &'a u32, y: Box<&'a mut u32>) -> &'a mut u32 {
+    unsafe { unimplemented!() }
+}
+
+struct RefMut<'a>(&'a mut u32);
+
+fn works_parameter<'a>(x: &'a u32, y: RefMut<'a>) -> &'a mut u32 {
+    unsafe { unimplemented!() }
+}
+
 unsafe fn also_broken(x: &u32) -> &mut u32 {
     //~^ mut_from_ref
 
diff --git a/src/tools/clippy/tests/ui/mut_from_ref.stderr b/src/tools/clippy/tests/ui/mut_from_ref.stderr
index 8c3c8e0c3d8..09742687346 100644
--- a/src/tools/clippy/tests/ui/mut_from_ref.stderr
+++ b/src/tools/clippy/tests/ui/mut_from_ref.stderr
@@ -1,11 +1,11 @@
 error: mutable borrow from immutable input(s)
-  --> tests/ui/mut_from_ref.rs:7:39
+  --> tests/ui/mut_from_ref.rs:13:39
    |
 LL |     fn this_wont_hurt_a_bit(&self) -> &mut Foo {
    |                                       ^^^^^^^^
    |
 note: immutable borrow here
-  --> tests/ui/mut_from_ref.rs:7:29
+  --> tests/ui/mut_from_ref.rs:13:29
    |
 LL |     fn this_wont_hurt_a_bit(&self) -> &mut Foo {
    |                             ^^^^^
@@ -13,64 +13,88 @@ LL |     fn this_wont_hurt_a_bit(&self) -> &mut Foo {
    = help: to override `-D warnings` add `#[allow(clippy::mut_from_ref)]`
 
 error: mutable borrow from immutable input(s)
-  --> tests/ui/mut_from_ref.rs:15:25
+  --> tests/ui/mut_from_ref.rs:21:25
    |
 LL |     fn ouch(x: &Foo) -> &mut Foo;
    |                         ^^^^^^^^
    |
 note: immutable borrow here
-  --> tests/ui/mut_from_ref.rs:15:16
+  --> tests/ui/mut_from_ref.rs:21:16
    |
 LL |     fn ouch(x: &Foo) -> &mut Foo;
    |                ^^^^
 
 error: mutable borrow from immutable input(s)
-  --> tests/ui/mut_from_ref.rs:25:21
+  --> tests/ui/mut_from_ref.rs:31:21
    |
 LL | fn fail(x: &u32) -> &mut u16 {
    |                     ^^^^^^^^
    |
 note: immutable borrow here
-  --> tests/ui/mut_from_ref.rs:25:12
+  --> tests/ui/mut_from_ref.rs:31:12
    |
 LL | fn fail(x: &u32) -> &mut u16 {
    |            ^^^^
 
 error: mutable borrow from immutable input(s)
-  --> tests/ui/mut_from_ref.rs:31:50
+  --> tests/ui/mut_from_ref.rs:37:50
    |
 LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 {
    |                                                  ^^^^^^^^^^^
    |
 note: immutable borrow here
-  --> tests/ui/mut_from_ref.rs:31:25
+  --> tests/ui/mut_from_ref.rs:37:25
    |
 LL | fn fail_lifetime<'a>(x: &'a u32, y: &mut u32) -> &'a mut u32 {
    |                         ^^^^^^^
 
 error: mutable borrow from immutable input(s)
-  --> tests/ui/mut_from_ref.rs:37:67
+  --> tests/ui/mut_from_ref.rs:43:67
    |
 LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 {
    |                                                                   ^^^^^^^^^^^
    |
 note: immutable borrow here
-  --> tests/ui/mut_from_ref.rs:37:27
+  --> tests/ui/mut_from_ref.rs:43:27
    |
 LL | fn fail_double<'a, 'b>(x: &'a u32, y: &'a u32, z: &'b mut u32) -> &'a mut u32 {
    |                           ^^^^^^^     ^^^^^^^
 
 error: mutable borrow from immutable input(s)
-  --> tests/ui/mut_from_ref.rs:53:35
+  --> tests/ui/mut_from_ref.rs:49:46
+   |
+LL | fn fail_tuples<'a>(x: (&'a u32, &'a u32)) -> &'a mut u32 {
+   |                                              ^^^^^^^^^^^
+   |
+note: immutable borrow here
+  --> tests/ui/mut_from_ref.rs:49:24
+   |
+LL | fn fail_tuples<'a>(x: (&'a u32, &'a u32)) -> &'a mut u32 {
+   |                        ^^^^^^^  ^^^^^^^
+
+error: mutable borrow from immutable input(s)
+  --> tests/ui/mut_from_ref.rs:55:37
+   |
+LL | fn fail_box<'a>(x: Box<&'a u32>) -> &'a mut u32 {
+   |                                     ^^^^^^^^^^^
+   |
+note: immutable borrow here
+  --> tests/ui/mut_from_ref.rs:55:24
+   |
+LL | fn fail_box<'a>(x: Box<&'a u32>) -> &'a mut u32 {
+   |                        ^^^^^^^
+
+error: mutable borrow from immutable input(s)
+  --> tests/ui/mut_from_ref.rs:85:35
    |
 LL | unsafe fn also_broken(x: &u32) -> &mut u32 {
    |                                   ^^^^^^^^
    |
 note: immutable borrow here
-  --> tests/ui/mut_from_ref.rs:53:26
+  --> tests/ui/mut_from_ref.rs:85:26
    |
 LL | unsafe fn also_broken(x: &u32) -> &mut u32 {
    |                          ^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mutex_atomic.rs b/src/tools/clippy/tests/ui/mutex_atomic.rs
index 80a712a9286..7db5c9f274f 100644
--- a/src/tools/clippy/tests/ui/mutex_atomic.rs
+++ b/src/tools/clippy/tests/ui/mutex_atomic.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all)]
 #![warn(clippy::mutex_integer)]
 #![warn(clippy::mutex_atomic)]
 #![allow(clippy::borrow_as_ptr)]
diff --git a/src/tools/clippy/tests/ui/mutex_atomic.stderr b/src/tools/clippy/tests/ui/mutex_atomic.stderr
index 838fc1d7c36..a6d5d60fbf0 100644
--- a/src/tools/clippy/tests/ui/mutex_atomic.stderr
+++ b/src/tools/clippy/tests/ui/mutex_atomic.stderr
@@ -1,5 +1,5 @@
 error: consider using an `AtomicBool` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:8:5
+  --> tests/ui/mutex_atomic.rs:7:5
    |
 LL |     Mutex::new(true);
    |     ^^^^^^^^^^^^^^^^
@@ -8,31 +8,31 @@ LL |     Mutex::new(true);
    = help: to override `-D warnings` add `#[allow(clippy::mutex_atomic)]`
 
 error: consider using an `AtomicUsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:11:5
+  --> tests/ui/mutex_atomic.rs:10:5
    |
 LL |     Mutex::new(5usize);
    |     ^^^^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicIsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:14:5
+  --> tests/ui/mutex_atomic.rs:13:5
    |
 LL |     Mutex::new(9isize);
    |     ^^^^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:18:5
+  --> tests/ui/mutex_atomic.rs:17:5
    |
 LL |     Mutex::new(&x as *const u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:21:5
+  --> tests/ui/mutex_atomic.rs:20:5
    |
 LL |     Mutex::new(&mut x as *mut u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicU32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:24:5
+  --> tests/ui/mutex_atomic.rs:23:5
    |
 LL |     Mutex::new(0u32);
    |     ^^^^^^^^^^^^^^^^
@@ -41,31 +41,31 @@ LL |     Mutex::new(0u32);
    = help: to override `-D warnings` add `#[allow(clippy::mutex_integer)]`
 
 error: consider using an `AtomicI32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:27:5
+  --> tests/ui/mutex_atomic.rs:26:5
    |
 LL |     Mutex::new(0i32);
    |     ^^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicU8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:31:5
+  --> tests/ui/mutex_atomic.rs:30:5
    |
 LL |     Mutex::new(0u8);
    |     ^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicI16` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:34:5
+  --> tests/ui/mutex_atomic.rs:33:5
    |
 LL |     Mutex::new(0i16);
    |     ^^^^^^^^^^^^^^^^
 
 error: consider using an `AtomicI8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:37:25
+  --> tests/ui/mutex_atomic.rs:36:25
    |
 LL |     let _x: Mutex<i8> = Mutex::new(0);
    |                         ^^^^^^^^^^^^^
 
 error: consider using an `AtomicI64` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
-  --> tests/ui/mutex_atomic.rs:41:5
+  --> tests/ui/mutex_atomic.rs:40:5
    |
 LL |     Mutex::new(X);
    |     ^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
index e4504bc2784..84924cac62d 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
@@ -89,7 +89,7 @@ fn should_not_lint(
     tuple_struct: TupleStruct,
     s: Struct,
 ) {
-    if let [ref a] = slice {}
+    if let [a] = slice {}
     if let &[ref a, b] = slice {}
     if let &[ref a, .., b] = slice {}
 
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
index 7edfda60b97..280cef43340 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
@@ -89,7 +89,7 @@ fn should_not_lint(
     tuple_struct: TupleStruct,
     s: Struct,
 ) {
-    if let [ref a] = slice {}
+    if let [a] = slice {}
     if let &[ref a, b] = slice {}
     if let &[ref a, .., b] = slice {}
 
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index 6551fa56b42..b09efe9888f 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -126,3 +126,87 @@ fn main() {
 fn foo(_: impl IntoIterator<Item = usize>) {}
 fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
 fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
+
+mod issue9191 {
+    use std::cell::Cell;
+    use std::collections::HashSet;
+    use std::hash::Hash;
+    use std::marker::PhantomData;
+    use std::ops::Deref;
+
+    fn captures_ref_mut(xs: Vec<i32>, mut ys: HashSet<i32>) {
+        if xs.iter().map(|x| ys.remove(x)).collect::<Vec<_>>().contains(&true) {
+            todo!()
+        }
+    }
+
+    #[derive(Debug, Clone)]
+    struct MyRef<'a>(PhantomData<&'a mut Cell<HashSet<i32>>>, *mut Cell<HashSet<i32>>);
+
+    impl MyRef<'_> {
+        fn new(target: &mut Cell<HashSet<i32>>) -> Self {
+            MyRef(PhantomData, target)
+        }
+
+        fn get(&mut self) -> &mut Cell<HashSet<i32>> {
+            unsafe { &mut *self.1 }
+        }
+    }
+
+    fn captures_phantom(xs: Vec<i32>, mut ys: Cell<HashSet<i32>>) {
+        let mut ys_ref = MyRef::new(&mut ys);
+        if xs
+            .iter()
+            .map({
+                let mut ys_ref = ys_ref.clone();
+                move |x| ys_ref.get().get_mut().remove(x)
+            })
+            .collect::<Vec<_>>()
+            .contains(&true)
+        {
+            todo!()
+        }
+    }
+}
+
+pub fn issue8055(v: impl IntoIterator<Item = i32>) -> Result<impl Iterator<Item = i32>, usize> {
+    let mut zeros = 0;
+
+    let res: Vec<_> = v
+        .into_iter()
+        .filter(|i| {
+            if *i == 0 {
+                zeros += 1
+            };
+            *i != 0
+        })
+        .collect();
+
+    if zeros != 0 {
+        return Err(zeros);
+    }
+    Ok(res.into_iter())
+}
+
+mod issue8055_regression {
+    struct Foo<T> {
+        inner: T,
+        marker: core::marker::PhantomData<Self>,
+    }
+
+    impl<T: Iterator> Iterator for Foo<T> {
+        type Item = T::Item;
+        fn next(&mut self) -> Option<Self::Item> {
+            self.inner.next()
+        }
+    }
+
+    fn foo() {
+        Foo {
+            inner: [].iter(),
+            marker: core::marker::PhantomData,
+        }
+        .collect::<Vec<&i32>>()
+        .len();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 973c41c6875..da4182966bb 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -126,3 +126,87 @@ fn main() {
 fn foo(_: impl IntoIterator<Item = usize>) {}
 fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
 fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
+
+mod issue9191 {
+    use std::cell::Cell;
+    use std::collections::HashSet;
+    use std::hash::Hash;
+    use std::marker::PhantomData;
+    use std::ops::Deref;
+
+    fn captures_ref_mut(xs: Vec<i32>, mut ys: HashSet<i32>) {
+        if xs.iter().map(|x| ys.remove(x)).collect::<Vec<_>>().contains(&true) {
+            todo!()
+        }
+    }
+
+    #[derive(Debug, Clone)]
+    struct MyRef<'a>(PhantomData<&'a mut Cell<HashSet<i32>>>, *mut Cell<HashSet<i32>>);
+
+    impl MyRef<'_> {
+        fn new(target: &mut Cell<HashSet<i32>>) -> Self {
+            MyRef(PhantomData, target)
+        }
+
+        fn get(&mut self) -> &mut Cell<HashSet<i32>> {
+            unsafe { &mut *self.1 }
+        }
+    }
+
+    fn captures_phantom(xs: Vec<i32>, mut ys: Cell<HashSet<i32>>) {
+        let mut ys_ref = MyRef::new(&mut ys);
+        if xs
+            .iter()
+            .map({
+                let mut ys_ref = ys_ref.clone();
+                move |x| ys_ref.get().get_mut().remove(x)
+            })
+            .collect::<Vec<_>>()
+            .contains(&true)
+        {
+            todo!()
+        }
+    }
+}
+
+pub fn issue8055(v: impl IntoIterator<Item = i32>) -> Result<impl Iterator<Item = i32>, usize> {
+    let mut zeros = 0;
+
+    let res: Vec<_> = v
+        .into_iter()
+        .filter(|i| {
+            if *i == 0 {
+                zeros += 1
+            };
+            *i != 0
+        })
+        .collect();
+
+    if zeros != 0 {
+        return Err(zeros);
+    }
+    Ok(res.into_iter())
+}
+
+mod issue8055_regression {
+    struct Foo<T> {
+        inner: T,
+        marker: core::marker::PhantomData<Self>,
+    }
+
+    impl<T: Iterator> Iterator for Foo<T> {
+        type Item = T::Item;
+        fn next(&mut self) -> Option<Self::Item> {
+            self.inner.next()
+        }
+    }
+
+    fn foo() {
+        Foo {
+            inner: [].iter(),
+            marker: core::marker::PhantomData,
+        }
+        .collect::<Vec<&i32>>()
+        .len();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
index d59393fb3f3..e9d811986aa 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -534,4 +534,11 @@ mod issue13749bis {
     impl<'a, T: 'a> Generic<T> {}
 }
 
+pub fn issue14607<'s>(x: &'s u8) {
+    #[expect(clippy::redundant_closure_call)]
+    (|| {
+        let _: &'s u8 = x;
+    })();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index e24907ab5fc..0b6eb9755b9 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -534,4 +534,11 @@ mod issue13749bis {
     impl<'a, T: 'a> Generic<T> {}
 }
 
+pub fn issue14607<'s>(x: &'s u8) {
+    #[expect(clippy::redundant_closure_call)]
+    (|| {
+        let _: &'s u8 = x;
+    })();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
index f0c5a716ac9..bdad3e3d5b0 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
@@ -1,8 +1,9 @@
 #![allow(
     clippy::if_same_then_else,
     clippy::no_effect,
+    clippy::ptr_arg,
     clippy::redundant_closure_call,
-    clippy::ptr_arg
+    clippy::uninlined_format_args
 )]
 #![warn(clippy::needless_pass_by_ref_mut)]
 //@no-rustfix
@@ -300,7 +301,7 @@ struct Data<T: ?Sized> {
 }
 // Unsafe functions should not warn.
 unsafe fn get_mut_unchecked<T>(ptr: &mut NonNull<Data<T>>) -> &mut T {
-    &mut (*ptr.as_ptr()).value
+    unsafe { &mut (*ptr.as_ptr()).value }
 }
 // Unsafe blocks should not warn.
 fn get_mut_unchecked2<T>(ptr: &mut NonNull<Data<T>>) -> &mut T {
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
index 6637a255b5f..94d98f0e9b1 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
@@ -1,5 +1,5 @@
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:11:11
+  --> tests/ui/needless_pass_by_ref_mut.rs:12:11
    |
 LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    |           ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
@@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:37:12
+  --> tests/ui/needless_pass_by_ref_mut.rs:38:12
    |
 LL | fn foo6(s: &mut Vec<u32>) {
    |            ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:48:12
+  --> tests/ui/needless_pass_by_ref_mut.rs:49:12
    |
 LL |     fn bar(&mut self) {}
    |            ^^^^^^^^^ help: consider changing to: `&self`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:51:29
+  --> tests/ui/needless_pass_by_ref_mut.rs:52:29
    |
 LL |     fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
    |                             ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:129:16
+  --> tests/ui/needless_pass_by_ref_mut.rs:130:16
    |
 LL | async fn a1(x: &mut i32) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:134:16
+  --> tests/ui/needless_pass_by_ref_mut.rs:135:16
    |
 LL | async fn a2(x: &mut i32, y: String) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:139:16
+  --> tests/ui/needless_pass_by_ref_mut.rs:140:16
    |
 LL | async fn a3(x: &mut i32, y: String, z: String) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:144:16
+  --> tests/ui/needless_pass_by_ref_mut.rs:145:16
    |
 LL | async fn a4(x: &mut i32, y: i32) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:149:24
+  --> tests/ui/needless_pass_by_ref_mut.rs:150:24
    |
 LL | async fn a5(x: i32, y: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:154:24
+  --> tests/ui/needless_pass_by_ref_mut.rs:155:24
    |
 LL | async fn a6(x: i32, y: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:159:32
+  --> tests/ui/needless_pass_by_ref_mut.rs:160:32
    |
 LL | async fn a7(x: i32, y: i32, z: &mut i32) {
    |                                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:164:24
+  --> tests/ui/needless_pass_by_ref_mut.rs:165:24
    |
 LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:164:45
+  --> tests/ui/needless_pass_by_ref_mut.rs:165:45
    |
 LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
    |                                             ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:200:16
+  --> tests/ui/needless_pass_by_ref_mut.rs:201:16
    |
 LL | fn cfg_warn(s: &mut u32) {}
    |                ^^^^^^^^ help: consider changing to: `&u32`
@@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {}
    = note: this is cfg-gated and may require further changes
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:205:20
+  --> tests/ui/needless_pass_by_ref_mut.rs:206:20
    |
 LL |     fn cfg_warn(s: &mut u32) {}
    |                    ^^^^^^^^ help: consider changing to: `&u32`
@@ -96,115 +96,115 @@ LL |     fn cfg_warn(s: &mut u32) {}
    = note: this is cfg-gated and may require further changes
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:218:39
+  --> tests/ui/needless_pass_by_ref_mut.rs:219:39
    |
 LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
    |                                       ^^^^^^^^ help: consider changing to: `&u32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:227:26
+  --> tests/ui/needless_pass_by_ref_mut.rs:228:26
    |
 LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
    |                          ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:247:30
+  --> tests/ui/needless_pass_by_ref_mut.rs:248:30
    |
 LL | async fn call_in_closure1(n: &mut str) {
    |                              ^^^^^^^^ help: consider changing to: `&str`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:267:16
+  --> tests/ui/needless_pass_by_ref_mut.rs:268:16
    |
 LL | fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
    |                ^^^^^^^^^^ help: consider changing to: `&usize`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:279:22
+  --> tests/ui/needless_pass_by_ref_mut.rs:280:22
    |
 LL | async fn closure4(n: &mut usize) {
    |                      ^^^^^^^^^^ help: consider changing to: `&usize`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:334:12
+  --> tests/ui/needless_pass_by_ref_mut.rs:335:12
    |
 LL |     fn bar(&mut self) {}
    |            ^^^^^^^^^ help: consider changing to: `&self`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:337:18
+  --> tests/ui/needless_pass_by_ref_mut.rs:338:18
    |
 LL |     async fn foo(&mut self, u: &mut i32, v: &mut u32) {
    |                  ^^^^^^^^^ help: consider changing to: `&self`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:337:45
+  --> tests/ui/needless_pass_by_ref_mut.rs:338:45
    |
 LL |     async fn foo(&mut self, u: &mut i32, v: &mut u32) {
    |                                             ^^^^^^^^ help: consider changing to: `&u32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:346:46
+  --> tests/ui/needless_pass_by_ref_mut.rs:347:46
    |
 LL |     async fn foo2(&mut self, u: &mut i32, v: &mut u32) {
    |                                              ^^^^^^^^ help: consider changing to: `&u32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:363:18
+  --> tests/ui/needless_pass_by_ref_mut.rs:364:18
    |
 LL | fn _empty_tup(x: &mut (())) {}
    |                  ^^^^^^^^^ help: consider changing to: `&()`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:365:19
+  --> tests/ui/needless_pass_by_ref_mut.rs:366:19
    |
 LL | fn _single_tup(x: &mut ((i32,))) {}
    |                   ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:367:18
+  --> tests/ui/needless_pass_by_ref_mut.rs:368:18
    |
 LL | fn _multi_tup(x: &mut ((i32, u32))) {}
    |                  ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:369:11
+  --> tests/ui/needless_pass_by_ref_mut.rs:370:11
    |
 LL | fn _fn(x: &mut (fn())) {}
    |           ^^^^^^^^^^^ help: consider changing to: `&fn()`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:372:23
+  --> tests/ui/needless_pass_by_ref_mut.rs:373:23
    |
 LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {}
    |                       ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:374:20
+  --> tests/ui/needless_pass_by_ref_mut.rs:375:20
    |
 LL | fn _extern_c_fn(x: &mut extern "C" fn()) {}
    |                    ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:376:18
+  --> tests/ui/needless_pass_by_ref_mut.rs:377:18
    |
 LL | fn _unsafe_fn(x: &mut unsafe fn()) {}
    |                  ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:378:25
+  --> tests/ui/needless_pass_by_ref_mut.rs:379:25
    |
 LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:380:20
+  --> tests/ui/needless_pass_by_ref_mut.rs:381:20
    |
 LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {}
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)`
 
 error: this argument is a mutable reference, but not used mutably
-  --> tests/ui/needless_pass_by_ref_mut.rs:382:20
+  --> tests/ui/needless_pass_by_ref_mut.rs:383:20
    |
 LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {}
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)`
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut_2021.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut_2021.rs
new file mode 100644
index 00000000000..994eba9cae3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut_2021.rs
@@ -0,0 +1,12 @@
+//@edition: 2021
+//@check-pass
+#![warn(clippy::needless_pass_by_ref_mut)]
+
+struct Data<T: ?Sized> {
+    value: T,
+}
+
+// Unsafe functions should not warn.
+unsafe fn get_mut_unchecked<T>(ptr: &mut std::ptr::NonNull<Data<T>>) -> &mut T {
+    &mut (*ptr.as_ptr()).value
+}
diff --git a/src/tools/clippy/tests/ui/neg_multiply.fixed b/src/tools/clippy/tests/ui/neg_multiply.fixed
index 995470493bf..ff6e08300e2 100644
--- a/src/tools/clippy/tests/ui/neg_multiply.fixed
+++ b/src/tools/clippy/tests/ui/neg_multiply.fixed
@@ -53,3 +53,32 @@ fn main() {
     X * -1; // should be ok
     -1 * X; // should also be ok
 }
+
+fn float() {
+    let x = 0.0;
+
+    -x;
+    //~^ neg_multiply
+
+    -x;
+    //~^ neg_multiply
+
+    100.0 + -x;
+    //~^ neg_multiply
+
+    -(100.0 + x);
+    //~^ neg_multiply
+
+    -17.0;
+    //~^ neg_multiply
+
+    0.0 + -0.0;
+    //~^ neg_multiply
+
+    -(3.0_f32 as f64);
+    //~^ neg_multiply
+    -(3.0_f32 as f64);
+    //~^ neg_multiply
+
+    -1.0 * -1.0; // should be ok
+}
diff --git a/src/tools/clippy/tests/ui/neg_multiply.rs b/src/tools/clippy/tests/ui/neg_multiply.rs
index 95b94e29517..b0f4e85c78e 100644
--- a/src/tools/clippy/tests/ui/neg_multiply.rs
+++ b/src/tools/clippy/tests/ui/neg_multiply.rs
@@ -53,3 +53,32 @@ fn main() {
     X * -1; // should be ok
     -1 * X; // should also be ok
 }
+
+fn float() {
+    let x = 0.0;
+
+    x * -1.0;
+    //~^ neg_multiply
+
+    -1.0 * x;
+    //~^ neg_multiply
+
+    100.0 + x * -1.0;
+    //~^ neg_multiply
+
+    (100.0 + x) * -1.0;
+    //~^ neg_multiply
+
+    -1.0 * 17.0;
+    //~^ neg_multiply
+
+    0.0 + 0.0 * -1.0;
+    //~^ neg_multiply
+
+    3.0_f32 as f64 * -1.0;
+    //~^ neg_multiply
+    (3.0_f32 as f64) * -1.0;
+    //~^ neg_multiply
+
+    -1.0 * -1.0; // should be ok
+}
diff --git a/src/tools/clippy/tests/ui/neg_multiply.stderr b/src/tools/clippy/tests/ui/neg_multiply.stderr
index 9efa5d3ba1f..2ef7e32ce05 100644
--- a/src/tools/clippy/tests/ui/neg_multiply.stderr
+++ b/src/tools/clippy/tests/ui/neg_multiply.stderr
@@ -49,5 +49,53 @@ error: this multiplication by -1 can be written more succinctly
 LL |     (3_usize as i32) * -1;
    |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3_usize as i32)`
 
-error: aborting due to 8 previous errors
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:60:5
+   |
+LL |     x * -1.0;
+   |     ^^^^^^^^ help: consider using: `-x`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:63:5
+   |
+LL |     -1.0 * x;
+   |     ^^^^^^^^ help: consider using: `-x`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:66:13
+   |
+LL |     100.0 + x * -1.0;
+   |             ^^^^^^^^ help: consider using: `-x`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:69:5
+   |
+LL |     (100.0 + x) * -1.0;
+   |     ^^^^^^^^^^^^^^^^^^ help: consider using: `-(100.0 + x)`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:72:5
+   |
+LL |     -1.0 * 17.0;
+   |     ^^^^^^^^^^^ help: consider using: `-17.0`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:75:11
+   |
+LL |     0.0 + 0.0 * -1.0;
+   |           ^^^^^^^^^^ help: consider using: `-0.0`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:78:5
+   |
+LL |     3.0_f32 as f64 * -1.0;
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3.0_f32 as f64)`
+
+error: this multiplication by -1 can be written more succinctly
+  --> tests/ui/neg_multiply.rs:80:5
+   |
+LL |     (3.0_f32 as f64) * -1.0;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3.0_f32 as f64)`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
index 0d09b3ceecd..f4248ffc0f4 100644
--- a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
@@ -43,7 +43,7 @@ extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
 
 extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
 
-extern "C" {
+unsafe extern "C" {
     fn c_abi_in_block(arg_one: u32, arg_two: usize);
 }
 
diff --git a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed
index 8774c666db1..23dbee5a084 100644
--- a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed
+++ b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.fixed
@@ -162,3 +162,36 @@ impl PartialOrd for I {
         return Some(self.cmp(other));
     }
 }
+
+// #13640, do not lint
+
+#[derive(Eq, PartialEq)]
+struct J(u32);
+
+impl Ord for J {
+    fn cmp(&self, other: &Self) -> Ordering {
+        todo!();
+    }
+}
+
+impl PartialOrd for J {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.cmp(other).into()
+    }
+}
+
+// #13640, check that a simple `.into()` does not obliterate the lint
+
+#[derive(Eq, PartialEq)]
+struct K(u32);
+
+impl Ord for K {
+    fn cmp(&self, other: &Self) -> Ordering {
+        todo!();
+    }
+}
+
+impl PartialOrd for K {
+    //~^ non_canonical_partial_ord_impl
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
+}
diff --git a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs
index 568b97c8fff..12f055a542b 100644
--- a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs
+++ b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.rs
@@ -166,3 +166,38 @@ impl PartialOrd for I {
         return Some(self.cmp(other));
     }
 }
+
+// #13640, do not lint
+
+#[derive(Eq, PartialEq)]
+struct J(u32);
+
+impl Ord for J {
+    fn cmp(&self, other: &Self) -> Ordering {
+        todo!();
+    }
+}
+
+impl PartialOrd for J {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.cmp(other).into()
+    }
+}
+
+// #13640, check that a simple `.into()` does not obliterate the lint
+
+#[derive(Eq, PartialEq)]
+struct K(u32);
+
+impl Ord for K {
+    fn cmp(&self, other: &Self) -> Ordering {
+        todo!();
+    }
+}
+
+impl PartialOrd for K {
+    //~^ non_canonical_partial_ord_impl
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Ordering::Greater.into()
+    }
+}
diff --git a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.stderr b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.stderr
index 86845df4ea9..c7de968588f 100644
--- a/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.stderr
+++ b/src/tools/clippy/tests/ui/non_canonical_partial_ord_impl.stderr
@@ -31,5 +31,18 @@ LL -     fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
 LL +     fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
    |
 
-error: aborting due to 2 previous errors
+error: non-canonical implementation of `partial_cmp` on an `Ord` type
+  --> tests/ui/non_canonical_partial_ord_impl.rs:198:1
+   |
+LL | /  impl PartialOrd for K {
+LL | |
+LL | |      fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+   | | _____________________________________________________________-
+LL | ||         Ordering::Greater.into()
+LL | ||     }
+   | ||_____- help: change this to: `{ Some(self.cmp(other)) }`
+LL | |  }
+   | |__^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/non_expressive_names.rs b/src/tools/clippy/tests/ui/non_expressive_names.rs
index b772c754f8b..3f34dff563d 100644
--- a/src/tools/clippy/tests/ui/non_expressive_names.rs
+++ b/src/tools/clippy/tests/ui/non_expressive_names.rs
@@ -1,5 +1,4 @@
-#![warn(clippy::all)]
-#![allow(unused, clippy::println_empty_string, non_snake_case, clippy::let_unit_value)]
+#![allow(clippy::println_empty_string, non_snake_case, clippy::let_unit_value)]
 
 #[derive(Clone, Debug)]
 enum MaybeInst {
diff --git a/src/tools/clippy/tests/ui/non_expressive_names.stderr b/src/tools/clippy/tests/ui/non_expressive_names.stderr
index 3bd77a730fe..11b12d2c5f1 100644
--- a/src/tools/clippy/tests/ui/non_expressive_names.stderr
+++ b/src/tools/clippy/tests/ui/non_expressive_names.stderr
@@ -1,5 +1,5 @@
 error: consider choosing a more descriptive name
-  --> tests/ui/non_expressive_names.rs:28:9
+  --> tests/ui/non_expressive_names.rs:27:9
    |
 LL |     let _1 = 1;
    |         ^^
@@ -8,31 +8,31 @@ LL |     let _1 = 1;
    = help: to override `-D warnings` add `#[allow(clippy::just_underscores_and_digits)]`
 
 error: consider choosing a more descriptive name
-  --> tests/ui/non_expressive_names.rs:30:9
+  --> tests/ui/non_expressive_names.rs:29:9
    |
 LL |     let ____1 = 1;
    |         ^^^^^
 
 error: consider choosing a more descriptive name
-  --> tests/ui/non_expressive_names.rs:32:9
+  --> tests/ui/non_expressive_names.rs:31:9
    |
 LL |     let __1___2 = 12;
    |         ^^^^^^^
 
 error: consider choosing a more descriptive name
-  --> tests/ui/non_expressive_names.rs:54:13
+  --> tests/ui/non_expressive_names.rs:53:13
    |
 LL |         let _1 = 1;
    |             ^^
 
 error: consider choosing a more descriptive name
-  --> tests/ui/non_expressive_names.rs:56:13
+  --> tests/ui/non_expressive_names.rs:55:13
    |
 LL |         let ____1 = 1;
    |             ^^^^^
 
 error: consider choosing a more descriptive name
-  --> tests/ui/non_expressive_names.rs:58:13
+  --> tests/ui/non_expressive_names.rs:57:13
    |
 LL |         let __1___2 = 12;
    |             ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs
index 046ea70b08f..31778f74509 100644
--- a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs
@@ -35,7 +35,7 @@ unsafe impl<RC, T: Send> Send for ArcGuard<RC, T> {}
 //~^ ERROR: some fields in `ArcGuard<RC, T>` are not safe to be sent to another thread
 
 // rusb / RUSTSEC-2020-0098
-extern "C" {
+unsafe extern "C" {
     type libusb_device_handle;
 }
 
@@ -90,7 +90,7 @@ unsafe impl<A, B> Send for MultiParam<A, B> {}
 //~^ ERROR: some fields in `MultiParam<A, B>` are not safe to be sent to another thread
 
 // Tests for raw pointer heuristic
-extern "C" {
+unsafe extern "C" {
     type NonSend;
 }
 
diff --git a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed
index f7c56b6fffe..2b30c8f984e 100644
--- a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed
+++ b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.fixed
@@ -9,16 +9,16 @@ use once_cell::sync::Lazy;
 fn main() {}
 
 static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
-//~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+//~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| {
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     let x = "bar";
     x.to_uppercase()
 });
 static LAZY_BAZ: std::sync::LazyLock<String> = { std::sync::LazyLock::new(|| "baz".to_uppercase()) };
-//~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+//~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 static LAZY_QUX: std::sync::LazyLock<String> = {
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     if "qux".len() == 3 {
         std::sync::LazyLock::new(|| "qux".to_uppercase())
     } else if "qux".is_ascii() {
@@ -39,11 +39,11 @@ mod once_cell_lazy_with_fns {
     use once_cell::sync::Lazy;
 
     static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "bar".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     static mut LAZY_BAZ: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "baz".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 
     fn calling_replaceable_fns() {
         let _ = std::sync::LazyLock::force(&LAZY_FOO);
diff --git a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs
index 90bc428137c..c52338eee83 100644
--- a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs
+++ b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs
@@ -9,16 +9,16 @@ use once_cell::sync::Lazy;
 fn main() {}
 
 static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
-//~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+//~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 static LAZY_BAR: Lazy<String> = Lazy::new(|| {
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     let x = "bar";
     x.to_uppercase()
 });
 static LAZY_BAZ: Lazy<String> = { Lazy::new(|| "baz".to_uppercase()) };
-//~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+//~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 static LAZY_QUX: Lazy<String> = {
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     if "qux".len() == 3 {
         Lazy::new(|| "qux".to_uppercase())
     } else if "qux".is_ascii() {
@@ -39,11 +39,11 @@ mod once_cell_lazy_with_fns {
     use once_cell::sync::Lazy;
 
     static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     static LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 
     fn calling_replaceable_fns() {
         let _ = Lazy::force(&LAZY_FOO);
diff --git a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr
index 333052ae1c1..bb80cd11c71 100644
--- a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr
+++ b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.stderr
@@ -1,4 +1,4 @@
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:11:18
    |
 LL | static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
@@ -12,7 +12,7 @@ LL - static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
 LL + static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:13:18
    |
 LL | static LAZY_BAR: Lazy<String> = Lazy::new(|| {
@@ -24,7 +24,7 @@ LL - static LAZY_BAR: Lazy<String> = Lazy::new(|| {
 LL + static LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| {
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:18:18
    |
 LL | static LAZY_BAZ: Lazy<String> = { Lazy::new(|| "baz".to_uppercase()) };
@@ -36,7 +36,7 @@ LL - static LAZY_BAZ: Lazy<String> = { Lazy::new(|| "baz".to_uppercase()) };
 LL + static LAZY_BAZ: std::sync::LazyLock<String> = { std::sync::LazyLock::new(|| "baz".to_uppercase()) };
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:20:18
    |
 LL | static LAZY_QUX: Lazy<String> = {
@@ -54,7 +54,7 @@ LL |     } else {
 LL ~         std::sync::LazyLock::new(|| "qux".to_string())
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:41:22
    |
 LL |     static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
@@ -69,7 +69,7 @@ LL |     fn calling_replaceable_fns() {
 LL ~         let _ = std::sync::LazyLock::force(&LAZY_FOO);
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:43:22
    |
 LL |     static LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
@@ -84,7 +84,7 @@ LL |         let _ = Lazy::force(&LAZY_FOO);
 LL ~         let _ = std::sync::LazyLock::force(&LAZY_BAR);
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_fixable.rs:45:26
    |
 LL |     static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
diff --git a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs
index 34f8dd1ccb2..acc8c04678f 100644
--- a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs
+++ b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs
@@ -9,11 +9,11 @@ mod once_cell_lazy {
     use once_cell::sync::Lazy;
 
     static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     static mut LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
     static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
-    //~^ ERROR: this type has been superceded by `LazyLock` in the standard library
+    //~^ ERROR: this type has been superseded by `LazyLock` in the standard library
 
     fn calling_irreplaceable_fns() {
         let _ = Lazy::get(&LAZY_FOO);
@@ -31,13 +31,13 @@ mod lazy_static_lazy_static {
     lazy_static! {
         static ref LAZY_FOO: String = "foo".to_uppercase();
     }
-    //~^^^ ERROR: this macro has been superceded by `std::sync::LazyLock`
+    //~^^^ ERROR: this macro has been superseded by `std::sync::LazyLock`
     lazy_static! {
         static ref LAZY_BAR: String = "bar".to_uppercase();
         static ref LAZY_BAZ: String = "baz".to_uppercase();
     }
-    //~^^^^ ERROR: this macro has been superceded by `std::sync::LazyLock`
-    //~| ERROR: this macro has been superceded by `std::sync::LazyLock`
+    //~^^^^ ERROR: this macro has been superseded by `std::sync::LazyLock`
+    //~| ERROR: this macro has been superseded by `std::sync::LazyLock`
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr
index 216190ae4ca..2c35cad6237 100644
--- a/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.stderr
@@ -1,4 +1,4 @@
-error: this macro has been superceded by `std::sync::LazyLock`
+error: this macro has been superseded by `std::sync::LazyLock`
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:31:5
    |
 LL | /     lazy_static! {
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::non-std-lazy-statics` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::non_std_lazy_statics)]`
 
-error: this macro has been superceded by `std::sync::LazyLock`
+error: this macro has been superseded by `std::sync::LazyLock`
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:35:5
    |
 LL | /     lazy_static! {
@@ -18,7 +18,7 @@ LL | |         static ref LAZY_BAZ: String = "baz".to_uppercase();
 LL | |     }
    | |_____^
 
-error: this macro has been superceded by `std::sync::LazyLock`
+error: this macro has been superseded by `std::sync::LazyLock`
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:35:5
    |
 LL | /     lazy_static! {
@@ -29,7 +29,7 @@ LL | |     }
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:11:22
    |
 LL |     static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
@@ -41,7 +41,7 @@ LL -     static LAZY_FOO: Lazy<String> = Lazy::new(|| "foo".to_uppercase());
 LL +     static LAZY_FOO: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "foo".to_uppercase());
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:13:26
    |
 LL |     static mut LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
@@ -53,7 +53,7 @@ LL -     static mut LAZY_BAR: Lazy<String> = Lazy::new(|| "bar".to_uppercase());
 LL +     static mut LAZY_BAR: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| "bar".to_uppercase());
    |
 
-error: this type has been superceded by `LazyLock` in the standard library
+error: this type has been superseded by `LazyLock` in the standard library
   --> tests/ui/non_std_lazy_static/non_std_lazy_static_unfixable.rs:15:26
    |
 LL |     static mut LAZY_BAZ: Lazy<String> = Lazy::new(|| "baz".to_uppercase());
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index a155ff3508b..1eecc3dee3d 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -216,3 +216,23 @@ fn issue14184(a: f32, b: bool) {
         println!("Hi");
     }
 }
+
+mod issue14404 {
+    enum TyKind {
+        Ref(i32, i32, i32),
+        Other,
+    }
+
+    struct Expr;
+
+    fn is_mutable(expr: &Expr) -> bool {
+        todo!()
+    }
+
+    fn should_not_give_macro(ty: TyKind, expr: Expr) {
+        if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) {
+            //~^ nonminimal_bool
+            todo!()
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
index 336cce40abf..0e3e4cf7988 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
@@ -227,7 +227,13 @@ error: this boolean expression can be simplified
   --> tests/ui/nonminimal_bool.rs:214:8
    |
 LL |     if !(a < 2.0 && !b) {
-   |        ^^^^^^^^^^^^^^^^ help: try: `!(a < 2.0) || b`
+   |        ^^^^^^^^^^^^^^^^ help: try: `a >= 2.0 || b`
 
-error: aborting due to 30 previous errors
+error: this boolean expression can be simplified
+  --> tests/ui/nonminimal_bool.rs:233:12
+   |
+LL |         if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!matches!(ty, TyKind::Ref(_, _, _)) || is_mutable(&expr)`
+
+error: aborting due to 31 previous errors
 
diff --git a/src/tools/clippy/tests/ui/obfuscated_if_else.fixed b/src/tools/clippy/tests/ui/obfuscated_if_else.fixed
index 66f5070787b..70ae090626b 100644
--- a/src/tools/clippy/tests/ui/obfuscated_if_else.fixed
+++ b/src/tools/clippy/tests/ui/obfuscated_if_else.fixed
@@ -46,6 +46,18 @@ fn main() {
 
     let partial = true.then_some(1);
     partial.unwrap_or_else(|| n * 2); // not lint
+
+    if true { () } else { Default::default() };
+    //~^ obfuscated_if_else
+
+    if true { () } else { Default::default() };
+    //~^ obfuscated_if_else
+
+    if true { 1 } else { Default::default() };
+    //~^ obfuscated_if_else
+
+    if true { 1 } else { Default::default() };
+    //~^ obfuscated_if_else
 }
 
 fn issue11141() {
diff --git a/src/tools/clippy/tests/ui/obfuscated_if_else.rs b/src/tools/clippy/tests/ui/obfuscated_if_else.rs
index 4efd740eb60..8e1f57ca2c0 100644
--- a/src/tools/clippy/tests/ui/obfuscated_if_else.rs
+++ b/src/tools/clippy/tests/ui/obfuscated_if_else.rs
@@ -46,6 +46,18 @@ fn main() {
 
     let partial = true.then_some(1);
     partial.unwrap_or_else(|| n * 2); // not lint
+
+    true.then_some(()).unwrap_or_default();
+    //~^ obfuscated_if_else
+
+    true.then(|| ()).unwrap_or_default();
+    //~^ obfuscated_if_else
+
+    true.then_some(1).unwrap_or_default();
+    //~^ obfuscated_if_else
+
+    true.then(|| 1).unwrap_or_default();
+    //~^ obfuscated_if_else
 }
 
 fn issue11141() {
diff --git a/src/tools/clippy/tests/ui/obfuscated_if_else.stderr b/src/tools/clippy/tests/ui/obfuscated_if_else.stderr
index d676c256695..0de7259d8bb 100644
--- a/src/tools/clippy/tests/ui/obfuscated_if_else.stderr
+++ b/src/tools/clippy/tests/ui/obfuscated_if_else.stderr
@@ -68,52 +68,76 @@ LL |     true.then_some(1).unwrap_or_else(Default::default);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { Default::default() }`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:53:13
+  --> tests/ui/obfuscated_if_else.rs:50:5
+   |
+LL |     true.then_some(()).unwrap_or_default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { () } else { Default::default() }`
+
+error: this method chain can be written more clearly with `if .. else ..`
+  --> tests/ui/obfuscated_if_else.rs:53:5
+   |
+LL |     true.then(|| ()).unwrap_or_default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { () } else { Default::default() }`
+
+error: this method chain can be written more clearly with `if .. else ..`
+  --> tests/ui/obfuscated_if_else.rs:56:5
+   |
+LL |     true.then_some(1).unwrap_or_default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { Default::default() }`
+
+error: this method chain can be written more clearly with `if .. else ..`
+  --> tests/ui/obfuscated_if_else.rs:59:5
+   |
+LL |     true.then(|| 1).unwrap_or_default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { Default::default() }`
+
+error: this method chain can be written more clearly with `if .. else ..`
+  --> tests/ui/obfuscated_if_else.rs:65:13
    |
 LL |     let _ = true.then_some(40).unwrap_or(17) | 2;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(if true { 40 } else { 17 })`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:57:13
+  --> tests/ui/obfuscated_if_else.rs:69:13
    |
 LL |     let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(if true { 30 } else { 17 })`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:57:48
+  --> tests/ui/obfuscated_if_else.rs:69:48
    |
 LL |     let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1);
    |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 2 } else { 3 }`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:57:81
+  --> tests/ui/obfuscated_if_else.rs:69:81
    |
 LL |     let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1);
    |                                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 10 } else { 1 }`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:63:17
+  --> tests/ui/obfuscated_if_else.rs:75:17
    |
 LL |     let _ = 2 | true.then_some(40).unwrap_or(17);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 40 } else { 17 }`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:67:13
+  --> tests/ui/obfuscated_if_else.rs:79:13
    |
 LL |     let _ = true.then_some(42).unwrap_or(17) as u8;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 42 } else { 17 }`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:71:14
+  --> tests/ui/obfuscated_if_else.rs:83:14
    |
 LL |     let _ = *true.then_some(&42).unwrap_or(&17);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { &42 } else { &17 }`
 
 error: this method chain can be written more clearly with `if .. else ..`
-  --> tests/ui/obfuscated_if_else.rs:75:14
+  --> tests/ui/obfuscated_if_else.rs:87:14
    |
 LL |     let _ = *true.then_some(&42).unwrap_or(&17) as u8;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { &42 } else { &17 }`
 
-error: aborting due to 19 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/op_ref.fixed b/src/tools/clippy/tests/ui/op_ref.fixed
index 46a59e419cc..f412190b9fd 100644
--- a/src/tools/clippy/tests/ui/op_ref.fixed
+++ b/src/tools/clippy/tests/ui/op_ref.fixed
@@ -98,3 +98,15 @@ impl Mul<A> for A {
         self * &rhs
     }
 }
+
+mod issue_2597 {
+    fn ex1() {
+        let a: &str = "abc";
+        let b: String = "abc".to_owned();
+        println!("{}", a > &b);
+    }
+
+    pub fn ex2<T: Ord + PartialOrd>(array: &[T], val: &T, idx: usize) -> bool {
+        &array[idx] < val
+    }
+}
diff --git a/src/tools/clippy/tests/ui/op_ref.rs b/src/tools/clippy/tests/ui/op_ref.rs
index e10840ff4b9..a4bbd86c7e9 100644
--- a/src/tools/clippy/tests/ui/op_ref.rs
+++ b/src/tools/clippy/tests/ui/op_ref.rs
@@ -98,3 +98,15 @@ impl Mul<A> for A {
         self * &rhs
     }
 }
+
+mod issue_2597 {
+    fn ex1() {
+        let a: &str = "abc";
+        let b: String = "abc".to_owned();
+        println!("{}", a > &b);
+    }
+
+    pub fn ex2<T: Ord + PartialOrd>(array: &[T], val: &T, idx: usize) -> bool {
+        &array[idx] < val
+    }
+}
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index ee309889601..fe3ac9e8f92 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -288,3 +288,17 @@ mod issue13964 {
         };
     }
 }
+
+mod issue11059 {
+    use std::fmt::Debug;
+
+    fn box_coercion_unsize(o: Option<i32>) -> Box<dyn Debug> {
+        if let Some(o) = o { Box::new(o) } else { Box::new("foo") }
+    }
+
+    static S: String = String::new();
+
+    fn deref_with_overload(o: Option<&str>) -> &str {
+        if let Some(o) = o { o } else { &S }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 525a5df4371..5b7498bc8e2 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -351,3 +351,17 @@ mod issue13964 {
         };
     }
 }
+
+mod issue11059 {
+    use std::fmt::Debug;
+
+    fn box_coercion_unsize(o: Option<i32>) -> Box<dyn Debug> {
+        if let Some(o) = o { Box::new(o) } else { Box::new("foo") }
+    }
+
+    static S: String = String::new();
+
+    fn deref_with_overload(o: Option<&str>) -> &str {
+        if let Some(o) = o { o } else { &S }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index 1794ac57fe5..a1119d75c23 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -179,16 +179,20 @@ fn f() -> Option<()> {
 
 mod issue6675 {
     unsafe fn ptr_to_ref<'a, T>(p: *const T) -> &'a T {
-        #[allow(unused)]
-        let x = vec![0; 1000]; // future-proofing, make this function expensive.
-        &*p
+        unsafe {
+            #[allow(unused)]
+            let x = vec![0; 1000]; // future-proofing, make this function expensive.
+            &*p
+        }
     }
 
     unsafe fn foo() {
-        let s = "test".to_owned();
-        let s = &s as *const _;
-        None.unwrap_or_else(|| ptr_to_ref(s));
-        //~^ or_fun_call
+        unsafe {
+            let s = "test".to_owned();
+            let s = &s as *const _;
+            None.unwrap_or_else(|| ptr_to_ref(s));
+            //~^ or_fun_call
+        }
     }
 
     fn bar() {
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index 256db343c05..a7cd632bf16 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -179,16 +179,20 @@ fn f() -> Option<()> {
 
 mod issue6675 {
     unsafe fn ptr_to_ref<'a, T>(p: *const T) -> &'a T {
-        #[allow(unused)]
-        let x = vec![0; 1000]; // future-proofing, make this function expensive.
-        &*p
+        unsafe {
+            #[allow(unused)]
+            let x = vec![0; 1000]; // future-proofing, make this function expensive.
+            &*p
+        }
     }
 
     unsafe fn foo() {
-        let s = "test".to_owned();
-        let s = &s as *const _;
-        None.unwrap_or(ptr_to_ref(s));
-        //~^ or_fun_call
+        unsafe {
+            let s = "test".to_owned();
+            let s = &s as *const _;
+            None.unwrap_or(ptr_to_ref(s));
+            //~^ or_fun_call
+        }
     }
 
     fn bar() {
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index 93c87b2f12c..35bda7e4d33 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -125,91 +125,91 @@ LL |     let _ = Some("a".to_string()).or(Some("b".to_string()));
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:190:14
+  --> tests/ui/or_fun_call.rs:193:18
    |
-LL |         None.unwrap_or(ptr_to_ref(s));
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))`
+LL |             None.unwrap_or(ptr_to_ref(s));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:197:14
+  --> tests/ui/or_fun_call.rs:201:14
    |
 LL |         None.unwrap_or(unsafe { ptr_to_ref(s) });
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:200:14
+  --> tests/ui/or_fun_call.rs:204:14
    |
 LL |         None.unwrap_or( unsafe { ptr_to_ref(s) }    );
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: function call inside of `map_or`
-  --> tests/ui/or_fun_call.rs:276:25
+  --> tests/ui/or_fun_call.rs:280:25
    |
 LL |         let _ = Some(4).map_or(g(), |v| v);
    |                         ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)`
 
 error: function call inside of `map_or`
-  --> tests/ui/or_fun_call.rs:278:25
+  --> tests/ui/or_fun_call.rs:282:25
    |
 LL |         let _ = Some(4).map_or(g(), f);
    |                         ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:310:18
+  --> tests/ui/or_fun_call.rs:314:18
    |
 LL |         with_new.unwrap_or_else(Vec::new);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:314:28
+  --> tests/ui/or_fun_call.rs:318:28
    |
 LL |         with_default_trait.unwrap_or_else(Default::default);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:318:27
+  --> tests/ui/or_fun_call.rs:322:27
    |
 LL |         with_default_type.unwrap_or_else(u64::default);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:322:22
+  --> tests/ui/or_fun_call.rs:326:22
    |
 LL |         real_default.unwrap_or_else(<FakeDefault as Default>::default);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `or_insert_with` to construct default value
-  --> tests/ui/or_fun_call.rs:326:23
+  --> tests/ui/or_fun_call.rs:330:23
    |
 LL |         map.entry(42).or_insert_with(String::new);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `or_insert_with` to construct default value
-  --> tests/ui/or_fun_call.rs:330:25
+  --> tests/ui/or_fun_call.rs:334:25
    |
 LL |         btree.entry(42).or_insert_with(String::new);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:334:25
+  --> tests/ui/or_fun_call.rs:338:25
    |
 LL |         let _ = stringy.unwrap_or_else(String::new);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:376:17
+  --> tests/ui/or_fun_call.rs:380:17
    |
 LL |     let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
    |                 ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:381:17
+  --> tests/ui/or_fun_call.rs:385:17
    |
 LL |     let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
    |                 ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:386:17
+  --> tests/ui/or_fun_call.rs:390:17
    |
 LL |       let _ = opt.unwrap_or({
    |  _________________^
@@ -229,19 +229,19 @@ LL ~     });
    |
 
 error: function call inside of `map_or`
-  --> tests/ui/or_fun_call.rs:392:17
+  --> tests/ui/or_fun_call.rs:396:17
    |
 LL |     let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:397:17
+  --> tests/ui/or_fun_call.rs:401:17
    |
 LL |     let _ = opt.unwrap_or({ i32::default() });
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:404:21
+  --> tests/ui/or_fun_call.rs:408:21
    |
 LL |     let _ = opt_foo.unwrap_or(Foo { val: String::default() });
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })`
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.rs b/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.rs
index bdac3764bf1..643d8fedda9 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.rs
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.rs
@@ -1,5 +1,5 @@
-#![allow(clippy::all)]
 #![warn(clippy::pattern_type_mismatch)]
+#![allow(clippy::single_match)]
 
 fn main() {}
 
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.rs b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.rs
index 3c789f570b0..a1c447d2583 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.rs
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.rs
@@ -1,4 +1,3 @@
-#![allow(clippy::all)]
 #![warn(clippy::pattern_type_mismatch)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr
index 763f688ea89..b3ae63ec031 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr
@@ -1,5 +1,5 @@
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:15:12
+  --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:14:12
    |
 LL |     if let Value::B | Value::A(_) = ref_value {}
    |            ^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     if let Value::B | Value::A(_) = ref_value {}
    = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]`
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:18:34
+  --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:17:34
    |
 LL |     if let &Value::B | &Value::A(Some(_)) = ref_value {}
    |                                  ^^^^^^^
@@ -17,7 +17,7 @@ LL |     if let &Value::B | &Value::A(Some(_)) = ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:21:32
+  --> tests/ui/pattern_type_mismatch/pattern_alternatives.rs:20:32
    |
 LL |     if let Value::B | Value::A(Some(_)) = *ref_value {}
    |                                ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.rs b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.rs
index 7fc53d591a9..c5e395c4084 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.rs
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.rs
@@ -1,4 +1,3 @@
-#![allow(clippy::all)]
 #![warn(clippy::pattern_type_mismatch)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr
index 70f7bdc3890..e18a88c2bf5 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr
@@ -1,5 +1,5 @@
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:13:9
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:12:9
    |
 LL |     let Struct { .. } = ref_value;
    |         ^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     let Struct { .. } = ref_value;
    = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]`
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:16:33
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:15:33
    |
 LL |     if let &Struct { ref_inner: Some(_) } = ref_value {}
    |                                 ^^^^^^^
@@ -17,7 +17,7 @@ LL |     if let &Struct { ref_inner: Some(_) } = ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:19:32
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:18:32
    |
 LL |     if let Struct { ref_inner: Some(_) } = *ref_value {}
    |                                ^^^^^^^
@@ -25,7 +25,7 @@ LL |     if let Struct { ref_inner: Some(_) } = *ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:37:12
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:36:12
    |
 LL |     if let StructEnum::Var { .. } = ref_value {}
    |            ^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     if let StructEnum::Var { .. } = ref_value {}
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:40:12
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:39:12
    |
 LL |     if let StructEnum::Var { inner_ref: Some(_) } = ref_value {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL |     if let StructEnum::Var { inner_ref: Some(_) } = ref_value {}
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:43:42
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:42:42
    |
 LL |     if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {}
    |                                          ^^^^^^^
@@ -49,7 +49,7 @@ LL |     if let &StructEnum::Var { inner_ref: Some(_) } = ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:46:41
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:45:41
    |
 LL |     if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {}
    |                                         ^^^^^^^
@@ -57,7 +57,7 @@ LL |     if let StructEnum::Var { inner_ref: Some(_) } = *ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:49:12
+  --> tests/ui/pattern_type_mismatch/pattern_structs.rs:48:12
    |
 LL |     if let StructEnum::Empty = ref_value {}
    |            ^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.rs b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.rs
index ecd95d9ae2b..8bec5abc88f 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.rs
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.rs
@@ -1,4 +1,3 @@
-#![allow(clippy::all)]
 #![warn(clippy::pattern_type_mismatch)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr
index d47c5d509c3..ee307be63c1 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr
@@ -1,5 +1,5 @@
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:11:9
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:10:9
    |
 LL |     let TupleStruct(_) = ref_value;
    |         ^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     let TupleStruct(_) = ref_value;
    = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]`
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:14:25
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:13:25
    |
 LL |     if let &TupleStruct(Some(_)) = ref_value {}
    |                         ^^^^^^^
@@ -17,7 +17,7 @@ LL |     if let &TupleStruct(Some(_)) = ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:17:24
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:16:24
    |
 LL |     if let TupleStruct(Some(_)) = *ref_value {}
    |                        ^^^^^^^
@@ -25,7 +25,7 @@ LL |     if let TupleStruct(Some(_)) = *ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:35:12
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:34:12
    |
 LL |     if let TupleEnum::Var(_) = ref_value {}
    |            ^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     if let TupleEnum::Var(_) = ref_value {}
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:38:28
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:37:28
    |
 LL |     if let &TupleEnum::Var(Some(_)) = ref_value {}
    |                            ^^^^^^^
@@ -41,7 +41,7 @@ LL |     if let &TupleEnum::Var(Some(_)) = ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:41:27
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:40:27
    |
 LL |     if let TupleEnum::Var(Some(_)) = *ref_value {}
    |                           ^^^^^^^
@@ -49,7 +49,7 @@ LL |     if let TupleEnum::Var(Some(_)) = *ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:44:12
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:43:12
    |
 LL |     if let TupleEnum::Empty = ref_value {}
    |            ^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@ LL |     if let TupleEnum::Empty = ref_value {}
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:60:9
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:59:9
    |
 LL |     let (_a, _b) = ref_value;
    |         ^^^^^^^^
@@ -65,7 +65,7 @@ LL |     let (_a, _b) = ref_value;
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:63:18
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:62:18
    |
 LL |     if let &(_a, Some(_)) = ref_value {}
    |                  ^^^^^^^
@@ -73,7 +73,7 @@ LL |     if let &(_a, Some(_)) = ref_value {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:66:17
+  --> tests/ui/pattern_type_mismatch/pattern_tuples.rs:65:17
    |
 LL |     if let (_a, Some(_)) = *ref_value {}
    |                 ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.rs b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.rs
index 0bbc26a0c27..49ea1d3f7a6 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.rs
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.rs
@@ -1,5 +1,10 @@
-#![allow(clippy::all)]
 #![warn(clippy::pattern_type_mismatch)]
+#![allow(
+    clippy::match_ref_pats,
+    clippy::never_loop,
+    clippy::redundant_pattern_matching,
+    clippy::single_match
+)]
 
 fn main() {}
 
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr
index 3f6b5feb9b0..cd604d604c1 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr
@@ -1,5 +1,5 @@
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:11:9
+  --> tests/ui/pattern_type_mismatch/syntax.rs:16:9
    |
 LL |         Some(_) => (),
    |         ^^^^^^^
@@ -9,7 +9,7 @@ LL |         Some(_) => (),
    = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]`
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:31:12
+  --> tests/ui/pattern_type_mismatch/syntax.rs:36:12
    |
 LL |     if let Some(_) = ref_value {}
    |            ^^^^^^^
@@ -17,7 +17,7 @@ LL |     if let Some(_) = ref_value {}
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:43:15
+  --> tests/ui/pattern_type_mismatch/syntax.rs:48:15
    |
 LL |     while let Some(_) = ref_value {
    |               ^^^^^^^
@@ -25,7 +25,7 @@ LL |     while let Some(_) = ref_value {
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:63:9
+  --> tests/ui/pattern_type_mismatch/syntax.rs:68:9
    |
 LL |     for (_a, _b) in slice.iter() {}
    |         ^^^^^^^^
@@ -33,7 +33,7 @@ LL |     for (_a, _b) in slice.iter() {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:74:9
+  --> tests/ui/pattern_type_mismatch/syntax.rs:79:9
    |
 LL |     let (_n, _m) = ref_value;
    |         ^^^^^^^^
@@ -41,7 +41,7 @@ LL |     let (_n, _m) = ref_value;
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:84:12
+  --> tests/ui/pattern_type_mismatch/syntax.rs:89:12
    |
 LL |     fn foo((_a, _b): &(i32, i32)) {}
    |            ^^^^^^^^
@@ -49,7 +49,7 @@ LL |     fn foo((_a, _b): &(i32, i32)) {}
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:99:10
+  --> tests/ui/pattern_type_mismatch/syntax.rs:104:10
    |
 LL |     foo(|(_a, _b)| ());
    |          ^^^^^^^^
@@ -57,7 +57,7 @@ LL |     foo(|(_a, _b)| ());
    = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:116:9
+  --> tests/ui/pattern_type_mismatch/syntax.rs:121:9
    |
 LL |         Some(_) => (),
    |         ^^^^^^^
@@ -65,7 +65,7 @@ LL |         Some(_) => (),
    = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
 
 error: type of pattern does not match the expression type
-  --> tests/ui/pattern_type_mismatch/syntax.rs:137:17
+  --> tests/ui/pattern_type_mismatch/syntax.rs:142:17
    |
 LL |                 Some(_) => (),
    |                 ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/patterns.fixed b/src/tools/clippy/tests/ui/patterns.fixed
index bcb8ecfc38d..a6dd5fd63a9 100644
--- a/src/tools/clippy/tests/ui/patterns.fixed
+++ b/src/tools/clippy/tests/ui/patterns.fixed
@@ -1,6 +1,4 @@
 //@aux-build:proc_macros.rs
-#![warn(clippy::all)]
-#![allow(unused)]
 #![allow(clippy::uninlined_format_args, clippy::single_match)]
 
 #[macro_use]
diff --git a/src/tools/clippy/tests/ui/patterns.rs b/src/tools/clippy/tests/ui/patterns.rs
index 19639ebd13d..64bfbdecdac 100644
--- a/src/tools/clippy/tests/ui/patterns.rs
+++ b/src/tools/clippy/tests/ui/patterns.rs
@@ -1,6 +1,4 @@
 //@aux-build:proc_macros.rs
-#![warn(clippy::all)]
-#![allow(unused)]
 #![allow(clippy::uninlined_format_args, clippy::single_match)]
 
 #[macro_use]
diff --git a/src/tools/clippy/tests/ui/patterns.stderr b/src/tools/clippy/tests/ui/patterns.stderr
index b9950fe181c..ff5e1a8de90 100644
--- a/src/tools/clippy/tests/ui/patterns.stderr
+++ b/src/tools/clippy/tests/ui/patterns.stderr
@@ -1,5 +1,5 @@
 error: the `y @ _` pattern can be written as just `y`
-  --> tests/ui/patterns.rs:14:9
+  --> tests/ui/patterns.rs:12:9
    |
 LL |         y @ _ => (),
    |         ^^^^^ help: try: `y`
@@ -8,13 +8,13 @@ LL |         y @ _ => (),
    = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern)]`
 
 error: the `x @ _` pattern can be written as just `x`
-  --> tests/ui/patterns.rs:30:9
+  --> tests/ui/patterns.rs:28:9
    |
 LL |         ref mut x @ _ => {
    |         ^^^^^^^^^^^^^ help: try: `ref mut x`
 
 error: the `x @ _` pattern can be written as just `x`
-  --> tests/ui/patterns.rs:39:9
+  --> tests/ui/patterns.rs:37:9
    |
 LL |         ref x @ _ => println!("vec: {:?}", x),
    |         ^^^^^^^^^ help: try: `ref x`
diff --git a/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs
index 171716be260..7f69c61b028 100644
--- a/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs
+++ b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs
@@ -6,29 +6,37 @@
 use core::arch::asm;
 
 unsafe fn nomem_bad(p: &i32) {
-    asm!(
-        "asdf {p1}, {p2}, {p3}",
-        p1 = in(reg) p,
-        //~^ pointers_in_nomem_asm_block
+    unsafe {
+        asm!(
+            "asdf {p1}, {p2}, {p3}",
+            p1 = in(reg) p,
+            //~^ pointers_in_nomem_asm_block
 
-        p2 = in(reg) p as *const _ as usize,
-        p3 = in(reg) p,
-        options(nomem, nostack, preserves_flags)
-    );
+            p2 = in(reg) p as *const _ as usize,
+            p3 = in(reg) p,
+            options(nomem, nostack, preserves_flags)
+        );
+    }
 }
 
 unsafe fn nomem_good(p: &i32) {
-    asm!("asdf {p}", p = in(reg) p, options(readonly, nostack, preserves_flags));
-    let p = p as *const i32 as usize;
-    asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+    unsafe {
+        asm!("asdf {p}", p = in(reg) p, options(readonly, nostack, preserves_flags));
+        let p = p as *const i32 as usize;
+        asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+    }
 }
 
 unsafe fn nomem_bad2(p: &mut i32) {
-    asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
-    //~^ pointers_in_nomem_asm_block
+    unsafe {
+        asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+        //~^ pointers_in_nomem_asm_block
+    }
 }
 
 unsafe fn nomem_fn(p: extern "C" fn()) {
-    asm!("call {p}", p = in(reg) p, options(nomem));
-    //~^ pointers_in_nomem_asm_block
+    unsafe {
+        asm!("call {p}", p = in(reg) p, options(nomem));
+        //~^ pointers_in_nomem_asm_block
+    }
 }
diff --git a/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr
index ca24e34f63c..eabac2444ec 100644
--- a/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr
+++ b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr
@@ -1,11 +1,11 @@
 error: passing pointers to nomem asm block
-  --> tests/ui/pointers_in_nomem_asm_block.rs:11:9
+  --> tests/ui/pointers_in_nomem_asm_block.rs:12:13
    |
-LL |         p1 = in(reg) p,
-   |         ^^^^^^^^^^^^^^
+LL |             p1 = in(reg) p,
+   |             ^^^^^^^^^^^^^^
 ...
-LL |         p3 = in(reg) p,
-   |         ^^^^^^^^^^^^^^
+LL |             p3 = in(reg) p,
+   |             ^^^^^^^^^^^^^^
    |
    = note: `nomem` means that no memory write or read happens inside the asm! block
    = note: if this is intentional and no pointers are read or written to, consider allowing the lint
@@ -13,19 +13,19 @@ LL |         p3 = in(reg) p,
    = help: to override `-D warnings` add `#[allow(clippy::pointers_in_nomem_asm_block)]`
 
 error: passing pointers to nomem asm block
-  --> tests/ui/pointers_in_nomem_asm_block.rs:27:22
+  --> tests/ui/pointers_in_nomem_asm_block.rs:32:26
    |
-LL |     asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
-   |                      ^^^^^^^^^^^^^
+LL |         asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+   |                          ^^^^^^^^^^^^^
    |
    = note: `nomem` means that no memory write or read happens inside the asm! block
    = note: if this is intentional and no pointers are read or written to, consider allowing the lint
 
 error: passing pointers to nomem asm block
-  --> tests/ui/pointers_in_nomem_asm_block.rs:32:22
+  --> tests/ui/pointers_in_nomem_asm_block.rs:39:26
    |
-LL |     asm!("call {p}", p = in(reg) p, options(nomem));
-   |                      ^^^^^^^^^^^^^
+LL |         asm!("call {p}", p = in(reg) p, options(nomem));
+   |                          ^^^^^^^^^^^^^
    |
    = note: `nomem` means that no memory write or read happens inside the asm! block
    = note: if this is intentional and no pointers are read or written to, consider allowing the lint
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
index 6dded72d3e1..79bfae1f7eb 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
@@ -12,11 +12,13 @@ extern crate proc_macros;
 use proc_macros::{external, inline_macros};
 
 unsafe fn ptr_to_ref<T, U>(p: *const T, om: *mut U) {
-    let _: &mut T = std::mem::transmute(p.cast_mut());
-    //~^ ptr_cast_constness
-    let _ = &mut *p.cast_mut();
-    //~^ ptr_cast_constness
-    let _: &T = &*(om as *const T);
+    unsafe {
+        let _: &mut T = std::mem::transmute(p.cast_mut());
+        //~^ ptr_cast_constness
+        let _ = &mut *p.cast_mut();
+        //~^ ptr_cast_constness
+        let _: &T = &*(om as *const T);
+    }
 }
 
 #[inline_macros]
@@ -98,3 +100,9 @@ fn null_pointers() {
     let _ = external!(ptr::null::<u32>() as *mut u32);
     let _ = external!(ptr::null::<u32>().cast_mut());
 }
+
+fn issue14621() {
+    let mut local = 4;
+    let _ = std::ptr::addr_of_mut!(local).cast_const();
+    //~^ ptr_cast_constness
+}
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.rs b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
index e9629f5290e..f6590dabd5b 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.rs
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
@@ -12,11 +12,13 @@ extern crate proc_macros;
 use proc_macros::{external, inline_macros};
 
 unsafe fn ptr_to_ref<T, U>(p: *const T, om: *mut U) {
-    let _: &mut T = std::mem::transmute(p as *mut T);
-    //~^ ptr_cast_constness
-    let _ = &mut *(p as *mut T);
-    //~^ ptr_cast_constness
-    let _: &T = &*(om as *const T);
+    unsafe {
+        let _: &mut T = std::mem::transmute(p as *mut T);
+        //~^ ptr_cast_constness
+        let _ = &mut *(p as *mut T);
+        //~^ ptr_cast_constness
+        let _: &T = &*(om as *const T);
+    }
 }
 
 #[inline_macros]
@@ -98,3 +100,9 @@ fn null_pointers() {
     let _ = external!(ptr::null::<u32>() as *mut u32);
     let _ = external!(ptr::null::<u32>().cast_mut());
 }
+
+fn issue14621() {
+    let mut local = 4;
+    let _ = std::ptr::addr_of_mut!(local) as *const _;
+    //~^ ptr_cast_constness
+}
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
index 1eeeef74701..0b1644168ff 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
@@ -1,74 +1,74 @@
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:15:41
+  --> tests/ui/ptr_cast_constness.rs:16:45
    |
-LL |     let _: &mut T = std::mem::transmute(p as *mut T);
-   |                                         ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
+LL |         let _: &mut T = std::mem::transmute(p as *mut T);
+   |                                             ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
    |
    = note: `-D clippy::ptr-cast-constness` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::ptr_cast_constness)]`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:17:19
+  --> tests/ui/ptr_cast_constness.rs:18:23
    |
-LL |     let _ = &mut *(p as *mut T);
-   |                   ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
+LL |         let _ = &mut *(p as *mut T);
+   |                       ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:33:17
+  --> tests/ui/ptr_cast_constness.rs:35:17
    |
 LL |         let _ = *ptr_ptr as *mut u32;
    |                 ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:37:13
+  --> tests/ui/ptr_cast_constness.rs:39:13
    |
 LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:39:13
+  --> tests/ui/ptr_cast_constness.rs:41:13
    |
 LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:73:13
+  --> tests/ui/ptr_cast_constness.rs:75:13
    |
 LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:75:13
+  --> tests/ui/ptr_cast_constness.rs:77:13
    |
 LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
 error: `as` casting to make a const null pointer into a mutable null pointer
-  --> tests/ui/ptr_cast_constness.rs:82:13
+  --> tests/ui/ptr_cast_constness.rs:84:13
    |
 LL |     let _ = ptr::null::<String>() as *mut String;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<String>()`
 
 error: `as` casting to make a mutable null pointer into a const null pointer
-  --> tests/ui/ptr_cast_constness.rs:84:13
+  --> tests/ui/ptr_cast_constness.rs:86:13
    |
 LL |     let _ = ptr::null_mut::<u32>() as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
 
 error: changing constness of a null pointer
-  --> tests/ui/ptr_cast_constness.rs:86:13
+  --> tests/ui/ptr_cast_constness.rs:88:13
    |
 LL |     let _ = ptr::null::<u32>().cast_mut();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
 
 error: changing constness of a null pointer
-  --> tests/ui/ptr_cast_constness.rs:88:13
+  --> tests/ui/ptr_cast_constness.rs:90:13
    |
 LL |     let _ = ptr::null_mut::<u32>().cast_const();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
 
 error: `as` casting to make a const null pointer into a mutable null pointer
-  --> tests/ui/ptr_cast_constness.rs:92:21
+  --> tests/ui/ptr_cast_constness.rs:94:21
    |
 LL |     let _ = inline!(ptr::null::<u32>() as *mut u32);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
@@ -76,12 +76,18 @@ LL |     let _ = inline!(ptr::null::<u32>() as *mut u32);
    = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: changing constness of a null pointer
-  --> tests/ui/ptr_cast_constness.rs:94:21
+  --> tests/ui/ptr_cast_constness.rs:96:21
    |
 LL |     let _ = inline!(ptr::null::<u32>().cast_mut());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
    |
    = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 13 previous errors
+error: `as` casting between raw pointers while changing only its constness
+  --> tests/ui/ptr_cast_constness.rs:106:13
+   |
+LL |     let _ = std::ptr::addr_of_mut!(local) as *const _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `std::ptr::addr_of_mut!(local).cast_const()`
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ptr_eq.fixed b/src/tools/clippy/tests/ui/ptr_eq.fixed
index df6305ed497..484ff307323 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.fixed
+++ b/src/tools/clippy/tests/ui/ptr_eq.fixed
@@ -4,6 +4,9 @@ macro_rules! mac {
     ($a:expr, $b:expr) => {
         $a as *const _ as usize == $b as *const _ as usize
     };
+    (cast $a:expr) => {
+        $a as *const [i32; 3]
+    };
 }
 
 macro_rules! another_mac {
@@ -51,4 +54,8 @@ fn main() {
     #[allow(clippy::eq_op)]
     let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
     //~^ ptr_eq
+
+    // Do not peel the content of macros
+    let _ = std::ptr::eq(mac!(cast a), mac!(cast b));
+    //~^ ptr_eq
 }
diff --git a/src/tools/clippy/tests/ui/ptr_eq.rs b/src/tools/clippy/tests/ui/ptr_eq.rs
index 0ed0ff0d137..f28707cc3e9 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.rs
+++ b/src/tools/clippy/tests/ui/ptr_eq.rs
@@ -4,6 +4,9 @@ macro_rules! mac {
     ($a:expr, $b:expr) => {
         $a as *const _ as usize == $b as *const _ as usize
     };
+    (cast $a:expr) => {
+        $a as *const [i32; 3]
+    };
 }
 
 macro_rules! another_mac {
@@ -51,4 +54,8 @@ fn main() {
     #[allow(clippy::eq_op)]
     let _issue14337 = main as *const () == main as *const ();
     //~^ ptr_eq
+
+    // Do not peel the content of macros
+    let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
+    //~^ ptr_eq
 }
diff --git a/src/tools/clippy/tests/ui/ptr_eq.stderr b/src/tools/clippy/tests/ui/ptr_eq.stderr
index 33190df284a..906831b9e03 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.stderr
+++ b/src/tools/clippy/tests/ui/ptr_eq.stderr
@@ -1,5 +1,5 @@
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:19:13
+  --> tests/ui/ptr_eq.rs:22:13
    |
 LL |     let _ = a as *const _ as usize == b as *const _ as usize;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
@@ -8,52 +8,58 @@ LL |     let _ = a as *const _ as usize == b as *const _ as usize;
    = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:21:13
+  --> tests/ui/ptr_eq.rs:24:13
    |
 LL |     let _ = a as *const _ == b as *const _;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:23:13
+  --> tests/ui/ptr_eq.rs:26:13
    |
 LL |     let _ = a.as_ptr() == b as *const _;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:25:13
+  --> tests/ui/ptr_eq.rs:28:13
    |
 LL |     let _ = a.as_ptr() == b.as_ptr();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:36:13
+  --> tests/ui/ptr_eq.rs:39:13
    |
 LL |     let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:38:13
+  --> tests/ui/ptr_eq.rs:41:13
    |
 LL |     let _ = a.as_mut_ptr() == b.as_mut_ptr();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:45:13
+  --> tests/ui/ptr_eq.rs:48:13
    |
 LL |     let _ = x as *const u32 == y as *mut u32 as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:48:13
+  --> tests/ui/ptr_eq.rs:51:13
    |
 LL |     let _ = x as *const u32 != y as *mut u32 as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:52:23
+  --> tests/ui/ptr_eq.rs:55:23
    |
 LL |     let _issue14337 = main as *const () == main as *const ();
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
 
-error: aborting due to 9 previous errors
+error: use `std::ptr::eq` when comparing raw pointers
+  --> tests/ui/ptr_eq.rs:59:13
+   |
+LL |     let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index fff41f57828..6bd071d07f5 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -3,6 +3,8 @@
 #![allow(dead_code)]
 #![allow(clippy::unnecessary_wraps)]
 
+use std::sync::MutexGuard;
+
 fn some_func(a: Option<u32>) -> Option<u32> {
     a?;
 
@@ -430,3 +432,9 @@ fn msrv_1_13(arg: Option<i32>) -> Option<i32> {
     println!("{}", val);
     Some(val)
 }
+
+fn issue_14615(a: MutexGuard<Option<u32>>) -> Option<String> {
+    let a = (*a)?;
+    //~^^^ question_mark
+    Some(format!("{a}"))
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index c71c8ee984e..dd093c9bf48 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -3,6 +3,8 @@
 #![allow(dead_code)]
 #![allow(clippy::unnecessary_wraps)]
 
+use std::sync::MutexGuard;
+
 fn some_func(a: Option<u32>) -> Option<u32> {
     if a.is_none() {
         //~^ question_mark
@@ -524,3 +526,11 @@ fn msrv_1_13(arg: Option<i32>) -> Option<i32> {
     println!("{}", val);
     Some(val)
 }
+
+fn issue_14615(a: MutexGuard<Option<u32>>) -> Option<String> {
+    let Some(a) = *a else {
+        return None;
+    };
+    //~^^^ question_mark
+    Some(format!("{a}"))
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 183b8866a74..8fe04b895ce 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -1,5 +1,5 @@
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:7:5
+  --> tests/ui/question_mark.rs:9:5
    |
 LL | /     if a.is_none() {
 LL | |
@@ -11,7 +11,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::question_mark)]`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:53:9
+  --> tests/ui/question_mark.rs:55:9
    |
 LL | /         if (self.opt).is_none() {
 LL | |
@@ -20,7 +20,7 @@ LL | |         }
    | |_________^ help: replace it with: `(self.opt)?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:58:9
+  --> tests/ui/question_mark.rs:60:9
    |
 LL | /         if self.opt.is_none() {
 LL | |
@@ -29,7 +29,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:63:17
+  --> tests/ui/question_mark.rs:65:17
    |
 LL |           let _ = if self.opt.is_none() {
    |  _________________^
@@ -41,7 +41,7 @@ LL | |         };
    | |_________^ help: replace it with: `Some(self.opt?)`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:70:17
+  --> tests/ui/question_mark.rs:72:17
    |
 LL |           let _ = if let Some(x) = self.opt {
    |  _________________^
@@ -53,7 +53,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:88:9
+  --> tests/ui/question_mark.rs:90:9
    |
 LL | /         if self.opt.is_none() {
 LL | |
@@ -62,7 +62,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:97:9
+  --> tests/ui/question_mark.rs:99:9
    |
 LL | /         if self.opt.is_none() {
 LL | |
@@ -71,7 +71,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:106:9
+  --> tests/ui/question_mark.rs:108:9
    |
 LL | /         if self.opt.is_none() {
 LL | |
@@ -80,7 +80,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:114:26
+  --> tests/ui/question_mark.rs:116:26
    |
 LL |           let v: &Vec<_> = if let Some(ref v) = self.opt {
    |  __________________________^
@@ -92,7 +92,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt.as_ref()?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:125:17
+  --> tests/ui/question_mark.rs:127:17
    |
 LL |           let v = if let Some(v) = self.opt {
    |  _________________^
@@ -104,7 +104,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:147:5
+  --> tests/ui/question_mark.rs:149:5
    |
 LL | /     if f().is_none() {
 LL | |
@@ -113,7 +113,7 @@ LL | |     }
    | |_____^ help: replace it with: `f()?;`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:152:16
+  --> tests/ui/question_mark.rs:154:16
    |
 LL |       let _val = match f() {
    |  ________________^
@@ -124,7 +124,7 @@ LL | |     };
    | |_____^ help: try instead: `f()?`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:163:5
+  --> tests/ui/question_mark.rs:165:5
    |
 LL | /     match f() {
 LL | |
@@ -134,7 +134,7 @@ LL | |     };
    | |_____^ help: try instead: `f()?`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:169:5
+  --> tests/ui/question_mark.rs:171:5
    |
 LL | /     match opt_none!() {
 LL | |
@@ -144,13 +144,13 @@ LL | |     };
    | |_____^ help: try instead: `opt_none!()?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:196:13
+  --> tests/ui/question_mark.rs:198:13
    |
 LL |     let _ = if let Ok(x) = x { x } else { return x };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:199:5
+  --> tests/ui/question_mark.rs:201:5
    |
 LL | /     if x.is_err() {
 LL | |
@@ -159,7 +159,7 @@ LL | |     }
    | |_____^ help: replace it with: `x?;`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:204:16
+  --> tests/ui/question_mark.rs:206:16
    |
 LL |       let _val = match func_returning_result() {
    |  ________________^
@@ -170,7 +170,7 @@ LL | |     };
    | |_____^ help: try instead: `func_returning_result()?`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:210:5
+  --> tests/ui/question_mark.rs:212:5
    |
 LL | /     match func_returning_result() {
 LL | |
@@ -180,7 +180,7 @@ LL | |     };
    | |_____^ help: try instead: `func_returning_result()?`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:302:5
+  --> tests/ui/question_mark.rs:304:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |
@@ -189,7 +189,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:310:5
+  --> tests/ui/question_mark.rs:312:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |
@@ -198,7 +198,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:388:13
+  --> tests/ui/question_mark.rs:390:13
    |
 LL | /             if a.is_none() {
 LL | |
@@ -208,7 +208,7 @@ LL | |             }
    | |_____________^ help: replace it with: `a?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:449:5
+  --> tests/ui/question_mark.rs:451:5
    |
 LL | /     let Some(v) = bar.foo.owned.clone() else {
 LL | |         return None;
@@ -216,7 +216,7 @@ LL | |     };
    | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:464:5
+  --> tests/ui/question_mark.rs:466:5
    |
 LL | /     let Some(ref x) = foo.opt_x else {
 LL | |         return None;
@@ -224,7 +224,7 @@ LL | |     };
    | |______^ help: replace it with: `let x = foo.opt_x.as_ref()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:474:5
+  --> tests/ui/question_mark.rs:476:5
    |
 LL | /     let Some(ref mut x) = foo.opt_x else {
 LL | |         return None;
@@ -232,7 +232,7 @@ LL | |     };
    | |______^ help: replace it with: `let x = foo.opt_x.as_mut()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:485:5
+  --> tests/ui/question_mark.rs:487:5
    |
 LL | /     let Some(ref x @ ref y) = foo.opt_x else {
 LL | |         return None;
@@ -240,7 +240,7 @@ LL | |     };
    | |______^ help: replace it with: `let x @ y = foo.opt_x.as_ref()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:489:5
+  --> tests/ui/question_mark.rs:491:5
    |
 LL | /     let Some(ref x @ WrapperStructWithString(_)) = bar else {
 LL | |         return None;
@@ -248,7 +248,7 @@ LL | |     };
    | |______^ help: replace it with: `let x @ &WrapperStructWithString(_) = bar.as_ref()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:493:5
+  --> tests/ui/question_mark.rs:495:5
    |
 LL | /     let Some(ref mut x @ WrapperStructWithString(_)) = bar else {
 LL | |         return None;
@@ -256,7 +256,7 @@ LL | |     };
    | |______^ help: replace it with: `let x @ &mut WrapperStructWithString(_) = bar.as_mut()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:515:5
+  --> tests/ui/question_mark.rs:517:5
    |
 LL | /     if arg.is_none() {
 LL | |
@@ -265,7 +265,7 @@ LL | |     }
    | |_____^ help: replace it with: `arg?;`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:519:15
+  --> tests/ui/question_mark.rs:521:15
    |
 LL |       let val = match arg {
    |  _______________^
@@ -275,5 +275,13 @@ LL | |         None => return None,
 LL | |     };
    | |_____^ help: try instead: `arg?`
 
-error: aborting due to 29 previous errors
+error: this `let...else` may be rewritten with the `?` operator
+  --> tests/ui/question_mark.rs:531:5
+   |
+LL | /     let Some(a) = *a else {
+LL | |         return None;
+LL | |     };
+   | |______^ help: replace it with: `let a = (*a)?;`
+
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_allocation.rs b/src/tools/clippy/tests/ui/redundant_allocation.rs
index 0562f7dcc76..832f147c6ed 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation.rs
+++ b/src/tools/clippy/tests/ui/redundant_allocation.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all)]
 #![allow(clippy::boxed_local, clippy::disallowed_names)]
 
 pub struct MyStruct;
diff --git a/src/tools/clippy/tests/ui/redundant_allocation.stderr b/src/tools/clippy/tests/ui/redundant_allocation.stderr
index 44d30f95d7b..886ed2088c6 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation.stderr
+++ b/src/tools/clippy/tests/ui/redundant_allocation.stderr
@@ -1,5 +1,5 @@
 error: usage of `Box<Rc<T>>`
-  --> tests/ui/redundant_allocation.rs:16:30
+  --> tests/ui/redundant_allocation.rs:15:30
    |
 LL |     pub fn box_test6<T>(foo: Box<Rc<T>>) {}
    |                              ^^^^^^^^^^
@@ -10,7 +10,7 @@ LL |     pub fn box_test6<T>(foo: Box<Rc<T>>) {}
    = help: to override `-D warnings` add `#[allow(clippy::redundant_allocation)]`
 
 error: usage of `Box<Arc<T>>`
-  --> tests/ui/redundant_allocation.rs:19:30
+  --> tests/ui/redundant_allocation.rs:18:30
    |
 LL |     pub fn box_test7<T>(foo: Box<Arc<T>>) {}
    |                              ^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     pub fn box_test7<T>(foo: Box<Arc<T>>) {}
    = help: consider using just `Box<T>` or `Arc<T>`
 
 error: usage of `Box<Rc<SubT<usize>>>`
-  --> tests/ui/redundant_allocation.rs:22:27
+  --> tests/ui/redundant_allocation.rs:21:27
    |
 LL |     pub fn box_test8() -> Box<Rc<SubT<usize>>> {
    |                           ^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL |     pub fn box_test8() -> Box<Rc<SubT<usize>>> {
    = help: consider using just `Box<SubT<usize>>` or `Rc<SubT<usize>>`
 
 error: usage of `Box<Arc<T>>`
-  --> tests/ui/redundant_allocation.rs:28:30
+  --> tests/ui/redundant_allocation.rs:27:30
    |
 LL |     pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
    |                              ^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL |     pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
    = help: consider using just `Box<T>` or `Arc<T>`
 
 error: usage of `Box<Arc<SubT<T>>>`
-  --> tests/ui/redundant_allocation.rs:28:46
+  --> tests/ui/redundant_allocation.rs:27:46
    |
 LL |     pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
    |                                              ^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL |     pub fn box_test9<T>(foo: Box<Arc<T>>) -> Box<Arc<SubT<T>>> {
    = help: consider using just `Box<SubT<T>>` or `Arc<SubT<T>>`
 
 error: usage of `Rc<Box<bool>>`
-  --> tests/ui/redundant_allocation.rs:42:24
+  --> tests/ui/redundant_allocation.rs:41:24
    |
 LL |     pub fn rc_test5(a: Rc<Box<bool>>) {}
    |                        ^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     pub fn rc_test5(a: Rc<Box<bool>>) {}
    = help: consider using just `Rc<bool>` or `Box<bool>`
 
 error: usage of `Rc<Arc<bool>>`
-  --> tests/ui/redundant_allocation.rs:45:24
+  --> tests/ui/redundant_allocation.rs:44:24
    |
 LL |     pub fn rc_test7(a: Rc<Arc<bool>>) {}
    |                        ^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     pub fn rc_test7(a: Rc<Arc<bool>>) {}
    = help: consider using just `Rc<bool>` or `Arc<bool>`
 
 error: usage of `Rc<Box<SubT<usize>>>`
-  --> tests/ui/redundant_allocation.rs:48:26
+  --> tests/ui/redundant_allocation.rs:47:26
    |
 LL |     pub fn rc_test8() -> Rc<Box<SubT<usize>>> {
    |                          ^^^^^^^^^^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL |     pub fn rc_test8() -> Rc<Box<SubT<usize>>> {
    = help: consider using just `Rc<SubT<usize>>` or `Box<SubT<usize>>`
 
 error: usage of `Rc<Arc<T>>`
-  --> tests/ui/redundant_allocation.rs:54:29
+  --> tests/ui/redundant_allocation.rs:53:29
    |
 LL |     pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
    |                             ^^^^^^^^^^
@@ -82,7 +82,7 @@ LL |     pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
    = help: consider using just `Rc<T>` or `Arc<T>`
 
 error: usage of `Rc<Arc<SubT<T>>>`
-  --> tests/ui/redundant_allocation.rs:54:44
+  --> tests/ui/redundant_allocation.rs:53:44
    |
 LL |     pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
    |                                            ^^^^^^^^^^^^^^^^
@@ -91,7 +91,7 @@ LL |     pub fn rc_test9<T>(foo: Rc<Arc<T>>) -> Rc<Arc<SubT<T>>> {
    = help: consider using just `Rc<SubT<T>>` or `Arc<SubT<T>>`
 
 error: usage of `Arc<Box<bool>>`
-  --> tests/ui/redundant_allocation.rs:68:25
+  --> tests/ui/redundant_allocation.rs:67:25
    |
 LL |     pub fn arc_test5(a: Arc<Box<bool>>) {}
    |                         ^^^^^^^^^^^^^^
@@ -100,7 +100,7 @@ LL |     pub fn arc_test5(a: Arc<Box<bool>>) {}
    = help: consider using just `Arc<bool>` or `Box<bool>`
 
 error: usage of `Arc<Rc<bool>>`
-  --> tests/ui/redundant_allocation.rs:71:25
+  --> tests/ui/redundant_allocation.rs:70:25
    |
 LL |     pub fn arc_test6(a: Arc<Rc<bool>>) {}
    |                         ^^^^^^^^^^^^^
@@ -109,7 +109,7 @@ LL |     pub fn arc_test6(a: Arc<Rc<bool>>) {}
    = help: consider using just `Arc<bool>` or `Rc<bool>`
 
 error: usage of `Arc<Box<SubT<usize>>>`
-  --> tests/ui/redundant_allocation.rs:74:27
+  --> tests/ui/redundant_allocation.rs:73:27
    |
 LL |     pub fn arc_test8() -> Arc<Box<SubT<usize>>> {
    |                           ^^^^^^^^^^^^^^^^^^^^^
@@ -118,7 +118,7 @@ LL |     pub fn arc_test8() -> Arc<Box<SubT<usize>>> {
    = help: consider using just `Arc<SubT<usize>>` or `Box<SubT<usize>>`
 
 error: usage of `Arc<Rc<T>>`
-  --> tests/ui/redundant_allocation.rs:80:30
+  --> tests/ui/redundant_allocation.rs:79:30
    |
 LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
    |                              ^^^^^^^^^^
@@ -127,7 +127,7 @@ LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
    = help: consider using just `Arc<T>` or `Rc<T>`
 
 error: usage of `Arc<Rc<SubT<T>>>`
-  --> tests/ui/redundant_allocation.rs:80:45
+  --> tests/ui/redundant_allocation.rs:79:45
    |
 LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
    |                                             ^^^^^^^^^^^^^^^^
@@ -136,7 +136,7 @@ LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
    = help: consider using just `Arc<SubT<T>>` or `Rc<SubT<T>>`
 
 error: usage of `Rc<Box<Box<dyn T>>>`
-  --> tests/ui/redundant_allocation.rs:105:27
+  --> tests/ui/redundant_allocation.rs:104:27
    |
 LL |     pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {}
    |                           ^^^^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ LL |     pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {}
    = help: consider using just `Rc<Box<dyn T>>` or `Box<Box<dyn T>>`
 
 error: usage of `Rc<Box<Box<str>>>`
-  --> tests/ui/redundant_allocation.rs:138:31
+  --> tests/ui/redundant_allocation.rs:137:31
    |
 LL |     pub fn test_rc_box_str(_: Rc<Box<Box<str>>>) {}
    |                               ^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL |     pub fn test_rc_box_str(_: Rc<Box<Box<str>>>) {}
    = help: consider using just `Rc<Box<str>>` or `Box<Box<str>>`
 
 error: usage of `Rc<Box<Box<[usize]>>>`
-  --> tests/ui/redundant_allocation.rs:141:33
+  --> tests/ui/redundant_allocation.rs:140:33
    |
 LL |     pub fn test_rc_box_slice(_: Rc<Box<Box<[usize]>>>) {}
    |                                 ^^^^^^^^^^^^^^^^^^^^^
@@ -163,7 +163,7 @@ LL |     pub fn test_rc_box_slice(_: Rc<Box<Box<[usize]>>>) {}
    = help: consider using just `Rc<Box<[usize]>>` or `Box<Box<[usize]>>`
 
 error: usage of `Rc<Box<Box<Path>>>`
-  --> tests/ui/redundant_allocation.rs:144:32
+  --> tests/ui/redundant_allocation.rs:143:32
    |
 LL |     pub fn test_rc_box_path(_: Rc<Box<Box<Path>>>) {}
    |                                ^^^^^^^^^^^^^^^^^^
@@ -172,7 +172,7 @@ LL |     pub fn test_rc_box_path(_: Rc<Box<Box<Path>>>) {}
    = help: consider using just `Rc<Box<Path>>` or `Box<Box<Path>>`
 
 error: usage of `Rc<Box<Box<DynSized>>>`
-  --> tests/ui/redundant_allocation.rs:147:34
+  --> tests/ui/redundant_allocation.rs:146:34
    |
 LL |     pub fn test_rc_box_custom(_: Rc<Box<Box<DynSized>>>) {}
    |                                  ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
index 7773ba11f97..dbc6c0794d1 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
+++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.fixed
@@ -1,7 +1,5 @@
-#![warn(clippy::all)]
 #![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
-#![allow(clippy::disallowed_names, unused_variables, dead_code)]
-#![allow(unused_imports)]
+#![allow(clippy::disallowed_names)]
 
 pub struct MyStruct;
 
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
index fb86ed2b3cf..05b6429492c 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
+++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.rs
@@ -1,7 +1,5 @@
-#![warn(clippy::all)]
 #![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
-#![allow(clippy::disallowed_names, unused_variables, dead_code)]
-#![allow(unused_imports)]
+#![allow(clippy::disallowed_names)]
 
 pub struct MyStruct;
 
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr b/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
index ed8282cc82c..40737668871 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
+++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
@@ -1,5 +1,5 @@
 error: usage of `Box<&T>`
-  --> tests/ui/redundant_allocation_fixable.rs:23:30
+  --> tests/ui/redundant_allocation_fixable.rs:21:30
    |
 LL |     pub fn box_test1<T>(foo: Box<&T>) {}
    |                              ^^^^^^^ help: try: `&T`
@@ -9,7 +9,7 @@ LL |     pub fn box_test1<T>(foo: Box<&T>) {}
    = help: to override `-D warnings` add `#[allow(clippy::redundant_allocation)]`
 
 error: usage of `Box<&MyStruct>`
-  --> tests/ui/redundant_allocation_fixable.rs:26:27
+  --> tests/ui/redundant_allocation_fixable.rs:24:27
    |
 LL |     pub fn box_test2(foo: Box<&MyStruct>) {}
    |                           ^^^^^^^^^^^^^^ help: try: `&MyStruct`
@@ -17,7 +17,7 @@ LL |     pub fn box_test2(foo: Box<&MyStruct>) {}
    = note: `&MyStruct` is already a pointer, `Box<&MyStruct>` allocates a pointer on the heap
 
 error: usage of `Box<&MyEnum>`
-  --> tests/ui/redundant_allocation_fixable.rs:29:27
+  --> tests/ui/redundant_allocation_fixable.rs:27:27
    |
 LL |     pub fn box_test3(foo: Box<&MyEnum>) {}
    |                           ^^^^^^^^^^^^ help: try: `&MyEnum`
@@ -25,7 +25,7 @@ LL |     pub fn box_test3(foo: Box<&MyEnum>) {}
    = note: `&MyEnum` is already a pointer, `Box<&MyEnum>` allocates a pointer on the heap
 
 error: usage of `Box<Box<T>>`
-  --> tests/ui/redundant_allocation_fixable.rs:34:30
+  --> tests/ui/redundant_allocation_fixable.rs:32:30
    |
 LL |     pub fn box_test5<T>(foo: Box<Box<T>>) {}
    |                              ^^^^^^^^^^^ help: try: `Box<T>`
@@ -33,7 +33,7 @@ LL |     pub fn box_test5<T>(foo: Box<Box<T>>) {}
    = note: `Box<T>` is already on the heap, `Box<Box<T>>` makes an extra allocation
 
 error: usage of `Rc<&T>`
-  --> tests/ui/redundant_allocation_fixable.rs:44:29
+  --> tests/ui/redundant_allocation_fixable.rs:42:29
    |
 LL |     pub fn rc_test1<T>(foo: Rc<&T>) {}
    |                             ^^^^^^ help: try: `&T`
@@ -41,7 +41,7 @@ LL |     pub fn rc_test1<T>(foo: Rc<&T>) {}
    = note: `&T` is already a pointer, `Rc<&T>` allocates a pointer on the heap
 
 error: usage of `Rc<&MyStruct>`
-  --> tests/ui/redundant_allocation_fixable.rs:47:26
+  --> tests/ui/redundant_allocation_fixable.rs:45:26
    |
 LL |     pub fn rc_test2(foo: Rc<&MyStruct>) {}
    |                          ^^^^^^^^^^^^^ help: try: `&MyStruct`
@@ -49,7 +49,7 @@ LL |     pub fn rc_test2(foo: Rc<&MyStruct>) {}
    = note: `&MyStruct` is already a pointer, `Rc<&MyStruct>` allocates a pointer on the heap
 
 error: usage of `Rc<&MyEnum>`
-  --> tests/ui/redundant_allocation_fixable.rs:50:26
+  --> tests/ui/redundant_allocation_fixable.rs:48:26
    |
 LL |     pub fn rc_test3(foo: Rc<&MyEnum>) {}
    |                          ^^^^^^^^^^^ help: try: `&MyEnum`
@@ -57,7 +57,7 @@ LL |     pub fn rc_test3(foo: Rc<&MyEnum>) {}
    = note: `&MyEnum` is already a pointer, `Rc<&MyEnum>` allocates a pointer on the heap
 
 error: usage of `Rc<Rc<bool>>`
-  --> tests/ui/redundant_allocation_fixable.rs:55:24
+  --> tests/ui/redundant_allocation_fixable.rs:53:24
    |
 LL |     pub fn rc_test6(a: Rc<Rc<bool>>) {}
    |                        ^^^^^^^^^^^^ help: try: `Rc<bool>`
@@ -65,7 +65,7 @@ LL |     pub fn rc_test6(a: Rc<Rc<bool>>) {}
    = note: `Rc<bool>` is already on the heap, `Rc<Rc<bool>>` makes an extra allocation
 
 error: usage of `Arc<&T>`
-  --> tests/ui/redundant_allocation_fixable.rs:65:30
+  --> tests/ui/redundant_allocation_fixable.rs:63:30
    |
 LL |     pub fn arc_test1<T>(foo: Arc<&T>) {}
    |                              ^^^^^^^ help: try: `&T`
@@ -73,7 +73,7 @@ LL |     pub fn arc_test1<T>(foo: Arc<&T>) {}
    = note: `&T` is already a pointer, `Arc<&T>` allocates a pointer on the heap
 
 error: usage of `Arc<&MyStruct>`
-  --> tests/ui/redundant_allocation_fixable.rs:68:27
+  --> tests/ui/redundant_allocation_fixable.rs:66:27
    |
 LL |     pub fn arc_test2(foo: Arc<&MyStruct>) {}
    |                           ^^^^^^^^^^^^^^ help: try: `&MyStruct`
@@ -81,7 +81,7 @@ LL |     pub fn arc_test2(foo: Arc<&MyStruct>) {}
    = note: `&MyStruct` is already a pointer, `Arc<&MyStruct>` allocates a pointer on the heap
 
 error: usage of `Arc<&MyEnum>`
-  --> tests/ui/redundant_allocation_fixable.rs:71:27
+  --> tests/ui/redundant_allocation_fixable.rs:69:27
    |
 LL |     pub fn arc_test3(foo: Arc<&MyEnum>) {}
    |                           ^^^^^^^^^^^^ help: try: `&MyEnum`
@@ -89,7 +89,7 @@ LL |     pub fn arc_test3(foo: Arc<&MyEnum>) {}
    = note: `&MyEnum` is already a pointer, `Arc<&MyEnum>` allocates a pointer on the heap
 
 error: usage of `Arc<Arc<bool>>`
-  --> tests/ui/redundant_allocation_fixable.rs:76:25
+  --> tests/ui/redundant_allocation_fixable.rs:74:25
    |
 LL |     pub fn arc_test7(a: Arc<Arc<bool>>) {}
    |                         ^^^^^^^^^^^^^^ help: try: `Arc<bool>`
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index 23c00b34a00..c1c389f7c4e 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -259,3 +259,35 @@ fn false_negative_5707() {
     let _z = x.clone(); // pr 7346 can't lint on `x`
     drop(y);
 }
+
+mod issue10074 {
+    #[derive(Debug, Clone)]
+    enum MyEnum {
+        A = 1,
+    }
+
+    fn false_positive_on_as() {
+        let e = MyEnum::A;
+        let v = e.clone() as u16;
+
+        println!("{e:?}");
+        println!("{v}");
+    }
+}
+
+mod issue13900 {
+    use std::fmt::Display;
+
+    fn do_something(f: impl Display + Clone) -> String {
+        let g = f.clone();
+        format!("{} + {}", f, g)
+    }
+
+    fn regression() {
+        let mut a = String::new();
+        let mut b = String::new();
+        for _ in 1..10 {
+            b = a.clone();
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs
index f9fe8ba0236..78d98762efc 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.rs
+++ b/src/tools/clippy/tests/ui/redundant_clone.rs
@@ -259,3 +259,35 @@ fn false_negative_5707() {
     let _z = x.clone(); // pr 7346 can't lint on `x`
     drop(y);
 }
+
+mod issue10074 {
+    #[derive(Debug, Clone)]
+    enum MyEnum {
+        A = 1,
+    }
+
+    fn false_positive_on_as() {
+        let e = MyEnum::A;
+        let v = e.clone() as u16;
+
+        println!("{e:?}");
+        println!("{v}");
+    }
+}
+
+mod issue13900 {
+    use std::fmt::Display;
+
+    fn do_something(f: impl Display + Clone) -> String {
+        let g = f.clone();
+        format!("{} + {}", f, g)
+    }
+
+    fn regression() {
+        let mut a = String::new();
+        let mut b = String::new();
+        for _ in 1..10 {
+            b = a.clone();
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
index 549c97d9534..1cec19ab8c9 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
@@ -1,5 +1,4 @@
-#![warn(clippy::all, clippy::redundant_pattern_matching)]
-#![allow(unused_must_use)]
+#![warn(clippy::redundant_pattern_matching)]
 #![allow(
     clippy::match_like_matches_macro,
     clippy::needless_bool,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
index decb1396d56..123573a8602 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
@@ -1,5 +1,4 @@
-#![warn(clippy::all, clippy::redundant_pattern_matching)]
-#![allow(unused_must_use)]
+#![warn(clippy::redundant_pattern_matching)]
 #![allow(
     clippy::match_like_matches_macro,
     clippy::needless_bool,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
index 66d2cecdc0c..3be7cf81afe 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:15:12
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:14:12
    |
 LL |     if let V4(_) = &ipaddr {}
    |     -------^^^^^---------- help: try: `if ipaddr.is_ipv4()`
@@ -8,43 +8,43 @@ LL |     if let V4(_) = &ipaddr {}
    = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:18:12
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:17:12
    |
 LL |     if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:21:12
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:20:12
    |
 LL |     if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:25:8
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:24:8
    |
 LL |     if matches!(V4(Ipv4Addr::LOCALHOST), V4(_)) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:29:8
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:28:8
    |
 LL |     if matches!(V6(Ipv6Addr::LOCALHOST), V6(_)) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:32:15
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:31:15
    |
 LL |     while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:35:15
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:34:15
    |
 LL |     while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:46:5
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:45:5
    |
 LL | /     match V4(Ipv4Addr::LOCALHOST) {
 LL | |
@@ -54,7 +54,7 @@ LL | |     };
    | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:52:5
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:51:5
    |
 LL | /     match V4(Ipv4Addr::LOCALHOST) {
 LL | |
@@ -64,7 +64,7 @@ LL | |     };
    | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:58:5
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:57:5
    |
 LL | /     match V6(Ipv6Addr::LOCALHOST) {
 LL | |
@@ -74,7 +74,7 @@ LL | |     };
    | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:64:5
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:63:5
    |
 LL | /     match V6(Ipv6Addr::LOCALHOST) {
 LL | |
@@ -84,49 +84,49 @@ LL | |     };
    | |_____^ help: try: `V6(Ipv6Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:70:20
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:69:20
    |
 LL |     let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) {
    |             -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:79:20
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:78:20
    |
 LL |     let _ = if let V4(_) = gen_ipaddr() {
    |             -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:82:19
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:81:19
    |
 LL |     } else if let V6(_) = gen_ipaddr() {
    |            -------^^^^^--------------- help: try: `if gen_ipaddr().is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:95:12
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:94:12
    |
 LL |     if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:98:12
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:97:12
    |
 LL |     if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:101:15
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:100:15
    |
 LL |     while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:104:15
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:103:15
    |
 LL |     while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:107:5
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:106:5
    |
 LL | /     match V4(Ipv4Addr::LOCALHOST) {
 LL | |
@@ -136,7 +136,7 @@ LL | |     };
    | |_____^ help: try: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> tests/ui/redundant_pattern_matching_ipaddr.rs:113:5
+  --> tests/ui/redundant_pattern_matching_ipaddr.rs:112:5
    |
 LL | /     match V6(Ipv6Addr::LOCALHOST) {
 LL | |
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
index 5585006dc36..33a5308bd35 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
@@ -1,14 +1,12 @@
-#![warn(clippy::all)]
+#![feature(let_chains, if_let_guard)]
 #![warn(clippy::redundant_pattern_matching)]
 #![allow(
-    unused_must_use,
     clippy::needless_bool,
     clippy::needless_if,
     clippy::match_like_matches_macro,
     clippy::equatable_if_let,
     clippy::if_same_then_else
 )]
-#![feature(let_chains, if_let_guard)]
 
 fn issue_11174<T>(boolean: bool, maybe_some: Option<T>) -> bool {
     maybe_some.is_none() && (!boolean)
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
index 581a432f38e..60bce2994ea 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
@@ -1,14 +1,12 @@
-#![warn(clippy::all)]
+#![feature(let_chains, if_let_guard)]
 #![warn(clippy::redundant_pattern_matching)]
 #![allow(
-    unused_must_use,
     clippy::needless_bool,
     clippy::needless_if,
     clippy::match_like_matches_macro,
     clippy::equatable_if_let,
     clippy::if_same_then_else
 )]
-#![feature(let_chains, if_let_guard)]
 
 fn issue_11174<T>(boolean: bool, maybe_some: Option<T>) -> bool {
     matches!(maybe_some, None if !boolean)
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
index 681602567d2..e5a6598898a 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:14:5
+  --> tests/ui/redundant_pattern_matching_option.rs:12:5
    |
 LL |     matches!(maybe_some, None if !boolean)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `maybe_some.is_none() && (!boolean)`
@@ -8,55 +8,55 @@ LL |     matches!(maybe_some, None if !boolean)
    = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:19:13
+  --> tests/ui/redundant_pattern_matching_option.rs:17:13
    |
 LL |     let _ = matches!(maybe_some, None if boolean || boolean2); // guard needs parentheses
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `maybe_some.is_none() && (boolean || boolean2)`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:35:12
+  --> tests/ui/redundant_pattern_matching_option.rs:33:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:38:12
+  --> tests/ui/redundant_pattern_matching_option.rs:36:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:41:12
+  --> tests/ui/redundant_pattern_matching_option.rs:39:12
    |
 LL |     if let Some(_) = Some(42) {
    |     -------^^^^^^^----------- help: try: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:48:15
+  --> tests/ui/redundant_pattern_matching_option.rs:46:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:51:15
+  --> tests/ui/redundant_pattern_matching_option.rs:49:15
    |
 LL |     while let None = Some(42) {}
    |     ----------^^^^----------- help: try: `while Some(42).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:54:15
+  --> tests/ui/redundant_pattern_matching_option.rs:52:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:58:15
+  --> tests/ui/redundant_pattern_matching_option.rs:56:15
    |
 LL |     while let Some(_) = v.pop() {
    |     ----------^^^^^^^---------- help: try: `while v.pop().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:67:5
+  --> tests/ui/redundant_pattern_matching_option.rs:65:5
    |
 LL | /     match Some(42) {
 LL | |
@@ -66,7 +66,7 @@ LL | |     };
    | |_____^ help: try: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:73:5
+  --> tests/ui/redundant_pattern_matching_option.rs:71:5
    |
 LL | /     match None::<()> {
 LL | |
@@ -76,7 +76,7 @@ LL | |     };
    | |_____^ help: try: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:79:13
+  --> tests/ui/redundant_pattern_matching_option.rs:77:13
    |
 LL |       let _ = match None::<()> {
    |  _____________^
@@ -87,55 +87,55 @@ LL | |     };
    | |_____^ help: try: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:86:20
+  --> tests/ui/redundant_pattern_matching_option.rs:84:20
    |
 LL |     let _ = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:93:20
+  --> tests/ui/redundant_pattern_matching_option.rs:91:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:96:19
+  --> tests/ui/redundant_pattern_matching_option.rs:94:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:103:12
+  --> tests/ui/redundant_pattern_matching_option.rs:101:12
    |
 LL |     if let Some(..) = gen_opt() {}
    |     -------^^^^^^^^------------ help: try: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:119:12
+  --> tests/ui/redundant_pattern_matching_option.rs:117:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:122:12
+  --> tests/ui/redundant_pattern_matching_option.rs:120:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:125:15
+  --> tests/ui/redundant_pattern_matching_option.rs:123:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:128:15
+  --> tests/ui/redundant_pattern_matching_option.rs:126:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:131:5
+  --> tests/ui/redundant_pattern_matching_option.rs:129:5
    |
 LL | /     match Some(42) {
 LL | |
@@ -145,7 +145,7 @@ LL | |     };
    | |_____^ help: try: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:137:5
+  --> tests/ui/redundant_pattern_matching_option.rs:135:5
    |
 LL | /     match None::<()> {
 LL | |
@@ -155,19 +155,19 @@ LL | |     };
    | |_____^ help: try: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:146:12
+  --> tests/ui/redundant_pattern_matching_option.rs:144:12
    |
 LL |     if let None = *(&None::<()>) {}
    |     -------^^^^----------------- help: try: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:148:12
+  --> tests/ui/redundant_pattern_matching_option.rs:146:12
    |
 LL |     if let None = *&None::<()> {}
    |     -------^^^^--------------- help: try: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:155:5
+  --> tests/ui/redundant_pattern_matching_option.rs:153:5
    |
 LL | /     match x {
 LL | |
@@ -177,7 +177,7 @@ LL | |     };
    | |_____^ help: try: `x.is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:161:5
+  --> tests/ui/redundant_pattern_matching_option.rs:159:5
    |
 LL | /     match x {
 LL | |
@@ -187,7 +187,7 @@ LL | |     };
    | |_____^ help: try: `x.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:167:5
+  --> tests/ui/redundant_pattern_matching_option.rs:165:5
    |
 LL | /     match x {
 LL | |
@@ -197,7 +197,7 @@ LL | |     };
    | |_____^ help: try: `x.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:173:5
+  --> tests/ui/redundant_pattern_matching_option.rs:171:5
    |
 LL | /     match x {
 LL | |
@@ -207,19 +207,19 @@ LL | |     };
    | |_____^ help: try: `x.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_option.rs:189:13
+  --> tests/ui/redundant_pattern_matching_option.rs:187:13
    |
 LL |     let _ = matches!(x, Some(_));
    |             ^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:192:13
+  --> tests/ui/redundant_pattern_matching_option.rs:190:13
    |
 LL |     let _ = matches!(x, None);
    |             ^^^^^^^^^^^^^^^^^ help: try: `x.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> tests/ui/redundant_pattern_matching_option.rs:203:17
+  --> tests/ui/redundant_pattern_matching_option.rs:201:17
    |
 LL |         let _ = matches!(*p, None);
    |                 ^^^^^^^^^^^^^^^^^^ help: try: `(*p).is_none()`
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
index c8e18e8676f..800889b5fda 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
@@ -1,7 +1,5 @@
-#![warn(clippy::all)]
 #![warn(clippy::redundant_pattern_matching)]
 #![allow(
-    unused_must_use,
     clippy::needless_bool,
     clippy::needless_if,
     clippy::match_like_matches_macro,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
index 727503d21a5..1668c2ff2bb 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
@@ -1,7 +1,5 @@
-#![warn(clippy::all)]
 #![warn(clippy::redundant_pattern_matching)]
 #![allow(
-    unused_must_use,
     clippy::needless_bool,
     clippy::needless_if,
     clippy::match_like_matches_macro,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
index 5f659184f7b..5cd9d9636e4 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:15:12
+  --> tests/ui/redundant_pattern_matching_poll.rs:13:12
    |
 LL |     if let Pending = Pending::<()> {}
    |     -------^^^^^^^---------------- help: try: `if Pending::<()>.is_pending()`
@@ -8,49 +8,49 @@ LL |     if let Pending = Pending::<()> {}
    = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:18:12
+  --> tests/ui/redundant_pattern_matching_poll.rs:16:12
    |
 LL |     if let Ready(_) = Ready(42) {}
    |     -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:21:12
+  --> tests/ui/redundant_pattern_matching_poll.rs:19:12
    |
 LL |     if let Ready(_) = Ready(42) {
    |     -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:29:8
+  --> tests/ui/redundant_pattern_matching_poll.rs:27:8
    |
 LL |     if matches!(Ready(42), Ready(_)) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:33:8
+  --> tests/ui/redundant_pattern_matching_poll.rs:31:8
    |
 LL |     if matches!(Pending::<()>, Pending) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:36:15
+  --> tests/ui/redundant_pattern_matching_poll.rs:34:15
    |
 LL |     while let Ready(_) = Ready(42) {}
    |     ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:39:15
+  --> tests/ui/redundant_pattern_matching_poll.rs:37:15
    |
 LL |     while let Pending = Ready(42) {}
    |     ----------^^^^^^^------------ help: try: `while Ready(42).is_pending()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:42:15
+  --> tests/ui/redundant_pattern_matching_poll.rs:40:15
    |
 LL |     while let Pending = Pending::<()> {}
    |     ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:49:5
+  --> tests/ui/redundant_pattern_matching_poll.rs:47:5
    |
 LL | /     match Ready(42) {
 LL | |
@@ -60,7 +60,7 @@ LL | |     };
    | |_____^ help: try: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:55:5
+  --> tests/ui/redundant_pattern_matching_poll.rs:53:5
    |
 LL | /     match Pending::<()> {
 LL | |
@@ -70,7 +70,7 @@ LL | |     };
    | |_____^ help: try: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:61:13
+  --> tests/ui/redundant_pattern_matching_poll.rs:59:13
    |
 LL |       let _ = match Pending::<()> {
    |  _____________^
@@ -81,49 +81,49 @@ LL | |     };
    | |_____^ help: try: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:68:20
+  --> tests/ui/redundant_pattern_matching_poll.rs:66:20
    |
 LL |     let _ = if let Ready(_) = poll { true } else { false };
    |             -------^^^^^^^^------- help: try: `if poll.is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:73:20
+  --> tests/ui/redundant_pattern_matching_poll.rs:71:20
    |
 LL |     let _ = if let Ready(_) = gen_poll() {
    |             -------^^^^^^^^------------- help: try: `if gen_poll().is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:76:19
+  --> tests/ui/redundant_pattern_matching_poll.rs:74:19
    |
 LL |     } else if let Pending = gen_poll() {
    |            -------^^^^^^^------------- help: try: `if gen_poll().is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:93:12
+  --> tests/ui/redundant_pattern_matching_poll.rs:91:12
    |
 LL |     if let Ready(_) = Ready(42) {}
    |     -------^^^^^^^^------------ help: try: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:96:12
+  --> tests/ui/redundant_pattern_matching_poll.rs:94:12
    |
 LL |     if let Pending = Pending::<()> {}
    |     -------^^^^^^^---------------- help: try: `if Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:99:15
+  --> tests/ui/redundant_pattern_matching_poll.rs:97:15
    |
 LL |     while let Ready(_) = Ready(42) {}
    |     ----------^^^^^^^^------------ help: try: `while Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:102:15
+  --> tests/ui/redundant_pattern_matching_poll.rs:100:15
    |
 LL |     while let Pending = Pending::<()> {}
    |     ----------^^^^^^^---------------- help: try: `while Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:105:5
+  --> tests/ui/redundant_pattern_matching_poll.rs:103:5
    |
 LL | /     match Ready(42) {
 LL | |
@@ -133,7 +133,7 @@ LL | |     };
    | |_____^ help: try: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> tests/ui/redundant_pattern_matching_poll.rs:111:5
+  --> tests/ui/redundant_pattern_matching_poll.rs:109:5
    |
 LL | /     match Pending::<()> {
 LL | |
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index 11587960831..dab816716d5 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -1,6 +1,5 @@
-#![warn(clippy::all)]
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(deprecated, unused_must_use)]
+#![allow(deprecated)]
 #![allow(
     clippy::if_same_then_else,
     clippy::match_like_matches_macro,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index 35f8f91b315..3fd70515d08 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -1,6 +1,5 @@
-#![warn(clippy::all)]
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(deprecated, unused_must_use)]
+#![allow(deprecated)]
 #![allow(
     clippy::if_same_then_else,
     clippy::match_like_matches_macro,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index 4f78b95356c..7e7d27d07a7 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:15:12
+  --> tests/ui/redundant_pattern_matching_result.rs:14:12
    |
 LL |     if let Ok(_) = &result {}
    |     -------^^^^^---------- help: try: `if result.is_ok()`
@@ -8,31 +8,31 @@ LL |     if let Ok(_) = &result {}
    = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:18:12
+  --> tests/ui/redundant_pattern_matching_result.rs:17:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:21:12
+  --> tests/ui/redundant_pattern_matching_result.rs:20:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:24:15
+  --> tests/ui/redundant_pattern_matching_result.rs:23:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:27:15
+  --> tests/ui/redundant_pattern_matching_result.rs:26:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:38:5
+  --> tests/ui/redundant_pattern_matching_result.rs:37:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |
@@ -42,7 +42,7 @@ LL | |     };
    | |_____^ help: try: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:44:5
+  --> tests/ui/redundant_pattern_matching_result.rs:43:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |
@@ -52,7 +52,7 @@ LL | |     };
    | |_____^ help: try: `Ok::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:50:5
+  --> tests/ui/redundant_pattern_matching_result.rs:49:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |
@@ -62,7 +62,7 @@ LL | |     };
    | |_____^ help: try: `Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:56:5
+  --> tests/ui/redundant_pattern_matching_result.rs:55:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |
@@ -72,73 +72,73 @@ LL | |     };
    | |_____^ help: try: `Err::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:62:20
+  --> tests/ui/redundant_pattern_matching_result.rs:61:20
    |
 LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
    |             -------^^^^^--------------------- help: try: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:71:20
+  --> tests/ui/redundant_pattern_matching_result.rs:70:20
    |
 LL |     let _ = if let Ok(_) = gen_res() {
    |             -------^^^^^------------ help: try: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:74:19
+  --> tests/ui/redundant_pattern_matching_result.rs:73:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_result.rs:98:19
+  --> tests/ui/redundant_pattern_matching_result.rs:97:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_result.rs:100:16
+  --> tests/ui/redundant_pattern_matching_result.rs:99:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_result.rs:107:12
+  --> tests/ui/redundant_pattern_matching_result.rs:106:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> tests/ui/redundant_pattern_matching_result.rs:109:15
+  --> tests/ui/redundant_pattern_matching_result.rs:108:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try: `while m!().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:128:12
+  --> tests/ui/redundant_pattern_matching_result.rs:127:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:131:12
+  --> tests/ui/redundant_pattern_matching_result.rs:130:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:134:15
+  --> tests/ui/redundant_pattern_matching_result.rs:133:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:137:15
+  --> tests/ui/redundant_pattern_matching_result.rs:136:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:140:5
+  --> tests/ui/redundant_pattern_matching_result.rs:139:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |
@@ -148,7 +148,7 @@ LL | |     };
    | |_____^ help: try: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:146:5
+  --> tests/ui/redundant_pattern_matching_result.rs:145:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |
@@ -158,7 +158,7 @@ LL | |     };
    | |_____^ help: try: `Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:157:5
+  --> tests/ui/redundant_pattern_matching_result.rs:156:5
    |
 LL | /     match x {
 LL | |
@@ -168,7 +168,7 @@ LL | |     };
    | |_____^ help: try: `x.is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:163:5
+  --> tests/ui/redundant_pattern_matching_result.rs:162:5
    |
 LL | /     match x {
 LL | |
@@ -178,7 +178,7 @@ LL | |     };
    | |_____^ help: try: `x.is_err()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:169:5
+  --> tests/ui/redundant_pattern_matching_result.rs:168:5
    |
 LL | /     match x {
 LL | |
@@ -188,7 +188,7 @@ LL | |     };
    | |_____^ help: try: `x.is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:175:5
+  --> tests/ui/redundant_pattern_matching_result.rs:174:5
    |
 LL | /     match x {
 LL | |
@@ -198,13 +198,13 @@ LL | |     };
    | |_____^ help: try: `x.is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> tests/ui/redundant_pattern_matching_result.rs:197:13
+  --> tests/ui/redundant_pattern_matching_result.rs:196:13
    |
 LL |     let _ = matches!(x, Ok(_));
    |             ^^^^^^^^^^^^^^^^^^ help: try: `x.is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> tests/ui/redundant_pattern_matching_result.rs:200:13
+  --> tests/ui/redundant_pattern_matching_result.rs:199:13
    |
 LL |     let _ = matches!(x, Err(_));
    |             ^^^^^^^^^^^^^^^^^^^ help: try: `x.is_err()`
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.fixed b/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
index a6450123f4c..8a30fedede4 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
@@ -131,6 +131,14 @@ mod m4 {
     }
 }
 
+mod m5 {
+    pub mod m5_1 {}
+    // Test that the primary span isn't butchered for item kinds that don't have an ident.
+    pub use m5_1::*; //~ redundant_pub_crate
+    #[rustfmt::skip]
+    pub use m5_1::{*}; //~ redundant_pub_crate
+}
+
 pub use m4::*;
 
 mod issue_8732 {
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.rs b/src/tools/clippy/tests/ui/redundant_pub_crate.rs
index 7415d34d50c..45ba13a63b2 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.rs
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.rs
@@ -131,6 +131,14 @@ mod m4 {
     }
 }
 
+mod m5 {
+    pub mod m5_1 {}
+    // Test that the primary span isn't butchered for item kinds that don't have an ident.
+    pub(crate) use m5_1::*; //~ redundant_pub_crate
+    #[rustfmt::skip]
+    pub(crate) use m5_1::{*}; //~ redundant_pub_crate
+}
+
 pub use m4::*;
 
 mod issue_8732 {
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.stderr b/src/tools/clippy/tests/ui/redundant_pub_crate.stderr
index 95909ea8b06..4a47a321028 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.stderr
@@ -129,5 +129,21 @@ LL |         pub(crate) fn g() {} // private due to m4_2
    |         |
    |         help: consider using: `pub`
 
-error: aborting due to 16 previous errors
+error: pub(crate) import inside private module
+  --> tests/ui/redundant_pub_crate.rs:137:5
+   |
+LL |     pub(crate) use m5_1::*;
+   |     ----------^^^^^^^^^^^^^
+   |     |
+   |     help: consider using: `pub`
+
+error: pub(crate) import inside private module
+  --> tests/ui/redundant_pub_crate.rs:139:27
+   |
+LL |     pub(crate) use m5_1::{*};
+   |     ----------            ^
+   |     |
+   |     help: consider using: `pub`
+
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_test_prefix.fixed b/src/tools/clippy/tests/ui/redundant_test_prefix.fixed
new file mode 100644
index 00000000000..b99771f0640
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_test_prefix.fixed
@@ -0,0 +1,158 @@
+#![allow(dead_code)]
+#![warn(clippy::redundant_test_prefix)]
+
+fn main() {
+    // Normal function, no redundant prefix.
+}
+
+fn f1() {
+    // Normal function, no redundant prefix.
+}
+
+fn test_f2() {
+    // Has prefix, but no `#[test]` attribute, ignore.
+}
+
+#[test]
+fn f3() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute. Not within a `#[cfg(test)]`.
+    // No collision with other functions, should emit warning.
+}
+
+#[cfg(test)]
+#[test]
+fn f4() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision with other functions, should emit warning.
+}
+
+mod m1 {
+    pub fn f5() {}
+}
+
+#[cfg(test)]
+#[test]
+fn f6() {
+    //~^ redundant_test_prefix
+
+    use m1::f5;
+
+    f5();
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision, has function call, but it will not result in recursion.
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn foo() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn foo_with_call() {
+        //~^ redundant_test_prefix
+
+        main();
+    }
+
+    #[test]
+    fn f1() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f2() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f3() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f4() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f5() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f6() {
+        //~^ redundant_test_prefix
+    }
+}
+
+mod tests_no_annotations {
+    use super::*;
+
+    #[test]
+    fn foo() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn foo_with_call() {
+        //~^ redundant_test_prefix
+
+        main();
+    }
+
+    #[test]
+    fn f1() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f2() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f3() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f4() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f5() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn f6() {
+        //~^ redundant_test_prefix
+    }
+}
+
+// This test is inspired by real test in `clippy_utils/src/sugg.rs`.
+// The `is_in_test_function()` checks whether any identifier within a given node's parents is
+// marked with `#[test]` attribute. Thus flagging false positives when nested functions are
+// prefixed with `test_`. Therefore `is_test_function()` has been defined in `clippy_utils`,
+// allowing to select only functions that are immediately marked with `#[test]` annotation.
+//
+// This test case ensures that for such nested functions no error is emitted.
+#[test]
+fn not_op() {
+    fn test_not(foo: bool) {
+        assert!(foo);
+    }
+
+    // Use helper function
+    test_not(true);
+    test_not(false);
+}
diff --git a/src/tools/clippy/tests/ui/redundant_test_prefix.rs b/src/tools/clippy/tests/ui/redundant_test_prefix.rs
new file mode 100644
index 00000000000..3aec577cffa
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_test_prefix.rs
@@ -0,0 +1,158 @@
+#![allow(dead_code)]
+#![warn(clippy::redundant_test_prefix)]
+
+fn main() {
+    // Normal function, no redundant prefix.
+}
+
+fn f1() {
+    // Normal function, no redundant prefix.
+}
+
+fn test_f2() {
+    // Has prefix, but no `#[test]` attribute, ignore.
+}
+
+#[test]
+fn test_f3() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute. Not within a `#[cfg(test)]`.
+    // No collision with other functions, should emit warning.
+}
+
+#[cfg(test)]
+#[test]
+fn test_f4() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision with other functions, should emit warning.
+}
+
+mod m1 {
+    pub fn f5() {}
+}
+
+#[cfg(test)]
+#[test]
+fn test_f6() {
+    //~^ redundant_test_prefix
+
+    use m1::f5;
+
+    f5();
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision, has function call, but it will not result in recursion.
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_foo() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_foo_with_call() {
+        //~^ redundant_test_prefix
+
+        main();
+    }
+
+    #[test]
+    fn test_f1() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f2() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f3() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f4() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f5() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f6() {
+        //~^ redundant_test_prefix
+    }
+}
+
+mod tests_no_annotations {
+    use super::*;
+
+    #[test]
+    fn test_foo() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_foo_with_call() {
+        //~^ redundant_test_prefix
+
+        main();
+    }
+
+    #[test]
+    fn test_f1() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f2() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f3() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f4() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f5() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f6() {
+        //~^ redundant_test_prefix
+    }
+}
+
+// This test is inspired by real test in `clippy_utils/src/sugg.rs`.
+// The `is_in_test_function()` checks whether any identifier within a given node's parents is
+// marked with `#[test]` attribute. Thus flagging false positives when nested functions are
+// prefixed with `test_`. Therefore `is_test_function()` has been defined in `clippy_utils`,
+// allowing to select only functions that are immediately marked with `#[test]` annotation.
+//
+// This test case ensures that for such nested functions no error is emitted.
+#[test]
+fn not_op() {
+    fn test_not(foo: bool) {
+        assert!(foo);
+    }
+
+    // Use helper function
+    test_not(true);
+    test_not(false);
+}
diff --git a/src/tools/clippy/tests/ui/redundant_test_prefix.stderr b/src/tools/clippy/tests/ui/redundant_test_prefix.stderr
new file mode 100644
index 00000000000..d156af586df
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_test_prefix.stderr
@@ -0,0 +1,119 @@
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:17:4
+   |
+LL | fn test_f3() {
+   |    ^^^^^^^ help: consider removing the `test_` prefix: `f3`
+   |
+   = note: `-D clippy::redundant-test-prefix` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::redundant_test_prefix)]`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:26:4
+   |
+LL | fn test_f4() {
+   |    ^^^^^^^ help: consider removing the `test_` prefix: `f4`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:39:4
+   |
+LL | fn test_f6() {
+   |    ^^^^^^^ help: consider removing the `test_` prefix: `f6`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:54:8
+   |
+LL |     fn test_foo() {
+   |        ^^^^^^^^ help: consider removing the `test_` prefix: `foo`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:59:8
+   |
+LL |     fn test_foo_with_call() {
+   |        ^^^^^^^^^^^^^^^^^^ help: consider removing the `test_` prefix: `foo_with_call`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:66:8
+   |
+LL |     fn test_f1() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f1`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:71:8
+   |
+LL |     fn test_f2() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f2`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:76:8
+   |
+LL |     fn test_f3() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f3`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:81:8
+   |
+LL |     fn test_f4() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f4`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:86:8
+   |
+LL |     fn test_f5() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f5`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:91:8
+   |
+LL |     fn test_f6() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f6`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:100:8
+   |
+LL |     fn test_foo() {
+   |        ^^^^^^^^ help: consider removing the `test_` prefix: `foo`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:105:8
+   |
+LL |     fn test_foo_with_call() {
+   |        ^^^^^^^^^^^^^^^^^^ help: consider removing the `test_` prefix: `foo_with_call`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:112:8
+   |
+LL |     fn test_f1() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f1`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:117:8
+   |
+LL |     fn test_f2() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f2`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:122:8
+   |
+LL |     fn test_f3() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f3`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:127:8
+   |
+LL |     fn test_f4() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f4`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:132:8
+   |
+LL |     fn test_f5() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f5`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix.rs:137:8
+   |
+LL |     fn test_f6() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f6`
+
+error: aborting due to 19 previous errors
+
diff --git a/src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.rs b/src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.rs
new file mode 100644
index 00000000000..6ad5d011d8b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.rs
@@ -0,0 +1,288 @@
+//@no-rustfix: name conflicts
+
+#![allow(dead_code)]
+#![warn(clippy::redundant_test_prefix)]
+
+fn main() {
+    // Normal function, no redundant prefix.
+}
+
+fn f1() {
+    // Normal function, no redundant prefix.
+}
+
+fn test_f2() {
+    // Has prefix, but no `#[test]` attribute, ignore.
+}
+
+#[test]
+fn test_f3() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute. Not within a `#[cfg(test)]`.
+    // No collision with other functions, should emit warning.
+}
+
+#[cfg(test)]
+#[test]
+fn test_f4() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision with other functions, should emit warning.
+}
+
+fn f5() {}
+
+#[cfg(test)]
+#[test]
+fn test_f5() {
+    //~^ redundant_test_prefix
+
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // Collision with existing function.
+}
+
+mod m1 {
+    pub fn f6() {}
+    pub fn f7() {}
+}
+
+#[cfg(test)]
+#[test]
+fn test_f6() {
+    //~^ redundant_test_prefix
+
+    use m1::f6;
+
+    f6();
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision, but has a function call that will result in recursion.
+}
+
+#[cfg(test)]
+#[test]
+fn test_f8() {
+    //~^ redundant_test_prefix
+
+    use m1::f7;
+
+    f7();
+    // Has prefix, has `#[test]` attribute, within a `#[cfg(test)]`.
+    // No collision, has function call, but it will not result in recursion.
+}
+
+// Although there's no direct call of `f` in the test, name collision still exists,
+// since all `m3` functions are imported and then `map` is used to call `f`.
+mod m2 {
+    mod m3 {
+        pub fn f(_: i32) -> i32 {
+            0
+        }
+    }
+
+    use m3::*;
+
+    #[cfg(test)]
+    #[test]
+    fn test_f() {
+        //~^ redundant_test_prefix
+        let a = Some(3);
+        let _ = a.map(f);
+    }
+}
+
+mod m3 {
+    fn test_m3_1() {
+        // Has prefix, but no `#[test]` attribute, ignore.
+    }
+
+    #[test]
+    fn test_m3_2() {
+        //~^ redundant_test_prefix
+
+        // Has prefix, has `#[test]` attribute. Not within a `#[cfg(test)]`.
+        // No collision with other functions, should emit warning.
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_foo() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_foo_with_call() {
+        //~^ redundant_test_prefix
+
+        main();
+    }
+
+    #[test]
+    fn test_f1() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f2() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f3() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f4() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f5() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f6() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_1() {
+        //~^ redundant_test_prefix
+
+        // `1` is invalid function name, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_const() {
+        //~^ redundant_test_prefix
+
+        // `const` is reserved keyword, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_async() {
+        //~^ redundant_test_prefix
+
+        // `async` is reserved keyword, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_yield() {
+        //~^ redundant_test_prefix
+
+        // `yield` is reserved keyword for future use, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_() {
+        //~^ redundant_test_prefix
+
+        // `` is invalid function name, so suggestion to rename is emitted
+    }
+}
+
+mod tests_no_annotations {
+    use super::*;
+
+    #[test]
+    fn test_foo() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_foo_with_call() {
+        //~^ redundant_test_prefix
+
+        main();
+    }
+
+    #[test]
+    fn test_f1() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f2() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f3() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f4() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f5() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_f6() {
+        //~^ redundant_test_prefix
+    }
+
+    #[test]
+    fn test_1() {
+        //~^ redundant_test_prefix
+
+        // `1` is invalid function name, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_const() {
+        //~^ redundant_test_prefix
+
+        // `const` is reserved keyword, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_async() {
+        //~^ redundant_test_prefix
+
+        // `async` is reserved keyword, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_yield() {
+        //~^ redundant_test_prefix
+
+        // `yield` is reserved keyword for future use, so suggestion to rename is emitted
+    }
+
+    #[test]
+    fn test_() {
+        //~^ redundant_test_prefix
+
+        // `` is invalid function name, so suggestion to rename is emitted
+    }
+}
+
+// This test is inspired by real test in `clippy_utils/src/sugg.rs`.
+// The `is_in_test_function()` checks whether any identifier within a given node's parents is
+// marked with `#[test]` attribute. Thus flagging false positives when nested functions are
+// prefixed with `test_`. Therefore `is_test_function()` has been defined in `clippy_utils`,
+// allowing to select only functions that are immediately marked with `#[test]` annotation.
+//
+// This test case ensures that for such nested functions no error is emitted.
+#[test]
+fn not_op() {
+    fn test_not(foo: bool) {
+        assert!(foo);
+    }
+
+    // Use helper function
+    test_not(true);
+    test_not(false);
+}
diff --git a/src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.stderr b/src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.stderr
new file mode 100644
index 00000000000..6440faf1b3c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_test_prefix_noautofix.stderr
@@ -0,0 +1,241 @@
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:19:4
+   |
+LL | fn test_f3() {
+   |    ^^^^^^^ help: consider removing the `test_` prefix: `f3`
+   |
+   = note: `-D clippy::redundant-test-prefix` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::redundant_test_prefix)]`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:28:4
+   |
+LL | fn test_f4() {
+   |    ^^^^^^^ help: consider removing the `test_` prefix: `f4`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:39:4
+   |
+LL | fn test_f5() {
+   |    ^^^^^^^
+   |
+help: consider function renaming (just removing `test_` prefix will cause a name conflict)
+   |
+LL - fn test_f5() {
+LL + fn f5_works() {
+   |
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:53:4
+   |
+LL | fn test_f6() {
+   |    ^^^^^^^
+   |
+help: consider function renaming (just removing `test_` prefix will cause a name conflict)
+   |
+LL - fn test_f6() {
+LL + fn f6_works() {
+   |
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:65:4
+   |
+LL | fn test_f8() {
+   |    ^^^^^^^ help: consider removing the `test_` prefix: `f8`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:88:8
+   |
+LL |     fn test_f() {
+   |        ^^^^^^
+   |
+help: consider function renaming (just removing `test_` prefix will cause a name conflict)
+   |
+LL -     fn test_f() {
+LL +     fn f_works() {
+   |
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:101:8
+   |
+LL |     fn test_m3_2() {
+   |        ^^^^^^^^^ help: consider removing the `test_` prefix: `m3_2`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:114:8
+   |
+LL |     fn test_foo() {
+   |        ^^^^^^^^ help: consider removing the `test_` prefix: `foo`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:119:8
+   |
+LL |     fn test_foo_with_call() {
+   |        ^^^^^^^^^^^^^^^^^^ help: consider removing the `test_` prefix: `foo_with_call`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:126:8
+   |
+LL |     fn test_f1() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f1`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:131:8
+   |
+LL |     fn test_f2() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f2`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:136:8
+   |
+LL |     fn test_f3() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f3`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:141:8
+   |
+LL |     fn test_f4() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f4`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:146:8
+   |
+LL |     fn test_f5() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f5`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:151:8
+   |
+LL |     fn test_f6() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f6`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:156:8
+   |
+LL |     fn test_1() {
+   |        ^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:163:8
+   |
+LL |     fn test_const() {
+   |        ^^^^^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:170:8
+   |
+LL |     fn test_async() {
+   |        ^^^^^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:177:8
+   |
+LL |     fn test_yield() {
+   |        ^^^^^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:184:8
+   |
+LL |     fn test_() {
+   |        ^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:195:8
+   |
+LL |     fn test_foo() {
+   |        ^^^^^^^^ help: consider removing the `test_` prefix: `foo`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:200:8
+   |
+LL |     fn test_foo_with_call() {
+   |        ^^^^^^^^^^^^^^^^^^ help: consider removing the `test_` prefix: `foo_with_call`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:207:8
+   |
+LL |     fn test_f1() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f1`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:212:8
+   |
+LL |     fn test_f2() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f2`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:217:8
+   |
+LL |     fn test_f3() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f3`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:222:8
+   |
+LL |     fn test_f4() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f4`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:227:8
+   |
+LL |     fn test_f5() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f5`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:232:8
+   |
+LL |     fn test_f6() {
+   |        ^^^^^^^ help: consider removing the `test_` prefix: `f6`
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:237:8
+   |
+LL |     fn test_1() {
+   |        ^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:244:8
+   |
+LL |     fn test_const() {
+   |        ^^^^^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:251:8
+   |
+LL |     fn test_async() {
+   |        ^^^^^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:258:8
+   |
+LL |     fn test_yield() {
+   |        ^^^^^^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: redundant `test_` prefix in test function name
+  --> tests/ui/redundant_test_prefix_noautofix.rs:265:8
+   |
+LL |     fn test_() {
+   |        ^^^^^
+   |
+   = help: consider function renaming (just removing `test_` prefix will produce invalid function name)
+
+error: aborting due to 33 previous errors
+
diff --git a/src/tools/clippy/tests/ui/ref_option/ref_option_traits.all.stderr b/src/tools/clippy/tests/ui/ref_option/ref_option_traits.all.stderr
index 030a9a28ec6..886bf2b0349 100644
--- a/src/tools/clippy/tests/ui/ref_option/ref_option_traits.all.stderr
+++ b/src/tools/clippy/tests/ui/ref_option/ref_option_traits.all.stderr
@@ -1,5 +1,5 @@
 error: it is more idiomatic to use `Option<&T>` instead of `&Option<T>`
-  --> tests/ui/ref_option/ref_option_traits.rs:10:5
+  --> tests/ui/ref_option/ref_option_traits.rs:9:5
    |
 LL |     fn pub_trait_opt(&self, a: &Option<Vec<u8>>);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^^
@@ -10,7 +10,7 @@ LL |     fn pub_trait_opt(&self, a: &Option<Vec<u8>>);
    = help: to override `-D warnings` add `#[allow(clippy::ref_option)]`
 
 error: it is more idiomatic to use `Option<&T>` instead of `&Option<T>`
-  --> tests/ui/ref_option/ref_option_traits.rs:12:5
+  --> tests/ui/ref_option/ref_option_traits.rs:11:5
    |
 LL |     fn pub_trait_ret(&self) -> &Option<Vec<u8>>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------^
@@ -18,7 +18,7 @@ LL |     fn pub_trait_ret(&self) -> &Option<Vec<u8>>;
    |                                help: change this to: `Option<&Vec<u8>>`
 
 error: it is more idiomatic to use `Option<&T>` instead of `&Option<T>`
-  --> tests/ui/ref_option/ref_option_traits.rs:17:5
+  --> tests/ui/ref_option/ref_option_traits.rs:16:5
    |
 LL |     fn trait_opt(&self, a: &Option<String>);
    |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^^
@@ -26,7 +26,7 @@ LL |     fn trait_opt(&self, a: &Option<String>);
    |                            help: change this to: `Option<&String>`
 
 error: it is more idiomatic to use `Option<&T>` instead of `&Option<T>`
-  --> tests/ui/ref_option/ref_option_traits.rs:19:5
+  --> tests/ui/ref_option/ref_option_traits.rs:18:5
    |
 LL |     fn trait_ret(&self) -> &Option<String>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^
diff --git a/src/tools/clippy/tests/ui/ref_option/ref_option_traits.private.stderr b/src/tools/clippy/tests/ui/ref_option/ref_option_traits.private.stderr
index 2837ee80fb2..cfab7fa5734 100644
--- a/src/tools/clippy/tests/ui/ref_option/ref_option_traits.private.stderr
+++ b/src/tools/clippy/tests/ui/ref_option/ref_option_traits.private.stderr
@@ -1,5 +1,5 @@
 error: it is more idiomatic to use `Option<&T>` instead of `&Option<T>`
-  --> tests/ui/ref_option/ref_option_traits.rs:17:5
+  --> tests/ui/ref_option/ref_option_traits.rs:16:5
    |
 LL |     fn trait_opt(&self, a: &Option<String>);
    |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^^
@@ -10,7 +10,7 @@ LL |     fn trait_opt(&self, a: &Option<String>);
    = help: to override `-D warnings` add `#[allow(clippy::ref_option)]`
 
 error: it is more idiomatic to use `Option<&T>` instead of `&Option<T>`
-  --> tests/ui/ref_option/ref_option_traits.rs:19:5
+  --> tests/ui/ref_option/ref_option_traits.rs:18:5
    |
 LL |     fn trait_ret(&self) -> &Option<String>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^
diff --git a/src/tools/clippy/tests/ui/ref_option/ref_option_traits.rs b/src/tools/clippy/tests/ui/ref_option/ref_option_traits.rs
index 811da2eb4d5..4c773e84f8d 100644
--- a/src/tools/clippy/tests/ui/ref_option/ref_option_traits.rs
+++ b/src/tools/clippy/tests/ui/ref_option/ref_option_traits.rs
@@ -3,7 +3,6 @@
 //@[private] rustc-env:CLIPPY_CONF_DIR=tests/ui/ref_option/private
 //@[all] rustc-env:CLIPPY_CONF_DIR=tests/ui/ref_option/all
 
-#![allow(unused, clippy::all)]
 #![warn(clippy::ref_option)]
 
 pub trait PubTrait {
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 79640470696..acf7914d253 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -13,8 +13,9 @@
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
-#![allow(clippy::manual_filter_map)]
 #![allow(clippy::manual_find_map)]
+#![allow(clippy::manual_filter_map)]
+#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::redundant_pattern_matching)]
 #![allow(clippy::match_result_ok)]
@@ -29,7 +30,6 @@
 #![allow(clippy::unwrap_used)]
 #![allow(clippy::panicking_overflow_checks)]
 #![allow(clippy::needless_borrow)]
-#![allow(clippy::reversed_empty_ranges)]
 #![allow(clippy::single_char_add_str)]
 #![allow(clippy::module_name_repetitions)]
 #![allow(clippy::missing_const_for_thread_local)]
@@ -39,11 +39,11 @@
 #![allow(invalid_reference_casting)]
 #![allow(suspicious_double_ref_op)]
 #![allow(invalid_nan_comparisons)]
+#![allow(invalid_null_arguments)]
 #![allow(double_negations)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
-#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(useless_ptr_null_checks)]
 #![allow(for_loops_over_fallibles)]
 #![allow(forgetting_copy_types)]
@@ -62,6 +62,7 @@
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
 #![allow(ambiguous_wide_pointer_comparisons)]
+#![allow(clippy::reversed_empty_ranges)]
 #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
 #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
 #![warn(clippy::blocks_in_conditions)] //~ ERROR: lint `clippy::block_in_if_condition_expr`
@@ -74,8 +75,9 @@
 #![warn(clippy::disallowed_methods)] //~ ERROR: lint `clippy::disallowed_method`
 #![warn(clippy::disallowed_types)] //~ ERROR: lint `clippy::disallowed_type`
 #![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence`
-#![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
 #![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
+#![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
 #![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
 #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`
@@ -94,7 +96,6 @@
 #![warn(clippy::expect_used)] //~ ERROR: lint `clippy::result_expect_used`
 #![warn(clippy::map_unwrap_or)] //~ ERROR: lint `clippy::result_map_unwrap_or_else`
 #![warn(clippy::unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used`
-#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop`
 #![warn(clippy::single_char_add_str)] //~ ERROR: lint `clippy::single_char_push_str`
 #![warn(clippy::module_name_repetitions)] //~ ERROR: lint `clippy::stutter`
 #![warn(clippy::missing_const_for_thread_local)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const`
@@ -104,11 +105,11 @@
 #![warn(invalid_reference_casting)] //~ ERROR: lint `clippy::cast_ref_to_mut`
 #![warn(suspicious_double_ref_op)] //~ ERROR: lint `clippy::clone_double_ref`
 #![warn(invalid_nan_comparisons)] //~ ERROR: lint `clippy::cmp_nan`
+#![warn(invalid_null_arguments)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
 #![warn(double_negations)] //~ ERROR: lint `clippy::double_neg`
 #![warn(drop_bounds)] //~ ERROR: lint `clippy::drop_bounds`
 #![warn(dropping_copy_types)] //~ ERROR: lint `clippy::drop_copy`
 #![warn(dropping_references)] //~ ERROR: lint `clippy::drop_ref`
-#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(useless_ptr_null_checks)] //~ ERROR: lint `clippy::fn_null_check`
 #![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_option`
 #![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_result`
@@ -119,7 +120,6 @@
 #![warn(invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
 #![warn(invalid_value)] //~ ERROR: lint `clippy::invalid_ref`
 #![warn(invalid_from_utf8_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
-#![warn(invalid_null_arguments)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
 #![warn(let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
 #![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::maybe_misused_cfg`
 #![warn(enum_intrinsics_non_enums)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
@@ -131,5 +131,6 @@
 #![warn(unknown_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
 #![warn(unused_labels)] //~ ERROR: lint `clippy::unused_label`
 #![warn(ambiguous_wide_pointer_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons`
+#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop`
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index aa7b905b4b8..32641a684a4 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -13,8 +13,9 @@
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
-#![allow(clippy::manual_filter_map)]
 #![allow(clippy::manual_find_map)]
+#![allow(clippy::manual_filter_map)]
+#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::redundant_pattern_matching)]
 #![allow(clippy::match_result_ok)]
@@ -29,7 +30,6 @@
 #![allow(clippy::unwrap_used)]
 #![allow(clippy::panicking_overflow_checks)]
 #![allow(clippy::needless_borrow)]
-#![allow(clippy::reversed_empty_ranges)]
 #![allow(clippy::single_char_add_str)]
 #![allow(clippy::module_name_repetitions)]
 #![allow(clippy::missing_const_for_thread_local)]
@@ -39,11 +39,11 @@
 #![allow(invalid_reference_casting)]
 #![allow(suspicious_double_ref_op)]
 #![allow(invalid_nan_comparisons)]
+#![allow(invalid_null_arguments)]
 #![allow(double_negations)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
-#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(useless_ptr_null_checks)]
 #![allow(for_loops_over_fallibles)]
 #![allow(forgetting_copy_types)]
@@ -62,6 +62,7 @@
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
 #![allow(ambiguous_wide_pointer_comparisons)]
+#![allow(clippy::reversed_empty_ranges)]
 #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
 #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
 #![warn(clippy::block_in_if_condition_expr)] //~ ERROR: lint `clippy::block_in_if_condition_expr`
@@ -74,8 +75,9 @@
 #![warn(clippy::disallowed_method)] //~ ERROR: lint `clippy::disallowed_method`
 #![warn(clippy::disallowed_type)] //~ ERROR: lint `clippy::disallowed_type`
 #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
-#![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
 #![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
+#![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion`
 #![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
 #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`
@@ -94,7 +96,6 @@
 #![warn(clippy::result_expect_used)] //~ ERROR: lint `clippy::result_expect_used`
 #![warn(clippy::result_map_unwrap_or_else)] //~ ERROR: lint `clippy::result_map_unwrap_or_else`
 #![warn(clippy::result_unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used`
-#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop`
 #![warn(clippy::single_char_push_str)] //~ ERROR: lint `clippy::single_char_push_str`
 #![warn(clippy::stutter)] //~ ERROR: lint `clippy::stutter`
 #![warn(clippy::thread_local_initializer_can_be_made_const)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const`
@@ -104,11 +105,11 @@
 #![warn(clippy::cast_ref_to_mut)] //~ ERROR: lint `clippy::cast_ref_to_mut`
 #![warn(clippy::clone_double_ref)] //~ ERROR: lint `clippy::clone_double_ref`
 #![warn(clippy::cmp_nan)] //~ ERROR: lint `clippy::cmp_nan`
+#![warn(clippy::invalid_null_ptr_usage)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
 #![warn(clippy::double_neg)] //~ ERROR: lint `clippy::double_neg`
 #![warn(clippy::drop_bounds)] //~ ERROR: lint `clippy::drop_bounds`
 #![warn(clippy::drop_copy)] //~ ERROR: lint `clippy::drop_copy`
 #![warn(clippy::drop_ref)] //~ ERROR: lint `clippy::drop_ref`
-#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::fn_null_check)] //~ ERROR: lint `clippy::fn_null_check`
 #![warn(clippy::for_loop_over_option)] //~ ERROR: lint `clippy::for_loop_over_option`
 #![warn(clippy::for_loop_over_result)] //~ ERROR: lint `clippy::for_loop_over_result`
@@ -119,7 +120,6 @@
 #![warn(clippy::invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
 #![warn(clippy::invalid_ref)] //~ ERROR: lint `clippy::invalid_ref`
 #![warn(clippy::invalid_utf8_in_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
-#![warn(clippy::invalid_null_ptr_usage)] //~ ERROR: lint `clippy::invalid_null_ptr_usage`
 #![warn(clippy::let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
 #![warn(clippy::maybe_misused_cfg)] //~ ERROR: lint `clippy::maybe_misused_cfg`
 #![warn(clippy::mem_discriminant_non_enum)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
@@ -131,5 +131,6 @@
 #![warn(clippy::unknown_clippy_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
 #![warn(clippy::unused_label)] //~ ERROR: lint `clippy::unused_label`
 #![warn(clippy::vtable_address_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons`
+#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop`
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index b3c88167c11..e9d2debff91 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> tests/ui/rename.rs:65:9
+  --> tests/ui/rename.rs:66:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,347 +8,341 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> tests/ui/rename.rs:66:9
+  --> tests/ui/rename.rs:67:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:67:9
+  --> tests/ui/rename.rs:68:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:68:9
+  --> tests/ui/rename.rs:69:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:69:9
+  --> tests/ui/rename.rs:70:9
    |
 LL | #![warn(clippy::blocks_in_if_conditions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> tests/ui/rename.rs:70:9
+  --> tests/ui/rename.rs:71:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> tests/ui/rename.rs:71:9
+  --> tests/ui/rename.rs:72:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> tests/ui/rename.rs:72:9
+  --> tests/ui/rename.rs:73:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> tests/ui/rename.rs:73:9
+  --> tests/ui/rename.rs:74:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> tests/ui/rename.rs:74:9
+  --> tests/ui/rename.rs:75:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> tests/ui/rename.rs:75:9
+  --> tests/ui/rename.rs:76:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> tests/ui/rename.rs:76:9
+  --> tests/ui/rename.rs:77:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
+error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
+  --> tests/ui/rename.rs:78:9
+   |
+LL | #![warn(clippy::find_map)]
+   |         ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
+
 error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
-  --> tests/ui/rename.rs:77:9
+  --> tests/ui/rename.rs:79:9
    |
 LL | #![warn(clippy::filter_map)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map`
 
-error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
-  --> tests/ui/rename.rs:78:9
+error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
+  --> tests/ui/rename.rs:80:9
    |
-LL | #![warn(clippy::find_map)]
-   |         ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
+LL | #![warn(clippy::fn_address_comparisons)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> tests/ui/rename.rs:79:9
+  --> tests/ui/rename.rs:81:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
-  --> tests/ui/rename.rs:80:9
+  --> tests/ui/rename.rs:82:9
    |
 LL | #![warn(clippy::if_let_redundant_pattern_matching)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> tests/ui/rename.rs:81:9
+  --> tests/ui/rename.rs:83:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
-  --> tests/ui/rename.rs:82:9
+  --> tests/ui/rename.rs:84:9
    |
 LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
 
 error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
-  --> tests/ui/rename.rs:83:9
+  --> tests/ui/rename.rs:85:9
    |
 LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> tests/ui/rename.rs:84:9
+  --> tests/ui/rename.rs:86:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> tests/ui/rename.rs:85:9
+  --> tests/ui/rename.rs:87:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> tests/ui/rename.rs:86:9
+  --> tests/ui/rename.rs:88:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> tests/ui/rename.rs:87:9
+  --> tests/ui/rename.rs:89:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:88:9
+  --> tests/ui/rename.rs:90:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:89:9
+  --> tests/ui/rename.rs:91:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:90:9
+  --> tests/ui/rename.rs:92:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:91:9
+  --> tests/ui/rename.rs:93:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
-  --> tests/ui/rename.rs:92:9
+  --> tests/ui/rename.rs:94:9
    |
 LL | #![warn(clippy::overflow_check_conditional)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> tests/ui/rename.rs:93:9
+  --> tests/ui/rename.rs:95:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:94:9
+  --> tests/ui/rename.rs:96:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:95:9
+  --> tests/ui/rename.rs:97:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:96:9
+  --> tests/ui/rename.rs:98:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
-error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
-  --> tests/ui/rename.rs:97:9
-   |
-LL | #![warn(clippy::reverse_range_loop)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
-
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> tests/ui/rename.rs:98:9
+  --> tests/ui/rename.rs:99:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> tests/ui/rename.rs:99:9
+  --> tests/ui/rename.rs:100:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local`
-  --> tests/ui/rename.rs:100:9
+  --> tests/ui/rename.rs:101:9
    |
 LL | #![warn(clippy::thread_local_initializer_can_be_made_const)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> tests/ui/rename.rs:101:9
+  --> tests/ui/rename.rs:102:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> tests/ui/rename.rs:102:9
+  --> tests/ui/rename.rs:103:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> tests/ui/rename.rs:103:9
+  --> tests/ui/rename.rs:104:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> tests/ui/rename.rs:104:9
+  --> tests/ui/rename.rs:105:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> tests/ui/rename.rs:105:9
+  --> tests/ui/rename.rs:106:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> tests/ui/rename.rs:106:9
+  --> tests/ui/rename.rs:107:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
+error: lint `clippy::invalid_null_ptr_usage` has been renamed to `invalid_null_arguments`
+  --> tests/ui/rename.rs:108:9
+   |
+LL | #![warn(clippy::invalid_null_ptr_usage)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_null_arguments`
+
 error: lint `clippy::double_neg` has been renamed to `double_negations`
-  --> tests/ui/rename.rs:107:9
+  --> tests/ui/rename.rs:109:9
    |
 LL | #![warn(clippy::double_neg)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `double_negations`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> tests/ui/rename.rs:108:9
+  --> tests/ui/rename.rs:110:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> tests/ui/rename.rs:109:9
+  --> tests/ui/rename.rs:111:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> tests/ui/rename.rs:110:9
+  --> tests/ui/rename.rs:112:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
-error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
-  --> tests/ui/rename.rs:111:9
-   |
-LL | #![warn(clippy::fn_address_comparisons)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
-
 error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> tests/ui/rename.rs:112:9
+  --> tests/ui/rename.rs:113:9
    |
 LL | #![warn(clippy::fn_null_check)]
    |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:113:9
+  --> tests/ui/rename.rs:114:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:114:9
+  --> tests/ui/rename.rs:115:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:115:9
+  --> tests/ui/rename.rs:116:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> tests/ui/rename.rs:116:9
+  --> tests/ui/rename.rs:117:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> tests/ui/rename.rs:117:9
+  --> tests/ui/rename.rs:118:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> tests/ui/rename.rs:118:9
+  --> tests/ui/rename.rs:119:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> tests/ui/rename.rs:119:9
+  --> tests/ui/rename.rs:120:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> tests/ui/rename.rs:120:9
+  --> tests/ui/rename.rs:121:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> tests/ui/rename.rs:121:9
+  --> tests/ui/rename.rs:122:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
-error: lint `clippy::invalid_null_ptr_usage` has been renamed to `invalid_null_arguments`
-  --> tests/ui/rename.rs:122:9
-   |
-LL | #![warn(clippy::invalid_null_ptr_usage)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_null_arguments`
-
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
   --> tests/ui/rename.rs:123:9
    |
@@ -415,5 +409,11 @@ error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_
 LL | #![warn(clippy::vtable_address_comparisons)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
 
+error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
+  --> tests/ui/rename.rs:134:9
+   |
+LL | #![warn(clippy::reverse_range_loop)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
+
 error: aborting due to 69 previous errors
 
diff --git a/src/tools/clippy/tests/ui/repr_packed_without_abi.stderr b/src/tools/clippy/tests/ui/repr_packed_without_abi.stderr
index d1078b3e8e4..f688e4bc744 100644
--- a/src/tools/clippy/tests/ui/repr_packed_without_abi.stderr
+++ b/src/tools/clippy/tests/ui/repr_packed_without_abi.stderr
@@ -11,7 +11,7 @@ LL | | }
    | |_^
    |
    = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
-   = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
+   = help: qualify the desired ABI explicitly via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
 note: the lint level is defined here
   --> tests/ui/repr_packed_without_abi.rs:1:9
    |
@@ -31,7 +31,7 @@ LL | | }
    | |_^
    |
    = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
-   = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
+   = help: qualify the desired ABI explicitly via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/result_unit_error_no_std.rs b/src/tools/clippy/tests/ui/result_unit_error_no_std.rs
index 8a1849b8490..a64e8414d78 100644
--- a/src/tools/clippy/tests/ui/result_unit_error_no_std.rs
+++ b/src/tools/clippy/tests/ui/result_unit_error_no_std.rs
@@ -14,7 +14,7 @@ pub fn returns_unit_error_lint() -> Result<u32, ()> {
     Err(())
 }
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int {
     0
 }
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
index 847e5140d3e..cc4dbc919d8 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
@@ -214,10 +214,9 @@ mod issue7392 {
     }
 
     fn ref_bindings() {
-        let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
-        //~^ search_is_some
-        let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
-        //~^ search_is_some
+        let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)]
+            //~^ search_is_some
+            .iter().any(|&&(&x, ref y)| x == *y);
     }
 
     fn test_string_1(s: &str) -> bool {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
index e976d12600c..fa31a9ddedc 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
@@ -221,10 +221,11 @@ mod issue7392 {
     }
 
     fn ref_bindings() {
-        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none();
-        //~^ search_is_some
-        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
-        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)]
+            //~^ search_is_some
+            .iter()
+            .find(|&&&(&x, ref y)| x == *y)
+            .is_none();
     }
 
     fn test_string_1(s: &str) -> bool {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr
index ccc17025222..b079cf7ea36 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr
@@ -248,116 +248,122 @@ LL |         let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_none();
 error: called `is_none()` after searching an `Iterator` with `find`
   --> tests/ui/search_is_some_fixable_none.rs:224:17
    |
-LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
-
-error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:226:17
+LL |           let _ = [&(&1, 2), &(&3, 4), &(&5, 4)]
+   |  _________________^
+LL | |
+LL | |             .iter()
+LL | |             .find(|&&&(&x, ref y)| x == *y)
+LL | |             .is_none();
+   | |______________________^
+   |
+help: consider using
+   |
+LL ~         let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)]
+LL +
+LL ~             .iter().any(|&&(&x, ref y)| x == *y);
    |
-LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:246:17
+  --> tests/ui/search_is_some_fixable_none.rs:247:17
    |
 LL |         let _ = v.iter().find(|s| s[0].is_empty()).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|s| s[0].is_empty())`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:248:17
+  --> tests/ui/search_is_some_fixable_none.rs:249:17
    |
 LL |         let _ = v.iter().find(|s| test_string_1(&s[0])).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|s| test_string_1(&s[0]))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:258:17
+  --> tests/ui/search_is_some_fixable_none.rs:259:17
    |
 LL |         let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| fp.field.is_power_of_two())`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:260:17
+  --> tests/ui/search_is_some_fixable_none.rs:261:17
    |
 LL |         let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_1(fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:262:17
+  --> tests/ui/search_is_some_fixable_none.rs:263:17
    |
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:279:17
+  --> tests/ui/search_is_some_fixable_none.rs:280:17
    |
 LL |         let _ = v.iter().find(|x| **x == 42).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:281:17
+  --> tests/ui/search_is_some_fixable_none.rs:282:17
    |
 LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:287:9
+  --> tests/ui/search_is_some_fixable_none.rs:288:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_none.rs:293:9
+  --> tests/ui/search_is_some_fixable_none.rs:294:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:299:17
+  --> tests/ui/search_is_some_fixable_none.rs:300:17
    |
 LL |         let _ = s.find("world").is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:301:17
+  --> tests/ui/search_is_some_fixable_none.rs:302:17
    |
 LL |         Foo.bar(s.find("world").is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:304:17
+  --> tests/ui/search_is_some_fixable_none.rs:305:17
    |
 LL |         let _ = s.find("world").is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:306:17
+  --> tests/ui/search_is_some_fixable_none.rs:307:17
    |
 LL |         Foo.bar(s.find("world").is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:312:17
+  --> tests/ui/search_is_some_fixable_none.rs:313:17
    |
 LL |         let _ = s.find("world").is_none().then(computations);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:315:17
+  --> tests/ui/search_is_some_fixable_none.rs:316:17
    |
 LL |         let _ = s.find("world").is_none().then(computations);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:321:17
+  --> tests/ui/search_is_some_fixable_none.rs:322:17
    |
 LL |         let _ = s.find("world").is_none().then_some(0);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> tests/ui/search_is_some_fixable_none.rs:324:17
+  --> tests/ui/search_is_some_fixable_none.rs:325:17
    |
 LL |         let _ = s.find("world").is_none().then_some(0);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
-error: aborting due to 55 previous errors
+error: aborting due to 54 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.fixed
new file mode 100644
index 00000000000..6e15244901c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.fixed
@@ -0,0 +1,14 @@
+//@edition: 2021
+#![warn(clippy::search_is_some)]
+
+fn main() {
+    fn ref_bindings() {
+        let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
+        //~^ search_is_some
+        let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
+        //~^ search_is_some
+        let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)]
+            //~^ search_is_some
+            .iter().any(|&&(&x, ref y)| x == *y);
+    }
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.rs
new file mode 100644
index 00000000000..4b1db3f9fc3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.rs
@@ -0,0 +1,16 @@
+//@edition: 2021
+#![warn(clippy::search_is_some)]
+
+fn main() {
+    fn ref_bindings() {
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none();
+        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
+        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)]
+            //~^ search_is_some
+            .iter()
+            .find(|&&&(&x, ref y)| x == *y)
+            .is_none();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.stderr
new file mode 100644
index 00000000000..af93be1a707
--- /dev/null
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none_2021.stderr
@@ -0,0 +1,35 @@
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some_fixable_none_2021.rs:6:17
+   |
+LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
+   |
+   = note: `-D clippy::search-is-some` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some_fixable_none_2021.rs:8:17
+   |
+LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some_fixable_none_2021.rs:10:17
+   |
+LL |           let _ = [&(&1, 2), &(&3, 4), &(&5, 4)]
+   |  _________________^
+LL | |
+LL | |             .iter()
+LL | |             .find(|&&&(&x, ref y)| x == *y)
+LL | |             .is_none();
+   | |______________________^
+   |
+help: consider using
+   |
+LL ~         let _ = ![&(&1, 2), &(&3, 4), &(&5, 4)]
+LL +
+LL ~             .iter().any(|&&(&x, ref y)| x == *y);
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
index 05e88b8528f..42b39b33b57 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
@@ -214,10 +214,9 @@ mod issue7392 {
     }
 
     fn ref_bindings() {
-        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
-        //~^ search_is_some
-        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
-        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)]
+            .iter()
+            .any(|&&(&x, ref y)| x == *y);
     }
 
     fn test_string_1(s: &str) -> bool {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
index caab816f243..ca4f4d941cb 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
@@ -220,10 +220,11 @@ mod issue7392 {
     }
 
     fn ref_bindings() {
-        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some();
-        //~^ search_is_some
-        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
-        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)]
+            .iter()
+            .find(|&&&(&x, ref y)| x == *y)
+            //~^ search_is_some
+            .is_some();
     }
 
     fn test_string_1(s: &str) -> bool {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
index af719b78831..8291f48d43c 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
@@ -227,70 +227,67 @@ LL |         let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_some();
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.by_ref(&v.bar))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:223:55
+  --> tests/ui/search_is_some_fixable_some.rs:225:14
    |
-LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some();
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)`
-
-error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:225:55
-   |
-LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)`
+LL |               .find(|&&&(&x, ref y)| x == *y)
+   |  ______________^
+LL | |
+LL | |             .is_some();
+   | |______________________^ help: consider using: `any(|&&(&x, ref y)| x == *y)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:245:26
+  --> tests/ui/search_is_some_fixable_some.rs:246:26
    |
 LL |         let _ = v.iter().find(|s| s[0].is_empty()).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| s[0].is_empty())`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:247:26
+  --> tests/ui/search_is_some_fixable_some.rs:248:26
    |
 LL |         let _ = v.iter().find(|s| test_string_1(&s[0])).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| test_string_1(&s[0]))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:257:26
+  --> tests/ui/search_is_some_fixable_some.rs:258:26
    |
 LL |         let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| fp.field.is_power_of_two())`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:259:26
+  --> tests/ui/search_is_some_fixable_some.rs:260:26
    |
 LL |         let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| test_u32_1(fp.field))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:261:26
+  --> tests/ui/search_is_some_fixable_some.rs:262:26
    |
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:277:18
+  --> tests/ui/search_is_some_fixable_some.rs:278:18
    |
 LL |         v.iter().find(|x: &&u32| func(x)).is_some()
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| func(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:287:26
+  --> tests/ui/search_is_some_fixable_some.rs:288:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| arg_no_deref_impl(x)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_impl(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:291:26
+  --> tests/ui/search_is_some_fixable_some.rs:292:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| arg_no_deref_dyn(x)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_dyn(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some_fixable_some.rs:295:26
+  --> tests/ui/search_is_some_fixable_some.rs:296:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))`
 
-error: aborting due to 47 previous errors
+error: aborting due to 46 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.fixed
new file mode 100644
index 00000000000..d2b05db562a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.fixed
@@ -0,0 +1,11 @@
+//@edition: 2021
+#![warn(clippy::search_is_some)]
+
+fn main() {
+    fn ref_bindings() {
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
+        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y);
+        //~^ search_is_some
+    }
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.rs
new file mode 100644
index 00000000000..c3f5ef769da
--- /dev/null
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.rs
@@ -0,0 +1,11 @@
+//@edition: 2021
+#![warn(clippy::search_is_some)]
+
+fn main() {
+    fn ref_bindings() {
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some();
+        //~^ search_is_some
+        let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
+        //~^ search_is_some
+    }
+}
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.stderr
new file mode 100644
index 00000000000..91d9540e6fc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some_2021.stderr
@@ -0,0 +1,17 @@
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some_fixable_some_2021.rs:6:55
+   |
+LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some();
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)`
+   |
+   = note: `-D clippy::search-is-some` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]`
+
+error: called `is_some()` after searching an `Iterator` with `find`
+  --> tests/ui/search_is_some_fixable_some_2021.rs:8:55
+   |
+LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/shadow.rs b/src/tools/clippy/tests/ui/shadow.rs
index 7d503a1cf6c..05009b2ddd4 100644
--- a/src/tools/clippy/tests/ui/shadow.rs
+++ b/src/tools/clippy/tests/ui/shadow.rs
@@ -167,4 +167,19 @@ fn issue13795(value: Issue13795) {
     //~^ shadow_same
 }
 
+fn issue14377() {
+    let a;
+    let b;
+    (a, b) = (0, 1);
+
+    struct S {
+        c: i32,
+        d: i32,
+    }
+
+    let c;
+    let d;
+    S { c, d } = S { c: 1, d: 2 };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
index 4ec0f02d664..53704f59cb9 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/corner_cases.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 
-#![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
     clippy::needless_pass_by_value,
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
index 87b3a7d2fa0..e8de0e04c0c 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
     clippy::needless_pass_by_value,
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
index 8738b61192a..5609d6a21a3 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
@@ -1,5 +1,5 @@
 error: method `add` can be confused for the standard trait method `std::ops::Add::add`
-  --> tests/ui/should_impl_trait/method_list_1.rs:25:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:24:5
    |
 LL | /     pub fn add(self, other: T) -> T {
 LL | |
@@ -13,7 +13,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]`
 
 error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
-  --> tests/ui/should_impl_trait/method_list_1.rs:31:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:30:5
    |
 LL | /     pub fn as_mut(&mut self) -> &mut T {
 LL | |
@@ -25,7 +25,7 @@ LL | |     }
    = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
 
 error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
-  --> tests/ui/should_impl_trait/method_list_1.rs:37:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:36:5
    |
 LL | /     pub fn as_ref(&self) -> &T {
 LL | |
@@ -37,7 +37,7 @@ LL | |     }
    = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
 
 error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
-  --> tests/ui/should_impl_trait/method_list_1.rs:43:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:42:5
    |
 LL | /     pub fn bitand(self, rhs: T) -> T {
 LL | |
@@ -49,7 +49,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
 
 error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
-  --> tests/ui/should_impl_trait/method_list_1.rs:49:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:48:5
    |
 LL | /     pub fn bitor(self, rhs: Self) -> Self {
 LL | |
@@ -61,7 +61,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
 
 error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
-  --> tests/ui/should_impl_trait/method_list_1.rs:55:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:54:5
    |
 LL | /     pub fn bitxor(self, rhs: Self) -> Self {
 LL | |
@@ -73,7 +73,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
 
 error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
-  --> tests/ui/should_impl_trait/method_list_1.rs:61:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:60:5
    |
 LL | /     pub fn borrow(&self) -> &str {
 LL | |
@@ -85,7 +85,7 @@ LL | |     }
    = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
 
 error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
-  --> tests/ui/should_impl_trait/method_list_1.rs:67:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:66:5
    |
 LL | /     pub fn borrow_mut(&mut self) -> &mut str {
 LL | |
@@ -97,7 +97,7 @@ LL | |     }
    = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
 
 error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
-  --> tests/ui/should_impl_trait/method_list_1.rs:73:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:72:5
    |
 LL | /     pub fn clone(&self) -> Self {
 LL | |
@@ -109,7 +109,7 @@ LL | |     }
    = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
 
 error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
-  --> tests/ui/should_impl_trait/method_list_1.rs:79:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:78:5
    |
 LL | /     pub fn cmp(&self, other: &Self) -> Self {
 LL | |
@@ -121,7 +121,7 @@ LL | |     }
    = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
 
 error: method `default` can be confused for the standard trait method `std::default::Default::default`
-  --> tests/ui/should_impl_trait/method_list_1.rs:85:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:84:5
    |
 LL | /     pub fn default() -> Self {
 LL | |
@@ -133,7 +133,7 @@ LL | |     }
    = help: consider implementing the trait `std::default::Default` or choosing a less ambiguous method name
 
 error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
-  --> tests/ui/should_impl_trait/method_list_1.rs:91:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:90:5
    |
 LL | /     pub fn deref(&self) -> &Self {
 LL | |
@@ -145,7 +145,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
 
 error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
-  --> tests/ui/should_impl_trait/method_list_1.rs:97:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:96:5
    |
 LL | /     pub fn deref_mut(&mut self) -> &mut Self {
 LL | |
@@ -157,7 +157,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
 
 error: method `div` can be confused for the standard trait method `std::ops::Div::div`
-  --> tests/ui/should_impl_trait/method_list_1.rs:103:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:102:5
    |
 LL | /     pub fn div(self, rhs: Self) -> Self {
 LL | |
@@ -169,7 +169,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
 
 error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
-  --> tests/ui/should_impl_trait/method_list_1.rs:109:5
+  --> tests/ui/should_impl_trait/method_list_1.rs:108:5
    |
 LL | /     pub fn drop(&mut self) {
 LL | |
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
index f0c4d4f15cb..1f25ab3938a 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.rs
@@ -1,4 +1,3 @@
-#![warn(clippy::all, clippy::pedantic)]
 #![allow(
     clippy::missing_errors_doc,
     clippy::needless_pass_by_value,
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
index 85de7433702..0f581850777 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
@@ -1,5 +1,5 @@
 error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
-  --> tests/ui/should_impl_trait/method_list_2.rs:26:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:25:5
    |
 LL | /     pub fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -13,7 +13,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::should_implement_trait)]`
 
 error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
-  --> tests/ui/should_impl_trait/method_list_2.rs:32:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:31:5
    |
 LL | /     pub fn from_iter<T>(iter: T) -> Self {
 LL | |
@@ -25,7 +25,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
 
 error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
-  --> tests/ui/should_impl_trait/method_list_2.rs:38:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:37:5
    |
 LL | /     pub fn from_str(s: &str) -> Result<Self, Self> {
 LL | |
@@ -37,7 +37,7 @@ LL | |     }
    = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
 
 error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
-  --> tests/ui/should_impl_trait/method_list_2.rs:44:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:43:5
    |
 LL | /     pub fn hash(&self, state: &mut T) {
 LL | |
@@ -49,7 +49,7 @@ LL | |     }
    = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
 
 error: method `index` can be confused for the standard trait method `std::ops::Index::index`
-  --> tests/ui/should_impl_trait/method_list_2.rs:50:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:49:5
    |
 LL | /     pub fn index(&self, index: usize) -> &Self {
 LL | |
@@ -61,7 +61,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
 
 error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
-  --> tests/ui/should_impl_trait/method_list_2.rs:56:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:55:5
    |
 LL | /     pub fn index_mut(&mut self, index: usize) -> &mut Self {
 LL | |
@@ -73,7 +73,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
 
 error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
-  --> tests/ui/should_impl_trait/method_list_2.rs:62:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:61:5
    |
 LL | /     pub fn into_iter(self) -> Self {
 LL | |
@@ -85,7 +85,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
 
 error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
-  --> tests/ui/should_impl_trait/method_list_2.rs:68:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:67:5
    |
 LL | /     pub fn mul(self, rhs: Self) -> Self {
 LL | |
@@ -97,7 +97,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
 
 error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
-  --> tests/ui/should_impl_trait/method_list_2.rs:74:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:73:5
    |
 LL | /     pub fn neg(self) -> Self {
 LL | |
@@ -109,7 +109,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
 
 error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
-  --> tests/ui/should_impl_trait/method_list_2.rs:80:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:79:5
    |
 LL | /     pub fn next(&mut self) -> Option<Self> {
 LL | |
@@ -121,7 +121,7 @@ LL | |     }
    = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
 
 error: method `not` can be confused for the standard trait method `std::ops::Not::not`
-  --> tests/ui/should_impl_trait/method_list_2.rs:86:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:85:5
    |
 LL | /     pub fn not(self) -> Self {
 LL | |
@@ -133,7 +133,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
 
 error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
-  --> tests/ui/should_impl_trait/method_list_2.rs:92:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:91:5
    |
 LL | /     pub fn rem(self, rhs: Self) -> Self {
 LL | |
@@ -145,7 +145,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
 
 error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
-  --> tests/ui/should_impl_trait/method_list_2.rs:98:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:97:5
    |
 LL | /     pub fn shl(self, rhs: Self) -> Self {
 LL | |
@@ -157,7 +157,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
 
 error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
-  --> tests/ui/should_impl_trait/method_list_2.rs:104:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:103:5
    |
 LL | /     pub fn shr(self, rhs: Self) -> Self {
 LL | |
@@ -169,7 +169,7 @@ LL | |     }
    = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
 
 error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
-  --> tests/ui/should_impl_trait/method_list_2.rs:110:5
+  --> tests/ui/should_impl_trait/method_list_2.rs:109:5
    |
 LL | /     pub fn sub(self, rhs: Self) -> Self {
 LL | |
diff --git a/src/tools/clippy/tests/ui/single_call_fn.rs b/src/tools/clippy/tests/ui/single_call_fn.rs
index c1cc4032bec..a1ecd7bc166 100644
--- a/src/tools/clippy/tests/ui/single_call_fn.rs
+++ b/src/tools/clippy/tests/ui/single_call_fn.rs
@@ -94,7 +94,7 @@ trait Trait {
     //~^ single_call_fn
     fn foo(&self);
 }
-extern "C" {
+unsafe extern "C" {
     // test some kind of foreign item
     fn rand() -> std::ffi::c_int;
 }
diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed
index 0e198ec7934..db5107600ee 100644
--- a/src/tools/clippy/tests/ui/single_match.fixed
+++ b/src/tools/clippy/tests/ui/single_match.fixed
@@ -366,3 +366,39 @@ fn irrefutable_match() {
     //~^^^^^^^^^ single_match
     //~| NOTE: you might want to preserve the comments from inside the `match`
 }
+
+fn issue_14493() {
+    macro_rules! mac {
+        (some) => {
+            Some(42)
+        };
+        (any) => {
+            _
+        };
+        (str) => {
+            "foo"
+        };
+    }
+
+    if let Some(u) = mac!(some) { println!("{u}") }
+    //~^^^^ single_match
+
+    // When scrutinee comes from macro, do not tell that arm will always match
+    // and suggest an equality check instead.
+    if mac!(str) == "foo" { println!("eq") }
+    //~^^^^ ERROR: for an equality check
+
+    // Do not lint if any match arm come from expansion
+    match Some(0) {
+        mac!(some) => println!("eq"),
+        mac!(any) => println!("neq"),
+    }
+    match Some(0) {
+        Some(42) => println!("eq"),
+        mac!(any) => println!("neq"),
+    }
+    match Some(0) {
+        mac!(some) => println!("eq"),
+        _ => println!("neq"),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index fcac65f8aaf..a367b94c4ca 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -461,3 +461,45 @@ fn irrefutable_match() {
     //~^^^^^^^^^ single_match
     //~| NOTE: you might want to preserve the comments from inside the `match`
 }
+
+fn issue_14493() {
+    macro_rules! mac {
+        (some) => {
+            Some(42)
+        };
+        (any) => {
+            _
+        };
+        (str) => {
+            "foo"
+        };
+    }
+
+    match mac!(some) {
+        Some(u) => println!("{u}"),
+        _ => (),
+    }
+    //~^^^^ single_match
+
+    // When scrutinee comes from macro, do not tell that arm will always match
+    // and suggest an equality check instead.
+    match mac!(str) {
+        "foo" => println!("eq"),
+        _ => (),
+    }
+    //~^^^^ ERROR: for an equality check
+
+    // Do not lint if any match arm come from expansion
+    match Some(0) {
+        mac!(some) => println!("eq"),
+        mac!(any) => println!("neq"),
+    }
+    match Some(0) {
+        Some(42) => println!("eq"),
+        mac!(any) => println!("neq"),
+    }
+    match Some(0) {
+        mac!(some) => println!("eq"),
+        _ => println!("neq"),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index 2467423b9c1..1a4edc45c92 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -321,5 +321,23 @@ LL +         println!("{u}");
 LL +     }
    |
 
-error: aborting due to 29 previous errors
+error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
+  --> tests/ui/single_match.rs:478:5
+   |
+LL | /     match mac!(some) {
+LL | |         Some(u) => println!("{u}"),
+LL | |         _ => (),
+LL | |     }
+   | |_____^ help: try: `if let Some(u) = mac!(some) { println!("{u}") }`
+
+error: you seem to be trying to use `match` for an equality check. Consider using `if`
+  --> tests/ui/single_match.rs:486:5
+   |
+LL | /     match mac!(str) {
+LL | |         "foo" => println!("eq"),
+LL | |         _ => (),
+LL | |     }
+   | |_____^ help: try: `if mac!(str) == "foo" { println!("eq") }`
+
+error: aborting due to 31 previous errors
 
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed b/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
index 3696b0e066d..3faa4b21ee4 100644
--- a/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
@@ -87,4 +87,8 @@ pub mod useless_outer_doc {
     use std::mem;
 }
 
+// Do not lint, this is not a `///!`
+#[doc = "! here's some docs !"]
+fn issue14265() {}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.rs b/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
index 4107f5526d1..4af6ed850c2 100644
--- a/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
@@ -87,4 +87,8 @@ pub mod useless_outer_doc {
     use std::mem;
 }
 
+// Do not lint, this is not a `///!`
+#[doc = "! here's some docs !"]
+fn issue14265() {}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/swap.fixed b/src/tools/clippy/tests/ui/swap.fixed
index 888665a17ad..6a64e64e98f 100644
--- a/src/tools/clippy/tests/ui/swap.fixed
+++ b/src/tools/clippy/tests/ui/swap.fixed
@@ -1,14 +1,9 @@
 //@aux-build: macro_rules.rs
 
-#![warn(clippy::all)]
 #![allow(
     clippy::disallowed_names,
     clippy::no_effect,
     clippy::redundant_clone,
-    redundant_semicolons,
-    dead_code,
-    unused_assignments,
-    unused_variables,
     clippy::let_and_return,
     clippy::useless_vec,
     clippy::redundant_locals
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs
index 51af55ecd27..e2d89c47382 100644
--- a/src/tools/clippy/tests/ui/swap.rs
+++ b/src/tools/clippy/tests/ui/swap.rs
@@ -1,14 +1,9 @@
 //@aux-build: macro_rules.rs
 
-#![warn(clippy::all)]
 #![allow(
     clippy::disallowed_names,
     clippy::no_effect,
     clippy::redundant_clone,
-    redundant_semicolons,
-    dead_code,
-    unused_assignments,
-    unused_variables,
     clippy::let_and_return,
     clippy::useless_vec,
     clippy::redundant_locals
diff --git a/src/tools/clippy/tests/ui/swap.stderr b/src/tools/clippy/tests/ui/swap.stderr
index 15f7566d589..195b888187e 100644
--- a/src/tools/clippy/tests/ui/swap.stderr
+++ b/src/tools/clippy/tests/ui/swap.stderr
@@ -1,5 +1,5 @@
 error: this looks like you are swapping `bar.a` and `bar.b` manually
-  --> tests/ui/swap.rs:28:5
+  --> tests/ui/swap.rs:23:5
    |
 LL | /     let temp = bar.a;
 LL | |
@@ -12,7 +12,7 @@ LL | |     bar.b = temp;
    = help: to override `-D warnings` add `#[allow(clippy::manual_swap)]`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> tests/ui/swap.rs:41:5
+  --> tests/ui/swap.rs:36:5
    |
 LL | /     let temp = foo[0];
 LL | |
@@ -21,7 +21,7 @@ LL | |     foo[1] = temp;
    | |__________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> tests/ui/swap.rs:51:5
+  --> tests/ui/swap.rs:46:5
    |
 LL | /     let temp = foo[0];
 LL | |
@@ -30,7 +30,7 @@ LL | |     foo[1] = temp;
    | |__________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> tests/ui/swap.rs:71:5
+  --> tests/ui/swap.rs:66:5
    |
 LL | /     let temp = foo[0];
 LL | |
@@ -39,7 +39,7 @@ LL | |     foo[1] = temp;
    | |__________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping `a` and `b` manually
-  --> tests/ui/swap.rs:83:5
+  --> tests/ui/swap.rs:78:5
    |
 LL | /     a ^= b;
 LL | |
@@ -48,7 +48,7 @@ LL | |     a ^= b;
    | |___________^ help: try: `std::mem::swap(&mut a, &mut b);`
 
 error: this looks like you are swapping `bar.a` and `bar.b` manually
-  --> tests/ui/swap.rs:92:5
+  --> tests/ui/swap.rs:87:5
    |
 LL | /     bar.a ^= bar.b;
 LL | |
@@ -57,7 +57,7 @@ LL | |     bar.a ^= bar.b;
    | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> tests/ui/swap.rs:101:5
+  --> tests/ui/swap.rs:96:5
    |
 LL | /     foo[0] ^= foo[1];
 LL | |
@@ -66,7 +66,7 @@ LL | |     foo[0] ^= foo[1];
    | |_____________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
-  --> tests/ui/swap.rs:131:5
+  --> tests/ui/swap.rs:126:5
    |
 LL | /     let temp = foo[0][1];
 LL | |
@@ -77,7 +77,7 @@ LL | |     bar[1][0] = temp;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `a` and `b` manually
-  --> tests/ui/swap.rs:147:7
+  --> tests/ui/swap.rs:142:7
    |
 LL |       ; let t = a;
    |  _______^
@@ -89,7 +89,7 @@ LL | |     b = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `c.0` and `a` manually
-  --> tests/ui/swap.rs:158:7
+  --> tests/ui/swap.rs:153:7
    |
 LL |       ; let t = c.0;
    |  _______^
@@ -101,7 +101,7 @@ LL | |     a = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `b` and `a` manually
-  --> tests/ui/swap.rs:188:5
+  --> tests/ui/swap.rs:183:5
    |
 LL | /     let t = b;
 LL | |
@@ -112,7 +112,7 @@ LL | |     a = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> tests/ui/swap.rs:143:5
+  --> tests/ui/swap.rs:138:5
    |
 LL | /     a = b;
 LL | |
@@ -120,11 +120,10 @@ LL | |     b = a;
    | |_________^ help: try: `std::mem::swap(&mut a, &mut b)`
    |
    = note: or maybe you should use `std::mem::replace`?
-   = note: `-D clippy::almost-swapped` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::almost_swapped)]`
+   = note: `#[deny(clippy::almost_swapped)]` on by default
 
 error: this looks like you are trying to swap `c.0` and `a`
-  --> tests/ui/swap.rs:154:5
+  --> tests/ui/swap.rs:149:5
    |
 LL | /     c.0 = a;
 LL | |
@@ -134,7 +133,7 @@ LL | |     a = c.0;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> tests/ui/swap.rs:163:5
+  --> tests/ui/swap.rs:158:5
    |
 LL | /     let a = b;
 LL | |
@@ -144,7 +143,7 @@ LL | |     let b = a;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `d` and `c`
-  --> tests/ui/swap.rs:169:5
+  --> tests/ui/swap.rs:164:5
    |
 LL | /     d = c;
 LL | |
@@ -154,7 +153,7 @@ LL | |     c = d;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> tests/ui/swap.rs:174:5
+  --> tests/ui/swap.rs:169:5
    |
 LL | /     let a = b;
 LL | |
@@ -164,7 +163,7 @@ LL | |     b = a;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `s.0.x` and `s.0.y` manually
-  --> tests/ui/swap.rs:224:5
+  --> tests/ui/swap.rs:219:5
    |
 LL | /     let t = s.0.x;
 LL | |
diff --git a/src/tools/clippy/tests/ui/swap_with_temporary.fixed b/src/tools/clippy/tests/ui/swap_with_temporary.fixed
new file mode 100644
index 00000000000..4007d998ba0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/swap_with_temporary.fixed
@@ -0,0 +1,74 @@
+#![warn(clippy::swap_with_temporary)]
+
+use std::mem::swap;
+
+fn func() -> String {
+    String::from("func")
+}
+
+fn func_returning_refmut(s: &mut String) -> &mut String {
+    s
+}
+
+fn main() {
+    let mut x = String::from("x");
+    let mut y = String::from("y");
+    let mut zz = String::from("zz");
+    let z = &mut zz;
+
+    // No lint
+    swap(&mut x, &mut y);
+
+    y = func();
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    x = func();
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    *z = func();
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    // No lint
+    swap(z, func_returning_refmut(&mut x));
+
+    swap(&mut y, z);
+
+    *z = func();
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    macro_rules! mac {
+        (refmut $x:expr) => {
+            &mut $x
+        };
+        (funcall $f:ident) => {
+            $f()
+        };
+        (wholeexpr) => {
+            swap(&mut 42, &mut 0)
+        };
+        (ident $v:ident) => {
+            $v
+        };
+    }
+    *z = mac!(funcall func);
+    //~^ ERROR: swapping with a temporary value is inefficient
+    *mac!(ident z) = mac!(funcall func);
+    //~^ ERROR: swapping with a temporary value is inefficient
+    *mac!(ident z) = mac!(funcall func);
+    //~^ ERROR: swapping with a temporary value is inefficient
+    *mac!(refmut y) = func();
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    // No lint if it comes from a macro as it may depend on the arguments
+    mac!(wholeexpr);
+}
+
+struct S {
+    t: String,
+}
+
+fn dont_lint_those(s: &mut S, v: &mut [String], w: Option<&mut String>) {
+    swap(&mut s.t, &mut v[0]);
+    swap(&mut s.t, v.get_mut(0).unwrap());
+    swap(w.unwrap(), &mut s.t);
+}
diff --git a/src/tools/clippy/tests/ui/swap_with_temporary.rs b/src/tools/clippy/tests/ui/swap_with_temporary.rs
new file mode 100644
index 00000000000..d403c086c0f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/swap_with_temporary.rs
@@ -0,0 +1,74 @@
+#![warn(clippy::swap_with_temporary)]
+
+use std::mem::swap;
+
+fn func() -> String {
+    String::from("func")
+}
+
+fn func_returning_refmut(s: &mut String) -> &mut String {
+    s
+}
+
+fn main() {
+    let mut x = String::from("x");
+    let mut y = String::from("y");
+    let mut zz = String::from("zz");
+    let z = &mut zz;
+
+    // No lint
+    swap(&mut x, &mut y);
+
+    swap(&mut func(), &mut y);
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    swap(&mut x, &mut func());
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    swap(z, &mut func());
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    // No lint
+    swap(z, func_returning_refmut(&mut x));
+
+    swap(&mut y, z);
+
+    swap(&mut func(), z);
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    macro_rules! mac {
+        (refmut $x:expr) => {
+            &mut $x
+        };
+        (funcall $f:ident) => {
+            $f()
+        };
+        (wholeexpr) => {
+            swap(&mut 42, &mut 0)
+        };
+        (ident $v:ident) => {
+            $v
+        };
+    }
+    swap(&mut mac!(funcall func), z);
+    //~^ ERROR: swapping with a temporary value is inefficient
+    swap(&mut mac!(funcall func), mac!(ident z));
+    //~^ ERROR: swapping with a temporary value is inefficient
+    swap(mac!(ident z), &mut mac!(funcall func));
+    //~^ ERROR: swapping with a temporary value is inefficient
+    swap(mac!(refmut y), &mut func());
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    // No lint if it comes from a macro as it may depend on the arguments
+    mac!(wholeexpr);
+}
+
+struct S {
+    t: String,
+}
+
+fn dont_lint_those(s: &mut S, v: &mut [String], w: Option<&mut String>) {
+    swap(&mut s.t, &mut v[0]);
+    swap(&mut s.t, v.get_mut(0).unwrap());
+    swap(w.unwrap(), &mut s.t);
+}
diff --git a/src/tools/clippy/tests/ui/swap_with_temporary.stderr b/src/tools/clippy/tests/ui/swap_with_temporary.stderr
new file mode 100644
index 00000000000..59355771a96
--- /dev/null
+++ b/src/tools/clippy/tests/ui/swap_with_temporary.stderr
@@ -0,0 +1,100 @@
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:22:5
+   |
+LL |     swap(&mut func(), &mut y);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `y = func()`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:22:15
+   |
+LL |     swap(&mut func(), &mut y);
+   |               ^^^^^^
+   = note: `-D clippy::swap-with-temporary` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::swap_with_temporary)]`
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:25:5
+   |
+LL |     swap(&mut x, &mut func());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `x = func()`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:25:23
+   |
+LL |     swap(&mut x, &mut func());
+   |                       ^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:28:5
+   |
+LL |     swap(z, &mut func());
+   |     ^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*z = func()`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:28:18
+   |
+LL |     swap(z, &mut func());
+   |                  ^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:36:5
+   |
+LL |     swap(&mut func(), z);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*z = func()`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:36:15
+   |
+LL |     swap(&mut func(), z);
+   |               ^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:53:5
+   |
+LL |     swap(&mut mac!(funcall func), z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*z = mac!(funcall func)`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:53:15
+   |
+LL |     swap(&mut mac!(funcall func), z);
+   |               ^^^^^^^^^^^^^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:55:5
+   |
+LL |     swap(&mut mac!(funcall func), mac!(ident z));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*mac!(ident z) = mac!(funcall func)`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:55:15
+   |
+LL |     swap(&mut mac!(funcall func), mac!(ident z));
+   |               ^^^^^^^^^^^^^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:57:5
+   |
+LL |     swap(mac!(ident z), &mut mac!(funcall func));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*mac!(ident z) = mac!(funcall func)`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:57:30
+   |
+LL |     swap(mac!(ident z), &mut mac!(funcall func));
+   |                              ^^^^^^^^^^^^^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:59:5
+   |
+LL |     swap(mac!(refmut y), &mut func());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*mac!(refmut y) = func()`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:59:31
+   |
+LL |     swap(mac!(refmut y), &mut func());
+   |                               ^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/tools/clippy/tests/ui/swap_with_temporary_unfixable.rs b/src/tools/clippy/tests/ui/swap_with_temporary_unfixable.rs
new file mode 100644
index 00000000000..a974ca82abf
--- /dev/null
+++ b/src/tools/clippy/tests/ui/swap_with_temporary_unfixable.rs
@@ -0,0 +1,62 @@
+//@no-rustfix
+#![warn(clippy::swap_with_temporary)]
+
+use std::mem::swap;
+
+fn func() -> String {
+    String::from("func")
+}
+
+fn func_returning_refmut(s: &mut String) -> &mut String {
+    s
+}
+
+fn main() {
+    let mut x = String::from("x");
+    let mut y = String::from("y");
+    let mut zz = String::from("zz");
+    let z = &mut zz;
+
+    swap(&mut func(), &mut func());
+    //~^ ERROR: swapping temporary values has no effect
+
+    if matches!(swap(&mut func(), &mut func()), ()) {
+        //~^ ERROR: swapping temporary values has no effect
+        println!("Yeah");
+    }
+
+    if matches!(swap(z, &mut func()), ()) {
+        //~^ ERROR: swapping with a temporary value is inefficient
+        println!("Yeah");
+    }
+
+    macro_rules! mac {
+        (refmut $x:expr) => {
+            &mut $x
+        };
+        (refmut) => {
+            mac!(refmut String::new())
+        };
+        (funcall $f:ident) => {
+            $f()
+        };
+    }
+
+    swap(mac!(refmut func()), z);
+    //~^ ERROR: swapping with a temporary value is inefficient
+    swap(&mut mac!(funcall func), &mut mac!(funcall func));
+    //~^ ERROR: swapping temporary values has no effect
+    swap(mac!(refmut), mac!(refmut));
+    //~^ ERROR: swapping temporary values has no effect
+    swap(mac!(refmut y), mac!(refmut));
+    //~^ ERROR: swapping with a temporary value is inefficient
+}
+
+fn bug(v1: &mut [i32], v2: &mut [i32]) {
+    // Incorrect: swapping temporary references (`&mut &mut` passed to swap)
+    std::mem::swap(&mut v1.last_mut().unwrap(), &mut v2.last_mut().unwrap());
+    //~^ ERROR: swapping temporary values has no effect
+
+    // Correct
+    std::mem::swap(v1.last_mut().unwrap(), v2.last_mut().unwrap());
+}
diff --git a/src/tools/clippy/tests/ui/swap_with_temporary_unfixable.stderr b/src/tools/clippy/tests/ui/swap_with_temporary_unfixable.stderr
new file mode 100644
index 00000000000..856c5415d67
--- /dev/null
+++ b/src/tools/clippy/tests/ui/swap_with_temporary_unfixable.stderr
@@ -0,0 +1,125 @@
+error: swapping temporary values has no effect
+  --> tests/ui/swap_with_temporary_unfixable.rs:20:5
+   |
+LL |     swap(&mut func(), &mut func());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:20:15
+   |
+LL |     swap(&mut func(), &mut func());
+   |               ^^^^^^
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:20:28
+   |
+LL |     swap(&mut func(), &mut func());
+   |                            ^^^^^^
+   = note: `-D clippy::swap-with-temporary` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::swap_with_temporary)]`
+
+error: swapping temporary values has no effect
+  --> tests/ui/swap_with_temporary_unfixable.rs:23:17
+   |
+LL |     if matches!(swap(&mut func(), &mut func()), ()) {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:23:27
+   |
+LL |     if matches!(swap(&mut func(), &mut func()), ()) {
+   |                           ^^^^^^
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:23:40
+   |
+LL |     if matches!(swap(&mut func(), &mut func()), ()) {
+   |                                        ^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary_unfixable.rs:28:17
+   |
+LL |     if matches!(swap(z, &mut func()), ()) {
+   |                 ^^^^^^^^^^^^^^^^^^^^
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:28:30
+   |
+LL |     if matches!(swap(z, &mut func()), ()) {
+   |                              ^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary_unfixable.rs:45:5
+   |
+LL |     swap(mac!(refmut func()), z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this is a mutable reference to a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:45:10
+   |
+LL |     swap(mac!(refmut func()), z);
+   |          ^^^^^^^^^^^^^^^^^^^
+
+error: swapping temporary values has no effect
+  --> tests/ui/swap_with_temporary_unfixable.rs:47:5
+   |
+LL |     swap(&mut mac!(funcall func), &mut mac!(funcall func));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:47:15
+   |
+LL |     swap(&mut mac!(funcall func), &mut mac!(funcall func));
+   |               ^^^^^^^^^^^^^^^^^^
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:47:40
+   |
+LL |     swap(&mut mac!(funcall func), &mut mac!(funcall func));
+   |                                        ^^^^^^^^^^^^^^^^^^
+
+error: swapping temporary values has no effect
+  --> tests/ui/swap_with_temporary_unfixable.rs:49:5
+   |
+LL |     swap(mac!(refmut), mac!(refmut));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this is a mutable reference to a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:49:10
+   |
+LL |     swap(mac!(refmut), mac!(refmut));
+   |          ^^^^^^^^^^^^
+note: this is a mutable reference to a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:49:24
+   |
+LL |     swap(mac!(refmut), mac!(refmut));
+   |                        ^^^^^^^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary_unfixable.rs:51:5
+   |
+LL |     swap(mac!(refmut y), mac!(refmut));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this is a mutable reference to a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:51:26
+   |
+LL |     swap(mac!(refmut y), mac!(refmut));
+   |                          ^^^^^^^^^^^^
+
+error: swapping temporary values has no effect
+  --> tests/ui/swap_with_temporary_unfixable.rs:57:5
+   |
+LL |     std::mem::swap(&mut v1.last_mut().unwrap(), &mut v2.last_mut().unwrap());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:57:25
+   |
+LL |     std::mem::swap(&mut v1.last_mut().unwrap(), &mut v2.last_mut().unwrap());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary_unfixable.rs:57:54
+   |
+LL |     std::mem::swap(&mut v1.last_mut().unwrap(), &mut v2.last_mut().unwrap());
+   |                                                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index 3aecde398dc..2b8b6c539ad 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     clippy::borrow_as_ptr,
+    unnecessary_transmutes,
     clippy::needless_lifetimes,
     clippy::missing_transmute_annotations
 )]
@@ -23,19 +24,21 @@ fn my_vec() -> MyVec<i32> {
 #[allow(clippy::needless_lifetimes, clippy::transmute_ptr_to_ptr)]
 #[warn(clippy::useless_transmute)]
 unsafe fn _generic<'a, T, U: 'a>(t: &'a T) {
-    // FIXME: should lint
-    // let _: &'a T = core::mem::transmute(t);
+    unsafe {
+        // FIXME: should lint
+        // let _: &'a T = core::mem::transmute(t);
 
-    let _: &'a U = core::mem::transmute(t);
+        let _: &'a U = core::mem::transmute(t);
 
-    let _: *const T = core::mem::transmute(t);
-    //~^ useless_transmute
+        let _: *const T = core::mem::transmute(t);
+        //~^ useless_transmute
 
-    let _: *mut T = core::mem::transmute(t);
-    //~^ useless_transmute
+        let _: *mut T = core::mem::transmute(t);
+        //~^ useless_transmute
 
-    let _: *const U = core::mem::transmute(t);
-    //~^ useless_transmute
+        let _: *const U = core::mem::transmute(t);
+        //~^ useless_transmute
+    }
 }
 
 #[warn(clippy::useless_transmute)]
@@ -59,7 +62,7 @@ fn useless() {
         let _: *const usize = std::mem::transmute(5_isize);
         //~^ useless_transmute
 
-        let _ = 5_isize as *const usize;
+        let _ = std::ptr::dangling::<usize>();
 
         let _: *const usize = std::mem::transmute(1 + 1usize);
         //~^ useless_transmute
@@ -68,19 +71,19 @@ fn useless() {
     }
 
     unsafe fn _f<'a, 'b>(x: &'a u32) -> &'b u32 {
-        std::mem::transmute(x)
+        unsafe { std::mem::transmute(x) }
     }
 
     unsafe fn _f2<'a, 'b>(x: *const (dyn Iterator<Item = u32> + 'a)) -> *const (dyn Iterator<Item = u32> + 'b) {
-        std::mem::transmute(x)
+        unsafe { std::mem::transmute(x) }
     }
 
     unsafe fn _f3<'a, 'b>(x: fn(&'a u32)) -> fn(&'b u32) {
-        std::mem::transmute(x)
+        unsafe { std::mem::transmute(x) }
     }
 
     unsafe fn _f4<'a, 'b>(x: std::borrow::Cow<'a, str>) -> std::borrow::Cow<'b, str> {
-        std::mem::transmute(x)
+        unsafe { std::mem::transmute(x) }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index e0d28437aaf..1bb70151965 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -1,68 +1,68 @@
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:31:23
+  --> tests/ui/transmute.rs:33:27
    |
-LL |     let _: *const T = core::mem::transmute(t);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
+LL |         let _: *const T = core::mem::transmute(t);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
    |
    = note: `-D clippy::useless-transmute` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:34:21
+  --> tests/ui/transmute.rs:36:25
    |
-LL |     let _: *mut T = core::mem::transmute(t);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
+LL |         let _: *mut T = core::mem::transmute(t);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:37:23
+  --> tests/ui/transmute.rs:39:27
    |
-LL |     let _: *const U = core::mem::transmute(t);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
+LL |         let _: *const U = core::mem::transmute(t);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:44:27
+  --> tests/ui/transmute.rs:47:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:47:27
+  --> tests/ui/transmute.rs:50:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:50:27
+  --> tests/ui/transmute.rs:53:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:53:27
+  --> tests/ui/transmute.rs:56:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:56:27
+  --> tests/ui/transmute.rs:59:27
    |
 LL |         let _: Vec<i32> = my_transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:59:31
+  --> tests/ui/transmute.rs:62:31
    |
 LL |         let _: *const usize = std::mem::transmute(5_isize);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`
 
 error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:64:31
+  --> tests/ui/transmute.rs:67:31
    |
 LL |         let _: *const usize = std::mem::transmute(1 + 1usize);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`
 
 error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:96:24
+  --> tests/ui/transmute.rs:99:24
    |
 LL |         let _: Usize = core::mem::transmute(int_const_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,25 +71,25 @@ LL |         let _: Usize = core::mem::transmute(int_const_ptr);
    = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]`
 
 error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:99:24
+  --> tests/ui/transmute.rs:102:24
    |
 LL |         let _: Usize = core::mem::transmute(int_mut_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
-  --> tests/ui/transmute.rs:102:31
+  --> tests/ui/transmute.rs:105:31
    |
 LL |         let _: *const Usize = core::mem::transmute(my_int());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
-  --> tests/ui/transmute.rs:105:29
+  --> tests/ui/transmute.rs:108:29
    |
 LL |         let _: *mut Usize = core::mem::transmute(my_int());
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a `u8` to a `bool`
-  --> tests/ui/transmute.rs:112:28
+  --> tests/ui/transmute.rs:115:28
    |
 LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@@ -98,7 +98,7 @@ LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]`
 
 error: transmute from a `u16` to a `f16`
-  --> tests/ui/transmute.rs:119:31
+  --> tests/ui/transmute.rs:122:31
    |
 LL |         let _: f16 = unsafe { std::mem::transmute(0_u16) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
@@ -107,97 +107,97 @@ LL |         let _: f16 = unsafe { std::mem::transmute(0_u16) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]`
 
 error: transmute from a `i16` to a `f16`
-  --> tests/ui/transmute.rs:122:31
+  --> tests/ui/transmute.rs:125:31
    |
 LL |         let _: f16 = unsafe { std::mem::transmute(0_i16) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_i16 as u16)`
 
 error: transmute from a `u32` to a `f32`
-  --> tests/ui/transmute.rs:125:31
+  --> tests/ui/transmute.rs:128:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_u32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
 
 error: transmute from a `i32` to a `f32`
-  --> tests/ui/transmute.rs:128:31
+  --> tests/ui/transmute.rs:131:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_i32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
 
 error: transmute from a `u64` to a `f64`
-  --> tests/ui/transmute.rs:131:31
+  --> tests/ui/transmute.rs:134:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_u64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)`
 
 error: transmute from a `i64` to a `f64`
-  --> tests/ui/transmute.rs:134:31
+  --> tests/ui/transmute.rs:137:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_i64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
 
 error: transmute from a `u128` to a `f128`
-  --> tests/ui/transmute.rs:137:32
+  --> tests/ui/transmute.rs:140:32
    |
 LL |         let _: f128 = unsafe { std::mem::transmute(0_u128) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_u128)`
 
 error: transmute from a `i128` to a `f128`
-  --> tests/ui/transmute.rs:140:32
+  --> tests/ui/transmute.rs:143:32
    |
 LL |         let _: f128 = unsafe { std::mem::transmute(0_i128) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
 
 error: transmute from a `u16` to a `f16`
-  --> tests/ui/transmute.rs:145:39
+  --> tests/ui/transmute.rs:148:39
    |
 LL |         const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
 
 error: transmute from a `u32` to a `f32`
-  --> tests/ui/transmute.rs:148:39
+  --> tests/ui/transmute.rs:151:39
    |
 LL |         const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
 
 error: transmute from a `i64` to a `f64`
-  --> tests/ui/transmute.rs:151:39
+  --> tests/ui/transmute.rs:154:39
    |
 LL |         const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
 
 error: transmute from a `i128` to a `f128`
-  --> tests/ui/transmute.rs:154:41
+  --> tests/ui/transmute.rs:157:41
    |
 LL |         const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
 
 error: transmute from a `i16` to a `f16`
-  --> tests/ui/transmute.rs:158:22
+  --> tests/ui/transmute.rs:161:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)`
 
 error: transmute from a `i32` to a `f32`
-  --> tests/ui/transmute.rs:163:22
+  --> tests/ui/transmute.rs:166:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)`
 
 error: transmute from a `u64` to a `f64`
-  --> tests/ui/transmute.rs:168:22
+  --> tests/ui/transmute.rs:171:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)`
 
 error: transmute from a `u128` to a `f128`
-  --> tests/ui/transmute.rs:173:22
+  --> tests/ui/transmute.rs:176:22
    |
 LL |             unsafe { std::mem::transmute(v) }
    |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:182:30
+  --> tests/ui/transmute.rs:185:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -206,121 +206,121 @@ LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:185:30
+  --> tests/ui/transmute.rs:188:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:188:31
+  --> tests/ui/transmute.rs:191:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:191:30
+  --> tests/ui/transmute.rs:194:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:194:30
+  --> tests/ui/transmute.rs:197:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:197:31
+  --> tests/ui/transmute.rs:200:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f16` to a `[u8; 2]`
-  --> tests/ui/transmute.rs:200:30
+  --> tests/ui/transmute.rs:203:30
    |
 LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:203:30
+  --> tests/ui/transmute.rs:206:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> tests/ui/transmute.rs:206:30
+  --> tests/ui/transmute.rs:209:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `f128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:209:31
+  --> tests/ui/transmute.rs:212:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:215:30
+  --> tests/ui/transmute.rs:218:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:218:30
+  --> tests/ui/transmute.rs:221:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:221:31
+  --> tests/ui/transmute.rs:224:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:224:30
+  --> tests/ui/transmute.rs:227:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:227:30
+  --> tests/ui/transmute.rs:230:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:230:31
+  --> tests/ui/transmute.rs:233:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f16` to a `[u8; 2]`
-  --> tests/ui/transmute.rs:233:30
+  --> tests/ui/transmute.rs:236:30
    |
 LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:236:30
+  --> tests/ui/transmute.rs:239:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> tests/ui/transmute.rs:239:30
+  --> tests/ui/transmute.rs:242:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `f128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:242:31
+  --> tests/ui/transmute.rs:245:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:251:28
+  --> tests/ui/transmute.rs:254:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -329,13 +329,13 @@ LL |     let _: &str = unsafe { std::mem::transmute(B) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
 
 error: transmute from a `&mut [u8]` to a `&mut str`
-  --> tests/ui/transmute.rs:254:32
+  --> tests/ui/transmute.rs:257:32
    |
 LL |     let _: &mut str = unsafe { std::mem::transmute(mb) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:257:30
+  --> tests/ui/transmute.rs:260:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
index 1f97b997eaa..844445907d7 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_float_to_int)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 #![feature(f128)]
 #![feature(f16)]
 
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.rs b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
index 788a7e1026c..a1f3b15bbfe 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.rs
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_float_to_int)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 #![feature(f128)]
 #![feature(f16)]
 
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.fixed b/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
index b5425a2e9e8..28644aa9ebb 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 fn int_to_char() {
     let _: char = unsafe { std::char::from_u32(0_u32).unwrap() };
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.rs b/src/tools/clippy/tests/ui/transmute_int_to_char.rs
index b24bb177c9f..8c83ecc8914 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char.rs
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 fn int_to_char() {
     let _: char = unsafe { std::mem::transmute(0_u32) };
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
index e525751e306..e6e09a2be4b 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
@@ -1,7 +1,7 @@
 #![no_std]
 #![feature(lang_items)]
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 use core::panic::PanicInfo;
 
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
index 7cb508ceaf3..0f2106df00e 100644
--- a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
@@ -1,7 +1,7 @@
 #![no_std]
 #![feature(lang_items)]
 #![warn(clippy::transmute_int_to_char)]
-#![allow(clippy::missing_transmute_annotations)]
+#![allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
 
 use core::panic::PanicInfo;
 
diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs
index e88f05bb662..4712374af93 100644
--- a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs
+++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs
@@ -1,6 +1,7 @@
 #![allow(dead_code)]
 #![warn(clippy::transmute_null_to_fn)]
 #![allow(clippy::zero_ptr, clippy::missing_transmute_annotations)]
+#![allow(clippy::manual_dangling_ptr)]
 
 // Easy to lint because these only span one line.
 fn one_liners() {
diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr
index f7d80147445..b5b0d4ecc7c 100644
--- a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr
+++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr
@@ -1,5 +1,5 @@
 error: transmuting a known null pointer into a function pointer
-  --> tests/ui/transmute_null_to_fn.rs:8:23
+  --> tests/ui/transmute_null_to_fn.rs:9:23
    |
 LL |         let _: fn() = std::mem::transmute(0 as *const ());
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
@@ -9,7 +9,7 @@ LL |         let _: fn() = std::mem::transmute(0 as *const ());
    = help: to override `-D warnings` add `#[allow(clippy::transmute_null_to_fn)]`
 
 error: transmuting a known null pointer into a function pointer
-  --> tests/ui/transmute_null_to_fn.rs:11:23
+  --> tests/ui/transmute_null_to_fn.rs:12:23
    |
 LL |         let _: fn() = std::mem::transmute(std::ptr::null::<()>());
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
@@ -17,7 +17,7 @@ LL |         let _: fn() = std::mem::transmute(std::ptr::null::<()>());
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
 
 error: transmuting a known null pointer into a function pointer
-  --> tests/ui/transmute_null_to_fn.rs:22:23
+  --> tests/ui/transmute_null_to_fn.rs:23:23
    |
 LL |         let _: fn() = std::mem::transmute(ZPTR);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
@@ -25,7 +25,7 @@ LL |         let _: fn() = std::mem::transmute(ZPTR);
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
 
 error: transmuting a known null pointer into a function pointer
-  --> tests/ui/transmute_null_to_fn.rs:32:23
+  --> tests/ui/transmute_null_to_fn.rs:33:23
    |
 LL |         let _: fn() = std::mem::transmute(0 as *const u8 as *const ());
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
@@ -33,7 +33,7 @@ LL |         let _: fn() = std::mem::transmute(0 as *const u8 as *const ());
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
 
 error: transmuting a known null pointer into a function pointer
-  --> tests/ui/transmute_null_to_fn.rs:35:23
+  --> tests/ui/transmute_null_to_fn.rs:36:23
    |
 LL |         let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
@@ -41,7 +41,7 @@ LL |         let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
 
 error: transmuting a known null pointer into a function pointer
-  --> tests/ui/transmute_null_to_fn.rs:38:23
+  --> tests/ui/transmute_null_to_fn.rs:39:23
    |
 LL |         let _: fn() = std::mem::transmute(ZPTR as *const u8);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed
index 3a67be5f45d..476e7e35a1f 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed
@@ -8,12 +8,12 @@ use std::mem::transmute;
 
 // Make sure we can do static lifetime transmutes
 unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
-    transmute::<&'a T, &'static T>(t)
+    unsafe { transmute::<&'a T, &'static T>(t) }
 }
 
 // Make sure we can do non-static lifetime transmutes
 unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
-    transmute::<&'a T, &'b T>(t)
+    unsafe { transmute::<&'a T, &'b T>(t) }
 }
 
 struct LifetimeParam<'a> {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
index 01ad3a3296b..7356668bcab 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
@@ -8,12 +8,12 @@ use std::mem::transmute;
 
 // Make sure we can do static lifetime transmutes
 unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
-    transmute::<&'a T, &'static T>(t)
+    unsafe { transmute::<&'a T, &'static T>(t) }
 }
 
 // Make sure we can do non-static lifetime transmutes
 unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
-    transmute::<&'a T, &'b T>(t)
+    unsafe { transmute::<&'a T, &'b T>(t) }
 }
 
 struct LifetimeParam<'a> {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
index 1bd45bc10a3..61e3ac2fe88 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
@@ -6,33 +6,35 @@
 )]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
-    let _: &T = &*p;
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*p;
+    unsafe {
+        let _: &T = &*p;
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*p;
 
-    let _: &mut T = &mut *m;
-    //~^ transmute_ptr_to_ref
-    let _: &mut T = &mut *m;
+        let _: &mut T = &mut *m;
+        //~^ transmute_ptr_to_ref
+        let _: &mut T = &mut *m;
 
-    let _: &T = &*m;
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*m;
+        let _: &T = &*m;
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*m;
 
-    let _: &mut T = &mut *(p as *mut T);
-    //~^ transmute_ptr_to_ref
-    let _ = &mut *(p as *mut T);
+        let _: &mut T = &mut *(p as *mut T);
+        //~^ transmute_ptr_to_ref
+        let _ = &mut *(p as *mut T);
 
-    let _: &T = &*(o as *const T);
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*(o as *const T);
+        let _: &T = &*(o as *const T);
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*(o as *const T);
 
-    let _: &mut T = &mut *(om as *mut T);
-    //~^ transmute_ptr_to_ref
-    let _: &mut T = &mut *(om as *mut T);
+        let _: &mut T = &mut *(om as *mut T);
+        //~^ transmute_ptr_to_ref
+        let _: &mut T = &mut *(om as *mut T);
 
-    let _: &T = &*(om as *const T);
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*(om as *const T);
+        let _: &T = &*(om as *const T);
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*(om as *const T);
+    }
 }
 
 fn _issue1231() {
@@ -54,47 +56,53 @@ fn _issue1231() {
 }
 
 unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {
-    match 0 {
-        0 => &*x.cast::<&u32>(),
-        //~^ transmute_ptr_to_ref
-        1 => &*y.cast::<&u32>(),
-        //~^ transmute_ptr_to_ref
-        2 => &*x.cast::<&'b u32>(),
-        //~^ transmute_ptr_to_ref
-        _ => &*y.cast::<&'b u32>(),
-        //~^ transmute_ptr_to_ref
+    unsafe {
+        match 0 {
+            0 => &*x.cast::<&u32>(),
+            //~^ transmute_ptr_to_ref
+            1 => &*y.cast::<&u32>(),
+            //~^ transmute_ptr_to_ref
+            2 => &*x.cast::<&'b u32>(),
+            //~^ transmute_ptr_to_ref
+            _ => &*y.cast::<&'b u32>(),
+            //~^ transmute_ptr_to_ref
+        }
     }
 }
 
 #[clippy::msrv = "1.38"]
 unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 {
-    let a = 0u32;
-    let a = &a as *const u32;
-    let _: &u32 = &*a;
-    //~^ transmute_ptr_to_ref
-    let _: &u32 = &*a.cast::<u32>();
-    //~^ transmute_ptr_to_ref
-    match 0 {
-        0 => &*x.cast::<&u32>(),
+    unsafe {
+        let a = 0u32;
+        let a = &a as *const u32;
+        let _: &u32 = &*a;
         //~^ transmute_ptr_to_ref
-        _ => &*x.cast::<&'b u32>(),
+        let _: &u32 = &*a.cast::<u32>();
         //~^ transmute_ptr_to_ref
+        match 0 {
+            0 => &*x.cast::<&u32>(),
+            //~^ transmute_ptr_to_ref
+            _ => &*x.cast::<&'b u32>(),
+            //~^ transmute_ptr_to_ref
+        }
     }
 }
 
 #[clippy::msrv = "1.37"]
 unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 {
-    let a = 0u32;
-    let a = &a as *const u32;
-    let _: &u32 = &*a;
-    //~^ transmute_ptr_to_ref
-    let _: &u32 = &*(a as *const u32);
-    //~^ transmute_ptr_to_ref
-    match 0 {
-        0 => &*(x as *const () as *const &u32),
+    unsafe {
+        let a = 0u32;
+        let a = &a as *const u32;
+        let _: &u32 = &*a;
         //~^ transmute_ptr_to_ref
-        _ => &*(x as *const () as *const &'b u32),
+        let _: &u32 = &*(a as *const u32);
         //~^ transmute_ptr_to_ref
+        match 0 {
+            0 => &*(x as *const () as *const &u32),
+            //~^ transmute_ptr_to_ref
+            _ => &*(x as *const () as *const &'b u32),
+            //~^ transmute_ptr_to_ref
+        }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
index cbe64bf1ea6..48e2f527b55 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
@@ -6,33 +6,35 @@
 )]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
-    let _: &T = std::mem::transmute(p);
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*p;
+    unsafe {
+        let _: &T = std::mem::transmute(p);
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*p;
 
-    let _: &mut T = std::mem::transmute(m);
-    //~^ transmute_ptr_to_ref
-    let _: &mut T = &mut *m;
+        let _: &mut T = std::mem::transmute(m);
+        //~^ transmute_ptr_to_ref
+        let _: &mut T = &mut *m;
 
-    let _: &T = std::mem::transmute(m);
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*m;
+        let _: &T = std::mem::transmute(m);
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*m;
 
-    let _: &mut T = std::mem::transmute(p as *mut T);
-    //~^ transmute_ptr_to_ref
-    let _ = &mut *(p as *mut T);
+        let _: &mut T = std::mem::transmute(p as *mut T);
+        //~^ transmute_ptr_to_ref
+        let _ = &mut *(p as *mut T);
 
-    let _: &T = std::mem::transmute(o);
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*(o as *const T);
+        let _: &T = std::mem::transmute(o);
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*(o as *const T);
 
-    let _: &mut T = std::mem::transmute(om);
-    //~^ transmute_ptr_to_ref
-    let _: &mut T = &mut *(om as *mut T);
+        let _: &mut T = std::mem::transmute(om);
+        //~^ transmute_ptr_to_ref
+        let _: &mut T = &mut *(om as *mut T);
 
-    let _: &T = std::mem::transmute(om);
-    //~^ transmute_ptr_to_ref
-    let _: &T = &*(om as *const T);
+        let _: &T = std::mem::transmute(om);
+        //~^ transmute_ptr_to_ref
+        let _: &T = &*(om as *const T);
+    }
 }
 
 fn _issue1231() {
@@ -54,47 +56,53 @@ fn _issue1231() {
 }
 
 unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {
-    match 0 {
-        0 => std::mem::transmute(x),
-        //~^ transmute_ptr_to_ref
-        1 => std::mem::transmute(y),
-        //~^ transmute_ptr_to_ref
-        2 => std::mem::transmute::<_, &&'b u32>(x),
-        //~^ transmute_ptr_to_ref
-        _ => std::mem::transmute::<_, &&'b u32>(y),
-        //~^ transmute_ptr_to_ref
+    unsafe {
+        match 0 {
+            0 => std::mem::transmute(x),
+            //~^ transmute_ptr_to_ref
+            1 => std::mem::transmute(y),
+            //~^ transmute_ptr_to_ref
+            2 => std::mem::transmute::<_, &&'b u32>(x),
+            //~^ transmute_ptr_to_ref
+            _ => std::mem::transmute::<_, &&'b u32>(y),
+            //~^ transmute_ptr_to_ref
+        }
     }
 }
 
 #[clippy::msrv = "1.38"]
 unsafe fn _meets_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 {
-    let a = 0u32;
-    let a = &a as *const u32;
-    let _: &u32 = std::mem::transmute(a);
-    //~^ transmute_ptr_to_ref
-    let _: &u32 = std::mem::transmute::<_, &u32>(a);
-    //~^ transmute_ptr_to_ref
-    match 0 {
-        0 => std::mem::transmute(x),
+    unsafe {
+        let a = 0u32;
+        let a = &a as *const u32;
+        let _: &u32 = std::mem::transmute(a);
         //~^ transmute_ptr_to_ref
-        _ => std::mem::transmute::<_, &&'b u32>(x),
+        let _: &u32 = std::mem::transmute::<_, &u32>(a);
         //~^ transmute_ptr_to_ref
+        match 0 {
+            0 => std::mem::transmute(x),
+            //~^ transmute_ptr_to_ref
+            _ => std::mem::transmute::<_, &&'b u32>(x),
+            //~^ transmute_ptr_to_ref
+        }
     }
 }
 
 #[clippy::msrv = "1.37"]
 unsafe fn _under_msrv<'a, 'b, 'c>(x: *const &'a u32) -> &'c &'b u32 {
-    let a = 0u32;
-    let a = &a as *const u32;
-    let _: &u32 = std::mem::transmute(a);
-    //~^ transmute_ptr_to_ref
-    let _: &u32 = std::mem::transmute::<_, &u32>(a);
-    //~^ transmute_ptr_to_ref
-    match 0 {
-        0 => std::mem::transmute(x),
+    unsafe {
+        let a = 0u32;
+        let a = &a as *const u32;
+        let _: &u32 = std::mem::transmute(a);
         //~^ transmute_ptr_to_ref
-        _ => std::mem::transmute::<_, &&'b u32>(x),
+        let _: &u32 = std::mem::transmute::<_, &u32>(a);
         //~^ transmute_ptr_to_ref
+        match 0 {
+            0 => std::mem::transmute(x),
+            //~^ transmute_ptr_to_ref
+            _ => std::mem::transmute::<_, &&'b u32>(x),
+            //~^ transmute_ptr_to_ref
+        }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
index 7fad9b4065a..7685c345c86 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
@@ -1,137 +1,137 @@
 error: transmute from a pointer type (`*const T`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:9:17
+  --> tests/ui/transmute_ptr_to_ref.rs:10:21
    |
-LL |     let _: &T = std::mem::transmute(p);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p`
+LL |         let _: &T = std::mem::transmute(p);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p`
    |
    = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ref)]`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:13:21
+  --> tests/ui/transmute_ptr_to_ref.rs:14:25
    |
-LL |     let _: &mut T = std::mem::transmute(m);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m`
+LL |         let _: &mut T = std::mem::transmute(m);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:17:17
+  --> tests/ui/transmute_ptr_to_ref.rs:18:21
    |
-LL |     let _: &T = std::mem::transmute(m);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m`
+LL |         let _: &T = std::mem::transmute(m);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:21:21
+  --> tests/ui/transmute_ptr_to_ref.rs:22:25
    |
-LL |     let _: &mut T = std::mem::transmute(p as *mut T);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)`
+LL |         let _: &mut T = std::mem::transmute(p as *mut T);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)`
 
 error: transmute from a pointer type (`*const U`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:25:17
+  --> tests/ui/transmute_ptr_to_ref.rs:26:21
    |
-LL |     let _: &T = std::mem::transmute(o);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)`
+LL |         let _: &T = std::mem::transmute(o);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:29:21
+  --> tests/ui/transmute_ptr_to_ref.rs:30:25
    |
-LL |     let _: &mut T = std::mem::transmute(om);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)`
+LL |         let _: &mut T = std::mem::transmute(om);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:33:17
+  --> tests/ui/transmute_ptr_to_ref.rs:34:21
    |
-LL |     let _: &T = std::mem::transmute(om);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
+LL |         let _: &T = std::mem::transmute(om);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`)
-  --> tests/ui/transmute_ptr_to_ref.rs:44:32
+  --> tests/ui/transmute_ptr_to_ref.rs:46:32
    |
 LL |     let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`)
-  --> tests/ui/transmute_ptr_to_ref.rs:47:33
+  --> tests/ui/transmute_ptr_to_ref.rs:49:33
    |
 LL |     let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
-  --> tests/ui/transmute_ptr_to_ref.rs:52:14
+  --> tests/ui/transmute_ptr_to_ref.rs:54:14
    |
 LL |     unsafe { std::mem::transmute::<_, Bar>(raw) };
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:58:14
+  --> tests/ui/transmute_ptr_to_ref.rs:61:18
    |
-LL |         0 => std::mem::transmute(x),
-   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
+LL |             0 => std::mem::transmute(x),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:60:14
+  --> tests/ui/transmute_ptr_to_ref.rs:63:18
    |
-LL |         1 => std::mem::transmute(y),
-   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()`
+LL |             1 => std::mem::transmute(y),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:62:14
+  --> tests/ui/transmute_ptr_to_ref.rs:65:18
    |
-LL |         2 => std::mem::transmute::<_, &&'b u32>(x),
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
+LL |             2 => std::mem::transmute::<_, &&'b u32>(x),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:64:14
+  --> tests/ui/transmute_ptr_to_ref.rs:67:18
    |
-LL |         _ => std::mem::transmute::<_, &&'b u32>(y),
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()`
+LL |             _ => std::mem::transmute::<_, &&'b u32>(y),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:73:19
+  --> tests/ui/transmute_ptr_to_ref.rs:78:23
    |
-LL |     let _: &u32 = std::mem::transmute(a);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
+LL |         let _: &u32 = std::mem::transmute(a);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:75:19
+  --> tests/ui/transmute_ptr_to_ref.rs:80:23
    |
-LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()`
+LL |         let _: &u32 = std::mem::transmute::<_, &u32>(a);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:78:14
+  --> tests/ui/transmute_ptr_to_ref.rs:83:18
    |
-LL |         0 => std::mem::transmute(x),
-   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
+LL |             0 => std::mem::transmute(x),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:80:14
+  --> tests/ui/transmute_ptr_to_ref.rs:85:18
    |
-LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
+LL |             _ => std::mem::transmute::<_, &&'b u32>(x),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:89:19
+  --> tests/ui/transmute_ptr_to_ref.rs:96:23
    |
-LL |     let _: &u32 = std::mem::transmute(a);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
+LL |         let _: &u32 = std::mem::transmute(a);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:91:19
+  --> tests/ui/transmute_ptr_to_ref.rs:98:23
    |
-LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)`
+LL |         let _: &u32 = std::mem::transmute::<_, &u32>(a);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:94:14
+  --> tests/ui/transmute_ptr_to_ref.rs:101:18
    |
-LL |         0 => std::mem::transmute(x),
-   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)`
+LL |             0 => std::mem::transmute(x),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:96:14
+  --> tests/ui/transmute_ptr_to_ref.rs:103:18
    |
-LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)`
+LL |             _ => std::mem::transmute::<_, &&'b u32>(x),
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)`
 
 error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmuting_null.rs b/src/tools/clippy/tests/ui/transmuting_null.rs
index bcd35bbd4e7..f3eb5060cd0 100644
--- a/src/tools/clippy/tests/ui/transmuting_null.rs
+++ b/src/tools/clippy/tests/ui/transmuting_null.rs
@@ -3,6 +3,7 @@
 #![allow(clippy::zero_ptr)]
 #![allow(clippy::transmute_ptr_to_ref)]
 #![allow(clippy::eq_op, clippy::missing_transmute_annotations)]
+#![allow(clippy::manual_dangling_ptr)]
 
 // Easy to lint because these only span one line.
 fn one_liners() {
diff --git a/src/tools/clippy/tests/ui/transmuting_null.stderr b/src/tools/clippy/tests/ui/transmuting_null.stderr
index 84e6e374d52..c68e4102e40 100644
--- a/src/tools/clippy/tests/ui/transmuting_null.stderr
+++ b/src/tools/clippy/tests/ui/transmuting_null.stderr
@@ -1,5 +1,5 @@
 error: transmuting a known null pointer into a reference
-  --> tests/ui/transmuting_null.rs:10:23
+  --> tests/ui/transmuting_null.rs:11:23
    |
 LL |         let _: &u64 = std::mem::transmute(0 as *const u64);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,13 +8,13 @@ LL |         let _: &u64 = std::mem::transmute(0 as *const u64);
    = help: to override `-D warnings` add `#[allow(clippy::transmuting_null)]`
 
 error: transmuting a known null pointer into a reference
-  --> tests/ui/transmuting_null.rs:13:23
+  --> tests/ui/transmuting_null.rs:14:23
    |
 LL |         let _: &u64 = std::mem::transmute(std::ptr::null::<u64>());
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmuting a known null pointer into a reference
-  --> tests/ui/transmuting_null.rs:24:23
+  --> tests/ui/transmuting_null.rs:25:23
    |
 LL |         let _: &u64 = std::mem::transmute(ZPTR);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/type_complexity.rs b/src/tools/clippy/tests/ui/type_complexity.rs
index 89c4955c9f6..9d145516d61 100644
--- a/src/tools/clippy/tests/ui/type_complexity.rs
+++ b/src/tools/clippy/tests/ui/type_complexity.rs
@@ -1,6 +1,5 @@
-#![warn(clippy::all)]
-#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)]
 #![feature(associated_type_defaults)]
+#![allow(clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)]
 
 type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here
 
diff --git a/src/tools/clippy/tests/ui/type_complexity.stderr b/src/tools/clippy/tests/ui/type_complexity.stderr
index 181e04d38e9..a7f6a074a4a 100644
--- a/src/tools/clippy/tests/ui/type_complexity.stderr
+++ b/src/tools/clippy/tests/ui/type_complexity.stderr
@@ -1,5 +1,5 @@
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:7:12
+  --> tests/ui/type_complexity.rs:6:12
    |
 LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,85 +8,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]`
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:10:12
+  --> tests/ui/type_complexity.rs:9:12
    |
 LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:14:8
+  --> tests/ui/type_complexity.rs:13:8
    |
 LL |     f: Vec<Vec<Box<(u32, u32, u32, u32)>>>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:18:11
+  --> tests/ui/type_complexity.rs:17:11
    |
 LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:22:11
+  --> tests/ui/type_complexity.rs:21:11
    |
 LL |     Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>),
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:24:17
+  --> tests/ui/type_complexity.rs:23:17
    |
 LL |     Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> },
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:29:14
+  --> tests/ui/type_complexity.rs:28:14
    |
 LL |     const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:32:30
+  --> tests/ui/type_complexity.rs:31:30
    |
 LL |     fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:37:14
+  --> tests/ui/type_complexity.rs:36:14
    |
 LL |     const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:40:14
+  --> tests/ui/type_complexity.rs:39:14
    |
 LL |     type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:43:25
+  --> tests/ui/type_complexity.rs:42:25
    |
 LL |     fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:46:29
+  --> tests/ui/type_complexity.rs:45:29
    |
 LL |     fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:59:15
+  --> tests/ui/type_complexity.rs:58:15
    |
 LL | fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:65:14
+  --> tests/ui/type_complexity.rs:64:14
    |
 LL | fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:69:13
+  --> tests/ui/type_complexity.rs:68:13
    |
 LL |     let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/uninit_vec.rs b/src/tools/clippy/tests/ui/uninit_vec.rs
index a4839713799..eeb281322da 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.rs
+++ b/src/tools/clippy/tests/ui/uninit_vec.rs
@@ -15,9 +15,17 @@ union MyOwnMaybeUninit {
 
 // https://github.com/rust-lang/rust/issues/119620
 unsafe fn requires_paramenv<S>() {
-    let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
+    unsafe {
+        let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
+        //~^ uninit_vec
+        vec.set_len(1);
+    }
+
+    let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(2);
     //~^ uninit_vec
-    vec.set_len(1);
+    unsafe {
+        vec.set_len(2);
+    }
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/uninit_vec.stderr b/src/tools/clippy/tests/ui/uninit_vec.stderr
index 7ff6140a2c3..1b821ef004e 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.stderr
+++ b/src/tools/clippy/tests/ui/uninit_vec.stderr
@@ -1,18 +1,29 @@
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:18:5
+  --> tests/ui/uninit_vec.rs:24:5
    |
-LL |     let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
+LL |     let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     vec.set_len(1);
-   |     ^^^^^^^^^^^^^^
+...
+LL |         vec.set_len(2);
+   |         ^^^^^^^^^^^^^^
    |
    = help: initialize the buffer or wrap the content in `MaybeUninit`
    = note: `-D clippy::uninit-vec` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::uninit_vec)]`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:25:5
+  --> tests/ui/uninit_vec.rs:19:9
+   |
+LL |         let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL |         vec.set_len(1);
+   |         ^^^^^^^^^^^^^^
+   |
+   = help: initialize the buffer or wrap the content in `MaybeUninit`
+
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+  --> tests/ui/uninit_vec.rs:33:5
    |
 LL |     let mut vec: Vec<u8> = Vec::with_capacity(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +34,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:33:5
+  --> tests/ui/uninit_vec.rs:41:5
    |
 LL |     vec.reserve(1000);
    |     ^^^^^^^^^^^^^^^^^^
@@ -34,7 +45,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` on empty `Vec` creates out-of-bound values
-  --> tests/ui/uninit_vec.rs:41:5
+  --> tests/ui/uninit_vec.rs:49:5
    |
 LL |     let mut vec: Vec<u8> = Vec::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +54,7 @@ LL |         vec.set_len(200);
    |         ^^^^^^^^^^^^^^^^
 
 error: calling `set_len()` on empty `Vec` creates out-of-bound values
-  --> tests/ui/uninit_vec.rs:49:5
+  --> tests/ui/uninit_vec.rs:57:5
    |
 LL |     let mut vec: Vec<u8> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,7 +63,7 @@ LL |         vec.set_len(200);
    |         ^^^^^^^^^^^^^^^^
 
 error: calling `set_len()` on empty `Vec` creates out-of-bound values
-  --> tests/ui/uninit_vec.rs:56:5
+  --> tests/ui/uninit_vec.rs:64:5
    |
 LL |     let mut vec: Vec<u8> = Vec::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +72,7 @@ LL |         vec.set_len(200);
    |         ^^^^^^^^^^^^^^^^
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:76:5
+  --> tests/ui/uninit_vec.rs:84:5
    |
 LL |     let mut vec: Vec<u8> = Vec::with_capacity(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +83,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:87:5
+  --> tests/ui/uninit_vec.rs:95:5
    |
 LL |     my_vec.vec.reserve(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -83,7 +94,7 @@ LL |         my_vec.vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:94:5
+  --> tests/ui/uninit_vec.rs:102:5
    |
 LL |     my_vec.vec = Vec::with_capacity(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -94,7 +105,7 @@ LL |         my_vec.vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:65:9
+  --> tests/ui/uninit_vec.rs:73:9
    |
 LL |         let mut vec: Vec<u8> = Vec::with_capacity(1000);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -105,7 +116,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:70:9
+  --> tests/ui/uninit_vec.rs:78:9
    |
 LL |         vec.reserve(1000);
    |         ^^^^^^^^^^^^^^^^^^
@@ -116,7 +127,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:150:9
+  --> tests/ui/uninit_vec.rs:158:9
    |
 LL |         let mut vec: Vec<T> = Vec::with_capacity(1000);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -127,7 +138,7 @@ LL |             vec.set_len(10);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:178:9
+  --> tests/ui/uninit_vec.rs:186:9
    |
 LL |         let mut vec: Vec<Recursive<T>> = Vec::with_capacity(1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,7 +149,7 @@ LL |             vec.set_len(1);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> tests/ui/uninit_vec.rs:192:9
+  --> tests/ui/uninit_vec.rs:200:9
    |
 LL |         let mut vec: Vec<Enum<T>> = Vec::with_capacity(1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,5 +159,5 @@ LL |             vec.set_len(1);
    |
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.rs
index 2bb64c3e80e..4b1f4f76cc4 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.rs
@@ -17,8 +17,10 @@ mod issue11113 {
 
     impl TearOff {
         unsafe fn query(&self) {
-            ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)()
-            //~^ unnecessary_cast
+            unsafe {
+                ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)()
+                //~^ unnecessary_cast
+            }
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.stderr
index 6ba1c787306..6b26bea9de2 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_cast_unfixable.stderr
@@ -8,10 +8,10 @@ LL |     let _ = std::ptr::null() as *const u8;
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*mut issue11113::Vtbl` -> `*mut issue11113::Vtbl`)
-  --> tests/ui/unnecessary_cast_unfixable.rs:20:16
+  --> tests/ui/unnecessary_cast_unfixable.rs:21:20
    |
-LL |             ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)()
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*(self.object as *mut *mut _)`
+LL |                 ((*(*(self.object as *mut *mut _) as *mut Vtbl)).query)()
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*(self.object as *mut *mut _)`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_filter_map.rs b/src/tools/clippy/tests/ui/unnecessary_filter_map.rs
index c4f1b6bc7e3..85582c399ce 100644
--- a/src/tools/clippy/tests/ui/unnecessary_filter_map.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_filter_map.rs
@@ -1,5 +1,4 @@
-//@no-rustfix
-#![allow(dead_code)]
+#![allow(clippy::redundant_closure)]
 
 fn main() {
     let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None });
@@ -27,9 +26,7 @@ fn main() {
     let _ = (0..4).filter_map(Some);
 
     let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
-    //~^ redundant_closure
-    //~| unnecessary_filter_map
-    //~| unnecessary_filter_map
+    //~^ unnecessary_filter_map
 }
 
 fn filter_map_none_changes_item_type() -> impl Iterator<Item = bool> {
diff --git a/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr b/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr
index 6683444b727..a879633e10f 100644
--- a/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_filter_map.stderr
@@ -1,14 +1,14 @@
-error: this `.filter_map` can be written more simply
-  --> tests/ui/unnecessary_filter_map.rs:5:13
+error: this `.filter_map(..)` can be written more simply using `.filter(..)`
+  --> tests/ui/unnecessary_filter_map.rs:4:13
    |
 LL |     let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None });
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unnecessary-filter-map` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_filter_map)]`
 
-error: this `.filter_map` can be written more simply
-  --> tests/ui/unnecessary_filter_map.rs:8:13
+error: this `.filter_map(..)` can be written more simply using `.filter(..)`
+  --> tests/ui/unnecessary_filter_map.rs:7:13
    |
 LL |       let _ = (0..4).filter_map(|x| {
    |  _____________^
@@ -18,10 +18,10 @@ LL | |         if x > 1 {
 ...  |
 LL | |         None
 LL | |     });
-   | |______^ help: try instead: `filter`
+   | |______^
 
-error: this `.filter_map` can be written more simply
-  --> tests/ui/unnecessary_filter_map.rs:16:13
+error: this `.filter_map(..)` can be written more simply using `.filter(..)`
+  --> tests/ui/unnecessary_filter_map.rs:15:13
    |
 LL |       let _ = (0..4).filter_map(|x| match x {
    |  _____________^
@@ -29,40 +29,25 @@ LL | |
 LL | |         0 | 1 => None,
 LL | |         _ => Some(x),
 LL | |     });
-   | |______^ help: try instead: `filter`
+   | |______^
 
-error: this `.filter_map` can be written more simply
-  --> tests/ui/unnecessary_filter_map.rs:22:13
+error: this `.filter_map(..)` can be written more simply using `.map(..)`
+  --> tests/ui/unnecessary_filter_map.rs:21:13
    |
 LL |     let _ = (0..4).filter_map(|x| Some(x + 1));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: redundant closure
-  --> tests/ui/unnecessary_filter_map.rs:29:57
+error: this call to `.filter_map(..)` is unnecessary
+  --> tests/ui/unnecessary_filter_map.rs:28:61
    |
 LL |     let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
-   |                                                         ^^^^^^^^^^^ help: replace the closure with the function itself: `Some`
-   |
-   = note: `-D clippy::redundant-closure` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
-
-error: filter_map is unnecessary
-  --> tests/ui/unnecessary_filter_map.rs:29:61
-   |
-LL |     let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
-   |                                                             ^^^^ help: try removing the filter_map
-
-error: this `.filter_map` can be written more simply
-  --> tests/ui/unnecessary_filter_map.rs:29:13
-   |
-LL |     let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map`
+   |                                                             ^^^^
 
-error: this `.filter_map` can be written more simply
-  --> tests/ui/unnecessary_filter_map.rs:169:14
+error: this `.filter_map(..)` can be written more simply using `.filter(..)`
+  --> tests/ui/unnecessary_filter_map.rs:166:14
    |
 LL |     let _x = std::iter::once(1).filter_map(|n| (n > 1).then_some(n));
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_find_map.rs b/src/tools/clippy/tests/ui/unnecessary_find_map.rs
index 8c8a3799f02..33ba7074d62 100644
--- a/src/tools/clippy/tests/ui/unnecessary_find_map.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_find_map.rs
@@ -1,4 +1,3 @@
-//@no-rustfix
 #![allow(dead_code)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unnecessary_find_map.stderr b/src/tools/clippy/tests/ui/unnecessary_find_map.stderr
index 94e320773a6..3754a3d9953 100644
--- a/src/tools/clippy/tests/ui/unnecessary_find_map.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_find_map.stderr
@@ -1,14 +1,14 @@
-error: this `.find_map` can be written more simply
-  --> tests/ui/unnecessary_find_map.rs:5:13
+error: this `.find_map(..)` can be written more simply using `.find(..)`
+  --> tests/ui/unnecessary_find_map.rs:4:13
    |
 LL |     let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None });
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unnecessary-find-map` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_find_map)]`
 
-error: this `.find_map` can be written more simply
-  --> tests/ui/unnecessary_find_map.rs:8:13
+error: this `.find_map(..)` can be written more simply using `.find(..)`
+  --> tests/ui/unnecessary_find_map.rs:7:13
    |
 LL |       let _ = (0..4).find_map(|x| {
    |  _____________^
@@ -18,10 +18,10 @@ LL | |         if x > 1 {
 ...  |
 LL | |         None
 LL | |     });
-   | |______^ help: try instead: `find`
+   | |______^
 
-error: this `.find_map` can be written more simply
-  --> tests/ui/unnecessary_find_map.rs:16:13
+error: this `.find_map(..)` can be written more simply using `.find(..)`
+  --> tests/ui/unnecessary_find_map.rs:15:13
    |
 LL |       let _ = (0..4).find_map(|x| match x {
    |  _____________^
@@ -29,19 +29,19 @@ LL | |
 LL | |         0 | 1 => None,
 LL | |         _ => Some(x),
 LL | |     });
-   | |______^ help: try instead: `find`
+   | |______^
 
-error: this `.find_map` can be written more simply
-  --> tests/ui/unnecessary_find_map.rs:22:13
+error: this `.find_map(..)` can be written more simply using `.map(..).next()`
+  --> tests/ui/unnecessary_find_map.rs:21:13
    |
 LL |     let _ = (0..4).find_map(|x| Some(x + 1));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map(..).next()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this `.find_map` can be written more simply
-  --> tests/ui/unnecessary_find_map.rs:34:14
+error: this `.find_map(..)` can be written more simply using `.find(..)`
+  --> tests/ui/unnecessary_find_map.rs:33:14
    |
 LL |     let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(n));
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
index aed2dbe1f1c..61f2e3745ad 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
@@ -1,4 +1,4 @@
-#![allow(unused_assignments)]
+#![allow(unused_assignments, clippy::uninlined_format_args)]
 #![warn(clippy::unnecessary_to_owned)]
 
 #[allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
index 12fdd150e42..b90ca00a5fe 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
@@ -1,4 +1,4 @@
-#![allow(unused_assignments)]
+#![allow(unused_assignments, clippy::uninlined_format_args)]
 #![warn(clippy::unnecessary_to_owned)]
 
 #[allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
index 9a329081638..409a8efbfeb 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
@@ -321,3 +321,7 @@ fn panicky_arithmetic_ops(x: usize, y: isize) {
     let _x = false.then_some(f1 + f2);
     //~^ unnecessary_lazy_evaluations
 }
+
+fn issue14578() {
+    let _: Box<dyn std::future::Future<Output = i32>> = Box::new(true.then(async || 42).unwrap());
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
index 2d05ef5c291..54735023a93 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
@@ -321,3 +321,7 @@ fn panicky_arithmetic_ops(x: usize, y: isize) {
     let _x = false.then(|| f1 + f2);
     //~^ unnecessary_lazy_evaluations
 }
+
+fn issue14578() {
+    let _: Box<dyn std::future::Future<Output = i32>> = Box::new(true.then(async || 42).unwrap());
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.fixed b/src/tools/clippy/tests/ui/unnecessary_operation.fixed
index 05dfb72f48d..645b56fe95e 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.fixed
@@ -1,9 +1,10 @@
 #![allow(
     clippy::deref_addrof,
-    dead_code,
-    unused,
     clippy::no_effect,
-    clippy::unnecessary_struct_initialization
+    clippy::uninlined_format_args,
+    clippy::unnecessary_struct_initialization,
+    dead_code,
+    unused
 )]
 #![warn(clippy::unnecessary_operation)]
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.rs b/src/tools/clippy/tests/ui/unnecessary_operation.rs
index 6ef74c3eb1c..97e90269c5c 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.rs
@@ -1,9 +1,10 @@
 #![allow(
     clippy::deref_addrof,
-    dead_code,
-    unused,
     clippy::no_effect,
-    clippy::unnecessary_struct_initialization
+    clippy::uninlined_format_args,
+    clippy::unnecessary_struct_initialization,
+    dead_code,
+    unused
 )]
 #![warn(clippy::unnecessary_operation)]
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.stderr b/src/tools/clippy/tests/ui/unnecessary_operation.stderr
index eb98af09e7a..0fda1dfde19 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.stderr
@@ -1,5 +1,5 @@
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:70:5
+  --> tests/ui/unnecessary_operation.rs:71:5
    |
 LL |     Tuple(get_number());
    |     ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
@@ -8,103 +8,103 @@ LL |     Tuple(get_number());
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_operation)]`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:72:5
+  --> tests/ui/unnecessary_operation.rs:73:5
    |
 LL |     Struct { field: get_number() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:74:5
+  --> tests/ui/unnecessary_operation.rs:75:5
    |
 LL |     Struct { ..get_struct() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:76:5
+  --> tests/ui/unnecessary_operation.rs:77:5
    |
 LL |     Enum::Tuple(get_number());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:78:5
+  --> tests/ui/unnecessary_operation.rs:79:5
    |
 LL |     Enum::Struct { field: get_number() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:80:5
+  --> tests/ui/unnecessary_operation.rs:81:5
    |
 LL |     5 + get_number();
    |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:82:5
+  --> tests/ui/unnecessary_operation.rs:83:5
    |
 LL |     *&get_number();
    |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:84:5
+  --> tests/ui/unnecessary_operation.rs:85:5
    |
 LL |     &get_number();
    |     ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:86:5
+  --> tests/ui/unnecessary_operation.rs:87:5
    |
 LL |     (5, 6, get_number());
    |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:88:5
+  --> tests/ui/unnecessary_operation.rs:89:5
    |
 LL |     get_number()..;
    |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:90:5
+  --> tests/ui/unnecessary_operation.rs:91:5
    |
 LL |     ..get_number();
    |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:92:5
+  --> tests/ui/unnecessary_operation.rs:93:5
    |
 LL |     5..get_number();
    |     ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:94:5
+  --> tests/ui/unnecessary_operation.rs:95:5
    |
 LL |     [42, get_number()];
    |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:96:5
+  --> tests/ui/unnecessary_operation.rs:97:5
    |
 LL |     [42, 55][get_usize()];
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:98:5
+  --> tests/ui/unnecessary_operation.rs:99:5
    |
 LL |     (42, get_number()).1;
    |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:100:5
+  --> tests/ui/unnecessary_operation.rs:101:5
    |
 LL |     [get_number(); 55];
    |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:102:5
+  --> tests/ui/unnecessary_operation.rs:103:5
    |
 LL |     [42; 55][get_usize()];
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:104:5
+  --> tests/ui/unnecessary_operation.rs:105:5
    |
 LL | /     {
 LL | |
@@ -113,7 +113,7 @@ LL | |     };
    | |______^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:108:5
+  --> tests/ui/unnecessary_operation.rs:109:5
    |
 LL | /     FooString {
 LL | |
@@ -122,7 +122,7 @@ LL | |     };
    | |______^ help: statement can be reduced to: `String::from("blah");`
 
 error: unnecessary operation
-  --> tests/ui/unnecessary_operation.rs:149:5
+  --> tests/ui/unnecessary_operation.rs:150:5
    |
 LL |     [42, 55][get_usize()];
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
diff --git a/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.rs b/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.rs
index 12663ec9a52..6652efd9ae1 100644
--- a/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::unnecessary_debug_formatting)]
+#![allow(clippy::uninlined_format_args)]
 
 use std::ffi::{OsStr, OsString};
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.stderr b/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.stderr
index 001309ab817..382e59b0461 100644
--- a/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_os_str_debug_formatting.stderr
@@ -1,5 +1,5 @@
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_os_str_debug_formatting.rs:14:22
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:15:22
    |
 LL |     println!("{:?}", os_str);
    |                      ^^^^^^
@@ -10,7 +10,7 @@ LL |     println!("{:?}", os_str);
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_debug_formatting)]`
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_os_str_debug_formatting.rs:15:22
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:16:22
    |
 LL |     println!("{:?}", os_string);
    |                      ^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     println!("{:?}", os_string);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_os_str_debug_formatting.rs:17:16
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:18:16
    |
 LL |     println!("{os_str:?}");
    |                ^^^^^^
@@ -28,7 +28,7 @@ LL |     println!("{os_str:?}");
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_os_str_debug_formatting.rs:18:16
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:19:16
    |
 LL |     println!("{os_string:?}");
    |                ^^^^^^^^^
@@ -37,7 +37,7 @@ LL |     println!("{os_string:?}");
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `format!` args
-  --> tests/ui/unnecessary_os_str_debug_formatting.rs:20:37
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:21:37
    |
 LL |     let _: String = format!("{:?}", os_str);
    |                                     ^^^^^^
@@ -46,7 +46,7 @@ LL |     let _: String = format!("{:?}", os_str);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `format!` args
-  --> tests/ui/unnecessary_os_str_debug_formatting.rs:21:37
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:22:37
    |
 LL |     let _: String = format!("{:?}", os_string);
    |                                     ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs b/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs
index f14f6085c9a..215e0d5d780 100644
--- a/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::unnecessary_debug_formatting)]
+#![allow(clippy::uninlined_format_args)]
 
 use std::ffi::{OsStr, OsString};
 use std::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.stderr b/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.stderr
index f12fa72c84b..d244b9ad671 100644
--- a/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.stderr
@@ -1,5 +1,5 @@
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:29:22
+  --> tests/ui/unnecessary_path_debug_formatting.rs:30:22
    |
 LL |     println!("{:?}", os_str);
    |                      ^^^^^^
@@ -10,7 +10,7 @@ LL |     println!("{:?}", os_str);
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_debug_formatting)]`
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:30:22
+  --> tests/ui/unnecessary_path_debug_formatting.rs:31:22
    |
 LL |     println!("{:?}", os_string);
    |                      ^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     println!("{:?}", os_string);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:32:22
+  --> tests/ui/unnecessary_path_debug_formatting.rs:33:22
    |
 LL |     println!("{:?}", path);
    |                      ^^^^
@@ -28,7 +28,7 @@ LL |     println!("{:?}", path);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:33:22
+  --> tests/ui/unnecessary_path_debug_formatting.rs:34:22
    |
 LL |     println!("{:?}", path_buf);
    |                      ^^^^^^^^
@@ -37,7 +37,7 @@ LL |     println!("{:?}", path_buf);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:35:16
+  --> tests/ui/unnecessary_path_debug_formatting.rs:36:16
    |
 LL |     println!("{path:?}");
    |                ^^^^
@@ -46,7 +46,7 @@ LL |     println!("{path:?}");
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:36:16
+  --> tests/ui/unnecessary_path_debug_formatting.rs:37:16
    |
 LL |     println!("{path_buf:?}");
    |                ^^^^^^^^
@@ -55,7 +55,7 @@ LL |     println!("{path_buf:?}");
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `format!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:38:37
+  --> tests/ui/unnecessary_path_debug_formatting.rs:39:37
    |
 LL |     let _: String = format!("{:?}", path);
    |                                     ^^^^
@@ -64,7 +64,7 @@ LL |     let _: String = format!("{:?}", path);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `format!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:39:37
+  --> tests/ui/unnecessary_path_debug_formatting.rs:40:37
    |
 LL |     let _: String = format!("{:?}", path_buf);
    |                                     ^^^^^^^^
@@ -73,7 +73,7 @@ LL |     let _: String = format!("{:?}", path_buf);
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
 error: unnecessary `Debug` formatting in `println!` args
-  --> tests/ui/unnecessary_path_debug_formatting.rs:42:22
+  --> tests/ui/unnecessary_path_debug_formatting.rs:43:22
    |
 LL |     println!("{:?}", &*deref_path);
    |                      ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
index 5410033dbd8..b064a8b8f46 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
@@ -1,10 +1,11 @@
 #![allow(
+    clippy::manual_async_fn,
     clippy::needless_borrow,
     clippy::needless_borrows_for_generic_args,
-    clippy::ptr_arg,
-    clippy::manual_async_fn,
     clippy::needless_lifetimes,
-    clippy::owned_cow
+    clippy::owned_cow,
+    clippy::ptr_arg,
+    clippy::uninlined_format_args
 )]
 #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
index 0619dd4ddec..7954a4ad4ce 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
@@ -1,10 +1,11 @@
 #![allow(
+    clippy::manual_async_fn,
     clippy::needless_borrow,
     clippy::needless_borrows_for_generic_args,
-    clippy::ptr_arg,
-    clippy::manual_async_fn,
     clippy::needless_lifetimes,
-    clippy::owned_cow
+    clippy::owned_cow,
+    clippy::ptr_arg,
+    clippy::uninlined_format_args
 )]
 #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
index 8926db34da8..6c52be83930 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
@@ -1,11 +1,11 @@
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:217:64
+  --> tests/ui/unnecessary_to_owned.rs:218:64
    |
 LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
    |                                                                ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:217:20
+  --> tests/ui/unnecessary_to_owned.rs:218:20
    |
 LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,55 +13,55 @@ LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned())
    = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]`
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:219:40
+  --> tests/ui/unnecessary_to_owned.rs:220:40
    |
 LL |     require_os_str(&OsString::from("x").to_os_string());
    |                                        ^^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:219:21
+  --> tests/ui/unnecessary_to_owned.rs:220:21
    |
 LL |     require_os_str(&OsString::from("x").to_os_string());
    |                     ^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:221:48
+  --> tests/ui/unnecessary_to_owned.rs:222:48
    |
 LL |     require_path(&std::path::PathBuf::from("x").to_path_buf());
    |                                                ^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:221:19
+  --> tests/ui/unnecessary_to_owned.rs:222:19
    |
 LL |     require_path(&std::path::PathBuf::from("x").to_path_buf());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:223:35
+  --> tests/ui/unnecessary_to_owned.rs:224:35
    |
 LL |     require_str(&String::from("x").to_string());
    |                                   ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:223:18
+  --> tests/ui/unnecessary_to_owned.rs:224:18
    |
 LL |     require_str(&String::from("x").to_string());
    |                  ^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:225:39
+  --> tests/ui/unnecessary_to_owned.rs:226:39
    |
 LL |     require_slice(&[String::from("x")].to_owned());
    |                                       ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:225:20
+  --> tests/ui/unnecessary_to_owned.rs:226:20
    |
 LL |     require_slice(&[String::from("x")].to_owned());
    |                    ^^^^^^^^^^^^^^^^^^^
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:65:36
+  --> tests/ui/unnecessary_to_owned.rs:66:36
    |
 LL |     require_c_str(&Cow::from(c_str).into_owned());
    |                                    ^^^^^^^^^^^^^ help: remove this
@@ -70,391 +70,391 @@ LL |     require_c_str(&Cow::from(c_str).into_owned());
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:67:19
+  --> tests/ui/unnecessary_to_owned.rs:68:19
    |
 LL |     require_c_str(&c_str.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_os_string`
-  --> tests/ui/unnecessary_to_owned.rs:70:20
+  --> tests/ui/unnecessary_to_owned.rs:71:20
    |
 LL |     require_os_str(&os_str.to_os_string());
    |                    ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:72:38
+  --> tests/ui/unnecessary_to_owned.rs:73:38
    |
 LL |     require_os_str(&Cow::from(os_str).into_owned());
    |                                      ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:74:20
+  --> tests/ui/unnecessary_to_owned.rs:75:20
    |
 LL |     require_os_str(&os_str.to_owned());
    |                    ^^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_path_buf`
-  --> tests/ui/unnecessary_to_owned.rs:77:18
+  --> tests/ui/unnecessary_to_owned.rs:78:18
    |
 LL |     require_path(&path.to_path_buf());
    |                  ^^^^^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:79:34
+  --> tests/ui/unnecessary_to_owned.rs:80:34
    |
 LL |     require_path(&Cow::from(path).into_owned());
    |                                  ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:81:18
+  --> tests/ui/unnecessary_to_owned.rs:82:18
    |
 LL |     require_path(&path.to_owned());
    |                  ^^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:84:17
+  --> tests/ui/unnecessary_to_owned.rs:85:17
    |
 LL |     require_str(&s.to_string());
    |                 ^^^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:86:30
+  --> tests/ui/unnecessary_to_owned.rs:87:30
    |
 LL |     require_str(&Cow::from(s).into_owned());
    |                              ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:88:17
+  --> tests/ui/unnecessary_to_owned.rs:89:17
    |
 LL |     require_str(&s.to_owned());
    |                 ^^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:90:17
+  --> tests/ui/unnecessary_to_owned.rs:91:17
    |
 LL |     require_str(&x_ref.to_string());
    |                 ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:93:19
+  --> tests/ui/unnecessary_to_owned.rs:94:19
    |
 LL |     require_slice(&slice.to_vec());
    |                   ^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:95:36
+  --> tests/ui/unnecessary_to_owned.rs:96:36
    |
 LL |     require_slice(&Cow::from(slice).into_owned());
    |                                    ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:97:19
+  --> tests/ui/unnecessary_to_owned.rs:98:19
    |
 LL |     require_slice(&array.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:99:19
+  --> tests/ui/unnecessary_to_owned.rs:100:19
    |
 LL |     require_slice(&array_ref.to_owned());
    |                   ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:101:19
+  --> tests/ui/unnecessary_to_owned.rs:102:19
    |
 LL |     require_slice(&slice.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:105:42
+  --> tests/ui/unnecessary_to_owned.rs:106:42
    |
 LL |     require_x(&Cow::<X>::Owned(x.clone()).into_owned());
    |                                          ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:109:25
+  --> tests/ui/unnecessary_to_owned.rs:110:25
    |
 LL |     require_deref_c_str(c_str.to_owned());
    |                         ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:111:26
+  --> tests/ui/unnecessary_to_owned.rs:112:26
    |
 LL |     require_deref_os_str(os_str.to_owned());
    |                          ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:113:24
+  --> tests/ui/unnecessary_to_owned.rs:114:24
    |
 LL |     require_deref_path(path.to_owned());
    |                        ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:115:23
+  --> tests/ui/unnecessary_to_owned.rs:116:23
    |
 LL |     require_deref_str(s.to_owned());
    |                       ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:117:25
+  --> tests/ui/unnecessary_to_owned.rs:118:25
    |
 LL |     require_deref_slice(slice.to_owned());
    |                         ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:120:30
+  --> tests/ui/unnecessary_to_owned.rs:121:30
    |
 LL |     require_impl_deref_c_str(c_str.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:122:31
+  --> tests/ui/unnecessary_to_owned.rs:123:31
    |
 LL |     require_impl_deref_os_str(os_str.to_owned());
    |                               ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:124:29
+  --> tests/ui/unnecessary_to_owned.rs:125:29
    |
 LL |     require_impl_deref_path(path.to_owned());
    |                             ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:126:28
+  --> tests/ui/unnecessary_to_owned.rs:127:28
    |
 LL |     require_impl_deref_str(s.to_owned());
    |                            ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:128:30
+  --> tests/ui/unnecessary_to_owned.rs:129:30
    |
 LL |     require_impl_deref_slice(slice.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:131:29
+  --> tests/ui/unnecessary_to_owned.rs:132:29
    |
 LL |     require_deref_str_slice(s.to_owned(), slice.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:131:43
+  --> tests/ui/unnecessary_to_owned.rs:132:43
    |
 LL |     require_deref_str_slice(s.to_owned(), slice.to_owned());
    |                                           ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:134:29
+  --> tests/ui/unnecessary_to_owned.rs:135:29
    |
 LL |     require_deref_slice_str(slice.to_owned(), s.to_owned());
    |                             ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:134:47
+  --> tests/ui/unnecessary_to_owned.rs:135:47
    |
 LL |     require_deref_slice_str(slice.to_owned(), s.to_owned());
    |                                               ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:138:26
+  --> tests/ui/unnecessary_to_owned.rs:139:26
    |
 LL |     require_as_ref_c_str(c_str.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:140:27
+  --> tests/ui/unnecessary_to_owned.rs:141:27
    |
 LL |     require_as_ref_os_str(os_str.to_owned());
    |                           ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:142:25
+  --> tests/ui/unnecessary_to_owned.rs:143:25
    |
 LL |     require_as_ref_path(path.to_owned());
    |                         ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:144:24
+  --> tests/ui/unnecessary_to_owned.rs:145:24
    |
 LL |     require_as_ref_str(s.to_owned());
    |                        ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:146:24
+  --> tests/ui/unnecessary_to_owned.rs:147:24
    |
 LL |     require_as_ref_str(x.to_owned());
    |                        ^^^^^^^^^^^^ help: use: `&x`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:148:26
+  --> tests/ui/unnecessary_to_owned.rs:149:26
    |
 LL |     require_as_ref_slice(array.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:150:26
+  --> tests/ui/unnecessary_to_owned.rs:151:26
    |
 LL |     require_as_ref_slice(array_ref.to_owned());
    |                          ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:152:26
+  --> tests/ui/unnecessary_to_owned.rs:153:26
    |
 LL |     require_as_ref_slice(slice.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:155:31
+  --> tests/ui/unnecessary_to_owned.rs:156:31
    |
 LL |     require_impl_as_ref_c_str(c_str.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:157:32
+  --> tests/ui/unnecessary_to_owned.rs:158:32
    |
 LL |     require_impl_as_ref_os_str(os_str.to_owned());
    |                                ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:159:30
+  --> tests/ui/unnecessary_to_owned.rs:160:30
    |
 LL |     require_impl_as_ref_path(path.to_owned());
    |                              ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:161:29
+  --> tests/ui/unnecessary_to_owned.rs:162:29
    |
 LL |     require_impl_as_ref_str(s.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:163:29
+  --> tests/ui/unnecessary_to_owned.rs:164:29
    |
 LL |     require_impl_as_ref_str(x.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `&x`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:165:31
+  --> tests/ui/unnecessary_to_owned.rs:166:31
    |
 LL |     require_impl_as_ref_slice(array.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:167:31
+  --> tests/ui/unnecessary_to_owned.rs:168:31
    |
 LL |     require_impl_as_ref_slice(array_ref.to_owned());
    |                               ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:169:31
+  --> tests/ui/unnecessary_to_owned.rs:170:31
    |
 LL |     require_impl_as_ref_slice(slice.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:172:30
+  --> tests/ui/unnecessary_to_owned.rs:173:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:172:44
+  --> tests/ui/unnecessary_to_owned.rs:173:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array.to_owned());
    |                                            ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:175:30
+  --> tests/ui/unnecessary_to_owned.rs:176:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:175:44
+  --> tests/ui/unnecessary_to_owned.rs:176:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
    |                                            ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:178:30
+  --> tests/ui/unnecessary_to_owned.rs:179:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:178:44
+  --> tests/ui/unnecessary_to_owned.rs:179:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
    |                                            ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:181:30
+  --> tests/ui/unnecessary_to_owned.rs:182:30
    |
 LL |     require_as_ref_slice_str(array.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:181:48
+  --> tests/ui/unnecessary_to_owned.rs:182:48
    |
 LL |     require_as_ref_slice_str(array.to_owned(), s.to_owned());
    |                                                ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:184:30
+  --> tests/ui/unnecessary_to_owned.rs:185:30
    |
 LL |     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:184:52
+  --> tests/ui/unnecessary_to_owned.rs:185:52
    |
 LL |     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
    |                                                    ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:187:30
+  --> tests/ui/unnecessary_to_owned.rs:188:30
    |
 LL |     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:187:48
+  --> tests/ui/unnecessary_to_owned.rs:188:48
    |
 LL |     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
    |                                                ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:191:20
+  --> tests/ui/unnecessary_to_owned.rs:192:20
    |
 LL |     let _ = x.join(&x_ref.to_string());
    |                    ^^^^^^^^^^^^^^^^^^ help: use: `x_ref`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:194:13
+  --> tests/ui/unnecessary_to_owned.rs:195:13
    |
 LL |     let _ = slice.to_vec().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:196:13
+  --> tests/ui/unnecessary_to_owned.rs:197:13
    |
 LL |     let _ = slice.to_owned().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:199:13
+  --> tests/ui/unnecessary_to_owned.rs:200:13
    |
 LL |     let _ = IntoIterator::into_iter(slice.to_vec());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:201:13
+  --> tests/ui/unnecessary_to_owned.rs:202:13
    |
 LL |     let _ = IntoIterator::into_iter(slice.to_owned());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: allocating a new `String` only to create a temporary `&str` from it
-  --> tests/ui/unnecessary_to_owned.rs:229:26
+  --> tests/ui/unnecessary_to_owned.rs:230:26
    |
 LL |     let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8");
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -466,7 +466,7 @@ LL +     let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8");
    |
 
 error: allocating a new `String` only to create a temporary `&str` from it
-  --> tests/ui/unnecessary_to_owned.rs:231:26
+  --> tests/ui/unnecessary_to_owned.rs:232:26
    |
 LL |     let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -478,7 +478,7 @@ LL +     let _ref_str: &str = core::str::from_utf8(b"foo").unwrap();
    |
 
 error: allocating a new `String` only to create a temporary `&str` from it
-  --> tests/ui/unnecessary_to_owned.rs:233:26
+  --> tests/ui/unnecessary_to_owned.rs:234:26
    |
 LL |     let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -490,7 +490,7 @@ LL +     let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap();
    |
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:291:14
+  --> tests/ui/unnecessary_to_owned.rs:292:14
    |
 LL |     for t in file_types.to_vec() {
    |              ^^^^^^^^^^^^^^^^^^^
@@ -503,49 +503,49 @@ LL ~         let path = match get_file_path(t) {
    |
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:357:24
+  --> tests/ui/unnecessary_to_owned.rs:358:24
    |
 LL |         Box::new(build(y.to_string()))
    |                        ^^^^^^^^^^^^^ help: use: `y`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:467:12
+  --> tests/ui/unnecessary_to_owned.rs:468:12
    |
 LL |         id("abc".to_string())
    |            ^^^^^^^^^^^^^^^^^ help: use: `"abc"`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:611:37
+  --> tests/ui/unnecessary_to_owned.rs:612:37
    |
 LL |         IntoFuture::into_future(foo([].to_vec(), &0));
    |                                     ^^^^^^^^^^^ help: use: `[]`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:622:18
+  --> tests/ui/unnecessary_to_owned.rs:623:18
    |
 LL |         s.remove(&a.to_vec());
    |                  ^^^^^^^^^^^ help: replace it with: `a`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:627:14
+  --> tests/ui/unnecessary_to_owned.rs:628:14
    |
 LL |     s.remove(&"b".to_owned());
    |              ^^^^^^^^^^^^^^^ help: replace it with: `"b"`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:629:14
+  --> tests/ui/unnecessary_to_owned.rs:630:14
    |
 LL |     s.remove(&"b".to_string());
    |              ^^^^^^^^^^^^^^^^ help: replace it with: `"b"`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:635:14
+  --> tests/ui/unnecessary_to_owned.rs:636:14
    |
 LL |     s.remove(&["b"].to_vec());
    |              ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:637:14
+  --> tests/ui/unnecessary_to_owned.rs:638:14
    |
 LL |     s.remove(&(&["b"]).to_vec());
    |              ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()`
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
index 791b2fa131f..2081772d06b 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
@@ -64,3 +64,16 @@ fn msrv_1_53() {
     if let [1 | 53] = [0] {}
     //~^ unnested_or_patterns
 }
+
+mod issue9952 {
+    fn or_in_local() {
+        let (0 | 1 | _) = 0;
+        //~^ unnested_or_patterns
+
+        if let (0 | 1 | _) = 0 {}
+        //~^ unnested_or_patterns
+    }
+
+    fn or_in_param((x | x | x): i32) {}
+    //~^ unnested_or_patterns
+}
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.rs b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
index e7e7c7cd2e4..6bf8fce3661 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.rs
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
@@ -64,3 +64,16 @@ fn msrv_1_53() {
     if let [1] | [53] = [0] {}
     //~^ unnested_or_patterns
 }
+
+mod issue9952 {
+    fn or_in_local() {
+        let (0 | (1 | _)) = 0;
+        //~^ unnested_or_patterns
+
+        if let (0 | (1 | _)) = 0 {}
+        //~^ unnested_or_patterns
+    }
+
+    fn or_in_param((x | (x | x)): i32) {}
+    //~^ unnested_or_patterns
+}
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
index ec5eb983c5a..c805dc992b1 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
@@ -204,5 +204,41 @@ LL -     if let [1] | [53] = [0] {}
 LL +     if let [1 | 53] = [0] {}
    |
 
-error: aborting due to 17 previous errors
+error: unnested or-patterns
+  --> tests/ui/unnested_or_patterns.rs:70:13
+   |
+LL |         let (0 | (1 | _)) = 0;
+   |             ^^^^^^^^^^^^^
+   |
+help: nest the patterns
+   |
+LL -         let (0 | (1 | _)) = 0;
+LL +         let (0 | 1 | _) = 0;
+   |
+
+error: unnested or-patterns
+  --> tests/ui/unnested_or_patterns.rs:73:16
+   |
+LL |         if let (0 | (1 | _)) = 0 {}
+   |                ^^^^^^^^^^^^^
+   |
+help: nest the patterns
+   |
+LL -         if let (0 | (1 | _)) = 0 {}
+LL +         if let (0 | 1 | _) = 0 {}
+   |
+
+error: unnested or-patterns
+  --> tests/ui/unnested_or_patterns.rs:77:20
+   |
+LL |     fn or_in_param((x | (x | x)): i32) {}
+   |                    ^^^^^^^^^^^^^
+   |
+help: nest the patterns
+   |
+LL -     fn or_in_param((x | (x | x)): i32) {}
+LL +     fn or_in_param((x | x | x): i32) {}
+   |
+
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unwrap_or.fixed b/src/tools/clippy/tests/ui/unwrap_or.fixed
index c794ed57703..e550484b5d9 100644
--- a/src/tools/clippy/tests/ui/unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/unwrap_or.fixed
@@ -1,4 +1,4 @@
-#![warn(clippy::all, clippy::or_fun_call)]
+#![warn(clippy::or_fun_call)]
 #![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unwrap_or.rs b/src/tools/clippy/tests/ui/unwrap_or.rs
index 11a6883b740..cdd61ac898e 100644
--- a/src/tools/clippy/tests/ui/unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/unwrap_or.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::all, clippy::or_fun_call)]
+#![warn(clippy::or_fun_call)]
 #![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/used_underscore_items.rs b/src/tools/clippy/tests/ui/used_underscore_items.rs
index 3401df6ae74..7e8289f1406 100644
--- a/src/tools/clippy/tests/ui/used_underscore_items.rs
+++ b/src/tools/clippy/tests/ui/used_underscore_items.rs
@@ -73,7 +73,7 @@ fn external_item_call() {
 
 // should not lint foreign functions.
 // issue #14156
-extern "C" {
+unsafe extern "C" {
     pub fn _exit(code: i32) -> !;
 }
 
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 33d3b0728f3..f27b109e995 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -9,11 +9,32 @@ allow-unauthenticated = [
 # See https://forge.rust-lang.org/triagebot/shortcuts.html
 [shortcut]
 
+[merge-conflicts]
+
+[note]
+
+[canonicalize-issue-links]
+
+# Prevents mentions in commits to avoid users being spammed
+[no-mentions]
+
 # Have rustbot inform users about the *No Merge Policy*
 [no-merges]
 exclude_titles = ["Rustup"] # exclude syncs from rust-lang/rust
 labels = ["has-merge-commits", "S-waiting-on-author"]
 
+[review-requested]
+# Those labels are removed when PR author requests a review from an assignee
+remove_labels = ["S-waiting-on-author"]
+# Those labels are added when PR author requests a review from an assignee
+add_labels = ["S-waiting-on-review"]
+
+[review-submitted]
+# These labels are removed when a review is submitted.
+review_labels = ["S-waiting-on-review"]
+# This label is added when a review is submitted.
+reviewed_label = "S-waiting-on-author"
+
 [autolabel."S-waiting-on-review"]
 new_pr = true
 
@@ -21,10 +42,12 @@ new_pr = true
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
 users_on_vacation = [
     "matthiaskrgr",
+    "samueltardieu",
 ]
 
 [assign.owners]
 "/.github" = ["@flip1995"]
+"/triagebot.toml" = ["@flip1995"]
 "/book" = ["@flip1995"]
 "*" = [
     "@Manishearth",
@@ -34,4 +57,5 @@ users_on_vacation = [
     "@Jarcho",
     "@blyxyas",
     "@y21",
+    "@samueltardieu",
 ]
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 31c696ed41f..de93e2b99ee 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -415,10 +415,13 @@ pub struct Config {
     /// ABI tests.
     pub minicore_path: Utf8PathBuf,
 
-    /// If true, run tests with the "new" executor that was written to replace
-    /// compiletest's dependency on libtest. Eventually this will become the
-    /// default, and the libtest dependency will be removed.
-    pub new_executor: bool,
+    /// If true, disable the "new" executor, and use the older libtest-based
+    /// executor to run tests instead. This is a temporary fallback, to make
+    /// manual comparative testing easier if bugs are found in the new executor.
+    ///
+    /// FIXME(Zalathar): Eventually remove this flag and remove the libtest
+    /// dependency.
+    pub no_new_executor: bool,
 }
 
 impl Config {
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index 0c173d476af..990be56ce0c 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -57,9 +57,11 @@ pub(crate) fn run_tests(config: &Config, tests: Vec<CollectedTest>) -> bool {
         }
 
         let completion = deadline_queue
-            .read_channel_while_checking_deadlines(&completion_rx, |_id, test| {
-                listener.test_timed_out(test);
-            })
+            .read_channel_while_checking_deadlines(
+                &completion_rx,
+                |id| running_tests.contains_key(&id),
+                |_id, test| listener.test_timed_out(test),
+            )
             .expect("receive channel should never be closed early");
 
         let RunningTest { test, join_handle } = running_tests.remove(&completion.id).unwrap();
diff --git a/src/tools/compiletest/src/executor/deadline.rs b/src/tools/compiletest/src/executor/deadline.rs
index 83b8591a416..3536eff2fd8 100644
--- a/src/tools/compiletest/src/executor/deadline.rs
+++ b/src/tools/compiletest/src/executor/deadline.rs
@@ -21,16 +21,26 @@ impl<'a> DeadlineQueue<'a> {
         Self { queue: VecDeque::with_capacity(capacity) }
     }
 
+    /// All calls to [`Instant::now`] go through this wrapper method.
+    /// This makes it easier to find all places that read the current time.
+    fn now(&self) -> Instant {
+        Instant::now()
+    }
+
     pub(crate) fn push(&mut self, id: TestId, test: &'a CollectedTest) {
-        let deadline = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
+        let deadline = self.now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
+        if let Some(back) = self.queue.back() {
+            assert!(back.deadline <= deadline);
+        }
         self.queue.push_back(DeadlineEntry { id, test, deadline });
     }
 
-    /// Equivalent to `rx.read()`, except that if any test exceeds its deadline
+    /// Equivalent to `rx.recv()`, except that if a test exceeds its deadline
     /// during the wait, the given callback will also be called for that test.
     pub(crate) fn read_channel_while_checking_deadlines<T>(
         &mut self,
         rx: &mpsc::Receiver<T>,
+        is_running: impl Fn(TestId) -> bool,
         mut on_deadline_passed: impl FnMut(TestId, &CollectedTest),
     ) -> Result<T, RecvError> {
         loop {
@@ -39,18 +49,18 @@ impl<'a> DeadlineQueue<'a> {
                 // deadline, so do a normal receive.
                 return rx.recv();
             };
-            let wait_duration = next_deadline.saturating_duration_since(Instant::now());
+            let next_deadline_timeout = next_deadline.saturating_duration_since(self.now());
+
+            let recv_result = rx.recv_timeout(next_deadline_timeout);
+            // Process deadlines after every receive attempt, regardless of
+            // outcome, so that we don't build up an unbounded backlog of stale
+            // entries due to a constant stream of tests finishing.
+            self.for_each_entry_past_deadline(&is_running, &mut on_deadline_passed);
 
-            let recv_result = rx.recv_timeout(wait_duration);
             match recv_result {
                 Ok(value) => return Ok(value),
-                Err(RecvTimeoutError::Timeout) => {
-                    // Notify the callback of tests that have exceeded their
-                    // deadline, then loop and do annother channel read.
-                    for DeadlineEntry { id, test, .. } in self.remove_tests_past_deadline() {
-                        on_deadline_passed(id, test);
-                    }
-                }
+                // Deadlines have already been processed, so loop and do another receive.
+                Err(RecvTimeoutError::Timeout) => {}
                 Err(RecvTimeoutError::Disconnected) => return Err(RecvError),
             }
         }
@@ -60,14 +70,28 @@ impl<'a> DeadlineQueue<'a> {
         Some(self.queue.front()?.deadline)
     }
 
-    fn remove_tests_past_deadline(&mut self) -> Vec<DeadlineEntry<'a>> {
-        let now = Instant::now();
-        let mut timed_out = vec![];
-        while let Some(deadline_entry) = pop_front_if(&mut self.queue, |entry| now < entry.deadline)
-        {
-            timed_out.push(deadline_entry);
+    fn for_each_entry_past_deadline(
+        &mut self,
+        is_running: impl Fn(TestId) -> bool,
+        mut on_deadline_passed: impl FnMut(TestId, &CollectedTest),
+    ) {
+        let now = self.now();
+
+        // Clear out entries that are past their deadline, but only invoke the
+        // callback for tests that are still considered running.
+        while let Some(entry) = pop_front_if(&mut self.queue, |entry| entry.deadline <= now) {
+            if is_running(entry.id) {
+                on_deadline_passed(entry.id, entry.test);
+            }
+        }
+
+        // Also clear out any leading entries that are no longer running, even
+        // if their deadline hasn't been reached.
+        while let Some(_) = pop_front_if(&mut self.queue, |entry| !is_running(entry.id)) {}
+
+        if let Some(front) = self.queue.front() {
+            assert!(now < front.deadline);
         }
-        timed_out
     }
 }
 
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 4bbd4ab4790..7948a273c1e 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -203,7 +203,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "COMMAND",
         )
         .reqopt("", "minicore-path", "path to minicore aux library", "PATH")
-        .optflag("n", "new-executor", "enables the new test executor instead of using libtest")
+        .optflag("N", "no-new-executor", "disables the new test executor, and uses libtest instead")
         .optopt(
             "",
             "debugger",
@@ -450,7 +450,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
         minicore_path: opt_path(matches, "minicore-path"),
 
-        new_executor: matches.opt_present("new-executor"),
+        no_new_executor: matches.opt_present("no-new-executor"),
     }
 }
 
@@ -577,9 +577,10 @@ pub fn run_tests(config: Arc<Config>) {
     // Delegate to the executor to filter and run the big list of test structures
     // created during test discovery. When the executor decides to run a test,
     // it will return control to the rest of compiletest by calling `runtest::run`.
-    let res = if config.new_executor {
+    let res = if !config.no_new_executor {
         Ok(executor::run_tests(&config, tests))
     } else {
+        // FIXME(Zalathar): Eventually remove the libtest executor entirely.
         crate::executor::libtest::execute_tests(&config, tests)
     };
 
@@ -745,7 +746,7 @@ fn modified_tests(config: &Config, dir: &Utf8Path) -> Result<Vec<Utf8PathBuf>, S
         &vec!["rs", "stderr", "fixed"],
     )?;
     // Add new test cases to the list, it will be convenient in daily development.
-    let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]);
+    let untracked_files = get_git_untracked_files(Some(dir.as_std_path()))?.unwrap_or(vec![]);
 
     let all_paths = [&files[..], &untracked_files[..]].concat();
     let full_paths = {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index cc09463c358..fe23cce81e9 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1710,12 +1710,16 @@ impl<'test> TestCx<'test> {
         rustc.args(&self.props.compile_flags);
 
         // FIXME(jieyouxu): we should report a fatal error or warning if user wrote `-Cpanic=` with
-        // something that's not `abort`, however, by moving this last we should override previous
-        // `-Cpanic=`s
+        // something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`,
+        // however, by moving this last we should override previous `-Cpanic`s and
+        // `-Cforce-unwind-tables`s. Note that checking here is very fragile, because we'd have to
+        // account for all possible compile flag splittings (they have some... intricacies and are
+        // not yet normalized).
         //
         // `minicore` requires `#![no_std]` and `#![no_core]`, which means no unwinding panics.
         if self.props.add_core_stubs {
             rustc.arg("-Cpanic=abort");
+            rustc.arg("-Cforce-unwind-tables=yes");
         }
 
         rustc
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index b6b2684dc6d..e03611e9b50 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -1,6 +1,5 @@
 #![feature(rustc_private)]
 #![feature(cfg_match)]
-#![feature(cell_update)]
 #![feature(float_gamma)]
 #![feature(float_erf)]
 #![feature(map_try_insert)]
diff --git a/src/tools/miri/tests/fail/validity/invalid_bool.rs b/src/tools/miri/tests/fail/validity/invalid_bool.rs
index 4f11bb2629f..bd448af834d 100644
--- a/src/tools/miri/tests/fail/validity/invalid_bool.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_bool.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 fn main() {
     let _b = unsafe { std::mem::transmute::<u8, bool>(2) }; //~ ERROR: expected a boolean
 }
diff --git a/src/tools/miri/tests/fail/validity/invalid_bool_op.rs b/src/tools/miri/tests/fail/validity/invalid_bool_op.rs
index fe9bb3bed7f..0cbe2d76dc6 100644
--- a/src/tools/miri/tests/fail/validity/invalid_bool_op.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_bool_op.rs
@@ -2,6 +2,7 @@
 // Make sure we find these even with many checks disabled.
 //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
 
+#![allow(unnecessary_transmutes)]
 fn main() {
     let b = unsafe { std::mem::transmute::<u8, bool>(2) };
     let _x = b == std::hint::black_box(true); //~ ERROR: interpreting an invalid 8-bit value as a bool
diff --git a/src/tools/miri/tests/fail/validity/invalid_char.rs b/src/tools/miri/tests/fail/validity/invalid_char.rs
index 568892e5910..d57c933dac1 100644
--- a/src/tools/miri/tests/fail/validity/invalid_char.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_char.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 fn main() {
     assert!(std::char::from_u32(-1_i32 as u32).is_none());
     let _val = match unsafe { std::mem::transmute::<i32, char>(-1) } {
diff --git a/src/tools/miri/tests/fail/validity/invalid_char_op.rs b/src/tools/miri/tests/fail/validity/invalid_char_op.rs
index 69924822944..e3a5f837e18 100644
--- a/src/tools/miri/tests/fail/validity/invalid_char_op.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_char_op.rs
@@ -2,6 +2,7 @@
 // Make sure we find these even with many checks disabled.
 //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
 
+#![allow(unnecessary_transmutes)]
 fn main() {
     let c = 0xFFFFFFu32;
     assert!(std::char::from_u32(c).is_none());
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index cd60b6bd563..575d70579a4 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -6,6 +6,7 @@
 #![feature(f16)]
 #![allow(arithmetic_overflow)]
 #![allow(internal_features)]
+#![allow(unnecessary_transmutes)]
 
 use std::any::type_name;
 use std::cmp::min;
diff --git a/src/tools/miri/tests/pass/fn_align.rs b/src/tools/miri/tests/pass/fn_align.rs
new file mode 100644
index 00000000000..550bb1cb4d7
--- /dev/null
+++ b/src/tools/miri/tests/pass/fn_align.rs
@@ -0,0 +1,21 @@
+//@compile-flags: -Zmin-function-alignment=8
+#![feature(fn_align)]
+
+// When a function uses `repr(align(N))`, the function address should be a multiple of `N`.
+
+#[repr(align(256))]
+fn foo() {}
+
+#[repr(align(16))]
+fn bar() {}
+
+#[repr(align(4))]
+fn baz() {}
+
+fn main() {
+    assert!((foo as usize).is_multiple_of(256));
+    assert!((bar as usize).is_multiple_of(16));
+
+    // The maximum of `repr(align(N))` and `-Zmin-function-alignment=N` is used.
+    assert!((baz as usize).is_multiple_of(8));
+}
diff --git a/src/tools/miri/tests/pass/issues/issue-miri-184.rs b/src/tools/miri/tests/pass/issues/issue-miri-184.rs
index 39c841403ef..964d850298f 100644
--- a/src/tools/miri/tests/pass/issues/issue-miri-184.rs
+++ b/src/tools/miri/tests/pass/issues/issue-miri-184.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 pub fn main() {
     let bytes: [u8; 8] = unsafe { ::std::mem::transmute(0u64) };
     let _val: &[u8] = &bytes;
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
index a629e2acfe9..882b5e3f795 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
@@ -368,7 +368,7 @@ unsafe fn load_m256i_word<T>(data: &[T], word_index: usize) -> __m256i {
 #[target_feature(enable = "avx512f")]
 unsafe fn load_m512i_word<T>(data: &[T], word_index: usize) -> __m512i {
     let byte_offset = word_index * 64 / size_of::<T>();
-    let pointer = data.as_ptr().add(byte_offset) as *const i32;
+    let pointer = data.as_ptr().add(byte_offset) as *const __m512i;
     _mm512_loadu_si512(black_box(pointer))
 }
 
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
index 6f7ab3b3c9f..be3f961e10f 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
@@ -1,5 +1,6 @@
 // We're testing x86 target specific features
 //@only-target: x86_64 i686
+#![allow(unnecessary_transmutes)]
 
 #[cfg(target_arch = "x86")]
 use std::arch::x86::*;
diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs
index e4122461087..d3e20f6ae1a 100644
--- a/tests/assembly/simd-bitmask.rs
+++ b/tests/assembly/simd-bitmask.rs
@@ -65,8 +65,9 @@ pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 {
     simd_bitmask(mask)
 }
 
-// CHECK-LABEL: bitmask_m8x64
+// x86-avx512-LABEL: bitmask_m8x64
 #[no_mangle]
+#[cfg(x86_avx512)]
 pub unsafe extern "C" fn bitmask_m8x64(mask: m8x64) -> u64 {
     // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
     // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
@@ -128,8 +129,10 @@ pub unsafe extern "C" fn bitmask_m64x2(mask: m64x2) -> u8 {
     simd_bitmask(mask)
 }
 
-// CHECK-LABEL: bitmask_m64x4
+// x86-avx2-LABEL: bitmask_m64x4
+// x86-avx512-LABEL: bitmask_m64x4
 #[no_mangle]
+#[cfg(any(x86_avx2, x86_avx512))]
 pub unsafe extern "C" fn bitmask_m64x4(mask: m64x4) -> u8 {
     // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
     //
diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs
index 4f8d6b825b6..e7c7b0db0d5 100644
--- a/tests/assembly/simd-intrinsic-select.rs
+++ b/tests/assembly/simd-intrinsic-select.rs
@@ -99,8 +99,10 @@ pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2
     simd_select(mask, a, b)
 }
 
-// CHECK-LABEL: select_f64x4
+// x86-avx2-LABEL: select_f64x4
+// x86-avx512-LABEL: select_f64x4
 #[no_mangle]
+#[cfg(any(x86_avx2, x86_avx512))]
 pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 {
     // The parameter is a 256 bit vector which in the C abi is only valid for avx targets.
     //
@@ -113,8 +115,9 @@ pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4
     simd_select(mask, a, b)
 }
 
-// CHECK-LABEL: select_f64x8
+// x86-avx512-LABEL: select_f64x8
 #[no_mangle]
+#[cfg(x86_avx512)]
 pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 {
     // The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets.
     //
diff --git a/tests/assembly/x86-return-float.rs b/tests/assembly/x86-return-float.rs
index 2c39c830684..165c11d2280 100644
--- a/tests/assembly/x86-return-float.rs
+++ b/tests/assembly/x86-return-float.rs
@@ -35,6 +35,7 @@ use minicore::*;
 pub fn return_f32(x: f32) -> f32 {
     // CHECK: movss {{.*}}(%ebp), %xmm0
     // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
     // CHECK-NEXT: retl
     x
 }
@@ -44,6 +45,7 @@ pub fn return_f32(x: f32) -> f32 {
 pub fn return_f64(x: f64) -> f64 {
     // CHECK: movsd {{.*}}(%ebp), %xmm0
     // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
     // CHECK-NEXT: retl
     x
 }
@@ -313,9 +315,13 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
 #[no_mangle]
 pub fn return_f16(x: f16) -> f16 {
     // CHECK: pushl %ebp
+    // linux-NEXT: .cfi_def_cfa_offset
+    // linux-NEXT: .cfi_offset
     // CHECK-NEXT: movl %esp, %ebp
+    // linux-NEXT: .cfi_def_cfa_register
     // CHECK-NEXT: pinsrw $0, 8(%ebp), %xmm0
     // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
     // CHECK-NEXT: retl
     x
 }
@@ -324,10 +330,14 @@ pub fn return_f16(x: f16) -> f16 {
 #[no_mangle]
 pub fn return_f128(x: f128) -> f128 {
     // CHECK: pushl %ebp
+    // linux-NEXT: .cfi_def_cfa_offset
+    // linux-NEXT: .cfi_offset
     // CHECK-NEXT: movl %esp, %ebp
+    // linux-NEXT: .cfi_def_cfa_register
     // linux-NEXT: movaps 8(%ebp), %xmm0
     // win-NEXT: movups 8(%ebp), %xmm0
     // CHECK-NEXT: popl %ebp
+    // linux-NEXT: .cfi_def_cfa
     // CHECK-NEXT: retl
     x
 }
diff --git a/tests/codegen/align-struct.rs b/tests/codegen/align-struct.rs
index cc65b08a922..402a184d4c0 100644
--- a/tests/codegen/align-struct.rs
+++ b/tests/codegen/align-struct.rs
@@ -1,5 +1,7 @@
 //@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
-//
+// 32bit MSVC does not align things properly so we suppress high alignment annotations (#112480)
+//@ ignore-i686-pc-windows-msvc
+//@ ignore-i686-pc-windows-gnu
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/autodiff/identical_fnc.rs b/tests/codegen/autodiff/identical_fnc.rs
new file mode 100644
index 00000000000..1c3277f52b4
--- /dev/null
+++ b/tests/codegen/autodiff/identical_fnc.rs
@@ -0,0 +1,45 @@
+//@ compile-flags: -Zautodiff=Enable -C opt-level=3  -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+//
+// Each autodiff invocation creates a new placeholder function, which we will replace on llvm-ir
+// level. If a user tries to differentiate two identical functions within the same compilation unit,
+// then LLVM might merge them in release mode before AD. In that case we can't rewrite one of the
+// merged placeholder function anymore, and compilation would fail. We prevent this by disabling
+// LLVM's merge_function pass before AD. Here we implicetely test that our solution keeps working.
+// We also explicetly test that we keep running merge_function after AD, by checking for two
+// identical function calls in the LLVM-IR, while having two different calls in the Rust code.
+#![feature(autodiff)]
+
+use std::autodiff::autodiff;
+
+#[autodiff(d_square, Reverse, Duplicated, Active)]
+fn square(x: &f64) -> f64 {
+    x * x
+}
+
+#[autodiff(d_square2, Reverse, Duplicated, Active)]
+fn square2(x: &f64) -> f64 {
+    x * x
+}
+
+// CHECK:; identical_fnc::main
+// CHECK-NEXT:; Function Attrs:
+// CHECK-NEXT:define internal void @_ZN13identical_fnc4main17hf4dbc69c8d2f9130E()
+// CHECK-NEXT:start:
+// CHECK-NOT:br
+// CHECK-NOT:ret
+// CHECK:; call identical_fnc::d_square
+// CHECK-NEXT:  call fastcc void @_ZN13identical_fnc8d_square17h4c364207a2f8e06dE(double %x.val, ptr noalias noundef nonnull align 8 dereferenceable(8) %dx1)
+// CHECK-NEXT:; call identical_fnc::d_square
+// CHECK-NEXT:  call fastcc void @_ZN13identical_fnc8d_square17h4c364207a2f8e06dE(double %x.val, ptr noalias noundef nonnull align 8 dereferenceable(8) %dx2)
+
+fn main() {
+    let x = std::hint::black_box(3.0);
+    let mut dx1 = std::hint::black_box(1.0);
+    let mut dx2 = std::hint::black_box(1.0);
+    let _ = d_square(&x, &mut dx1, 1.0);
+    let _ = d_square2(&x, &mut dx2, 1.0);
+    assert_eq!(dx1, 6.0);
+    assert_eq!(dx2, 6.0);
+}
diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs
index 8343594e5d2..1d4edc39b1c 100644
--- a/tests/codegen/const-vector.rs
+++ b/tests/codegen/const-vector.rs
@@ -8,6 +8,7 @@
 #![feature(repr_simd)]
 #![feature(rustc_attrs)]
 #![feature(simd_ffi)]
+#![feature(arm_target_feature)]
 #![allow(non_camel_case_types)]
 
 // Setting up structs that can be used as const vectors
@@ -28,33 +29,12 @@ pub struct Simd<T, const N: usize>([T; N]);
 
 extern "unadjusted" {
     fn test_i8x2(a: i8x2);
-}
-
-extern "unadjusted" {
     fn test_i8x2_two_args(a: i8x2, b: i8x2);
-}
-
-extern "unadjusted" {
     fn test_i8x2_mixed_args(a: i8x2, c: i32, b: i8x2);
-}
-
-extern "unadjusted" {
     fn test_i8x2_arr(a: i8x2);
-}
-
-extern "unadjusted" {
     fn test_f32x2(a: f32x2);
-}
-
-extern "unadjusted" {
     fn test_f32x2_arr(a: f32x2);
-}
-
-extern "unadjusted" {
     fn test_simd(a: Simd<i32, 4>);
-}
-
-extern "unadjusted" {
     fn test_simd_unaligned(a: Simd<i32, 3>);
 }
 
@@ -62,6 +42,9 @@ extern "unadjusted" {
 // if the size is not a power of 2
 // CHECK: %"Simd<i32, 3>" = type { [3 x i32] }
 
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 pub fn do_call() {
     unsafe {
         // CHECK: call void @test_i8x2(<2 x i8> <i8 32, i8 64>
diff --git a/tests/codegen/issues/issue-56927.rs b/tests/codegen/issues/issue-56927.rs
index a40718689b3..415ef073e03 100644
--- a/tests/codegen/issues/issue-56927.rs
+++ b/tests/codegen/issues/issue-56927.rs
@@ -1,4 +1,7 @@
 //@ compile-flags: -C no-prepopulate-passes
+// 32bit MSVC does not align things properly so we suppress high alignment annotations (#112480)
+//@ ignore-i686-pc-windows-msvc
+//@ ignore-i686-pc-windows-gnu
 
 #![crate_type = "rlib"]
 
diff --git a/tests/codegen/regparm-inreg.rs b/tests/codegen/regparm-inreg.rs
index 8dae3a83e4e..15702804dfd 100644
--- a/tests/codegen/regparm-inreg.rs
+++ b/tests/codegen/regparm-inreg.rs
@@ -3,7 +3,7 @@
 // x86 only.
 
 //@ add-core-stubs
-//@ compile-flags: --target i686-unknown-linux-gnu -Cno-prepopulate-passes -Copt-level=3
+//@ compile-flags: --target i686-unknown-linux-gnu -Cno-prepopulate-passes -Copt-level=3 -Ctarget-feature=+avx
 //@ needs-llvm-components: x86
 
 //@ revisions:regparm0 regparm1 regparm2 regparm3
diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs
index e7e4c40a099..5475bfb6b65 100644
--- a/tests/codegen/repr/transparent.rs
+++ b/tests/codegen/repr/transparent.rs
@@ -9,7 +9,7 @@
 // For LoongArch: see codegen/loongarch-abi
 
 #![crate_type = "lib"]
-#![feature(repr_simd, transparent_unions)]
+#![feature(repr_simd, transparent_unions, arm_target_feature)]
 
 use std::marker::PhantomData;
 
@@ -139,6 +139,9 @@ pub struct Vector(f32x4);
 
 // CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1)
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 pub extern "C" fn test_Vector(_: Vector) -> Vector {
     loop {}
 }
diff --git a/tests/codegen/simd/extract-insert-dyn.rs b/tests/codegen/simd/extract-insert-dyn.rs
index 584e2c7887a..2c64f5d3c09 100644
--- a/tests/codegen/simd/extract-insert-dyn.rs
+++ b/tests/codegen/simd/extract-insert-dyn.rs
@@ -1,6 +1,6 @@
 //@compile-flags: -C opt-level=3 -C no-prepopulate-passes
 
-#![feature(core_intrinsics, repr_simd)]
+#![feature(core_intrinsics, repr_simd, arm_target_feature)]
 #![no_std]
 #![crate_type = "lib"]
 #![allow(non_camel_case_types)]
@@ -21,6 +21,9 @@ pub struct i8x16([i8; 16]);
 // CHECK-LABEL: dyn_simd_extract
 // CHECK: extractelement <16 x i8> %x, i32 %idx
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 {
     simd_extract_dyn(x, idx)
 }
@@ -28,6 +31,9 @@ unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 {
 // CHECK-LABEL: literal_dyn_simd_extract
 // CHECK: extractelement <16 x i8> %x, i32 7
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 {
     simd_extract_dyn(x, 7)
 }
@@ -35,6 +41,9 @@ unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 {
 // CHECK-LABEL: const_dyn_simd_extract
 // CHECK: extractelement <16 x i8> %x, i32 7
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 {
     simd_extract_dyn(x, const { 3 + 4 })
 }
@@ -42,6 +51,9 @@ unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 {
 // CHECK-LABEL: const_simd_extract
 // CHECK: extractelement <16 x i8> %x, i32 7
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 {
     simd_extract(x, const { 3 + 4 })
 }
@@ -49,6 +61,9 @@ unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 {
 // CHECK-LABEL: dyn_simd_insert
 // CHECK: insertelement <16 x i8> %x, i8 %e, i32 %idx
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 {
     simd_insert_dyn(x, idx, e)
 }
@@ -56,6 +71,9 @@ unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 {
 // CHECK-LABEL: literal_dyn_simd_insert
 // CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
     simd_insert_dyn(x, 7, e)
 }
@@ -63,6 +81,9 @@ unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
 // CHECK-LABEL: const_dyn_simd_insert
 // CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
     simd_insert_dyn(x, const { 3 + 4 }, e)
 }
@@ -70,6 +91,9 @@ unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 {
 // CHECK-LABEL: const_simd_insert
 // CHECK: insertelement <16 x i8> %x, i8 %e, i32 7
 #[no_mangle]
+#[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))]
+#[cfg_attr(target_arch = "x86", target_feature(enable = "sse"))]
 unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 {
     simd_insert(x, const { 3 + 4 }, e)
 }
diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff/autodiff_forward.pp
index 713b8f541ae..713b8f541ae 100644
--- a/tests/pretty/autodiff_forward.pp
+++ b/tests/pretty/autodiff/autodiff_forward.pp
diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff/autodiff_forward.rs
index 5a0660a08e5..5a0660a08e5 100644
--- a/tests/pretty/autodiff_forward.rs
+++ b/tests/pretty/autodiff/autodiff_forward.rs
diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff/autodiff_reverse.pp
index 31920694a3a..31920694a3a 100644
--- a/tests/pretty/autodiff_reverse.pp
+++ b/tests/pretty/autodiff/autodiff_reverse.pp
diff --git a/tests/pretty/autodiff_reverse.rs b/tests/pretty/autodiff/autodiff_reverse.rs
index 3c024272f40..3c024272f40 100644
--- a/tests/pretty/autodiff_reverse.rs
+++ b/tests/pretty/autodiff/autodiff_reverse.rs
diff --git a/tests/pretty/autodiff/inherent_impl.pp b/tests/pretty/autodiff/inherent_impl.pp
new file mode 100644
index 00000000000..97ac766b6b9
--- /dev/null
+++ b/tests/pretty/autodiff/inherent_impl.pp
@@ -0,0 +1,41 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ needs-enzyme
+
+#![feature(autodiff)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+//@ pretty-mode:expanded
+//@ pretty-compare-only
+//@ pp-exact:inherent_impl.pp
+
+use std::autodiff::autodiff;
+
+struct Foo {
+    a: f64,
+}
+
+trait MyTrait {
+    fn f(&self, x: f64)
+    -> f64;
+    fn df(&self, x: f64, seed: f64)
+    -> (f64, f64);
+}
+
+impl MyTrait for Foo {
+    #[rustc_autodiff]
+    #[inline(never)]
+    fn f(&self, x: f64) -> f64 {
+        self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln())
+    }
+    #[rustc_autodiff(Reverse, 1, Const, Active, Active)]
+    #[inline(never)]
+    fn df(&self, x: f64, dret: f64) -> (f64, f64) {
+        unsafe { asm!("NOP", options(pure, nomem)); };
+        ::core::hint::black_box(self.f(x));
+        ::core::hint::black_box((dret,));
+        ::core::hint::black_box((self.f(x), f64::default()))
+    }
+}
diff --git a/tests/pretty/autodiff/inherent_impl.rs b/tests/pretty/autodiff/inherent_impl.rs
new file mode 100644
index 00000000000..59de93f7e0f
--- /dev/null
+++ b/tests/pretty/autodiff/inherent_impl.rs
@@ -0,0 +1,24 @@
+//@ needs-enzyme
+
+#![feature(autodiff)]
+//@ pretty-mode:expanded
+//@ pretty-compare-only
+//@ pp-exact:inherent_impl.pp
+
+use std::autodiff::autodiff;
+
+struct Foo {
+    a: f64,
+}
+
+trait MyTrait {
+    fn f(&self, x: f64) -> f64;
+    fn df(&self, x: f64, seed: f64) -> (f64, f64);
+}
+
+impl MyTrait for Foo {
+    #[autodiff(df, Reverse, Const, Active, Active)]
+    fn f(&self, x: f64) -> f64 {
+        self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln())
+    }
+}
diff --git a/tests/run-make/simd-ffi/rmake.rs b/tests/run-make/simd-ffi/rmake.rs
index ef71dfa4c30..c6315073fa8 100644
--- a/tests/run-make/simd-ffi/rmake.rs
+++ b/tests/run-make/simd-ffi/rmake.rs
@@ -52,11 +52,20 @@ fn main() {
         // enabled by-default for i686 and ARM; these features will be invalid
         // on some platforms, but LLVM just prints a warning so that's fine for
         // now.
+        let target_feature = if target.starts_with("i686") || target.starts_with("x86") {
+            "+sse2"
+        } else if target.starts_with("arm") || target.starts_with("aarch64") {
+            "-soft-float,+neon"
+        } else if target.starts_with("mips") {
+            "+msa,+fp64"
+        } else {
+            panic!("missing target_feature case for {target}");
+        };
         rustc()
             .target(&target)
             .emit("llvm-ir,asm")
             .input("simd.rs")
-            .arg("-Ctarget-feature=-soft-float,+neon,+sse")
+            .arg(format!("-Ctarget-feature={target_feature}"))
             .arg(&format!("-Cextra-filename=-{target}"))
             .run();
     }
diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs
index ebf2e333f08..71edf813a7b 100644
--- a/tests/ui-fulldeps/stable-mir/check_abi.rs
+++ b/tests/ui-fulldeps/stable-mir/check_abi.rs
@@ -145,7 +145,7 @@ fn get_item<'a>(
 fn main() {
     let path = "alloc_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs
index ae2609bbc12..692c24f0544 100644
--- a/tests/ui-fulldeps/stable-mir/check_allocation.rs
+++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs
@@ -219,7 +219,7 @@ fn get_item<'a>(
 fn main() {
     let path = "alloc_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--edition=2021".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
index 9d611543b5a..755bec8747b 100644
--- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
+++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
@@ -85,7 +85,7 @@ fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) {
 fn main() {
     let path = "assoc_items.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs
index 4148fc0cb6a..81d5399d88a 100644
--- a/tests/ui-fulldeps/stable-mir/check_attribute.rs
+++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs
@@ -57,7 +57,7 @@ fn get_item<'a>(
 fn main() {
     let path = "attribute_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_binop.rs b/tests/ui-fulldeps/stable-mir/check_binop.rs
index 6a141e9c577..f9559d9958d 100644
--- a/tests/ui-fulldeps/stable-mir/check_binop.rs
+++ b/tests/ui-fulldeps/stable-mir/check_binop.rs
@@ -81,7 +81,7 @@ impl<'a> MirVisitor for Visitor<'a> {
 fn main() {
     let path = "binop_input.rs";
     generate_input(&path).unwrap();
-    let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
+    let args = &["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
     run!(args, test_binops).unwrap();
 }
 
diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
index 31c47192d09..6863242f225 100644
--- a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
+++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
@@ -84,7 +84,7 @@ fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) {
 fn main() {
     let path = "crate_definitions.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs
index 00a34f13867..f86a8e0ae61 100644
--- a/tests/ui-fulldeps/stable-mir/check_def_ty.rs
+++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs
@@ -76,7 +76,7 @@ fn check_fn_def(ty: Ty) {
 fn main() {
     let path = "defs_ty_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs
index 1ba73377d6e..ab741378bb7 100644
--- a/tests/ui-fulldeps/stable-mir/check_defs.rs
+++ b/tests/ui-fulldeps/stable-mir/check_defs.rs
@@ -112,7 +112,7 @@ fn get_instances(body: mir::Body) -> Vec<Instance> {
 fn main() {
     let path = "defs_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs
index 4419050ceb2..398024c4ff0 100644
--- a/tests/ui-fulldeps/stable-mir/check_foreign.rs
+++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs
@@ -58,7 +58,7 @@ fn test_foreign() -> ControlFlow<()> {
 fn main() {
     let path = "foreign_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-type=lib".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs
index 1510a622cdf..b19e5b033c4 100644
--- a/tests/ui-fulldeps/stable-mir/check_instance.rs
+++ b/tests/ui-fulldeps/stable-mir/check_instance.rs
@@ -87,7 +87,7 @@ fn test_body(body: mir::Body) {
 fn main() {
     let path = "instance_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-type=lib".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
index 3f04abbb9d7..52424857dc1 100644
--- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
+++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
@@ -115,7 +115,7 @@ impl<'a> MirVisitor for CallsVisitor<'a> {
 fn main() {
     let path = "binop_input.rs";
     generate_input(&path).unwrap();
-    let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
+    let args = &["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
     run!(args, test_intrinsics).unwrap();
 }
 
diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs
index bb8c00c64c9..d1124c75a89 100644
--- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs
+++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs
@@ -47,7 +47,7 @@ fn test_item_kind() -> ControlFlow<()> {
 fn main() {
     let path = "item_kind_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-type=lib".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_normalization.rs b/tests/ui-fulldeps/stable-mir/check_normalization.rs
index 797cb4cd5d0..16e8c0339ed 100644
--- a/tests/ui-fulldeps/stable-mir/check_normalization.rs
+++ b/tests/ui-fulldeps/stable-mir/check_normalization.rs
@@ -61,7 +61,7 @@ fn check_ty(ty: Ty) {
 fn main() {
     let path = "normalization_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-type=lib".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs
index d9170d0c408..fcf04a1fc3a 100644
--- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs
+++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs
@@ -72,7 +72,7 @@ fn assert_impl(impl_names: &HashSet<String>, target: &str) {
 fn main() {
     let path = "trait_queries.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs
index 604cc72c341..9087c1cf450 100644
--- a/tests/ui-fulldeps/stable-mir/check_transform.rs
+++ b/tests/ui-fulldeps/stable-mir/check_transform.rs
@@ -120,7 +120,7 @@ fn get_item<'a>(
 fn main() {
     let path = "transform_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
index 23233f8406c..18b9e32e4e8 100644
--- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
+++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs
@@ -78,7 +78,7 @@ impl<'a> MirVisitor for PlaceVisitor<'a> {
 fn main() {
     let path = "ty_fold_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs
index 39416636fd6..19b9c8b7de5 100644
--- a/tests/ui-fulldeps/stable-mir/compilation-result.rs
+++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs
@@ -25,40 +25,42 @@ use std::io::Write;
 fn main() {
     let path = "input_compilation_result_test.rs";
     generate_input(&path).unwrap();
-    let args = vec!["rustc".to_string(), path.to_string()];
-    test_continue(args.clone());
-    test_break(args.clone());
-    test_failed(args.clone());
-    test_skipped(args.clone());
+    let args = &["rustc".to_string(), path.to_string()];
+    test_continue(args);
+    test_break(args);
+    test_failed(args);
+    test_skipped(args);
     test_captured(args)
 }
 
-fn test_continue(args: Vec<String>) {
+fn test_continue(args: &[String]) {
     let result = run!(args, || ControlFlow::Continue::<(), bool>(true));
     assert_eq!(result, Ok(true));
 }
 
-fn test_break(args: Vec<String>) {
+fn test_break(args: &[String]) {
     let result = run!(args, || ControlFlow::Break::<bool, i32>(false));
     assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false)));
 }
 
 #[allow(unreachable_code)]
-fn test_skipped(mut args: Vec<String>) {
+fn test_skipped(args: &[String]) {
+    let mut args = args.to_vec();
     args.push("--version".to_string());
-    let result = run!(args, || unreachable!() as ControlFlow<()>);
+    let result = run!(&args, || unreachable!() as ControlFlow<()>);
     assert_eq!(result, Err(stable_mir::CompilerError::Skipped));
 }
 
 #[allow(unreachable_code)]
-fn test_failed(mut args: Vec<String>) {
+fn test_failed(args: &[String]) {
+    let mut args = args.to_vec();
     args.push("--cfg=broken".to_string());
-    let result = run!(args, || unreachable!() as ControlFlow<()>);
+    let result = run!(&args, || unreachable!() as ControlFlow<()>);
     assert_eq!(result, Err(stable_mir::CompilerError::Failed));
 }
 
 /// Test that we are able to pass a closure and set the return according to the captured value.
-fn test_captured(args: Vec<String>) {
+fn test_captured(args: &[String]) {
     let captured = "10".to_string();
     let result = run!(args, || ControlFlow::Continue::<(), usize>(captured.len()));
     assert_eq!(result, Ok(captured.len()));
diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs
index e2086d5e579..7fc4edafb93 100644
--- a/tests/ui-fulldeps/stable-mir/crate-info.rs
+++ b/tests/ui-fulldeps/stable-mir/crate-info.rs
@@ -186,7 +186,7 @@ fn get_item<'a>(
 fn main() {
     let path = "input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs
index f3bd894ac69..103c97bc48e 100644
--- a/tests/ui-fulldeps/stable-mir/projections.rs
+++ b/tests/ui-fulldeps/stable-mir/projections.rs
@@ -146,7 +146,7 @@ fn get_item<'a>(
 fn main() {
     let path = "input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-type=lib".to_string(),
         "--crate-name".to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs
index f9972dc27e3..0519b9de680 100644
--- a/tests/ui-fulldeps/stable-mir/smir_internal.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs
@@ -40,7 +40,7 @@ fn test_translation(tcx: TyCtxt<'_>) -> ControlFlow<()> {
 fn main() {
     let path = "internal_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-name".to_string(),
         CRATE_NAME.to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs
index 3b3d743ad32..0b39ec05002 100644
--- a/tests/ui-fulldeps/stable-mir/smir_serde.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs
@@ -46,7 +46,7 @@ fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
 fn main() {
     let path = "internal_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "--crate-name".to_string(),
         CRATE_NAME.to_string(),
diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
index d225d9773fe..caf71de2556 100644
--- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs
+++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs
@@ -183,14 +183,14 @@ impl mir::MutMirVisitor for TestMutVisitor {
 fn main() {
     let path = "sim_visitor_input.rs";
     generate_input(&path).unwrap();
-    let args = vec![
+    let args = &[
         "rustc".to_string(),
         "-Cpanic=abort".to_string(),
         "--crate-name".to_string(),
         CRATE_NAME.to_string(),
         path.to_string(),
     ];
-    run!(args.clone(), test_visitor).unwrap();
+    run!(args, test_visitor).unwrap();
     run!(args, test_mut_visitor).unwrap();
 }
 
diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs
index c31af6460fc..772512702ec 100644
--- a/tests/ui/abi/simd-abi-checks-avx.rs
+++ b/tests/ui/abi/simd-abi-checks-avx.rs
@@ -1,6 +1,5 @@
 //@ only-x86_64
-//@ build-pass
-//@ ignore-pass (test emits codegen-time warnings)
+//@ build-fail
 //@ compile-flags: -C target-feature=-avx
 
 #![feature(avx512_target_feature)]
@@ -14,20 +13,17 @@ use std::arch::x86_64::*;
 struct Wrapper(__m256);
 
 unsafe extern "C" fn w(_: Wrapper) {
-    //~^ WARN requires the `avx` target feature, which is not enabled
-    //~| WARNING this was previously accepted by the compiler
+    //~^ ERROR: requires the `avx` target feature, which is not enabled
     todo!()
 }
 
 unsafe extern "C" fn f(_: __m256) {
-    //~^ WARN requires the `avx` target feature, which is not enabled
-    //~| WARNING this was previously accepted by the compiler
+    //~^ ERROR: requires the `avx` target feature, which is not enabled
     todo!()
 }
 
 unsafe extern "C" fn g() -> __m256 {
-    //~^ WARN requires the `avx` target feature, which is not enabled
-    //~| WARNING this was previously accepted by the compiler
+    //~^ ERROR: requires the `avx` target feature, which is not enabled
     todo!()
 }
 
@@ -56,25 +52,20 @@ unsafe fn test() {
 unsafe fn in_closure() -> impl FnOnce() -> __m256 {
     #[inline(always)] // this disables target-feature inheritance
     || g()
-    //~^ WARNING requires the `avx` target feature, which is not enabled in the caller
-    //~| WARNING this was previously accepted by the compiler
+    //~^ ERROR requires the `avx` target feature, which is not enabled in the caller
 }
 
 fn main() {
     unsafe {
         f(g());
-        //~^ WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING this was previously accepted by the compiler
-        //~| WARNING this was previously accepted by the compiler
+        //~^ ERROR requires the `avx` target feature, which is not enabled in the caller
+        //~| ERROR requires the `avx` target feature, which is not enabled in the caller
     }
 
     unsafe {
         gavx(favx());
-        //~^ WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING this was previously accepted by the compiler
-        //~| WARNING this was previously accepted by the compiler
+        //~^ ERROR requires the `avx` target feature, which is not enabled in the caller
+        //~| ERROR requires the `avx` target feature, which is not enabled in the caller
     }
 
     unsafe {
@@ -83,10 +74,8 @@ fn main() {
 
     unsafe {
         w(Wrapper(g()));
-        //~^ WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING this was previously accepted by the compiler
-        //~| WARNING this was previously accepted by the compiler
+        //~^ ERROR requires the `avx` target feature, which is not enabled in the caller
+        //~| ERROR requires the `avx` target feature, which is not enabled in the caller
     }
 
     unsafe {
@@ -99,8 +88,7 @@ fn main() {
             fn some_extern() -> __m256;
         }
         some_extern();
-        //~^ WARNING requires the `avx` target feature, which is not enabled in the caller
-        //~| WARNING this was previously accepted by the compiler
+        //~^ ERROR requires the `avx` target feature, which is not enabled in the caller
     }
 }
 
diff --git a/tests/ui/abi/simd-abi-checks-avx.stderr b/tests/ui/abi/simd-abi-checks-avx.stderr
index 5419970f809..48db30bf453 100644
--- a/tests/ui/abi/simd-abi-checks-avx.stderr
+++ b/tests/ui/abi/simd-abi-checks-avx.stderr
@@ -1,245 +1,96 @@
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:65:11
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:60:11
    |
 LL |         f(g());
    |           ^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
 
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:65:9
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:60:9
    |
 LL |         f(g());
    |         ^^^^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:73:14
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:66:14
    |
 LL |         gavx(favx());
    |              ^^^^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:73:9
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:66:9
    |
 LL |         gavx(favx());
    |         ^^^^^^^^^^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:85:19
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:76:19
    |
 LL |         w(Wrapper(g()));
    |                   ^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:85:9
+error: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:76:9
    |
 LL |         w(Wrapper(g()));
    |         ^^^^^^^^^^^^^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:101:9
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:90:9
    |
 LL |         some_extern();
    |         ^^^^^^^^^^^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:28:1
+error: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
+  --> $DIR/simd-abi-checks-avx.rs:25:1
    |
 LL | unsafe extern "C" fn g() -> __m256 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:22:1
+error: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
+  --> $DIR/simd-abi-checks-avx.rs:20:1
    |
 LL | unsafe extern "C" fn f(_: __m256) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:16:1
+error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
+  --> $DIR/simd-abi-checks-avx.rs:15:1
    |
 LL | unsafe extern "C" fn w(_: Wrapper) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:58:8
+error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+  --> $DIR/simd-abi-checks-avx.rs:54:8
    |
 LL |     || g()
    |        ^^^ function called here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
-warning: 11 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:65:11
-   |
-LL |         f(g());
-   |           ^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:65:9
-   |
-LL |         f(g());
-   |         ^^^^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:73:14
-   |
-LL |         gavx(favx());
-   |              ^^^^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:73:9
-   |
-LL |         gavx(favx());
-   |         ^^^^^^^^^^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:85:19
-   |
-LL |         w(Wrapper(g()));
-   |                   ^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:85:9
-   |
-LL |         w(Wrapper(g()));
-   |         ^^^^^^^^^^^^^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:101:9
-   |
-LL |         some_extern();
-   |         ^^^^^^^^^^^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:28:1
-   |
-LL | unsafe extern "C" fn g() -> __m256 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:22:1
-   |
-LL | unsafe extern "C" fn f(_: __m256) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-Future breakage diagnostic:
-warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:16:1
-   |
-LL | unsafe extern "C" fn w(_: Wrapper) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
+note: the above error was encountered while instantiating `fn in_closure::{closure#0}`
+  --> $DIR/simd-abi-checks-avx.rs:82:9
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
+LL |         in_closure()();
+   |         ^^^^^^^^^^^^^^
 
-Future breakage diagnostic:
-warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:58:8
-   |
-LL |     || g()
-   |        ^^^ function called here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/abi/simd-abi-checks-empty-list.rs b/tests/ui/abi/simd-abi-checks-empty-list.rs
index ba1b38af5b3..d00445b29e0 100644
--- a/tests/ui/abi/simd-abi-checks-empty-list.rs
+++ b/tests/ui/abi/simd-abi-checks-empty-list.rs
@@ -1,8 +1,9 @@
+//! At the time of writing, the list of "which target feature enables which vector size" is empty
+//! for SPARC. Ensure that this leads to all vector sizes causing an error.
 //@ add-core-stubs
 //@ needs-llvm-components: sparc
 //@ compile-flags: --target=sparc-unknown-none-elf --crate-type=rlib
-//@ build-pass
-//@ ignore-pass (test emits codegen-time warnings)
+//@ build-fail
 #![no_core]
 #![feature(no_core, repr_simd)]
 #![allow(improper_ctypes_definitions)]
@@ -14,5 +15,4 @@ use minicore::*;
 pub struct SimdVec([i32; 4]);
 
 pub extern "C" fn pass_by_vec(_: SimdVec) {}
-//~^ WARN this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI
diff --git a/tests/ui/abi/simd-abi-checks-empty-list.stderr b/tests/ui/abi/simd-abi-checks-empty-list.stderr
index 111dda42f33..780afb3844f 100644
--- a/tests/ui/abi/simd-abi-checks-empty-list.stderr
+++ b/tests/ui/abi/simd-abi-checks-empty-list.stderr
@@ -1,23 +1,8 @@
-warning: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI
-  --> $DIR/simd-abi-checks-empty-list.rs:16:1
+error: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI
+  --> $DIR/simd-abi-checks-empty-list.rs:17:1
    |
 LL | pub extern "C" fn pass_by_vec(_: SimdVec) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
-
-warning: 1 warning emitted
 
-Future incompatibility report: Future breakage diagnostic:
-warning: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI
-  --> $DIR/simd-abi-checks-empty-list.rs:16:1
-   |
-LL | pub extern "C" fn pass_by_vec(_: SimdVec) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs
index 3743c75bf1e..2d4eb7a350f 100644
--- a/tests/ui/abi/simd-abi-checks-s390x.rs
+++ b/tests/ui/abi/simd-abi-checks-s390x.rs
@@ -13,7 +13,6 @@
 #![no_core]
 #![crate_type = "lib"]
 #![allow(non_camel_case_types, improper_ctypes_definitions)]
-#![deny(abi_unsupported_vector_types)]
 
 extern crate minicore;
 use minicore::*;
@@ -38,13 +37,11 @@ impl<T: Copy> Copy for TransparentWrapper<T> {}
 #[no_mangle]
 extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     *x
 }
 #[no_mangle]
 extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     *x
 }
 #[no_mangle]
@@ -93,7 +90,6 @@ extern "C" fn vector_transparent_wrapper_ret_small(
     x: &TransparentWrapper<i8x8>,
 ) -> TransparentWrapper<i8x8> {
     //~^^^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^^^ WARN this was previously accepted
     *x
 }
 #[no_mangle]
@@ -101,7 +97,6 @@ extern "C" fn vector_transparent_wrapper_ret(
     x: &TransparentWrapper<i8x16>,
 ) -> TransparentWrapper<i8x16> {
     //~^^^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^^^ WARN this was previously accepted
     *x
 }
 #[no_mangle]
@@ -115,13 +110,11 @@ extern "C" fn vector_transparent_wrapper_ret_large(
 #[no_mangle]
 extern "C" fn vector_arg_small(x: i8x8) -> i64 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     unsafe { *(&x as *const i8x8 as *const i64) }
 }
 #[no_mangle]
 extern "C" fn vector_arg(x: i8x16) -> i64 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     unsafe { *(&x as *const i8x16 as *const i64) }
 }
 #[no_mangle]
@@ -133,13 +126,11 @@ extern "C" fn vector_arg_large(x: i8x32) -> i64 {
 #[no_mangle]
 extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     unsafe { *(&x as *const Wrapper<i8x8> as *const i64) }
 }
 #[no_mangle]
 extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     unsafe { *(&x as *const Wrapper<i8x16> as *const i64) }
 }
 #[no_mangle]
@@ -151,13 +142,11 @@ extern "C" fn vector_wrapper_arg_large(x: Wrapper<i8x32>) -> i64 {
 #[no_mangle]
 extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     unsafe { *(&x as *const TransparentWrapper<i8x8> as *const i64) }
 }
 #[no_mangle]
 extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
     //~^ ERROR requires the `vector` target feature, which is not enabled
-    //~^^ WARN this was previously accepted
     unsafe { *(&x as *const TransparentWrapper<i8x16> as *const i64) }
 }
 #[no_mangle]
diff --git a/tests/ui/abi/simd-abi-checks-s390x.z10.stderr b/tests/ui/abi/simd-abi-checks-s390x.z10.stderr
index d2f7abb7c32..c1c4e90f3cf 100644
--- a/tests/ui/abi/simd-abi-checks-s390x.z10.stderr
+++ b/tests/ui/abi/simd-abi-checks-s390x.z10.stderr
@@ -1,275 +1,86 @@
 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:39:1
+  --> $DIR/simd-abi-checks-s390x.rs:38:1
    |
 LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:45:1
+  --> $DIR/simd-abi-checks-s390x.rs:43:1
    |
 LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:92:1
+  --> $DIR/simd-abi-checks-s390x.rs:89:1
    |
 LL | / extern "C" fn vector_transparent_wrapper_ret_small(
 LL | |     x: &TransparentWrapper<i8x8>,
 LL | | ) -> TransparentWrapper<i8x8> {
    | |_____________________________^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:100:1
+  --> $DIR/simd-abi-checks-s390x.rs:96:1
    |
 LL | / extern "C" fn vector_transparent_wrapper_ret(
 LL | |     x: &TransparentWrapper<i8x16>,
 LL | | ) -> TransparentWrapper<i8x16> {
    | |______________________________^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:116:1
+  --> $DIR/simd-abi-checks-s390x.rs:111:1
    |
 LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:122:1
+  --> $DIR/simd-abi-checks-s390x.rs:116:1
    |
 LL | extern "C" fn vector_arg(x: i8x16) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `Wrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:134:1
+  --> $DIR/simd-abi-checks-s390x.rs:127:1
    |
 LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `Wrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:140:1
+  --> $DIR/simd-abi-checks-s390x.rs:132:1
    |
 LL | extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:152:1
+  --> $DIR/simd-abi-checks-s390x.rs:143:1
    |
 LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:158:1
+  --> $DIR/simd-abi-checks-s390x.rs:148:1
    |
 LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: aborting due to 10 previous errors
 
-Future incompatibility report: Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:39:1
-   |
-LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:45:1
-   |
-LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:92:1
-   |
-LL | / extern "C" fn vector_transparent_wrapper_ret_small(
-LL | |     x: &TransparentWrapper<i8x8>,
-LL | | ) -> TransparentWrapper<i8x8> {
-   | |_____________________________^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:100:1
-   |
-LL | / extern "C" fn vector_transparent_wrapper_ret(
-LL | |     x: &TransparentWrapper<i8x16>,
-LL | | ) -> TransparentWrapper<i8x16> {
-   | |______________________________^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:116:1
-   |
-LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:122:1
-   |
-LL | extern "C" fn vector_arg(x: i8x16) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `Wrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:134:1
-   |
-LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `Wrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:140:1
-   |
-LL | extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:152:1
-   |
-LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:158:1
-   |
-LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr
index d2f7abb7c32..c1c4e90f3cf 100644
--- a/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr
+++ b/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr
@@ -1,275 +1,86 @@
 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:39:1
+  --> $DIR/simd-abi-checks-s390x.rs:38:1
    |
 LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:45:1
+  --> $DIR/simd-abi-checks-s390x.rs:43:1
    |
 LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:92:1
+  --> $DIR/simd-abi-checks-s390x.rs:89:1
    |
 LL | / extern "C" fn vector_transparent_wrapper_ret_small(
 LL | |     x: &TransparentWrapper<i8x8>,
 LL | | ) -> TransparentWrapper<i8x8> {
    | |_____________________________^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:100:1
+  --> $DIR/simd-abi-checks-s390x.rs:96:1
    |
 LL | / extern "C" fn vector_transparent_wrapper_ret(
 LL | |     x: &TransparentWrapper<i8x16>,
 LL | | ) -> TransparentWrapper<i8x16> {
    | |______________________________^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:116:1
+  --> $DIR/simd-abi-checks-s390x.rs:111:1
    |
 LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:122:1
+  --> $DIR/simd-abi-checks-s390x.rs:116:1
    |
 LL | extern "C" fn vector_arg(x: i8x16) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `Wrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:134:1
+  --> $DIR/simd-abi-checks-s390x.rs:127:1
    |
 LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `Wrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:140:1
+  --> $DIR/simd-abi-checks-s390x.rs:132:1
    |
 LL | extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:152:1
+  --> $DIR/simd-abi-checks-s390x.rs:143:1
    |
 LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:158:1
+  --> $DIR/simd-abi-checks-s390x.rs:148:1
    |
 LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: aborting due to 10 previous errors
 
-Future incompatibility report: Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:39:1
-   |
-LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:45:1
-   |
-LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:92:1
-   |
-LL | / extern "C" fn vector_transparent_wrapper_ret_small(
-LL | |     x: &TransparentWrapper<i8x8>,
-LL | | ) -> TransparentWrapper<i8x8> {
-   | |_____________________________^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:100:1
-   |
-LL | / extern "C" fn vector_transparent_wrapper_ret(
-LL | |     x: &TransparentWrapper<i8x16>,
-LL | | ) -> TransparentWrapper<i8x16> {
-   | |______________________________^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:116:1
-   |
-LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:122:1
-   |
-LL | extern "C" fn vector_arg(x: i8x16) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `Wrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:134:1
-   |
-LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `Wrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:140:1
-   |
-LL | extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:152:1
-   |
-LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:158:1
-   |
-LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr
index d2f7abb7c32..c1c4e90f3cf 100644
--- a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr
+++ b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr
@@ -1,275 +1,86 @@
 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:39:1
+  --> $DIR/simd-abi-checks-s390x.rs:38:1
    |
 LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:45:1
+  --> $DIR/simd-abi-checks-s390x.rs:43:1
    |
 LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:92:1
+  --> $DIR/simd-abi-checks-s390x.rs:89:1
    |
 LL | / extern "C" fn vector_transparent_wrapper_ret_small(
 LL | |     x: &TransparentWrapper<i8x8>,
 LL | | ) -> TransparentWrapper<i8x8> {
    | |_____________________________^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:100:1
+  --> $DIR/simd-abi-checks-s390x.rs:96:1
    |
 LL | / extern "C" fn vector_transparent_wrapper_ret(
 LL | |     x: &TransparentWrapper<i8x16>,
 LL | | ) -> TransparentWrapper<i8x16> {
    | |______________________________^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:116:1
+  --> $DIR/simd-abi-checks-s390x.rs:111:1
    |
 LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:122:1
+  --> $DIR/simd-abi-checks-s390x.rs:116:1
    |
 LL | extern "C" fn vector_arg(x: i8x16) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `Wrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:134:1
+  --> $DIR/simd-abi-checks-s390x.rs:127:1
    |
 LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `Wrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:140:1
+  --> $DIR/simd-abi-checks-s390x.rs:132:1
    |
 LL | extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:152:1
+  --> $DIR/simd-abi-checks-s390x.rs:143:1
    |
 LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:158:1
+  --> $DIR/simd-abi-checks-s390x.rs:148:1
    |
 LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
 
 error: aborting due to 10 previous errors
 
-Future incompatibility report: Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:39:1
-   |
-LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:45:1
-   |
-LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:92:1
-   |
-LL | / extern "C" fn vector_transparent_wrapper_ret_small(
-LL | |     x: &TransparentWrapper<i8x8>,
-LL | | ) -> TransparentWrapper<i8x8> {
-   | |_____________________________^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:100:1
-   |
-LL | / extern "C" fn vector_transparent_wrapper_ret(
-LL | |     x: &TransparentWrapper<i8x16>,
-LL | | ) -> TransparentWrapper<i8x16> {
-   | |______________________________^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:116:1
-   |
-LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:122:1
-   |
-LL | extern "C" fn vector_arg(x: i8x16) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `Wrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:134:1
-   |
-LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `Wrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:140:1
-   |
-LL | extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x8>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:152:1
-   |
-LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-error: this function definition uses SIMD vector type `TransparentWrapper<i8x16>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-s390x.rs:158:1
-   |
-LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`)
-note: the lint level is defined here
-  --> $DIR/simd-abi-checks-s390x.rs:16:9
-   |
-LL | #![deny(abi_unsupported_vector_types)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
diff --git a/tests/ui/abi/simd-abi-checks-sse.rs b/tests/ui/abi/simd-abi-checks-sse.rs
index d5fa9c0c0a3..817f9b6d13b 100644
--- a/tests/ui/abi/simd-abi-checks-sse.rs
+++ b/tests/ui/abi/simd-abi-checks-sse.rs
@@ -3,8 +3,7 @@
 //@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu
 //@ compile-flags: -Ctarget-cpu=pentium4 -C target-feature=-sse,-sse2
 //@ add-core-stubs
-//@ build-pass
-//@ ignore-pass (test emits codegen-time warnings)
+//@ build-fail
 //@ needs-llvm-components: x86
 #![feature(no_core, repr_simd)]
 #![no_core]
@@ -18,6 +17,5 @@ pub struct SseVector([i64; 2]);
 
 #[no_mangle]
 pub unsafe extern "C" fn f(_: SseVector) {
-    //~^ WARN this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
-    //~| WARNING this was previously accepted by the compiler
+    //~^ ERROR: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
 }
diff --git a/tests/ui/abi/simd-abi-checks-sse.stderr b/tests/ui/abi/simd-abi-checks-sse.stderr
index c0f2e6e1e1b..a5a2ba808c6 100644
--- a/tests/ui/abi/simd-abi-checks-sse.stderr
+++ b/tests/ui/abi/simd-abi-checks-sse.stderr
@@ -1,25 +1,10 @@
-warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-sse.rs:20:1
+error: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
+  --> $DIR/simd-abi-checks-sse.rs:19:1
    |
 LL | pub unsafe extern "C" fn f(_: SseVector) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
    |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
    = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
 
-warning: 1 warning emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-sse.rs:20:1
-   |
-LL | pub unsafe extern "C" fn f(_: SseVector) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
-   |
-   = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
-   = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`)
-   = note: `#[warn(abi_unsupported_vector_types)]` on by default
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/async-closures/is-not-fn.next.stderr b/tests/ui/async-await/async-closures/is-not-fn.next.stderr
index 0fab1c15f27..970970a9151 100644
--- a/tests/ui/async-await/async-closures/is-not-fn.next.stderr
+++ b/tests/ui/async-await/async-closures/is-not-fn.next.stderr
@@ -1,13 +1,11 @@
-error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to return `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
+error[E0271]: type mismatch resolving `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25} == ()`
   --> $DIR/is-not-fn.rs:8:14
    |
 LL |     needs_fn(async || {});
-   |     -------- ^^^^^^^^^^^ expected `()`, found `async` closure body
+   |     -------- ^^^^^^^^^^^ types differ
    |     |
    |     required by a bound introduced by this call
    |
-   = note:         expected unit type `()`
-           found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
 note: required by a bound in `needs_fn`
   --> $DIR/is-not-fn.rs:7:25
    |
diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs
index e5ab4742dab..c09ccb3fc2b 100644
--- a/tests/ui/async-await/async-closures/is-not-fn.rs
+++ b/tests/ui/async-await/async-closures/is-not-fn.rs
@@ -6,5 +6,6 @@
 fn main() {
     fn needs_fn(x: impl FnOnce()) {}
     needs_fn(async || {});
-    //~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to return `()`
+    //[current]~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to return `()`
+    //[next]~^^ ERROR type mismatch resolving `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25} == ()`
 }
diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs
index 9187de56362..20f1a9aae70 100644
--- a/tests/ui/consts/const-eval/raw-bytes.rs
+++ b/tests/ui/consts/const-eval/raw-bytes.rs
@@ -2,7 +2,7 @@
 //@ ignore-endian-big
 // ignore-tidy-linelength
 //@ normalize-stderr: "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼" -> "╾ALLOC_ID$1╼"
-#![allow(invalid_value)]
+#![allow(invalid_value, unnecessary_transmutes)]
 #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)]
 
 use std::mem;
diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.rs b/tests/ui/consts/const-eval/transmute-const-promotion.rs
index 1f0240d4b5a..840334f43c0 100644
--- a/tests/ui/consts/const-eval/transmute-const-promotion.rs
+++ b/tests/ui/consts/const-eval/transmute-const-promotion.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 use std::mem;
 
 fn main() {
diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.stderr b/tests/ui/consts/const-eval/transmute-const-promotion.stderr
index 3603db03bb2..eb2fed091c3 100644
--- a/tests/ui/consts/const-eval/transmute-const-promotion.stderr
+++ b/tests/ui/consts/const-eval/transmute-const-promotion.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/transmute-const-promotion.rs:4:37
+  --> $DIR/transmute-const-promotion.rs:5:37
    |
 LL |     let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
    |            ------------             ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
diff --git a/tests/ui/consts/const-eval/transmute-const.rs b/tests/ui/consts/const-eval/transmute-const.rs
index 1cfad00ca76..fb6cb77675f 100644
--- a/tests/ui/consts/const-eval/transmute-const.rs
+++ b/tests/ui/consts/const-eval/transmute-const.rs
@@ -1,3 +1,4 @@
+#![allow(unnecessary_transmutes)]
 use std::mem;
 
 static FOO: bool = unsafe { mem::transmute(3u8) };
diff --git a/tests/ui/consts/const-eval/transmute-const.stderr b/tests/ui/consts/const-eval/transmute-const.stderr
index d72289487d7..35a5cabaa67 100644
--- a/tests/ui/consts/const-eval/transmute-const.stderr
+++ b/tests/ui/consts/const-eval/transmute-const.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/transmute-const.rs:3:1
+  --> $DIR/transmute-const.rs:4:1
    |
 LL | static FOO: bool = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
diff --git a/tests/ui/consts/const-eval/ub-enum.rs b/tests/ui/consts/const-eval/ub-enum.rs
index 5be444e667a..a5255ef95aa 100644
--- a/tests/ui/consts/const-eval/ub-enum.rs
+++ b/tests/ui/consts/const-eval/ub-enum.rs
@@ -3,7 +3,7 @@
 //@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
 //@ normalize-stderr: "0x0+" -> "0x0"
 #![feature(never_type)]
-#![allow(invalid_value)]
+#![allow(invalid_value, unnecessary_transmutes)]
 
 use std::mem;
 
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs
index a071a44272b..4e2defc1a09 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-linelength
-#![allow(unused)]
+#![allow(unused, unnecessary_transmutes)]
 #![feature(ptr_metadata)]
 
 use std::{ptr, mem};
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
index 481f2ff88df..c3bd8301d5c 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
@@ -2,6 +2,7 @@
 //@ [no_flag] check-pass
 //@ [with_flag] compile-flags: -Zextra-const-ub-checks
 #![feature(never_type)]
+#![allow(unnecessary_transmutes)]
 
 use std::mem::transmute;
 use std::ptr::addr_of;
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 0100aafb6b7..ea3b0e70b82 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:29:20
+  --> $DIR/detect-extra-ub.rs:30:20
    |
 LL |     let _x: bool = transmute(3u8);
    |                    ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:35:21
+  --> $DIR/detect-extra-ub.rs:36:21
    |
 LL |     let _x: usize = transmute(&3u8);
    |                     ^^^^^^^^^^^^^^^ constructing invalid value: encountered a pointer, but expected an integer
@@ -14,7 +14,7 @@ LL |     let _x: usize = transmute(&3u8);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:41:28
+  --> $DIR/detect-extra-ub.rs:42:28
    |
 LL |     let _x: PtrSizedEnum = transmute(&3u8);
    |                            ^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
@@ -23,7 +23,7 @@ LL |     let _x: PtrSizedEnum = transmute(&3u8);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:48:30
+  --> $DIR/detect-extra-ub.rs:49:30
    |
 LL |     let _x: (usize, usize) = transmute(x);
    |                              ^^^^^^^^^^^^ constructing invalid value at .0: encountered a pointer, but expected an integer
@@ -32,19 +32,19 @@ LL |     let _x: (usize, usize) = transmute(x);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:54:20
+  --> $DIR/detect-extra-ub.rs:55:20
    |
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:62:13
+  --> $DIR/detect-extra-ub.rs:63:13
    |
 LL |     let v = *addr_of!(data).cast::<UninhDiscriminant>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:82:16
+  --> $DIR/detect-extra-ub.rs:83:16
    |
 LL |     let _val = *(&mem as *const Align as *const [*const u8; 2]);
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a partial pointer or a mix of pointers
@@ -53,7 +53,7 @@ LL |     let _val = *(&mem as *const Align as *const [*const u8; 2]);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:97:16
+  --> $DIR/detect-extra-ub.rs:98:16
    |
 LL |     let _val = &*slice;
    |                ^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
diff --git a/tests/ui/consts/issue-69532.rs b/tests/ui/consts/issue-69532.rs
index 285cfe7213b..43ab1d6cca7 100644
--- a/tests/ui/consts/issue-69532.rs
+++ b/tests/ui/consts/issue-69532.rs
@@ -1,8 +1,8 @@
 //@ run-pass
 
 const fn make_nans() -> (f64, f64, f32, f32) {
-    let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) };
-    let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) };
+    let nan1 = f64::from_bits(0x7FF0_0001_0000_0001);
+    let nan2 = f64::from_bits(0x7FF0_0000_0000_0001);
 
     let nan1_32 = nan1 as f32;
     let nan2_32 = nan2 as f32;
diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr
deleted file mode 100644
index 213e9e908f5..00000000000
--- a/tests/ui/coroutine/clone-rpit.next.stderr
+++ /dev/null
@@ -1,47 +0,0 @@
-error[E0391]: cycle detected when type-checking `foo`
-  --> $DIR/clone-rpit.rs:13:1
-   |
-LL | pub fn foo<'a, 'b>() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires coroutine witness types for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:15:5
-   |
-LL |     move |_: ()| {
-   |     ^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:15:5
-   |
-LL |     move |_: ()| {
-   |     ^^^^^^^^^^^^
-note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
-  --> $DIR/clone-rpit.rs:15:5
-   |
-LL |     move |_: ()| {
-   |     ^^^^^^^^^^^^
-note: ...which requires building MIR for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:15:5
-   |
-LL |     move |_: ()| {
-   |     ^^^^^^^^^^^^
-note: ...which requires match-checking `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:15:5
-   |
-LL |     move |_: ()| {
-   |     ^^^^^^^^^^^^
-note: ...which requires type-checking `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:15:5
-   |
-LL |     move |_: ()| {
-   |     ^^^^^^^^^^^^
-   = note: ...which again requires type-checking `foo`, completing the cycle
-note: cycle used when match-checking `foo`
-  --> $DIR/clone-rpit.rs:13:1
-   |
-LL | pub fn foo<'a, 'b>() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = 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 1 previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/coroutine/clone-rpit.rs b/tests/ui/coroutine/clone-rpit.rs
index 66569b4f427..3882564639b 100644
--- a/tests/ui/coroutine/clone-rpit.rs
+++ b/tests/ui/coroutine/clone-rpit.rs
@@ -1,8 +1,7 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
-//@[current] check-pass
-//@[next] known-bug: trait-system-refactor-initiative#82
+//@ check-pass
 
 #![feature(coroutines, coroutine_trait, coroutine_clone)]
 
diff --git a/tests/ui/generics/single-colon-path-not-const-generics.stderr b/tests/ui/generics/single-colon-path-not-const-generics.stderr
index 9eb62de2756..163ea4bbda6 100644
--- a/tests/ui/generics/single-colon-path-not-const-generics.stderr
+++ b/tests/ui/generics/single-colon-path-not-const-generics.stderr
@@ -1,13 +1,15 @@
 error: path separator must be a double colon
   --> $DIR/single-colon-path-not-const-generics.rs:8:18
    |
+LL | pub struct Foo {
+   |            --- while parsing this struct
 LL |   a: Vec<foo::bar:A>,
    |                  ^
    |
 help: use a double colon instead
    |
 LL |   a: Vec<foo::bar::A>,
-   |                   +
+   |                  +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-25746-bool-transmute.rs b/tests/ui/issues/issue-25746-bool-transmute.rs
index f8cdc980daa..046dcf83f62 100644
--- a/tests/ui/issues/issue-25746-bool-transmute.rs
+++ b/tests/ui/issues/issue-25746-bool-transmute.rs
@@ -1,4 +1,5 @@
 //@ run-pass
+#![allow(unnecessary_transmutes)]
 use std::mem::transmute;
 
 fn main() {
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
index 7948f0d86d0..f40f06a0d36 100644
--- a/tests/ui/lint/invalid_null_args.rs
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -1,19 +1,19 @@
 // check-fail
 // run-rustfix
+#![allow(unnecessary_transmutes)]
 
-use std::ptr;
-use std::mem;
+use std::{mem, ptr};
 
 unsafe fn null_ptr() {
     ptr::write(
-    //~^ ERROR calling this function with a null pointer is undefined behavior
+        //~^ ERROR calling this function with a null pointer is undefined behavior
         ptr::null_mut() as *mut u32,
         mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
     );
 
     let null_ptr = ptr::null_mut();
     ptr::write(
-    //~^ ERROR calling this function with a null pointer is undefined behavior
+        //~^ ERROR calling this function with a null pointer is undefined behavior
         null_ptr as *mut u32,
         mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
     );
@@ -38,10 +38,10 @@ unsafe fn null_ptr() {
     ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
     //~^ ERROR calling this function with a null pointer is undefined behavior
     ptr::copy_nonoverlapping::<usize>(
-    //~^ ERROR calling this function with a null pointer is undefined behavior
+        //~^ ERROR calling this function with a null pointer is undefined behavior
         ptr::NonNull::dangling().as_ptr(),
         ptr::null_mut(),
-        0
+        0,
     );
 
     #[derive(Copy, Clone)]
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
index f95bc2afa82..11c6270cfb7 100644
--- a/tests/ui/lint/invalid_null_args.stderr
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -117,7 +117,7 @@ LL | |
 LL | |         ptr::NonNull::dangling().as_ptr(),
 LL | |         ptr::null_mut(),
    | |         --------------- null pointer originates from here
-LL | |         0
+LL | |         0,
 LL | |     );
    | |_____^
    |
diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs
index 0d19d5b5347..b2ef27b833b 100644
--- a/tests/ui/lint/lint-ctypes-enum.rs
+++ b/tests/ui/lint/lint-ctypes-enum.rs
@@ -2,6 +2,8 @@
 #![deny(improper_ctypes)]
 #![feature(ptr_internals)]
 #![feature(transparent_unions)]
+#![feature(repr128)]
+#![allow(incomplete_features)]
 
 use std::num;
 
@@ -40,6 +42,20 @@ enum Isize {
     C,
 }
 
+#[repr(u128)]
+enum U128 {
+    A,
+    B,
+    C,
+}
+
+#[repr(i128)]
+enum I128 {
+    A,
+    B,
+    C,
+}
+
 #[repr(transparent)]
 struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
 
@@ -71,6 +87,8 @@ extern "C" {
     fn repr_c(x: ReprC);
     fn repr_u8(x: U8);
     fn repr_isize(x: Isize);
+    fn repr_u128(x: U128); //~ ERROR `extern` block uses type `U128`
+    fn repr_i128(x: I128); //~ ERROR `extern` block uses type `I128`
     fn option_ref(x: Option<&'static u8>);
     fn option_fn(x: Option<extern "C" fn()>);
     fn option_nonnull(x: Option<std::ptr::NonNull<u8>>);
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index a491bd19605..d5fc844f756 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `U`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:68:14
+  --> $DIR/lint-ctypes-enum.rs:84:14
    |
 LL |     fn uf(x: U);
    |              ^ not FFI-safe
@@ -7,7 +7,7 @@ LL |     fn uf(x: U);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:9:1
+  --> $DIR/lint-ctypes-enum.rs:11:1
    |
 LL | enum U {
    | ^^^^^^
@@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `B`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:69:14
+  --> $DIR/lint-ctypes-enum.rs:85:14
    |
 LL |     fn bf(x: B);
    |              ^ not FFI-safe
@@ -26,13 +26,13 @@ LL |     fn bf(x: B);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:12:1
+  --> $DIR/lint-ctypes-enum.rs:14:1
    |
 LL | enum B {
    | ^^^^^^
 
 error: `extern` block uses type `T`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:70:14
+  --> $DIR/lint-ctypes-enum.rs:86:14
    |
 LL |     fn tf(x: T);
    |              ^ not FFI-safe
@@ -40,13 +40,39 @@ LL |     fn tf(x: T);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:16:1
+  --> $DIR/lint-ctypes-enum.rs:18:1
    |
 LL | enum T {
    | ^^^^^^
 
+error: `extern` block uses type `U128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:90:21
+   |
+LL |     fn repr_u128(x: U128);
+   |                     ^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+note: the type is defined here
+  --> $DIR/lint-ctypes-enum.rs:46:1
+   |
+LL | enum U128 {
+   | ^^^^^^^^^
+
+error: `extern` block uses type `I128`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:91:21
+   |
+LL |     fn repr_i128(x: I128);
+   |                     ^^^^ not FFI-safe
+   |
+   = note: 128-bit integers don't currently have a known stable ABI
+note: the type is defined here
+  --> $DIR/lint-ctypes-enum.rs:53:1
+   |
+LL | enum I128 {
+   | ^^^^^^^^^
+
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:82:31
+  --> $DIR/lint-ctypes-enum.rs:100:31
    |
 LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -54,7 +80,7 @@ LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:89:31
+  --> $DIR/lint-ctypes-enum.rs:107:31
    |
 LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -62,7 +88,7 @@ LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:94:36
+  --> $DIR/lint-ctypes-enum.rs:112:36
    |
 LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -71,7 +97,7 @@ LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:96:28
+  --> $DIR/lint-ctypes-enum.rs:114:28
    |
 LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -80,7 +106,7 @@ LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<u8>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:97:21
+  --> $DIR/lint-ctypes-enum.rs:115:21
    |
 LL |     fn option_u8(x: Option<u8>);
    |                     ^^^^^^^^^^ not FFI-safe
@@ -89,7 +115,7 @@ LL |     fn option_u8(x: Option<u8>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:107:33
+  --> $DIR/lint-ctypes-enum.rs:125:33
    |
 LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -97,7 +123,7 @@ LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:114:33
+  --> $DIR/lint-ctypes-enum.rs:132:33
    |
 LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -105,7 +131,7 @@ LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:119:38
+  --> $DIR/lint-ctypes-enum.rs:137:38
    |
 LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -114,7 +140,7 @@ LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:121:30
+  --> $DIR/lint-ctypes-enum.rs:139:30
    |
 LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -123,7 +149,7 @@ LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:125:51
+  --> $DIR/lint-ctypes-enum.rs:143:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -132,7 +158,7 @@ LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:127:53
+  --> $DIR/lint-ctypes-enum.rs:145:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -141,7 +167,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:129:51
+  --> $DIR/lint-ctypes-enum.rs:147:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -150,7 +176,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:132:49
+  --> $DIR/lint-ctypes-enum.rs:150:49
    |
 LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -159,7 +185,7 @@ LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:134:30
+  --> $DIR/lint-ctypes-enum.rs:152:30
    |
 LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -168,7 +194,7 @@ LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:145:33
+  --> $DIR/lint-ctypes-enum.rs:163:33
    |
 LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -176,7 +202,7 @@ LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:152:33
+  --> $DIR/lint-ctypes-enum.rs:170:33
    |
 LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -184,7 +210,7 @@ LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:157:38
+  --> $DIR/lint-ctypes-enum.rs:175:38
    |
 LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -193,7 +219,7 @@ LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:159:30
+  --> $DIR/lint-ctypes-enum.rs:177:30
    |
 LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -202,7 +228,7 @@ LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:163:51
+  --> $DIR/lint-ctypes-enum.rs:181:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -211,7 +237,7 @@ LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:165:53
+  --> $DIR/lint-ctypes-enum.rs:183:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -220,7 +246,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:167:51
+  --> $DIR/lint-ctypes-enum.rs:185:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -229,7 +255,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:170:49
+  --> $DIR/lint-ctypes-enum.rs:188:49
    |
 LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -238,7 +264,7 @@ LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:172:30
+  --> $DIR/lint-ctypes-enum.rs:190:30
    |
 LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -247,7 +273,7 @@ LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:174:27
+  --> $DIR/lint-ctypes-enum.rs:192:27
    |
 LL |     fn result_unit_t_e(x: Result<(), ()>);
    |                           ^^^^^^^^^^^^^^ not FFI-safe
@@ -255,5 +281,5 @@ LL |     fn result_unit_t_e(x: Result<(), ()>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: aborting due to 27 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs
index 6a933a0de03..411772ae890 100644
--- a/tests/ui/lint/wasm_c_abi_transition.rs
+++ b/tests/ui/lint/wasm_c_abi_transition.rs
@@ -3,7 +3,7 @@
 //@ add-core-stubs
 //@ build-fail
 
-#![feature(no_core)]
+#![feature(no_core, repr_simd)]
 #![no_core]
 #![crate_type = "lib"]
 #![deny(wasm_c_abi)]
@@ -45,3 +45,13 @@ pub fn call_other_fun(x: MyType) {
 pub struct MyZstType;
 #[allow(improper_ctypes_definitions)]
 pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {}
+
+// The old and new wasm ABI treats simd types like `v128` the same way, so no
+// wasm_c_abi warning should be emitted.
+#[repr(simd)]
+#[allow(non_camel_case_types)]
+pub struct v128([i32; 4]);
+#[target_feature(enable = "simd128")]
+pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
+//~^ WARN `extern` fn uses type `v128`, which is not FFI-safe
+//~| WARN `extern` fn uses type `v128`, which is not FFI-safe
diff --git a/tests/ui/lint/wasm_c_abi_transition.stderr b/tests/ui/lint/wasm_c_abi_transition.stderr
index 389710d5cb3..b4526bf8d68 100644
--- a/tests/ui/lint/wasm_c_abi_transition.stderr
+++ b/tests/ui/lint/wasm_c_abi_transition.stderr
@@ -1,3 +1,32 @@
+warning: `extern` fn uses type `v128`, which is not FFI-safe
+  --> $DIR/wasm_c_abi_transition.rs:55:35
+   |
+LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
+   |                                   ^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
+note: the type is defined here
+  --> $DIR/wasm_c_abi_transition.rs:53:1
+   |
+LL | pub struct v128([i32; 4]);
+   | ^^^^^^^^^^^^^^^
+   = note: `#[warn(improper_ctypes_definitions)]` on by default
+
+warning: `extern` fn uses type `v128`, which is not FFI-safe
+  --> $DIR/wasm_c_abi_transition.rs:55:44
+   |
+LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
+   |                                            ^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
+   = note: this struct has unspecified layout
+note: the type is defined here
+  --> $DIR/wasm_c_abi_transition.rs:53:1
+   |
+LL | pub struct v128([i32; 4]);
+   | ^^^^^^^^^^^^^^^
+
 error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
   --> $DIR/wasm_c_abi_transition.rs:18:1
    |
@@ -33,7 +62,7 @@ LL |     unsafe { other_fun(x) }
    = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
    = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
 
-error: aborting due to 3 previous errors
+error: aborting due to 3 previous errors; 2 warnings emitted
 
 Future incompatibility report: Future breakage diagnostic:
 error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
diff --git a/tests/ui/macros/reparse-expr-issue-139495.rs b/tests/ui/macros/reparse-expr-issue-139495.rs
index 38d24573a53..89734cae0a6 100644
--- a/tests/ui/macros/reparse-expr-issue-139495.rs
+++ b/tests/ui/macros/reparse-expr-issue-139495.rs
@@ -1,7 +1,15 @@
-macro_rules! m {
-  ($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
+macro_rules! m1 {
+  ($abi: literal) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
+}
+
+macro_rules! m2 {
+  ($abi: expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
 }
 
 fn main() {
-    m!(-2)
+    m1!(-2)
+}
+
+fn f() {
+    m2!(-2)
 }
diff --git a/tests/ui/macros/reparse-expr-issue-139495.stderr b/tests/ui/macros/reparse-expr-issue-139495.stderr
index 73a8ed87ba0..e2e05d67ecc 100644
--- a/tests/ui/macros/reparse-expr-issue-139495.stderr
+++ b/tests/ui/macros/reparse-expr-issue-139495.stderr
@@ -1,13 +1,24 @@
 error: expected expression, found keyword `extern`
-  --> $DIR/reparse-expr-issue-139495.rs:2:22
+  --> $DIR/reparse-expr-issue-139495.rs:2:24
    |
-LL |   ($abi : expr) => { extern $abi }
-   |                      ^^^^^^ expected expression
+LL |   ($abi: literal) => { extern $abi }
+   |                        ^^^^^^ expected expression
 ...
-LL |     m!(-2)
-   |     ------ in this macro invocation
+LL |     m1!(-2)
+   |     ------- in this macro invocation
    |
-   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 1 previous error
+error: expected expression, found keyword `extern`
+  --> $DIR/reparse-expr-issue-139495.rs:6:21
+   |
+LL |   ($abi: expr) => { extern $abi }
+   |                     ^^^^^^ expected expression
+...
+LL |     m2!(-2)
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs
new file mode 100644
index 00000000000..0ce5e233930
--- /dev/null
+++ b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.rs
@@ -0,0 +1,22 @@
+#![allow(
+    dead_code,
+    unused_must_use
+)]
+
+struct Named {
+    foo: usize,
+}
+
+struct Unnamed(usize);
+
+unsafe fn named_struct_field_access(named: *mut Named) {
+    named->foo += 1; //~ ERROR `->` is not valid syntax for field accesses and method calls
+    //~^ ERROR no field `foo` on type `*mut Named`
+}
+
+unsafe fn unnamed_struct_field_access(unnamed: *mut Unnamed) {
+    unnamed->0 += 1; //~ ERROR `->` is not valid syntax for field accesses and method calls
+    //~^ ERROR no field `0` on type `*mut Unnamed`
+}
+
+fn main() {}
diff --git a/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr
new file mode 100644
index 00000000000..45f3c5549f7
--- /dev/null
+++ b/tests/ui/parser/expr-rarrow-call-on-a-raw-pointer.stderr
@@ -0,0 +1,53 @@
+error: `->` is not valid syntax for field accesses and method calls
+  --> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:13:10
+   |
+LL |     named->foo += 1;
+   |          ^^
+   |
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
+help: try using `.` instead
+   |
+LL -     named->foo += 1;
+LL +     named.foo += 1;
+   |
+
+error: `->` is not valid syntax for field accesses and method calls
+  --> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:18:12
+   |
+LL |     unnamed->0 += 1;
+   |            ^^
+   |
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
+help: try using `.` instead
+   |
+LL -     unnamed->0 += 1;
+LL +     unnamed.0 += 1;
+   |
+
+error[E0609]: no field `foo` on type `*mut Named`
+  --> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:13:12
+   |
+LL |     named->foo += 1;
+   |            ^^^ unknown field
+   |
+help: `named` is a raw pointer; try dereferencing it
+   |
+LL -     named->foo += 1;
+LL +     (*named).foo += 1;
+   |
+
+error[E0609]: no field `0` on type `*mut Unnamed`
+  --> $DIR/expr-rarrow-call-on-a-raw-pointer.rs:18:14
+   |
+LL |     unnamed->0 += 1;
+   |              ^ unknown field
+   |
+help: `unnamed` is a raw pointer; try dereferencing it
+   |
+LL -     unnamed->0 += 1;
+LL +     (*unnamed).0 += 1;
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/parser/expr-rarrow-call.fixed b/tests/ui/parser/expr-rarrow-call.fixed
index 9a05e20092d..c97284c4b01 100644
--- a/tests/ui/parser/expr-rarrow-call.fixed
+++ b/tests/ui/parser/expr-rarrow-call.fixed
@@ -11,23 +11,23 @@ struct Named {
 struct Unnamed(usize);
 
 fn named_struct_field_access(named: &Named) {
-    named.foo; //~ ERROR `->` used for field access or method call
+    named.foo; //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 fn unnamed_struct_field_access(unnamed: &Unnamed) {
-    unnamed.0; //~ ERROR `->` used for field access or method call
+    unnamed.0; //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 fn tuple_field_access(t: &(u8, u8)) {
-    t.0; //~ ERROR `->` used for field access or method call
-    t.1; //~ ERROR `->` used for field access or method call
+    t.0; //~ ERROR `->` is not valid syntax for field accesses and method calls
+    t.1; //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 #[derive(Clone)]
 struct Foo;
 
 fn method_call(foo: &Foo) {
-    foo.clone(); //~ ERROR `->` used for field access or method call
+    foo.clone(); //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 fn main() {}
diff --git a/tests/ui/parser/expr-rarrow-call.rs b/tests/ui/parser/expr-rarrow-call.rs
index 760b0f6f345..78cd72b12ec 100644
--- a/tests/ui/parser/expr-rarrow-call.rs
+++ b/tests/ui/parser/expr-rarrow-call.rs
@@ -11,23 +11,23 @@ struct Named {
 struct Unnamed(usize);
 
 fn named_struct_field_access(named: &Named) {
-    named->foo; //~ ERROR `->` used for field access or method call
+    named->foo; //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 fn unnamed_struct_field_access(unnamed: &Unnamed) {
-    unnamed->0; //~ ERROR `->` used for field access or method call
+    unnamed->0; //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 fn tuple_field_access(t: &(u8, u8)) {
-    t->0; //~ ERROR `->` used for field access or method call
-    t->1; //~ ERROR `->` used for field access or method call
+    t->0; //~ ERROR `->` is not valid syntax for field accesses and method calls
+    t->1; //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 #[derive(Clone)]
 struct Foo;
 
 fn method_call(foo: &Foo) {
-    foo->clone(); //~ ERROR `->` used for field access or method call
+    foo->clone(); //~ ERROR `->` is not valid syntax for field accesses and method calls
 }
 
 fn main() {}
diff --git a/tests/ui/parser/expr-rarrow-call.stderr b/tests/ui/parser/expr-rarrow-call.stderr
index 2e168ca26fe..0b105273861 100644
--- a/tests/ui/parser/expr-rarrow-call.stderr
+++ b/tests/ui/parser/expr-rarrow-call.stderr
@@ -1,62 +1,62 @@
-error: `->` used for field access or method call
+error: `->` is not valid syntax for field accesses and method calls
   --> $DIR/expr-rarrow-call.rs:14:10
    |
 LL |     named->foo;
    |          ^^
    |
-   = help: the `.` operator will dereference the value if needed
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
 help: try using `.` instead
    |
 LL -     named->foo;
 LL +     named.foo;
    |
 
-error: `->` used for field access or method call
+error: `->` is not valid syntax for field accesses and method calls
   --> $DIR/expr-rarrow-call.rs:18:12
    |
 LL |     unnamed->0;
    |            ^^
    |
-   = help: the `.` operator will dereference the value if needed
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
 help: try using `.` instead
    |
 LL -     unnamed->0;
 LL +     unnamed.0;
    |
 
-error: `->` used for field access or method call
+error: `->` is not valid syntax for field accesses and method calls
   --> $DIR/expr-rarrow-call.rs:22:6
    |
 LL |     t->0;
    |      ^^
    |
-   = help: the `.` operator will dereference the value if needed
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
 help: try using `.` instead
    |
 LL -     t->0;
 LL +     t.0;
    |
 
-error: `->` used for field access or method call
+error: `->` is not valid syntax for field accesses and method calls
   --> $DIR/expr-rarrow-call.rs:23:6
    |
 LL |     t->1;
    |      ^^
    |
-   = help: the `.` operator will dereference the value if needed
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
 help: try using `.` instead
    |
 LL -     t->1;
 LL +     t.1;
    |
 
-error: `->` used for field access or method call
+error: `->` is not valid syntax for field accesses and method calls
   --> $DIR/expr-rarrow-call.rs:30:8
    |
 LL |     foo->clone();
    |        ^^
    |
-   = help: the `.` operator will dereference the value if needed
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
 help: try using `.` instead
    |
 LL -     foo->clone();
diff --git a/tests/ui/parser/issues/issue-118530-ice.rs b/tests/ui/parser/issues/issue-118530-ice.rs
index cf14eebec2b..8930eb86c6b 100644
--- a/tests/ui/parser/issues/issue-118530-ice.rs
+++ b/tests/ui/parser/issues/issue-118530-ice.rs
@@ -5,7 +5,7 @@ fn bar() -> String {
     attr::fn bar() -> String { //~ ERROR expected identifier, found keyword `fn`
     //~^ ERROR expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `{`
     //~| ERROR expected `;`, found `bar`
-    //~| ERROR `->` used for field access or method call
+    //~| ERROR `->` is not valid syntax for field accesses and method calls
     #[attr]
     [1, 2, 3].iter().map().collect::<String>()
     #[attr]
diff --git a/tests/ui/parser/issues/issue-118530-ice.stderr b/tests/ui/parser/issues/issue-118530-ice.stderr
index 72c0397e9c9..ef891d1dc29 100644
--- a/tests/ui/parser/issues/issue-118530-ice.stderr
+++ b/tests/ui/parser/issues/issue-118530-ice.stderr
@@ -33,13 +33,13 @@ LL |     attr::fn bar() -> String {
    |             |
    |             help: add `;` here
 
-error: `->` used for field access or method call
+error: `->` is not valid syntax for field accesses and method calls
   --> $DIR/issue-118530-ice.rs:5:20
    |
 LL |     attr::fn bar() -> String {
    |                    ^^
    |
-   = help: the `.` operator will dereference the value if needed
+   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
 help: try using `.` instead
    |
 LL -     attr::fn bar() -> String {
diff --git a/tests/ui/parser/ty-path-followed-by-single-colon.rs b/tests/ui/parser/ty-path-followed-by-single-colon.rs
new file mode 100644
index 00000000000..a9082ea317a
--- /dev/null
+++ b/tests/ui/parser/ty-path-followed-by-single-colon.rs
@@ -0,0 +1,22 @@
+// Paths in type contexts may be followed by single colons.
+// This means we can't generally assume that the user typo'ed a double colon.
+// issue: <https://github.com/rust-lang/rust/issues/140227>
+//@ check-pass
+#![crate_type = "lib"]
+#![expect(non_camel_case_types)]
+
+#[rustfmt::skip]
+mod garden {
+
+    fn f<path>() where path:to::somewhere {} // OK!
+
+    fn g(_: impl Take<path:to::somewhere>) {} // OK!
+
+    #[cfg(any())] fn h() where a::path:to::nowhere {} // OK!
+
+    fn i(_: impl Take<path::<>:to::somewhere>) {} // OK!
+
+    mod to { pub(super) trait somewhere {} }
+    trait Take { type path; }
+
+}
diff --git a/tests/ui/pattern/byte-string-mutability-mismatch.rs b/tests/ui/pattern/byte-string-mutability-mismatch.rs
new file mode 100644
index 00000000000..4ffdb5f9b99
--- /dev/null
+++ b/tests/ui/pattern/byte-string-mutability-mismatch.rs
@@ -0,0 +1,19 @@
+//! Byte string literal patterns use the mutability of the literal, rather than the mutability of
+//! the pattern's scrutinee. Since byte string literals are always shared references, it's a
+//! mismatch to use a byte string literal pattern to match on a mutable array or slice reference.
+
+fn main() {
+    let mut val = [97u8, 10u8];
+    match &mut val {
+        b"a\n" => {},
+        //~^ ERROR mismatched types
+        //~| types differ in mutability
+        _ => {},
+    }
+    match &mut val[..] {
+         b"a\n" => {},
+        //~^ ERROR mismatched types
+        //~| types differ in mutability
+         _ => {},
+    }
+}
diff --git a/tests/ui/pattern/byte-string-mutability-mismatch.stderr b/tests/ui/pattern/byte-string-mutability-mismatch.stderr
new file mode 100644
index 00000000000..ee796278e69
--- /dev/null
+++ b/tests/ui/pattern/byte-string-mutability-mismatch.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/byte-string-mutability-mismatch.rs:8:9
+   |
+LL |     match &mut val {
+   |           -------- this expression has type `&mut [u8; 2]`
+LL |         b"a\n" => {},
+   |         ^^^^^^ types differ in mutability
+   |
+   = note: expected mutable reference `&mut _`
+                      found reference `&'static _`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-mutability-mismatch.rs:14:10
+   |
+LL |     match &mut val[..] {
+   |           ------------ this expression has type `&mut [u8]`
+LL |          b"a\n" => {},
+   |          ^^^^^^ types differ in mutability
+   |
+   = note: expected mutable reference `&mut _`
+                      found reference `&'static _`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
new file mode 100644
index 00000000000..29a33e3e2c3
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs
@@ -0,0 +1,34 @@
+//! Test type errors for byte string literal patterns. `deref_patterns` allows byte string literal
+//! patterns to have type `[u8]` or `[u8; N]` when matching on a slice or array; this can affect the
+//! "found" type reported in error messages when matching on a slice or array of the wrong type.
+
+#![feature(deref_patterns)]
+#![expect(incomplete_features)]
+
+fn main() {
+    // Baseline 1: under normal circumstances, byte string literal patterns have type `&[u8; N]`,
+    // the same as byte string literals.
+    if let b"test" = () {}
+    //~^ ERROR mismatched types
+    //~| expected `()`, found `&[u8; 4]`
+
+    // Baseline 2: there's a special case for byte string patterns in stable rust, allowing them to
+    // match on slice references. This affects the error when matching on a non-`&[u8]` slice ref,
+    // reporting the "found" type as `&[u8]`.
+    if let b"test" = &[] as &[i8] {}
+    //~^ ERROR mismatched types
+    //~| expected `&[i8]`, found `&[u8]`
+
+    // Test matching on a non-`[u8]` slice: the pattern has type `[u8]` if a slice is expected.
+    if let b"test" = *(&[] as &[i8]) {}
+    //~^ ERROR mismatched types
+    //~| expected `[i8]`, found `[u8]`
+
+    // Test matching on a non-`[u8;4]` array: the pattern has type `[u8;4]` if an array is expected.
+    if let b"test" = [()] {}
+    //~^ ERROR mismatched types
+    //~| expected `[(); 1]`, found `[u8; 4]`
+    if let b"test" = *b"this array is too long" {}
+    //~^ ERROR mismatched types
+    //~| expected an array with a size of 22, found one with a size of 4
+}
diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
new file mode 100644
index 00000000000..d29a5b59252
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:11:12
+   |
+LL |     if let b"test" = () {}
+   |            ^^^^^^^   -- this expression has type `()`
+   |            |
+   |            expected `()`, found `&[u8; 4]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:18:12
+   |
+LL |     if let b"test" = &[] as &[i8] {}
+   |            ^^^^^^^   ------------ this expression has type `&[i8]`
+   |            |
+   |            expected `&[i8]`, found `&[u8]`
+   |
+   = note: expected reference `&[i8]`
+              found reference `&'static [u8]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:23:12
+   |
+LL |     if let b"test" = *(&[] as &[i8]) {}
+   |            ^^^^^^^   --------------- this expression has type `[i8]`
+   |            |
+   |            expected `[i8]`, found `[u8]`
+   |
+   = note: expected slice `[i8]`
+              found slice `[u8]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:28:12
+   |
+LL |     if let b"test" = [()] {}
+   |            ^^^^^^^   ---- this expression has type `[(); 1]`
+   |            |
+   |            expected `[(); 1]`, found `[u8; 4]`
+   |
+   = note: expected array `[(); 1]`
+              found array `[u8; 4]`
+
+error[E0308]: mismatched types
+  --> $DIR/byte-string-type-errors.rs:31:12
+   |
+LL |     if let b"test" = *b"this array is too long" {}
+   |            ^^^^^^^   -------------------------- this expression has type `[u8; 22]`
+   |            |
+   |            expected an array with a size of 22, found one with a size of 4
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/needs-gate.rs b/tests/ui/pattern/deref-patterns/needs-gate.rs
index 2d5ec45217f..7944744ee83 100644
--- a/tests/ui/pattern/deref-patterns/needs-gate.rs
+++ b/tests/ui/pattern/deref-patterns/needs-gate.rs
@@ -12,4 +12,21 @@ fn main() {
         //~^ ERROR: mismatched types
         _ => {}
     }
+
+    // `deref_patterns` allows string and byte string literals to have non-ref types.
+    match *"test" {
+        "test" => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match *b"test" {
+        b"test" => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
+    match *(b"test" as &[u8]) {
+        b"test" => {}
+        //~^ ERROR: mismatched types
+        _ => {}
+    }
 }
diff --git a/tests/ui/pattern/deref-patterns/needs-gate.stderr b/tests/ui/pattern/deref-patterns/needs-gate.stderr
index 8687b5dc977..e886ca98055 100644
--- a/tests/ui/pattern/deref-patterns/needs-gate.stderr
+++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr
@@ -23,7 +23,31 @@ help: consider dereferencing to access the inner value using the Deref trait
 LL |     match *Box::new(0) {
    |           +
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/needs-gate.rs:18:9
+   |
+LL |     match *"test" {
+   |           ------- this expression has type `str`
+LL |         "test" => {}
+   |         ^^^^^^ expected `str`, found `&str`
+
+error[E0308]: mismatched types
+  --> $DIR/needs-gate.rs:23:9
+   |
+LL |     match *b"test" {
+   |           -------- this expression has type `[u8; 4]`
+LL |         b"test" => {}
+   |         ^^^^^^^ expected `[u8; 4]`, found `&[u8; 4]`
+
+error[E0308]: mismatched types
+  --> $DIR/needs-gate.rs:28:9
+   |
+LL |     match *(b"test" as &[u8]) {
+   |           ------------------- this expression has type `[u8]`
+LL |         b"test" => {}
+   |         ^^^^^^^ expected `[u8]`, found `&[u8; 4]`
+
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/deref-patterns/strings.rs b/tests/ui/pattern/deref-patterns/strings.rs
new file mode 100644
index 00000000000..536e943b3f6
--- /dev/null
+++ b/tests/ui/pattern/deref-patterns/strings.rs
@@ -0,0 +1,66 @@
+//@ run-pass
+//! Test deref patterns using string and bytestring literals.
+
+#![feature(deref_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {
+    for (test_in, test_expect) in [("zero", 0), ("one", 1), ("two", 2)] {
+        // Test string literal patterns having type `str`.
+        let test_actual = match *test_in {
+            "zero" => 0,
+            "one" => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test string literals in explicit `deref!(_)` patterns.
+        let test_actual = match test_in.to_string() {
+            deref!("zero") => 0,
+            deref!("one") => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+    }
+
+    // Test that we can still mutate in the match arm after using a literal to test equality:
+    let mut test = "test".to_string();
+    if let deref!(s @ "test") = &mut test {
+        s.make_ascii_uppercase();
+    }
+    assert_eq!(test, "TEST");
+
+    for (test_in, test_expect) in [(b"0", 0), (b"1", 1), (b"2", 2)] {
+        // Test byte string literal patterns having type `[u8; N]`
+        let test_actual = match *test_in {
+            b"0" => 0,
+            b"1" => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test byte string literal patterns having type `[u8]`
+        let test_actual = match *(test_in as &[u8]) {
+            b"0" => 0,
+            b"1" => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test byte string literals used as arrays in explicit `deref!(_)` patterns.
+        let test_actual = match Box::new(*test_in) {
+            deref!(b"0") => 0,
+            deref!(b"1") => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+
+        // Test byte string literals used as slices in explicit `deref!(_)` patterns.
+        let test_actual = match test_in.to_vec() {
+            deref!(b"0") => 0,
+            deref!(b"1") => 1,
+            _ => 2,
+        };
+        assert_eq!(test_actual, test_expect);
+    }
+}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs
index 4b9ad7d25f0..52d84f7a34d 100644
--- a/tests/ui/pattern/deref-patterns/typeck_fail.rs
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs
@@ -2,18 +2,14 @@
 #![allow(incomplete_features)]
 
 fn main() {
-    // FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
-    // place of type `str`.
+    // FIXME(deref_patterns): fails to typecheck because string literal patterns don't peel
+    // references from the scrutinee.
     match "foo".to_string() {
-        deref!("foo") => {}
-        //~^ ERROR: mismatched types
         "foo" => {}
         //~^ ERROR: mismatched types
         _ => {}
     }
     match &"foo".to_string() {
-        deref!("foo") => {}
-        //~^ ERROR: mismatched types
         "foo" => {}
         //~^ ERROR: mismatched types
         _ => {}
diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
index 3e2f3561882..e87528c1c51 100644
--- a/tests/ui/pattern/deref-patterns/typeck_fail.stderr
+++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr
@@ -1,34 +1,16 @@
 error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:8:16
+  --> $DIR/typeck_fail.rs:8:9
    |
 LL |     match "foo".to_string() {
    |           ----------------- this expression has type `String`
-LL |         deref!("foo") => {}
-   |                ^^^^^ expected `str`, found `&str`
-
-error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:10:9
-   |
-LL |     match "foo".to_string() {
-   |           ----------------- this expression has type `String`
-...
 LL |         "foo" => {}
    |         ^^^^^ expected `String`, found `&str`
 
 error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:15:16
-   |
-LL |     match &"foo".to_string() {
-   |           ------------------ this expression has type `&String`
-LL |         deref!("foo") => {}
-   |                ^^^^^ expected `str`, found `&str`
-
-error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:17:9
+  --> $DIR/typeck_fail.rs:13:9
    |
 LL |     match &"foo".to_string() {
    |           ------------------ this expression has type `&String`
-...
 LL |         "foo" => {}
    |         ^^^^^ expected `&String`, found `&str`
    |
@@ -36,7 +18,7 @@ LL |         "foo" => {}
               found reference `&'static str`
 
 error[E0308]: mismatched types
-  --> $DIR/typeck_fail.rs:24:9
+  --> $DIR/typeck_fail.rs:20:9
    |
 LL |     match Some(0) {
    |           ------- this expression has type `Option<{integer}>`
@@ -46,6 +28,6 @@ LL |         Ok(0) => {}
    = note: expected enum `Option<{integer}>`
               found enum `Result<_, _>`
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.fixed b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.fixed
deleted file mode 100644
index f5dbf0c8b6f..00000000000
--- a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.fixed
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ run-rustfix
-
-use std::fmt;
-
-struct Hello;
-
-impl fmt::Display for Hello {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
-        write!(f, "hello")
-    }
-}
-
-fn main() {
-    let _ = Hello;
-}
diff --git a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.rs b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.rs
deleted file mode 100644
index c41880a26f6..00000000000
--- a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ run-rustfix
-
-use std::fmt;
-
-struct Hello;
-
-impl fmt::Display for Hello {
-    fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
-        write!(f, "hello")
-    }
-}
-
-fn main() {
-    let _ = Hello;
-}
diff --git a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr
deleted file mode 100644
index 713b071a625..00000000000
--- a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error: path separator must be a double colon
-  --> $DIR/argument-list-from-path-sep-error-129273.rs:8:30
-   |
-LL |     fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result {
-   |                              ^
-   |
-help: use a double colon instead
-   |
-LL |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-   |                               +
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/suggestions/raw-c-string-prefix.rs b/tests/ui/suggestions/raw-c-string-prefix.rs
new file mode 100644
index 00000000000..6af72df4024
--- /dev/null
+++ b/tests/ui/suggestions/raw-c-string-prefix.rs
@@ -0,0 +1,10 @@
+// `rc` and `cr` are easy to confuse; check that we issue a suggestion to help.
+
+//@ edition:2021
+
+fn main() {
+    rc"abc";
+    //~^ ERROR: prefix `rc` is unknown
+    //~| HELP: use `cr` for a raw C-string
+    //~| ERROR: expected one of
+}
diff --git a/tests/ui/suggestions/raw-c-string-prefix.stderr b/tests/ui/suggestions/raw-c-string-prefix.stderr
new file mode 100644
index 00000000000..5341e3d04e8
--- /dev/null
+++ b/tests/ui/suggestions/raw-c-string-prefix.stderr
@@ -0,0 +1,21 @@
+error: prefix `rc` is unknown
+  --> $DIR/raw-c-string-prefix.rs:6:5
+   |
+LL |     rc"abc";
+   |     ^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: use `cr` for a raw C-string
+   |
+LL -     rc"abc";
+LL +     cr"abc";
+   |
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"abc"`
+  --> $DIR/raw-c-string-prefix.rs:6:7
+   |
+LL |     rc"abc";
+   |       ^^^^^ expected one of 8 possible tokens
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.rs b/tests/ui/suggestions/struct-field-type-including-single-colon.rs
index a3111028895..482641fc7ca 100644
--- a/tests/ui/suggestions/struct-field-type-including-single-colon.rs
+++ b/tests/ui/suggestions/struct-field-type-including-single-colon.rs
@@ -7,14 +7,14 @@ mod foo {
 
 struct Foo {
     a: foo:A,
-    //~^ ERROR path separator must be a double colon
-    //~| ERROR struct `A` is private
+    //~^ ERROR found single colon in a struct field type path
+    //~| ERROR expected `,`, or `}`, found `:`
 }
 
 struct Bar {
     b: foo::bar:B,
-    //~^ ERROR path separator must be a double colon
-    //~| ERROR module `bar` is private
+    //~^ ERROR found single colon in a struct field type path
+    //~| ERROR expected `,`, or `}`, found `:`
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
index b9302b0453d..5ffc5b40849 100644
--- a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
+++ b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr
@@ -1,51 +1,40 @@
-error: path separator must be a double colon
+error: found single colon in a struct field type path
   --> $DIR/struct-field-type-including-single-colon.rs:9:11
    |
 LL |     a: foo:A,
    |           ^
    |
-help: use a double colon instead
+help: write a path separator here
    |
 LL |     a: foo::A,
    |            +
 
-error: path separator must be a double colon
+error: expected `,`, or `}`, found `:`
+  --> $DIR/struct-field-type-including-single-colon.rs:9:11
+   |
+LL | struct Foo {
+   |        --- while parsing this struct
+LL |     a: foo:A,
+   |           ^
+
+error: found single colon in a struct field type path
   --> $DIR/struct-field-type-including-single-colon.rs:15:16
    |
 LL |     b: foo::bar:B,
    |                ^
    |
-help: use a double colon instead
+help: write a path separator here
    |
 LL |     b: foo::bar::B,
    |                 +
 
-error[E0603]: struct `A` is private
-  --> $DIR/struct-field-type-including-single-colon.rs:9:12
-   |
-LL |     a: foo:A,
-   |            ^ private struct
-   |
-note: the struct `A` is defined here
-  --> $DIR/struct-field-type-including-single-colon.rs:2:5
-   |
-LL |     struct A;
-   |     ^^^^^^^^^
-
-error[E0603]: module `bar` is private
-  --> $DIR/struct-field-type-including-single-colon.rs:15:13
+error: expected `,`, or `}`, found `:`
+  --> $DIR/struct-field-type-including-single-colon.rs:15:16
    |
+LL | struct Bar {
+   |        --- while parsing this struct
 LL |     b: foo::bar:B,
-   |             ^^^ - struct `B` is not publicly re-exported
-   |             |
-   |             private module
-   |
-note: the module `bar` is defined here
-  --> $DIR/struct-field-type-including-single-colon.rs:3:5
-   |
-LL |     mod bar {
-   |     ^^^^^^^
+   |                ^
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/transmute/unnecessary-transmutation.fixed b/tests/ui/transmute/unnecessary-transmutation.fixed
new file mode 100644
index 00000000000..1a0df143cc5
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmutation.fixed
@@ -0,0 +1,85 @@
+//@ run-rustfix
+#![deny(unnecessary_transmutes)]
+#![allow(unused_unsafe, unused_imports, unused_variables, unused_parens)]
+use std::mem::transmute;
+
+pub fn bytes_at_home(x: u32) -> [u8; 4] {
+    unsafe { u32::to_ne_bytes(x) }
+    //~^ ERROR
+}
+
+fn main() {
+    unsafe {
+        let x: u16 = u16::from_ne_bytes(*b"01");
+        //~^ ERROR
+        let x: [u8; 2] = u16::to_ne_bytes(x);
+        //~^ ERROR
+        let x: u32 = u32::from_ne_bytes(*b"0123");
+        //~^ ERROR
+        let x: [u8; 4] = u32::to_ne_bytes(x);
+        //~^ ERROR
+        let x: u64 = u64::from_ne_bytes(*b"feriscat");
+        //~^ ERROR
+        let x: [u8; 8] = u64::to_ne_bytes(x);
+        //~^ ERROR
+
+        let y: i16 = i16::from_ne_bytes(*b"01");
+        //~^ ERROR
+        let y: [u8; 2] = i16::to_ne_bytes(y);
+        //~^ ERROR
+        let y: i32 = i32::from_ne_bytes(*b"0123");
+        //~^ ERROR
+        let y: [u8; 4] = i32::to_ne_bytes(y);
+        //~^ ERROR
+        let y: i64 = i64::from_ne_bytes(*b"feriscat");
+        //~^ ERROR
+        let y: [u8; 8] = i64::to_ne_bytes(y);
+        //~^ ERROR
+
+        let z: f32 = f32::from_ne_bytes(*b"0123");
+        //~^ ERROR
+        let z: [u8; 4] = f32::to_ne_bytes(z);
+        //~^ ERROR
+        let z: f64 = f64::from_ne_bytes(*b"feriscat");
+        //~^ ERROR
+        let z: [u8; 8] = f64::to_ne_bytes(z);
+        //~^ ERROR
+
+        let y: u32 = u32::from('🦀');
+        //~^ ERROR
+        let y: char = char::from_u32_unchecked(y);
+        //~^ ERROR
+
+        let x: u16 = i16::cast_unsigned(8i16);
+        //~^ ERROR
+        let x: i16 = u16::cast_signed(x);
+        //~^ ERROR
+        let x: u32 = i32::cast_unsigned(4i32);
+        //~^ ERROR
+        let x: i32 = u32::cast_signed(x);
+        //~^ ERROR
+        let x: u64 = i64::cast_unsigned(7i64);
+        //~^ ERROR
+        let x: i64 = u64::cast_signed(x);
+        //~^ ERROR
+
+        let y: f32 = f32::from_bits(1u32);
+        //~^ ERROR
+        let y: u32 = f32::to_bits(y);
+        //~^ ERROR
+        let y: f64 = f64::from_bits(3u64);
+        //~^ ERROR
+        let y: u64 = f64::to_bits(2.0);
+        //~^ ERROR
+
+        let z: bool = (1u8 == 1);
+        //~^ ERROR
+        let z: u8 = (z) as u8;
+        //~^ ERROR
+
+        let z: bool = transmute(1i8);
+        // no error!
+        let z: i8 = (z) as i8;
+        //~^ ERROR
+    }
+}
diff --git a/tests/ui/transmute/unnecessary-transmutation.rs b/tests/ui/transmute/unnecessary-transmutation.rs
new file mode 100644
index 00000000000..6b979263c56
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmutation.rs
@@ -0,0 +1,85 @@
+//@ run-rustfix
+#![deny(unnecessary_transmutes)]
+#![allow(unused_unsafe, unused_imports, unused_variables, unused_parens)]
+use std::mem::transmute;
+
+pub fn bytes_at_home(x: u32) -> [u8; 4] {
+    unsafe { transmute(x) }
+    //~^ ERROR
+}
+
+fn main() {
+    unsafe {
+        let x: u16 = transmute(*b"01");
+        //~^ ERROR
+        let x: [u8; 2] = transmute(x);
+        //~^ ERROR
+        let x: u32 = transmute(*b"0123");
+        //~^ ERROR
+        let x: [u8; 4] = transmute(x);
+        //~^ ERROR
+        let x: u64 = transmute(*b"feriscat");
+        //~^ ERROR
+        let x: [u8; 8] = transmute(x);
+        //~^ ERROR
+
+        let y: i16 = transmute(*b"01");
+        //~^ ERROR
+        let y: [u8; 2] = transmute(y);
+        //~^ ERROR
+        let y: i32 = transmute(*b"0123");
+        //~^ ERROR
+        let y: [u8; 4] = transmute(y);
+        //~^ ERROR
+        let y: i64 = transmute(*b"feriscat");
+        //~^ ERROR
+        let y: [u8; 8] = transmute(y);
+        //~^ ERROR
+
+        let z: f32 = transmute(*b"0123");
+        //~^ ERROR
+        let z: [u8; 4] = transmute(z);
+        //~^ ERROR
+        let z: f64 = transmute(*b"feriscat");
+        //~^ ERROR
+        let z: [u8; 8] = transmute(z);
+        //~^ ERROR
+
+        let y: u32 = transmute('🦀');
+        //~^ ERROR
+        let y: char = transmute(y);
+        //~^ ERROR
+
+        let x: u16 = transmute(8i16);
+        //~^ ERROR
+        let x: i16 = transmute(x);
+        //~^ ERROR
+        let x: u32 = transmute(4i32);
+        //~^ ERROR
+        let x: i32 = transmute(x);
+        //~^ ERROR
+        let x: u64 = transmute(7i64);
+        //~^ ERROR
+        let x: i64 = transmute(x);
+        //~^ ERROR
+
+        let y: f32 = transmute(1u32);
+        //~^ ERROR
+        let y: u32 = transmute(y);
+        //~^ ERROR
+        let y: f64 = transmute(3u64);
+        //~^ ERROR
+        let y: u64 = transmute(2.0);
+        //~^ ERROR
+
+        let z: bool = transmute(1u8);
+        //~^ ERROR
+        let z: u8 = transmute(z);
+        //~^ ERROR
+
+        let z: bool = transmute(1i8);
+        // no error!
+        let z: i8 = transmute(z);
+        //~^ ERROR
+    }
+}
diff --git a/tests/ui/transmute/unnecessary-transmutation.stderr b/tests/ui/transmute/unnecessary-transmutation.stderr
new file mode 100644
index 00000000000..b661aa13c98
--- /dev/null
+++ b/tests/ui/transmute/unnecessary-transmutation.stderr
@@ -0,0 +1,235 @@
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:7:14
+   |
+LL |     unsafe { transmute(x) }
+   |              ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+note: the lint level is defined here
+  --> $DIR/unnecessary-transmutation.rs:2:9
+   |
+LL | #![deny(unnecessary_transmutes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:13:22
+   |
+LL |         let x: u16 = transmute(*b"01");
+   |                      ^^^^^^^^^^^^^^^^^ help: replace this with: `u16::from_ne_bytes(*b"01")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:15:26
+   |
+LL |         let x: [u8; 2] = transmute(x);
+   |                          ^^^^^^^^^^^^ help: replace this with: `u16::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:17:22
+   |
+LL |         let x: u32 = transmute(*b"0123");
+   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `u32::from_ne_bytes(*b"0123")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:19:26
+   |
+LL |         let x: [u8; 4] = transmute(x);
+   |                          ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:21:22
+   |
+LL |         let x: u64 = transmute(*b"feriscat");
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `u64::from_ne_bytes(*b"feriscat")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:23:26
+   |
+LL |         let x: [u8; 8] = transmute(x);
+   |                          ^^^^^^^^^^^^ help: replace this with: `u64::to_ne_bytes(x)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:26:22
+   |
+LL |         let y: i16 = transmute(*b"01");
+   |                      ^^^^^^^^^^^^^^^^^ help: replace this with: `i16::from_ne_bytes(*b"01")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:28:26
+   |
+LL |         let y: [u8; 2] = transmute(y);
+   |                          ^^^^^^^^^^^^ help: replace this with: `i16::to_ne_bytes(y)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:30:22
+   |
+LL |         let y: i32 = transmute(*b"0123");
+   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `i32::from_ne_bytes(*b"0123")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:32:26
+   |
+LL |         let y: [u8; 4] = transmute(y);
+   |                          ^^^^^^^^^^^^ help: replace this with: `i32::to_ne_bytes(y)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:34:22
+   |
+LL |         let y: i64 = transmute(*b"feriscat");
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `i64::from_ne_bytes(*b"feriscat")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:36:26
+   |
+LL |         let y: [u8; 8] = transmute(y);
+   |                          ^^^^^^^^^^^^ help: replace this with: `i64::to_ne_bytes(y)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:39:22
+   |
+LL |         let z: f32 = transmute(*b"0123");
+   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `f32::from_ne_bytes(*b"0123")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:41:26
+   |
+LL |         let z: [u8; 4] = transmute(z);
+   |                          ^^^^^^^^^^^^ help: replace this with: `f32::to_ne_bytes(z)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:43:22
+   |
+LL |         let z: f64 = transmute(*b"feriscat");
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `f64::from_ne_bytes(*b"feriscat")`
+   |
+   = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:45:26
+   |
+LL |         let z: [u8; 8] = transmute(z);
+   |                          ^^^^^^^^^^^^ help: replace this with: `f64::to_ne_bytes(z)`
+   |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:48:22
+   |
+LL |         let y: u32 = transmute('🦀');
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🦀')`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:50:23
+   |
+LL |         let y: char = transmute(y);
+   |                       ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(y)`
+   |
+   = help: consider `char::from_u32(…).unwrap()`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:53:22
+   |
+LL |         let x: u16 = transmute(8i16);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:55:22
+   |
+LL |         let x: i16 = transmute(x);
+   |                      ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:57:22
+   |
+LL |         let x: u32 = transmute(4i32);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:59:22
+   |
+LL |         let x: i32 = transmute(x);
+   |                      ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:61:22
+   |
+LL |         let x: u64 = transmute(7i64);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:63:22
+   |
+LL |         let x: i64 = transmute(x);
+   |                      ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:66:22
+   |
+LL |         let y: f32 = transmute(1u32);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:68:22
+   |
+LL |         let y: u32 = transmute(y);
+   |                      ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:70:22
+   |
+LL |         let y: f64 = transmute(3u64);
+   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:72:22
+   |
+LL |         let y: u64 = transmute(2.0);
+   |                      ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:75:23
+   |
+LL |         let z: bool = transmute(1u8);
+   |                       ^^^^^^^^^^^^^^ help: replace this with: `(1u8 == 1)`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:77:21
+   |
+LL |         let z: u8 = transmute(z);
+   |                     ^^^^^^^^^^^^ help: replace this with: `(z) as u8`
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:82:21
+   |
+LL |         let z: i8 = transmute(z);
+   |                     ^^^^^^^^^^^^ help: replace this with: `(z) as i8`
+
+error: aborting due to 32 previous errors
+
diff --git a/triagebot.toml b/triagebot.toml
index 0f17d022fbb..422996cb200 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -585,6 +585,11 @@ trigger_files = [
     "src/tools/compiletest"
 ]
 
+[autolabel."A-test-infra-minicore"]
+trigger_files = [
+    "tests/auxiliary/minicore.rs",
+]
+
 [autolabel."A-rustc-dev-guide"]
 trigger_files = [
     "src/doc/rustc-dev-guide",
@@ -869,6 +874,10 @@ cc = ["@GuillaumeGomez"]
 message = "This PR modifies `run-make` tests."
 cc = ["@jieyouxu"]
 
+[mentions."tests/auxiliary/minicore.rs"]
+message = "This PR modifies `tests/auxiliary/minicore.rs`."
+cc = ["@jieyouxu"]
+
 [mentions."src/rustdoc-json-types"]
 message = """
 rustdoc-json-types is a **public** (although nightly-only) API. \
@@ -1120,6 +1129,11 @@ cc = ["@ZuseZ4"]
 [mentions."compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs"]
 cc = ["@ZuseZ4"]
 
+[mentions."library/core/src/fmt/rt.rs"]
+cc = ["@m-ou-se"]
+[mentions."compiler/rustc_ast_lowering/src/format.rs"]
+cc = ["@m-ou-se"]
+
 [assign]
 warn_non_default_branch.enable = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"