about summary refs log tree commit diff
path: root/clippy_lints/src
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2025-04-22 16:10:59 +0200
committerPhilipp Krones <hello@philkrones.com>2025-04-22 18:24:43 +0200
commitff428d91c2b690b8dbd8cc1e48274870c24fe1e2 (patch)
tree496897def77d0f71b6db9713a16c2ea4f5886f23 /clippy_lints/src
parented892e72dd05c6dbbd425343f84d1c1d348a898d (diff)
Merge commit '0621446356e20fd2ead13a6763bb936c95eb0cfa' into clippy-subtree-update
Diffstat (limited to 'clippy_lints/src')
-rw-r--r--clippy_lints/src/arbitrary_source_item_ordering.rs81
-rw-r--r--clippy_lints/src/as_conversions.rs22
-rw-r--r--clippy_lints/src/assigning_clones.rs6
-rw-r--r--clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs23
-rw-r--r--clippy_lints/src/attrs/deprecated_semver.rs8
-rw-r--r--clippy_lints/src/attrs/duplicated_attributes.rs5
-rw-r--r--clippy_lints/src/attrs/mod.rs86
-rw-r--r--clippy_lints/src/attrs/repr_attributes.rs2
-rw-r--r--clippy_lints/src/attrs/useless_attribute.rs130
-rw-r--r--clippy_lints/src/await_holding_invalid.rs16
-rw-r--r--clippy_lints/src/bool_to_int_with_if.rs29
-rw-r--r--clippy_lints/src/booleans.rs34
-rw-r--r--clippy_lints/src/borrow_deref_ref.rs13
-rw-r--r--clippy_lints/src/casts/borrow_as_ptr.rs33
-rw-r--r--clippy_lints/src/casts/cast_abs_to_unsigned.rs2
-rw-r--r--clippy_lints/src/casts/cast_lossless.rs2
-rw-r--r--clippy_lints/src/casts/cast_possible_truncation.rs10
-rw-r--r--clippy_lints/src/casts/cast_ptr_alignment.rs19
-rw-r--r--clippy_lints/src/casts/cast_slice_different_sizes.rs65
-rw-r--r--clippy_lints/src/casts/manual_dangling_ptr.rs82
-rw-r--r--clippy_lints/src/casts/mod.rs37
-rw-r--r--clippy_lints/src/casts/ptr_as_ptr.rs2
-rw-r--r--clippy_lints/src/casts/ptr_cast_constness.rs7
-rw-r--r--clippy_lints/src/casts/unnecessary_cast.rs10
-rw-r--r--clippy_lints/src/checked_conversions.rs8
-rw-r--r--clippy_lints/src/cognitive_complexity.rs8
-rw-r--r--clippy_lints/src/collapsible_if.rs221
-rw-r--r--clippy_lints/src/comparison_chain.rs2
-rw-r--r--clippy_lints/src/copies.rs10
-rw-r--r--clippy_lints/src/declare_clippy_lint.rs13
-rw-r--r--clippy_lints/src/declared_lints.rs39
-rw-r--r--clippy_lints/src/default_constructed_unit_structs.rs24
-rw-r--r--clippy_lints/src/deprecated_lints.rs2
-rw-r--r--clippy_lints/src/dereference.rs105
-rw-r--r--clippy_lints/src/derivable_impls.rs26
-rw-r--r--clippy_lints/src/derive.rs20
-rw-r--r--clippy_lints/src/disallowed_macros.rs10
-rw-r--r--clippy_lints/src/disallowed_methods.rs23
-rw-r--r--clippy_lints/src/disallowed_types.rs34
-rw-r--r--clippy_lints/src/doc/markdown.rs26
-rw-r--r--clippy_lints/src/doc/missing_headers.rs51
-rw-r--r--clippy_lints/src/doc/mod.rs136
-rw-r--r--clippy_lints/src/doc/needless_doctest_main.rs5
-rw-r--r--clippy_lints/src/drop_forget_ref.rs8
-rw-r--r--clippy_lints/src/empty_line_after.rs23
-rw-r--r--clippy_lints/src/empty_with_brackets.rs233
-rw-r--r--clippy_lints/src/entry.rs33
-rw-r--r--clippy_lints/src/enum_clike.rs8
-rw-r--r--clippy_lints/src/escape.rs46
-rw-r--r--clippy_lints/src/fallible_impl_from.rs8
-rw-r--r--clippy_lints/src/floating_point_arithmetic.rs170
-rw-r--r--clippy_lints/src/format.rs2
-rw-r--r--clippy_lints/src/format_args.rs4
-rw-r--r--clippy_lints/src/format_impl.rs16
-rw-r--r--clippy_lints/src/formatting.rs41
-rw-r--r--clippy_lints/src/from_str_radix_10.rs2
-rw-r--r--clippy_lints/src/functions/misnamed_getters.rs17
-rw-r--r--clippy_lints/src/functions/renamed_function_params.rs4
-rw-r--r--clippy_lints/src/functions/too_many_arguments.rs18
-rw-r--r--clippy_lints/src/if_then_some_else_none.rs2
-rw-r--r--clippy_lints/src/implicit_return.rs30
-rw-r--r--clippy_lints/src/implicit_saturating_sub.rs2
-rw-r--r--clippy_lints/src/implied_bounds_in_impls.rs4
-rw-r--r--clippy_lints/src/inconsistent_struct_constructor.rs6
-rw-r--r--clippy_lints/src/indexing_slicing.rs45
-rw-r--r--clippy_lints/src/infinite_iter.rs11
-rw-r--r--clippy_lints/src/instant_subtraction.rs2
-rw-r--r--clippy_lints/src/int_plus_one.rs24
-rw-r--r--clippy_lints/src/invalid_upcast_comparisons.rs84
-rw-r--r--clippy_lints/src/item_name_repetitions.rs116
-rw-r--r--clippy_lints/src/len_zero.rs85
-rw-r--r--clippy_lints/src/lib.rs69
-rw-r--r--clippy_lints/src/lifetimes.rs37
-rw-r--r--clippy_lints/src/literal_representation.rs11
-rw-r--r--clippy_lints/src/literal_string_with_formatting_args.rs9
-rw-r--r--clippy_lints/src/loops/char_indices_as_byte_indices.rs141
-rw-r--r--clippy_lints/src/loops/explicit_iter_loop.rs16
-rw-r--r--clippy_lints/src/loops/for_kv_map.rs74
-rw-r--r--clippy_lints/src/loops/manual_find.rs2
-rw-r--r--clippy_lints/src/loops/manual_memcpy.rs137
-rw-r--r--clippy_lints/src/loops/manual_while_let_some.rs16
-rw-r--r--clippy_lints/src/loops/mod.rs46
-rw-r--r--clippy_lints/src/loops/mut_range_bound.rs16
-rw-r--r--clippy_lints/src/loops/needless_range_loop.rs269
-rw-r--r--clippy_lints/src/loops/never_loop.rs8
-rw-r--r--clippy_lints/src/loops/utils.rs10
-rw-r--r--clippy_lints/src/macro_metavars_in_unsafe.rs17
-rw-r--r--clippy_lints/src/manual_abs_diff.rs152
-rw-r--r--clippy_lints/src/manual_assert.rs2
-rw-r--r--clippy_lints/src/manual_clamp.rs2
-rw-r--r--clippy_lints/src/manual_div_ceil.rs11
-rw-r--r--clippy_lints/src/manual_is_ascii_check.rs2
-rw-r--r--clippy_lints/src/manual_is_power_of_two.rs192
-rw-r--r--clippy_lints/src/manual_option_as_slice.rs2
-rw-r--r--clippy_lints/src/manual_retain.rs35
-rw-r--r--clippy_lints/src/manual_rotate.rs2
-rw-r--r--clippy_lints/src/manual_string_new.rs15
-rw-r--r--clippy_lints/src/manual_unwrap_or_default.rs212
-rw-r--r--clippy_lints/src/map_unit_fn.rs8
-rw-r--r--clippy_lints/src/matches/collapsible_match.rs4
-rw-r--r--clippy_lints/src/matches/manual_filter.rs20
-rw-r--r--clippy_lints/src/matches/manual_ok_err.rs4
-rw-r--r--clippy_lints/src/matches/manual_unwrap_or.rs294
-rw-r--r--clippy_lints/src/matches/match_like_matches.rs25
-rw-r--r--clippy_lints/src/matches/match_on_vec_items.rs50
-rw-r--r--clippy_lints/src/matches/match_single_binding.rs59
-rw-r--r--clippy_lints/src/matches/match_str_case_mismatch.rs8
-rw-r--r--clippy_lints/src/matches/match_wild_enum.rs18
-rw-r--r--clippy_lints/src/matches/match_wild_err_arm.rs11
-rw-r--r--clippy_lints/src/matches/mod.rs51
-rw-r--r--clippy_lints/src/matches/needless_match.rs8
-rw-r--r--clippy_lints/src/matches/overlapping_arms.rs22
-rw-r--r--clippy_lints/src/matches/redundant_pattern_match.rs22
-rw-r--r--clippy_lints/src/matches/significant_drop_in_scrutinee.rs9
-rw-r--r--clippy_lints/src/matches/single_match.rs17
-rw-r--r--clippy_lints/src/matches/wild_in_or_pats.rs22
-rw-r--r--clippy_lints/src/mem_replace.rs16
-rw-r--r--clippy_lints/src/methods/bind_instead_of_map.rs8
-rw-r--r--clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs24
-rw-r--r--clippy_lints/src/methods/clone_on_copy.rs8
-rw-r--r--clippy_lints/src/methods/double_ended_iterator_last.rs7
-rw-r--r--clippy_lints/src/methods/expect_fun_call.rs9
-rw-r--r--clippy_lints/src/methods/filter_map.rs31
-rw-r--r--clippy_lints/src/methods/filter_map_bool_then.rs76
-rw-r--r--clippy_lints/src/methods/from_iter_instead_of_collect.rs97
-rw-r--r--clippy_lints/src/methods/is_empty.rs16
-rw-r--r--clippy_lints/src/methods/iter_cloned_collect.rs10
-rw-r--r--clippy_lints/src/methods/iter_filter.rs8
-rw-r--r--clippy_lints/src/methods/iter_kv_map.rs2
-rw-r--r--clippy_lints/src/methods/iterator_step_by_zero.rs18
-rw-r--r--clippy_lints/src/methods/manual_saturating_arithmetic.rs26
-rw-r--r--clippy_lints/src/methods/manual_str_repeat.rs2
-rw-r--r--clippy_lints/src/methods/map_clone.rs36
-rw-r--r--clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs2
-rw-r--r--clippy_lints/src/methods/mod.rs94
-rw-r--r--clippy_lints/src/methods/needless_collect.rs36
-rw-r--r--clippy_lints/src/methods/needless_option_take.rs49
-rw-r--r--clippy_lints/src/methods/obfuscated_if_else.rs18
-rw-r--r--clippy_lints/src/methods/or_fun_call.rs11
-rw-r--r--clippy_lints/src/methods/seek_from_current.rs44
-rw-r--r--clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs6
-rw-r--r--clippy_lints/src/methods/str_splitn.rs15
-rw-r--r--clippy_lints/src/methods/suspicious_map.rs8
-rw-r--r--clippy_lints/src/methods/swap_with_temporary.rs125
-rw-r--r--clippy_lints/src/methods/unnecessary_filter_map.rs26
-rw-r--r--clippy_lints/src/methods/unnecessary_lazy_eval.rs99
-rw-r--r--clippy_lints/src/methods/unnecessary_map_or.rs8
-rw-r--r--clippy_lints/src/methods/utils.rs3
-rw-r--r--clippy_lints/src/misc_early/builtin_type_shadow.rs18
-rw-r--r--clippy_lints/src/misc_early/redundant_pattern.rs30
-rw-r--r--clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs46
-rw-r--r--clippy_lints/src/mismatching_type_param_order.rs8
-rw-r--r--clippy_lints/src/missing_asserts_for_indexing.rs79
-rw-r--r--clippy_lints/src/missing_const_for_fn.rs15
-rw-r--r--clippy_lints/src/missing_fields_in_debug.rs9
-rw-r--r--clippy_lints/src/missing_inline.rs13
-rw-r--r--clippy_lints/src/mixed_read_write_in_expression.rs46
-rw-r--r--clippy_lints/src/module_style.rs32
-rw-r--r--clippy_lints/src/multiple_unsafe_ops_per_block.rs5
-rw-r--r--clippy_lints/src/mut_key.rs8
-rw-r--r--clippy_lints/src/mut_mut.rs20
-rw-r--r--clippy_lints/src/mutable_debug_assertion.rs11
-rw-r--r--clippy_lints/src/mutex_atomic.rs24
-rw-r--r--clippy_lints/src/needless_bool.rs10
-rw-r--r--clippy_lints/src/needless_pass_by_ref_mut.rs65
-rw-r--r--clippy_lints/src/needless_pass_by_value.rs71
-rw-r--r--clippy_lints/src/needless_update.rs22
-rw-r--r--clippy_lints/src/neg_multiply.rs32
-rw-r--r--clippy_lints/src/new_without_default.rs8
-rw-r--r--clippy_lints/src/no_effect.rs31
-rw-r--r--clippy_lints/src/non_canonical_impls.rs112
-rw-r--r--clippy_lints/src/non_copy_const.rs2
-rw-r--r--clippy_lints/src/non_std_lazy_statics.rs6
-rw-r--r--clippy_lints/src/non_zero_suggestions.rs7
-rw-r--r--clippy_lints/src/operators/cmp_owned.rs2
-rw-r--r--clippy_lints/src/operators/float_equality_without_abs.rs2
-rw-r--r--clippy_lints/src/operators/identity_op.rs2
-rw-r--r--clippy_lints/src/operators/modulo_one.rs18
-rw-r--r--clippy_lints/src/operators/numeric_arithmetic.rs16
-rw-r--r--clippy_lints/src/operators/op_ref.rs19
-rw-r--r--clippy_lints/src/operators/verbose_bit_mask.rs2
-rw-r--r--clippy_lints/src/option_if_let_else.rs15
-rw-r--r--clippy_lints/src/partialeq_ne_impl.rs2
-rw-r--r--clippy_lints/src/partialeq_to_none.rs2
-rw-r--r--clippy_lints/src/pass_by_ref_or_value.rs32
-rw-r--r--clippy_lints/src/pathbuf_init_then_push.rs19
-rw-r--r--clippy_lints/src/pattern_type_mismatch.rs21
-rw-r--r--clippy_lints/src/ptr.rs75
-rw-r--r--clippy_lints/src/ptr_offset_with_cast.rs24
-rw-r--r--clippy_lints/src/question_mark.rs3
-rw-r--r--clippy_lints/src/ranges.rs40
-rw-r--r--clippy_lints/src/rc_clone_in_vec_init.rs6
-rw-r--r--clippy_lints/src/redundant_async_block.rs26
-rw-r--r--clippy_lints/src/redundant_clone.rs69
-rw-r--r--clippy_lints/src/redundant_closure_call.rs2
-rw-r--r--clippy_lints/src/redundant_pub_crate.rs11
-rw-r--r--clippy_lints/src/redundant_slicing.rs33
-rw-r--r--clippy_lints/src/redundant_test_prefix.rs161
-rw-r--r--clippy_lints/src/regex.rs8
-rw-r--r--clippy_lints/src/same_name_method.rs3
-rw-r--r--clippy_lints/src/serde_api.rs40
-rw-r--r--clippy_lints/src/set_contains_or_insert.rs8
-rw-r--r--clippy_lints/src/shadow.rs25
-rw-r--r--clippy_lints/src/significant_drop_tightening.rs32
-rw-r--r--clippy_lints/src/single_char_lifetime_names.rs27
-rw-r--r--clippy_lints/src/single_component_path_imports.rs22
-rw-r--r--clippy_lints/src/strings.rs16
-rw-r--r--clippy_lints/src/suspicious_trait_impl.rs44
-rw-r--r--clippy_lints/src/swap.rs13
-rw-r--r--clippy_lints/src/trait_bounds.rs23
-rw-r--r--clippy_lints/src/transmute/transmute_float_to_int.rs2
-rw-r--r--clippy_lints/src/transmute/transmute_ptr_to_ptr.rs4
-rw-r--r--clippy_lints/src/transmute/transmute_ptr_to_ref.rs4
-rw-r--r--clippy_lints/src/types/mod.rs40
-rw-r--r--clippy_lints/src/unconditional_recursion.rs34
-rw-r--r--clippy_lints/src/unicode.rs8
-rw-r--r--clippy_lints/src/unnecessary_wraps.rs10
-rw-r--r--clippy_lints/src/unnested_or_patterns.rs21
-rw-r--r--clippy_lints/src/unused_io_amount.rs17
-rw-r--r--clippy_lints/src/unwrap.rs8
-rw-r--r--clippy_lints/src/useless_conversion.rs58
-rw-r--r--clippy_lints/src/utils/internal_lints.rs11
-rw-r--r--clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs85
-rw-r--r--clippy_lints/src/utils/internal_lints/collapsible_calls.rs248
-rw-r--r--clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs241
-rw-r--r--clippy_lints/src/utils/internal_lints/invalid_paths.rs106
-rw-r--r--clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs283
-rw-r--r--clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs58
-rw-r--r--clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs59
-rw-r--r--clippy_lints/src/utils/internal_lints/produce_ice.rs41
-rw-r--r--clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs74
-rw-r--r--clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs301
-rw-r--r--clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs49
-rw-r--r--clippy_lints/src/utils/mod.rs3
-rw-r--r--clippy_lints/src/wildcard_imports.rs6
-rw-r--r--clippy_lints/src/zero_sized_map_values.rs8
-rw-r--r--clippy_lints/src/zombie_processes.rs2
237 files changed, 4243 insertions, 4757 deletions
diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs
index 57cabe43703..272444475c0 100644
--- a/clippy_lints/src/arbitrary_source_item_ordering.rs
+++ b/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/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs
index 78102772927..27e304a848e 100644
--- a/clippy_lints/src/as_conversions.rs
+++ b/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/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs
index e5439a6d401..9acff676d4f 100644
--- a/clippy_lints/src/assigning_clones.rs
+++ b/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/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
index fecf3166406..457692ed5dc 100644
--- a/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
+++ b/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/clippy_lints/src/attrs/deprecated_semver.rs b/clippy_lints/src/attrs/deprecated_semver.rs
index d3153ec6613..50943b36809 100644
--- a/clippy_lints/src/attrs/deprecated_semver.rs
+++ b/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/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs
index 4c84e61b1f2..a851daaede7 100644
--- a/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/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/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index e04d2ad5d13..f7f168cb267 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/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/clippy_lints/src/attrs/repr_attributes.rs b/clippy_lints/src/attrs/repr_attributes.rs
index e5cfbaf952a..df01c7fde18 100644
--- a/clippy_lints/src/attrs/repr_attributes.rs
+++ b/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/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs
index 1cb43ab02a3..d75b73280e6 100644
--- a/clippy_lints/src/attrs/useless_attribute.rs
+++ b/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/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs
index 92a0c7f9acb..52d1d5b4c67 100644
--- a/clippy_lints/src/await_holding_invalid.rs
+++ b/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/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs
index 612712d1684..129e7747840 100644
--- a/clippy_lints/src/bool_to_int_with_if.rs
+++ b/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/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index 7bb5dbee126..bc6ba84772b 100644
--- a/clippy_lints/src/booleans.rs
+++ b/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/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs
index 8892a9e6b6b..7cde007a9b6 100644
--- a/clippy_lints/src/borrow_deref_ref.rs
+++ b/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/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs
index 64345c81a24..ad0a4f8cdf3 100644
--- a/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/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/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs
index 8b3529e84fc..164d3540253 100644
--- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs
+++ b/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/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs
index 3ae43732dc0..0f066fae118 100644
--- a/clippy_lints/src/casts/cast_lossless.rs
+++ b/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/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index ca973f4bb1a..8742f5f1a0e 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/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/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs
index 57a135abc2e..3fca0f89707 100644
--- a/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/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/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs
index c48f253606d..a5b295c88b1 100644
--- a/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/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/clippy_lints/src/casts/manual_dangling_ptr.rs b/clippy_lints/src/casts/manual_dangling_ptr.rs
new file mode 100644
index 00000000000..8ace27eca89
--- /dev/null
+++ b/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/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index dc2a1fa85bf..76931fce209 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/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/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs
index d57e391b55d..6f944914b8f 100644
--- a/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/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/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs
index cad9c1df273..2471c735551 100644
--- a/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/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/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 72953818a70..ae994e94a32 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/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/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs
index b36c8662289..8ada608049c 100644
--- a/clippy_lints/src/checked_conversions.rs
+++ b/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/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index a1ff20dee72..1d44c7e9c88 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/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/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs
index e73bfc6ebf7..20fae8a6775 100644
--- a/clippy_lints/src/collapsible_if.rs
+++ b/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/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs
index 0e7f01e44b0..9c3009a86cd 100644
--- a/clippy_lints/src/comparison_chain.rs
+++ b/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/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 03ed9c657b3..42fbe6438d4 100644
--- a/clippy_lints/src/copies.rs
+++ b/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/clippy_lints/src/declare_clippy_lint.rs b/clippy_lints/src/declare_clippy_lint.rs
index 4d908af4084..9f82f876727 100644
--- a/clippy_lints/src/declare_clippy_lint.rs
+++ b/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/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 39e45163707..2cccd6ba270 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/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/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs
index bbd5dc15542..f8a9037fc80 100644
--- a/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/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/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs
index de66ead4f42..b60c11d79d4 100644
--- a/clippy_lints/src/deprecated_lints.rs
+++ b/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/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 849c60b89b9..7da5a530eaa 100644
--- a/clippy_lints/src/dereference.rs
+++ b/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/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index 8d9222e4bf6..10331b3855b 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/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/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index c85aca8d04e..06528f875a2 100644
--- a/clippy_lints/src/derive.rs
+++ b/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/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs
index 4b8a689e994..fc6af204a74 100644
--- a/clippy_lints/src/disallowed_macros.rs
+++ b/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/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs
index 149cf1cf2de..1382dafa931 100644
--- a/clippy_lints/src/disallowed_methods.rs
+++ b/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/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs
index 38903596414..2bae82648ac 100644
--- a/clippy_lints/src/disallowed_types.rs
+++ b/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/clippy_lints/src/doc/markdown.rs b/clippy_lints/src/doc/markdown.rs
index 8cdaba88e50..7a1c7c675d2 100644
--- a/clippy_lints/src/doc/markdown.rs
+++ b/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/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs
index e75abf28bac..039937e0207 100644
--- a/clippy_lints/src/doc/missing_headers.rs
+++ b/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/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index 36fd396cc1d..ab77edf1147 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/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/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs
index bf549dcdb50..ec4538039a9 100644
--- a/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/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/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs
index 617982f4da3..5c360ce6a5f 100644
--- a/clippy_lints/src/drop_forget_ref.rs
+++ b/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/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs
index c67dcd3c82b..0c5f8bbf4ca 100644
--- a/clippy_lints/src/empty_line_after.rs
+++ b/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/clippy_lints/src/empty_with_brackets.rs b/clippy_lints/src/empty_with_brackets.rs
index 7d87f04fef9..a38d6df89f2 100644
--- a/clippy_lints/src/empty_with_brackets.rs
+++ b/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/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index dcfee0b6d3c..182cb4e46d2 100644
--- a/clippy_lints/src/entry.rs
+++ b/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/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs
index f01b5c840d2..ec81294624e 100644
--- a/clippy_lints/src/enum_clike.rs
+++ b/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/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index e248f08789b..2cb3b32babe 100644
--- a/clippy_lints/src/escape.rs
+++ b/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/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs
index f67d38d932b..c868b782f43 100644
--- a/clippy_lints/src/fallible_impl_from.rs
+++ b/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/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index daa199779e3..d5f0659f842 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/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/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index 5e3f6b6a137..94e66769eb2 100644
--- a/clippy_lints/src/format.rs
+++ b/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/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs
index 06224f57c5c..8a3f8e1c587 100644
--- a/clippy_lints/src/format_args.rs
+++ b/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/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index 5b42a40d850..0535ecf5240 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/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/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs
index c8fe7ac73cb..4b482f7b233 100644
--- a/clippy_lints/src/formatting.rs
+++ b/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/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs
index 7361546153c..25b087e8484 100644
--- a/clippy_lints/src/from_str_radix_10.rs
+++ b/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/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs
index 854fe144c29..fa63876410f 100644
--- a/clippy_lints/src/functions/misnamed_getters.rs
+++ b/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/clippy_lints/src/functions/renamed_function_params.rs b/clippy_lints/src/functions/renamed_function_params.rs
index 4495aeb5953..2d22bb157a9 100644
--- a/clippy_lints/src/functions/renamed_function_params.rs
+++ b/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/clippy_lints/src/functions/too_many_arguments.rs b/clippy_lints/src/functions/too_many_arguments.rs
index 05dc47f6fe5..48d050aa36a 100644
--- a/clippy_lints/src/functions/too_many_arguments.rs
+++ b/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/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index fbbd33efd02..9e94280fc07 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/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/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs
index 5f95464e4d4..076017a247b 100644
--- a/clippy_lints/src/implicit_return.rs
+++ b/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/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 5d7d3ae3f24..514e72a4868 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/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/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs
index 430f2411183..6b89abdb036 100644
--- a/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/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/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs
index e1dd7872b9d..e6129757e56 100644
--- a/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/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/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs
index 33431385c7d..99a393b4d53 100644
--- a/clippy_lints/src/indexing_slicing.rs
+++ b/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/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs
index 960b9aa032b..427a1f82555 100644
--- a/clippy_lints/src/infinite_iter.rs
+++ b/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/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs
index 4ae1119ab3a..91f65d0b79c 100644
--- a/clippy_lints/src/instant_subtraction.rs
+++ b/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/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs
index fc575bff7e6..67ce57de254 100644
--- a/clippy_lints/src/int_plus_one.rs
+++ b/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/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs
index b42664340d1..b0ecc5d52dd 100644
--- a/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/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/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs
index 977fd5fce15..b1271a264b5 100644
--- a/clippy_lints/src/item_name_repetitions.rs
+++ b/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/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 77085d52a32..8c71d34c95f 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/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/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 3fe3cd67e16..5fa8f6f4bf3 100644
--- a/clippy_lints/src/lib.rs
+++ b/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/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index dabef18b98a..5ef5e3a44f8 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/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/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index 805de23408b..7cbfa2d097a 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/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/clippy_lints/src/literal_string_with_formatting_args.rs b/clippy_lints/src/literal_string_with_formatting_args.rs
index 975e6833a35..244e7c95122 100644
--- a/clippy_lints/src/literal_string_with_formatting_args.rs
+++ b/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/clippy_lints/src/loops/char_indices_as_byte_indices.rs b/clippy_lints/src/loops/char_indices_as_byte_indices.rs
new file mode 100644
index 00000000000..8916454ada1
--- /dev/null
+++ b/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/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs
index 412c78cc804..d0b26c91ffa 100644
--- a/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/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/clippy_lints/src/loops/for_kv_map.rs b/clippy_lints/src/loops/for_kv_map.rs
index 185d834beca..e314bc2068b 100644
--- a/clippy_lints/src/loops/for_kv_map.rs
+++ b/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/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs
index aa8a2934f89..35737f3eafe 100644
--- a/clippy_lints/src/loops/manual_find.rs
+++ b/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/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs
index 701567a7d84..d9c4b526da9 100644
--- a/clippy_lints/src/loops/manual_memcpy.rs
+++ b/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/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs
index 4473a3343c7..9527e258db8 100644
--- a/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/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/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index 4b0bf5a4b3c..2b66827e82e 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/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/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs
index a24dd44790e..70ca452013f 100644
--- a/clippy_lints/src/loops/mut_range_bound.rs
+++ b/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/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index 0f62183eb33..7837b18bcd3 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/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/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index c3a2a38b5ec..69c84bc7038 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/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/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs
index 3c6fbef2bda..2f6950b4380 100644
--- a/clippy_lints/src/loops/utils.rs
+++ b/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/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs
index df6e85611fb..9071c9c95f9 100644
--- a/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/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/clippy_lints/src/manual_abs_diff.rs b/clippy_lints/src/manual_abs_diff.rs
new file mode 100644
index 00000000000..c515e41f242
--- /dev/null
+++ b/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/clippy_lints/src/manual_assert.rs b/clippy_lints/src/manual_assert.rs
index 83c16d4466d..8378e15c581 100644
--- a/clippy_lints/src/manual_assert.rs
+++ b/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/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs
index 50c8331eeba..02afe9f0997 100644
--- a/clippy_lints/src/manual_clamp.rs
+++ b/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/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs
index 9944c4f8804..444ecd5d2bb 100644
--- a/clippy_lints/src/manual_div_ceil.rs
+++ b/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/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs
index faf01a276a1..8ab49bd2ea8 100644
--- a/clippy_lints/src/manual_is_ascii_check.rs
+++ b/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/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
index 841adfec462..b4cd988329d 100644
--- a/clippy_lints/src/manual_is_power_of_two.rs
+++ b/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/clippy_lints/src/manual_option_as_slice.rs b/clippy_lints/src/manual_option_as_slice.rs
index 8dee29b2a0b..e4ad3953b67 100644
--- a/clippy_lints/src/manual_option_as_slice.rs
+++ b/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/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs
index 16dd1ad4e47..98e8b1f5cf9 100644
--- a/clippy_lints/src/manual_retain.rs
+++ b/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/clippy_lints/src/manual_rotate.rs b/clippy_lints/src/manual_rotate.rs
index 07537fc65c0..06ee00c2cef 100644
--- a/clippy_lints/src/manual_rotate.rs
+++ b/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/clippy_lints/src/manual_string_new.rs b/clippy_lints/src/manual_string_new.rs
index 5c2a711b5cb..7ca3b712066 100644
--- a/clippy_lints/src/manual_string_new.rs
+++ b/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/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs
deleted file mode 100644
index 87d2faa225c..00000000000
--- a/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/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index 56aead85e7c..b607f8117eb 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/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/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index 6f446bf9565..5b50efad3e4 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/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/clippy_lints/src/matches/manual_filter.rs b/clippy_lints/src/matches/manual_filter.rs
index 4cc43e427ec..abf723fa6f4 100644
--- a/clippy_lints/src/matches/manual_filter.rs
+++ b/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/clippy_lints/src/matches/manual_ok_err.rs b/clippy_lints/src/matches/manual_ok_err.rs
index 576e42a564c..4959908dad6 100644
--- a/clippy_lints/src/matches/manual_ok_err.rs
+++ b/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/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs
index 2bf7ec8ab7d..b64ae0b24d8 100644
--- a/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/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/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs
index d29d1ea3e96..f14b69d91ce 100644
--- a/clippy_lints/src/matches/match_like_matches.rs
+++ b/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/clippy_lints/src/matches/match_on_vec_items.rs b/clippy_lints/src/matches/match_on_vec_items.rs
deleted file mode 100644
index dd71560e169..00000000000
--- a/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/clippy_lints/src/matches/match_single_binding.rs b/clippy_lints/src/matches/match_single_binding.rs
index 864923b2773..adda3586990 100644
--- a/clippy_lints/src/matches/match_single_binding.rs
+++ b/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/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs
index df1b83cbb51..65b93a095b9 100644
--- a/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/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/clippy_lints/src/matches/match_wild_enum.rs b/clippy_lints/src/matches/match_wild_enum.rs
index 11b588b3355..24b4a675800 100644
--- a/clippy_lints/src/matches/match_wild_enum.rs
+++ b/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/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs
index d0d2025878e..8ce8453360f 100644
--- a/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/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/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index 2b9173e6f41..c6ebd6144c7 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/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/clippy_lints/src/matches/needless_match.rs b/clippy_lints/src/matches/needless_match.rs
index 7e65d586110..6c5d7cab203 100644
--- a/clippy_lints/src/matches/needless_match.rs
+++ b/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/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs
index 4184f8b9e6e..d3136c89178 100644
--- a/clippy_lints/src/matches/overlapping_arms.rs
+++ b/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/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs
index 722ea7042dd..db20be40f27 100644
--- a/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/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/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 37bac561a6e..d7dc7604088 100644
--- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/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/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index 836c46240ce..08c0caa4266 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/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/clippy_lints/src/matches/wild_in_or_pats.rs b/clippy_lints/src/matches/wild_in_or_pats.rs
index b75d1ab9a7a..43102d78bfe 100644
--- a/clippy_lints/src/matches/wild_in_or_pats.rs
+++ b/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/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index a0919947b3f..a54d835b538 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/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/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs
index 1e9b29f567f..f8520c23ea5 100644
--- a/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/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/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index 18568e3661f..d07870d4951 100644
--- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/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/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs
index 1ee27d90d05..2ecf3eb8979 100644
--- a/clippy_lints/src/methods/clone_on_copy.rs
+++ b/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/clippy_lints/src/methods/double_ended_iterator_last.rs b/clippy_lints/src/methods/double_ended_iterator_last.rs
index b5adc69e9a7..e666f31217c 100644
--- a/clippy_lints/src/methods/double_ended_iterator_last.rs
+++ b/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/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs
index daa6e0e7f94..f5688e370a4 100644
--- a/clippy_lints/src/methods/expect_fun_call.rs
+++ b/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/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs
index ae300cd5fe5..da123f13d46 100644
--- a/clippy_lints/src/methods/filter_map.rs
+++ b/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/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs
index f7e116c5310..965993808f6 100644
--- a/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/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/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index f4840785584..045363058d1 100644
--- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/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/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs
index 4c81b22861b..545bef1a4c5 100644
--- a/clippy_lints/src/methods/is_empty.rs
+++ b/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/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs
index 49de83885a1..17cc07b91c5 100644
--- a/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/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/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs
index bafabec7e06..adeff375c8a 100644
--- a/clippy_lints/src/methods/iter_filter.rs
+++ b/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/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs
index 94415fc9106..3ac9299ba91 100644
--- a/clippy_lints/src/methods/iter_kv_map.rs
+++ b/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/clippy_lints/src/methods/iterator_step_by_zero.rs b/clippy_lints/src/methods/iterator_step_by_zero.rs
index 9b358235a40..90d5d9df55e 100644
--- a/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/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/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 13918ed11b8..18978a1d2bc 100644
--- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/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/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs
index 098721dc046..8167e4f9605 100644
--- a/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/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/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs
index 128b3695f48..333a33f7527 100644
--- a/clippy_lints/src/methods/map_clone.rs
+++ b/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/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
index 6cf0936c598..a2a522a6068 100644
--- a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
+++ b/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/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 1d9296016e2..ad374dee516 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/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/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs
index e4a29b6560e..6efaba525e3 100644
--- a/clippy_lints/src/methods/needless_collect.rs
+++ b/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/clippy_lints/src/methods/needless_option_take.rs b/clippy_lints/src/methods/needless_option_take.rs
index 88b9c69f6f9..cd1b97f3c51 100644
--- a/clippy_lints/src/methods/needless_option_take.rs
+++ b/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/clippy_lints/src/methods/obfuscated_if_else.rs b/clippy_lints/src/methods/obfuscated_if_else.rs
index 9a5ffdeaf4e..1cc56de4876 100644
--- a/clippy_lints/src/methods/obfuscated_if_else.rs
+++ b/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/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index 6eeeea5d77c..b78b082e460 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/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/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs
index d318462e584..8b51268da46 100644
--- a/clippy_lints/src/methods/seek_from_current.rs
+++ b/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/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index 7b1dd9e58c5..b8405a78f23 100644
--- a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/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/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs
index 4ccefb7ec9d..d183457da25 100644
--- a/clippy_lints/src/methods/str_splitn.rs
+++ b/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/clippy_lints/src/methods/suspicious_map.rs b/clippy_lints/src/methods/suspicious_map.rs
index 1bd48525f12..788014d9bb6 100644
--- a/clippy_lints/src/methods/suspicious_map.rs
+++ b/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/clippy_lints/src/methods/swap_with_temporary.rs b/clippy_lints/src/methods/swap_with_temporary.rs
new file mode 100644
index 00000000000..de729fb343a
--- /dev/null
+++ b/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/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs
index ca42a9ac04e..f920f306bc1 100644
--- a/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/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/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 9f4080100da..71e606add52 100644
--- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/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/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs
index d7bd522ddab..b90748dd158 100644
--- a/clippy_lints/src/methods/unnecessary_map_or.rs
+++ b/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/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index 3611b341897..b0cc7a785bc 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/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/clippy_lints/src/misc_early/builtin_type_shadow.rs b/clippy_lints/src/misc_early/builtin_type_shadow.rs
index 662f7cd8500..9ee1e2f3fd1 100644
--- a/clippy_lints/src/misc_early/builtin_type_shadow.rs
+++ b/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/clippy_lints/src/misc_early/redundant_pattern.rs b/clippy_lints/src/misc_early/redundant_pattern.rs
index d5b5b2bf2dd..3cb51671aaf 100644
--- a/clippy_lints/src/misc_early/redundant_pattern.rs
+++ b/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/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs b/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
index 00f46629f10..fffaf40c9d1 100644
--- a/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs
+++ b/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/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs
index d52fe7e7d5b..394bc4aef1c 100644
--- a/clippy_lints/src/mismatching_type_param_order.rs
+++ b/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/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs
index cdd6f4e5b03..c8e3462b24e 100644
--- a/clippy_lints/src/missing_asserts_for_indexing.rs
+++ b/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/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs
index 38a19dd2999..67537a251da 100644
--- a/clippy_lints/src/missing_const_for_fn.rs
+++ b/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/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs
index 28dc2427428..1932d2d5f97 100644
--- a/clippy_lints/src/missing_fields_in_debug.rs
+++ b/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/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs
index f49e03ea765..1f613171b46 100644
--- a/clippy_lints/src/missing_inline.rs
+++ b/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/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs
index fbd287f5285..0e085585962 100644
--- a/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/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/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index 7287193326f..98614baffce 100644
--- a/clippy_lints/src/module_style.rs
+++ b/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/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 2adc27c0b70..c6c27e22b90 100644
--- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/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/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index 7abc5870d00..a45031ce22b 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/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/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs
index 3c4ba5141dd..d98c70e7f5a 100644
--- a/clippy_lints/src/mut_mut.rs
+++ b/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/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs
index 13a23a13b9c..270eebe0758 100644
--- a/clippy_lints/src/mutable_debug_assertion.rs
+++ b/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/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs
index 49fd29d1dd6..fe2157ca533 100644
--- a/clippy_lints/src/mutex_atomic.rs
+++ b/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/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs
index 2eacd6875d6..f768e11a4a2 100644
--- a/clippy_lints/src/needless_bool.rs
+++ b/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/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs
index b61061d076b..7052e1d0fbe 100644
--- a/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/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/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 978fde33d51..275d710c76a 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/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/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs
index cce0617ba39..4a86c3720ca 100644
--- a/clippy_lints/src/needless_update.rs
+++ b/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/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs
index 429afff9b66..74c8142787e 100644
--- a/clippy_lints/src/neg_multiply.rs
+++ b/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/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index 1e469c3b63a..4b73a4455f5 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/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/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 7187a8f2c11..7ab7976d569 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/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/clippy_lints/src/non_canonical_impls.rs b/clippy_lints/src/non_canonical_impls.rs
index 448bb603cf2..93865197ec9 100644
--- a/clippy_lints/src/non_canonical_impls.rs
+++ b/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/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 9b53608ae7f..63859c0396e 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/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/clippy_lints/src/non_std_lazy_statics.rs b/clippy_lints/src/non_std_lazy_statics.rs
index 8305bf345ef..f6bc9428d65 100644
--- a/clippy_lints/src/non_std_lazy_statics.rs
+++ b/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/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index 16c4391c0fb..635f5678e2a 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/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/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs
index cf6b8992973..9b2cfd91b85 100644
--- a/clippy_lints/src/operators/cmp_owned.rs
+++ b/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/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs
index 74e0a6333db..047a5a0159c 100644
--- a/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/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/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs
index 03582322827..e1fd09549a4 100644
--- a/clippy_lints/src/operators/identity_op.rs
+++ b/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/clippy_lints/src/operators/modulo_one.rs b/clippy_lints/src/operators/modulo_one.rs
index fc5565e821e..2e6a071eb18 100644
--- a/clippy_lints/src/operators/modulo_one.rs
+++ b/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/clippy_lints/src/operators/numeric_arithmetic.rs b/clippy_lints/src/operators/numeric_arithmetic.rs
index 96c9775e292..e6be536ca0f 100644
--- a/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/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/clippy_lints/src/operators/op_ref.rs b/clippy_lints/src/operators/op_ref.rs
index 378fed481f4..0faa7b9e646 100644
--- a/clippy_lints/src/operators/op_ref.rs
+++ b/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/clippy_lints/src/operators/verbose_bit_mask.rs b/clippy_lints/src/operators/verbose_bit_mask.rs
index a6aba33e431..14773789141 100644
--- a/clippy_lints/src/operators/verbose_bit_mask.rs
+++ b/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/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index 6f302ea1962..9487cec87ef 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/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/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs
index 65671b478ba..8eaf65e6306 100644
--- a/clippy_lints/src/partialeq_ne_impl.rs
+++ b/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/clippy_lints/src/partialeq_to_none.rs b/clippy_lints/src/partialeq_to_none.rs
index 6d4216970cc..9b9024c8105 100644
--- a/clippy_lints/src/partialeq_to_none.rs
+++ b/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/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index 0a8e2885648..5d30b66def2 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/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/clippy_lints/src/pathbuf_init_then_push.rs b/clippy_lints/src/pathbuf_init_then_push.rs
index b653b459b04..35caac855cf 100644
--- a/clippy_lints/src/pathbuf_init_then_push.rs
+++ b/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/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs
index 96d3f7196c0..19d9acfc930 100644
--- a/clippy_lints/src/pattern_type_mismatch.rs
+++ b/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/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 901a1634ddc..491961408ad 100644
--- a/clippy_lints/src/ptr.rs
+++ b/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/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs
index 68ae575c906..7f74a2fff9f 100644
--- a/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/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/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index a80e1f79bbc..d318897443d 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/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/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index cc423eca74f..d292ed86ea4 100644
--- a/clippy_lints/src/ranges.rs
+++ b/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/clippy_lints/src/rc_clone_in_vec_init.rs b/clippy_lints/src/rc_clone_in_vec_init.rs
index 6bb7650a7e1..689a2ac4c6a 100644
--- a/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/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/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs
index 8289ec47bc7..d2442ad0f37 100644
--- a/clippy_lints/src/redundant_async_block.rs
+++ b/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/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index cfa622aea58..e57b8cc2d84 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/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/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index 1498a49a7a4..84597269a58 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/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/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs
index f2fdac5a8af..7b381fac5f1 100644
--- a/clippy_lints/src/redundant_pub_crate.rs
+++ b/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/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs
index 7038b19d275..1117dea703c 100644
--- a/clippy_lints/src/redundant_slicing.rs
+++ b/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/clippy_lints/src/redundant_test_prefix.rs b/clippy_lints/src/redundant_test_prefix.rs
new file mode 100644
index 00000000000..84276e32165
--- /dev/null
+++ b/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/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index 9443dca154e..834ff2af0e8 100644
--- a/clippy_lints/src/regex.rs
+++ b/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/clippy_lints/src/same_name_method.rs b/clippy_lints/src/same_name_method.rs
index 33815cc3bac..226e8ff6adb 100644
--- a/clippy_lints/src/same_name_method.rs
+++ b/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/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs
index 6a0dfde2d9c..a8c6518b592 100644
--- a/clippy_lints/src/serde_api.rs
+++ b/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/clippy_lints/src/set_contains_or_insert.rs b/clippy_lints/src/set_contains_or_insert.rs
index 1185d67b125..ff6e6ef214b 100644
--- a/clippy_lints/src/set_contains_or_insert.rs
+++ b/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/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index b82ddedd56c..14399867f31 100644
--- a/clippy_lints/src/shadow.rs
+++ b/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/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs
index 76874cc3420..ccb1209c6fc 100644
--- a/clippy_lints/src/significant_drop_tightening.rs
+++ b/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/clippy_lints/src/single_char_lifetime_names.rs b/clippy_lints/src/single_char_lifetime_names.rs
index 50a6ee316c8..8c34da0d14a 100644
--- a/clippy_lints/src/single_char_lifetime_names.rs
+++ b/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/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs
index 35f80b2acda..62939912304 100644
--- a/clippy_lints/src/single_component_path_imports.rs
+++ b/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/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 27c548bed9f..43a3e696105 100644
--- a/clippy_lints/src/strings.rs
+++ b/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/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs
index 56bd8fefdb4..83241f97a99 100644
--- a/clippy_lints/src/suspicious_trait_impl.rs
+++ b/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/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs
index 0337b74b4b1..e3ecd6508bf 100644
--- a/clippy_lints/src/swap.rs
+++ b/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/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index fa36c9a21f6..8aac3a59102 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/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/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index f2c757952af..df2f681a162 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/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/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
index fcc763763bd..933e25fe98c 100644
--- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
+++ b/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/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index 45ee83c78ab..e58212fae15 100644
--- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/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/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs
index b6f4c4d7f0a..3147058b4cd 100644
--- a/clippy_lints/src/types/mod.rs
+++ b/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/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs
index 0c17cc5d8f6..d321c48f6af 100644
--- a/clippy_lints/src/unconditional_recursion.rs
+++ b/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/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs
index e1fc644e4ce..79571b0409d 100644
--- a/clippy_lints/src/unicode.rs
+++ b/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/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs
index 937e35dea96..bcd05cceca9 100644
--- a/clippy_lints/src/unnecessary_wraps.rs
+++ b/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/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index 8966e6851ac..9ad184450de 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/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/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index 0687fc319af..2d88c490b1a 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/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/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index b466a8e127a..ce82b56eb94 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/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/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs
index 57bb2fc27f1..3a9c997a579 100644
--- a/clippy_lints/src/useless_conversion.rs
+++ b/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/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
deleted file mode 100644
index deb983b6971..00000000000
--- a/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/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
deleted file mode 100644
index 0a01a364a75..00000000000
--- a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-use crate::utils::internal_lints::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_session::impl_lint_pass;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks if lint formulations have a standardized format.
-    ///
-    /// ### Why is this bad?
-    /// It's not necessarily bad, but we try to enforce a standard in Clippy.
-    ///
-    /// ### Example
-    /// `Checks for use...` can be written as `Checks for usage...` .
-    pub ALMOST_STANDARD_LINT_FORMULATION,
-    internal,
-    "lint formulations must have a standardized format."
-}
-
-impl_lint_pass!(AlmostStandardFormulation => [ALMOST_STANDARD_LINT_FORMULATION]);
-
-pub struct AlmostStandardFormulation {
-    standard_formulations: Vec<StandardFormulations<'static>>,
-}
-
-#[derive(Debug)]
-struct StandardFormulations<'a> {
-    wrong_pattern: Regex,
-    correction: &'a str,
-}
-
-impl AlmostStandardFormulation {
-    pub fn new() -> Self {
-        let standard_formulations = vec![StandardFormulations {
-            wrong_pattern: Regex::new("^(Check for|Detects? uses?)").unwrap(),
-            correction: "Checks for",
-        }];
-        Self { standard_formulations }
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        let mut check_next = false;
-        if let ItemKind::Static(_, ty, Mutability::Not, _) = item.kind {
-            let lines = cx
-                .tcx
-                .hir_attrs(item.hir_id())
-                .iter()
-                .filter_map(|attr| Attribute::doc_str(attr).map(|sym| (sym, attr)));
-            if is_lint_ref_type(cx, ty) {
-                for (line, attr) in lines {
-                    let cur_line = line.as_str().trim();
-                    if check_next && !cur_line.is_empty() {
-                        for formulation in &self.standard_formulations {
-                            let starts_with_correct_formulation = cur_line.starts_with(formulation.correction);
-                            if !starts_with_correct_formulation && formulation.wrong_pattern.is_match(cur_line) {
-                                if let Some(ident) = attr.ident() {
-                                    span_lint_and_help(
-                                        cx,
-                                        ALMOST_STANDARD_LINT_FORMULATION,
-                                        ident.span,
-                                        "non-standard lint formulation",
-                                        None,
-                                        format!("consider using `{}`", formulation.correction),
-                                    );
-                                }
-                                return;
-                            }
-                        }
-                        return;
-                    } else if cur_line.contains("What it does") {
-                        check_next = true;
-                    } else if cur_line.contains("Why is this bad") {
-                        // Formulation documentation is done. Can add check to ensure that missing formulation is added
-                        // and add a check if it matches no accepted formulation
-                        return;
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
deleted file mode 100644
index 2e6fb7c4ce4..00000000000
--- a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ /dev/null
@@ -1,248 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
-use clippy_utils::{SpanlessEq, is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt};
-use rustc_errors::Applicability;
-use rustc_hir::{Closure, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
-use rustc_span::Span;
-
-use std::borrow::{Borrow, Cow};
-
-declare_clippy_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
-    /// call to `span_suggestion`, `span_help`, `span_note` (using the same
-    /// span), `help` or `note`.
-    ///
-    /// These usages of `span_lint_and_then` should be replaced with one of the
-    /// wrapper functions `span_lint_and_sugg`, span_lint_and_help`, or
-    /// `span_lint_and_note`.
-    ///
-    /// ### Why is this bad?
-    /// Using the wrapper `span_lint_and_*` functions, is more
-    /// convenient, readable and less error prone.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
-    ///     diag.span_suggestion(
-    ///         expr.span,
-    ///         help_msg,
-    ///         sugg.to_string(),
-    ///         Applicability::MachineApplicable,
-    ///     );
-    /// });
-    /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
-    ///     diag.span_help(expr.span, help_msg);
-    /// });
-    /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
-    ///     diag.help(help_msg);
-    /// });
-    /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
-    ///     diag.span_note(expr.span, note_msg);
-    /// });
-    /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
-    ///     diag.note(note_msg);
-    /// });
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust,ignore
-    /// span_lint_and_sugg(
-    ///     cx,
-    ///     TEST_LINT,
-    ///     expr.span,
-    ///     lint_msg,
-    ///     help_msg,
-    ///     sugg.to_string(),
-    ///     Applicability::MachineApplicable,
-    /// );
-    /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg);
-    /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg);
-    /// 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"
-}
-
-declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
-
-impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if is_lint_allowed(cx, COLLAPSIBLE_SPAN_LINT_CALLS, expr.hir_id) {
-            return;
-        }
-
-        if let ExprKind::Call(func, [call_cx, call_lint, call_sp, call_msg, call_f]) = expr.kind
-            && is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"])
-            && let ExprKind::Closure(&Closure { body, .. }) = call_f.kind
-            && let body = cx.tcx.hir_body(body)
-            && let only_expr = peel_blocks_with_stmt(body.value)
-            && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind
-            && let ExprKind::Path(..) = recv.kind
-        {
-            let and_then_snippets =
-                get_and_then_snippets(cx, call_cx.span, call_lint.span, call_sp.span, call_msg.span);
-            let mut sle = SpanlessEq::new(cx).deny_side_effects();
-            match ps.ident.as_str() {
-                "span_suggestion" if sle.eq_expr(call_sp, &span_call_args[0]) => {
-                    suggest_suggestion(
-                        cx,
-                        expr,
-                        &and_then_snippets,
-                        &span_suggestion_snippets(cx, span_call_args),
-                    );
-                },
-                "span_help" if sle.eq_expr(call_sp, &span_call_args[0]) => {
-                    let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
-                    suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true);
-                },
-                "span_note" if sle.eq_expr(call_sp, &span_call_args[0]) => {
-                    let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
-                    suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true);
-                },
-                "help" => {
-                    let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
-                    suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false);
-                },
-                "note" => {
-                    let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
-                    suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false);
-                },
-                _ => (),
-            }
-        }
-    }
-}
-
-struct AndThenSnippets<'a> {
-    cx: Cow<'a, str>,
-    lint: Cow<'a, str>,
-    span: Cow<'a, str>,
-    msg: Cow<'a, str>,
-}
-
-fn get_and_then_snippets(
-    cx: &LateContext<'_>,
-    cx_span: Span,
-    lint_span: Span,
-    span_span: Span,
-    msg_span: Span,
-) -> AndThenSnippets<'static> {
-    let cx_snippet = snippet(cx, cx_span, "cx");
-    let lint_snippet = snippet(cx, lint_span, "..");
-    let span_snippet = snippet(cx, span_span, "span");
-    let msg_snippet = snippet(cx, msg_span, r#""...""#);
-
-    AndThenSnippets {
-        cx: cx_snippet,
-        lint: lint_snippet,
-        span: span_snippet,
-        msg: msg_snippet,
-    }
-}
-
-struct SpanSuggestionSnippets<'a> {
-    help: Cow<'a, str>,
-    sugg: Cow<'a, str>,
-    applicability: Cow<'a, str>,
-}
-
-fn span_suggestion_snippets<'a, 'hir>(
-    cx: &LateContext<'_>,
-    span_call_args: &'hir [Expr<'hir>],
-) -> SpanSuggestionSnippets<'a> {
-    let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
-    let sugg_snippet = snippet(cx, span_call_args[2].span, "..");
-    let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable");
-
-    SpanSuggestionSnippets {
-        help: help_snippet,
-        sugg: sugg_snippet,
-        applicability: applicability_snippet,
-    }
-}
-
-fn suggest_suggestion(
-    cx: &LateContext<'_>,
-    expr: &Expr<'_>,
-    and_then_snippets: &AndThenSnippets<'_>,
-    span_suggestion_snippets: &SpanSuggestionSnippets<'_>,
-) {
-    span_lint_and_sugg(
-        cx,
-        COLLAPSIBLE_SPAN_LINT_CALLS,
-        expr.span,
-        "this call is collapsible",
-        "collapse into",
-        format!(
-            "span_lint_and_sugg({}, {}, {}, {}, {}, {}, {})",
-            and_then_snippets.cx,
-            and_then_snippets.lint,
-            and_then_snippets.span,
-            and_then_snippets.msg,
-            span_suggestion_snippets.help,
-            span_suggestion_snippets.sugg,
-            span_suggestion_snippets.applicability
-        ),
-        Applicability::MachineApplicable,
-    );
-}
-
-fn suggest_help(
-    cx: &LateContext<'_>,
-    expr: &Expr<'_>,
-    and_then_snippets: &AndThenSnippets<'_>,
-    help: &str,
-    with_span: bool,
-) {
-    let option_span = if with_span {
-        format!("Some({})", and_then_snippets.span)
-    } else {
-        "None".to_string()
-    };
-
-    span_lint_and_sugg(
-        cx,
-        COLLAPSIBLE_SPAN_LINT_CALLS,
-        expr.span,
-        "this call is collapsible",
-        "collapse into",
-        format!(
-            "span_lint_and_help({}, {}, {}, {}, {}, {help})",
-            and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span,
-        ),
-        Applicability::MachineApplicable,
-    );
-}
-
-fn suggest_note(
-    cx: &LateContext<'_>,
-    expr: &Expr<'_>,
-    and_then_snippets: &AndThenSnippets<'_>,
-    note: &str,
-    with_span: bool,
-) {
-    let note_span = if with_span {
-        format!("Some({})", and_then_snippets.span)
-    } else {
-        "None".to_string()
-    };
-
-    span_lint_and_sugg(
-        cx,
-        COLLAPSIBLE_SPAN_LINT_CALLS,
-        expr.span,
-        "this call is collapsible",
-        "collapse into",
-        format!(
-            "span_lint_and_note({}, {}, {}, {}, {note_span}, {note})",
-            and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg,
-        ),
-        Applicability::MachineApplicable,
-    );
-}
diff --git a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
deleted file mode 100644
index e454427adde..00000000000
--- a/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/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/clippy_lints/src/utils/internal_lints/invalid_paths.rs
deleted file mode 100644
index 252ac5e6768..00000000000
--- a/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant};
-use clippy_utils::def_path_res;
-use clippy_utils::diagnostics::span_lint;
-use rustc_hir as hir;
-use rustc_hir::Item;
-use rustc_hir::def::DefKind;
-use rustc_lint::{LateContext, LateLintPass};
-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! {
-    /// ### What it does
-    /// Checks the paths module for invalid paths.
-    ///
-    /// ### Why is this bad?
-    /// It indicates a bug in the code.
-    ///
-    /// ### Example
-    /// None.
-    pub INVALID_PATHS,
-    internal,
-    "invalid path"
-}
-
-declare_lint_pass!(InvalidPaths => [INVALID_PATHS]);
-
-impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        let local_def_id = &cx.tcx.parent_module(item.hir_id());
-        let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
-        if mod_name.as_str() == "paths"
-            && let hir::ItemKind::Const(.., body_id) = item.kind
-            && let Some(Constant::Vec(path)) = ConstEvalCtxt::with_env(
-                cx.tcx,
-                ty::TypingEnv::post_analysis(cx.tcx, item.owner_id),
-                cx.tcx.typeck(item.owner_id),
-            )
-            .eval_simple(cx.tcx.hir_body(body_id).value)
-            && let Some(path) = path
-                .iter()
-                .map(|x| {
-                    if let Constant::Str(s) = x {
-                        Some(s.as_str())
-                    } else {
-                        None
-                    }
-                })
-                .collect::<Option<Vec<&str>>>()
-            && !check_path(cx, &path[..])
-        {
-            span_lint(cx, INVALID_PATHS, item.span, "invalid path");
-        }
-    }
-}
-
-// This is not a complete resolver for paths. It works on all the paths currently used in the paths
-// module.  That's all it does and all it needs to do.
-pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
-    if !def_path_res(cx.tcx, path).is_empty() {
-        return true;
-    }
-
-    // Some implementations can't be found by `path_to_res`, particularly inherent
-    // implementations of native types. Check lang items.
-    let path_syms: Vec<_> = path.iter().map(|p| Symbol::intern(p)).collect();
-    let lang_items = cx.tcx.lang_items();
-    // This list isn't complete, but good enough for our current list of paths.
-    let incoherent_impls = [
-        SimplifiedType::Float(FloatTy::F32),
-        SimplifiedType::Float(FloatTy::F64),
-        SimplifiedType::Slice,
-        SimplifiedType::Str,
-        SimplifiedType::Bool,
-        SimplifiedType::Char,
-    ]
-    .iter()
-    .flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter())
-    .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;
-                        }
-                    }
-                } else {
-                    for child in cx.tcx.associated_item_def_ids(item_def_id) {
-                        if cx.tcx.item_name(*child) == *item {
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    false
-}
diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
deleted file mode 100644
index 94a2e598522..00000000000
--- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ /dev/null
@@ -1,283 +0,0 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::macros::root_macro_call_first_node;
-use clippy_utils::{is_lint_allowed, match_def_path, paths};
-use rustc_ast::ast::LitKind;
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-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_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! {
-    /// ### What it does
-    /// Ensures every lint is associated to a `LintPass`.
-    ///
-    /// ### Why is this bad?
-    /// The compiler only knows lints via a `LintPass`. Without
-    /// putting a lint to a `LintPass::lint_vec()`'s return, the compiler will not
-    /// know the name of the lint.
-    ///
-    /// ### Known problems
-    /// Only checks for lints associated using the `declare_lint_pass!` and
-    /// `impl_lint_pass!` macros.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// declare_lint! { pub LINT_1, ... }
-    /// declare_lint! { pub LINT_2, ... }
-    /// declare_lint! { pub FORGOTTEN_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"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for cases of an auto-generated lint without an updated description,
-    /// i.e. `default lint description`.
-    ///
-    /// ### Why is this bad?
-    /// Indicates that the lint is not finished.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// declare_lint! { pub COOL_LINT, nursery, "default lint description" }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust,ignore
-    /// declare_lint! { pub COOL_LINT, nursery, "a great new lint" }
-    /// ```
-    pub DEFAULT_LINT,
-    internal,
-    "found 'default lint description' in a lint declaration"
-}
-
-declare_clippy_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"
-}
-
-declare_clippy_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"
-}
-
-#[derive(Clone, Debug, Default)]
-pub struct LintWithoutLintPass {
-    declared_lints: FxIndexMap<Symbol, Span>,
-    registered_lints: FxIndexSet<Symbol>,
-}
-
-impl_lint_pass!(LintWithoutLintPass => [
-    DEFAULT_LINT,
-    LINT_WITHOUT_LINT_PASS,
-    INVALID_CLIPPY_VERSION_ATTRIBUTE,
-    MISSING_CLIPPY_VERSION_ATTRIBUTE,
-]);
-
-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);
-
-                let expr = &cx.tcx.hir_body(body_id).value;
-                let fields = if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
-                    && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind
-                {
-                    struct_fields
-                } else {
-                    return;
-                };
-
-                let field = fields
-                    .iter()
-                    .find(|f| f.ident.as_str() == "desc")
-                    .expect("lints must have a description field");
-
-                if let ExprKind::Lit(Spanned {
-                    node: LitKind::Str(sym, _),
-                    ..
-                }) = field.expr.kind
-                {
-                    let sym_str = sym.as_str();
-                    if sym_str == "default lint description" {
-                        span_lint(
-                            cx,
-                            DEFAULT_LINT,
-                            item.span,
-                            format!("the lint `{}` has the default lint description", ident.name),
-                        );
-                    }
-                    self.declared_lints.insert(ident.name, item.span);
-                }
-            }
-        } else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
-            if !matches!(
-                cx.tcx.item_name(macro_call.def_id).as_str(),
-                "impl_lint_pass" | "declare_lint_pass"
-            ) {
-                return;
-            }
-            if let hir::ItemKind::Impl(hir::Impl {
-                of_trait: None,
-                items: impl_item_refs,
-                ..
-            }) = item.kind
-            {
-                let mut collector = LintCollector {
-                    output: &mut self.registered_lints,
-                    cx,
-                };
-                let body = cx.tcx.hir_body_owned_by(
-                    impl_item_refs
-                        .iter()
-                        .find(|iiref| iiref.ident.as_str() == "lint_vec")
-                        .expect("LintPass needs to implement lint_vec")
-                        .id
-                        .owner_id
-                        .def_id,
-                );
-                collector.visit_expr(body.value);
-            }
-        }
-    }
-
-    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
-        if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) {
-            return;
-        }
-
-        for (lint_name, &lint_span) in &self.declared_lints {
-            // When using the `declare_tool_lint!` macro, the original `lint_span`'s
-            // file points to "<rustc macros>".
-            // `compiletest-rs` thinks that's an error in a different file and
-            // just ignores it. This causes the test in compile-fail/lint_pass
-            // not able to capture the error.
-            // Therefore, we need to climb the macro expansion tree and find the
-            // actual span that invoked `declare_tool_lint!`:
-            let lint_span = lint_span.ctxt().outer_expn_data().call_site;
-
-            if !self.registered_lints.contains(lint_name) {
-                span_lint(
-                    cx,
-                    LINT_WITHOUT_LINT_PASS,
-                    lint_span,
-                    format!("the lint `{lint_name}` is not added to any `LintPass`"),
-                );
-            }
-        }
-    }
-}
-
-pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
-    if let TyKind::Ref(
-        _,
-        MutTy {
-            ty: inner,
-            mutbl: Mutability::Not,
-        },
-    ) = ty.kind
-    {
-        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);
-            }
-        }
-    }
-
-    false
-}
-
-fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'_>) {
-    if let Some(value) = extract_clippy_version_value(cx, item) {
-        if value.as_str() == "pre 1.29.0" {
-            return;
-        }
-
-        if rustc_attr_parsing::parse_version(value).is_none() {
-            span_lint_and_help(
-                cx,
-                INVALID_CLIPPY_VERSION_ATTRIBUTE,
-                item.span,
-                "this item has an invalid `clippy::version` attribute",
-                None,
-                "please use a valid semantic version, see `doc/adding_lints.md`",
-            );
-        }
-    } else {
-        span_lint_and_help(
-            cx,
-            MISSING_CLIPPY_VERSION_ATTRIBUTE,
-            item.span,
-            "this lint is missing the `clippy::version` attribute or version value",
-            None,
-            "please use a `clippy::version` attribute, see `doc/adding_lints.md`",
-        );
-    }
-}
-
-/// This function extracts the version value of a `clippy::version` attribute if the given value has
-/// one
-pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
-    let attrs = cx.tcx.hir_attrs(item.hir_id());
-    attrs.iter().find_map(|attr| {
-        if let hir::Attribute::Unparsed(attr_kind) = &attr
-            // Identify attribute
-            && let [tool_name, attr_name] = &attr_kind.path.segments[..]
-            && tool_name.name == sym::clippy
-            && attr_name.name == sym::version
-            && let Some(version) = attr.value_str()
-        {
-            Some(version)
-        } else {
-            None
-        }
-    })
-}
-
-struct LintCollector<'a, 'tcx> {
-    output: &'a mut FxIndexSet<Symbol>,
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'tcx> Visitor<'tcx> for LintCollector<'_, 'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    fn visit_path(&mut self, path: &Path<'_>, _: HirId) {
-        if path.segments.len() == 1 {
-            self.output.insert(path.segments[0].ident.name);
-        }
-    }
-
-    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
-        self.cx.tcx
-    }
-}
diff --git a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
deleted file mode 100644
index 558acacb972..00000000000
--- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
-use clippy_utils::ty::match_type;
-use clippy_utils::{match_def_path, paths};
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::{self, EarlyBinder, GenericArgKind};
-use rustc_session::declare_lint_pass;
-
-declare_clippy_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"
-}
-
-declare_lint_pass!(MsrvAttrImpl => [MISSING_MSRV_ATTR_IMPL]);
-
-impl LateLintPass<'_> for MsrvAttrImpl {
-    fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if let hir::ItemKind::Impl(hir::Impl {
-            of_trait: Some(_),
-            items,
-            ..
-        }) = &item.kind
-            && let Some(trait_ref) = cx
-                .tcx
-                .impl_trait_ref(item.owner_id)
-                .map(EarlyBinder::instantiate_identity)
-            && match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS)
-            && let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind()
-            && self_ty_def.is_struct()
-            && self_ty_def.all_fields().any(|f| {
-                cx.tcx
-                    .type_of(f.did)
-                    .instantiate_identity()
-                    .walk()
-                    .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
-                    .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV_STACK))
-            })
-            && !items.iter().any(|item| item.ident.name.as_str() == "check_attributes")
-        {
-            let span = cx.sess().source_map().span_through_char(item.span, '{');
-            span_lint_and_sugg(
-                cx,
-                MISSING_MSRV_ATTR_IMPL,
-                span,
-                "`extract_msrv_attr!` macro missing from `EarlyLintPass` implementation",
-                "add `extract_msrv_attr!()` to the `EarlyLintPass` implementation",
-                format!("{}\n    extract_msrv_attr!();", snippet(cx, span, "..")),
-                Applicability::MachineApplicable,
-            );
-        }
-    }
-}
diff --git a/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs b/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
deleted file mode 100644
index 326e1721461..00000000000
--- a/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::ty::match_type;
-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_session::declare_lint_pass;
-use rustc_span::symbol::Symbol;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for calls to `cx.outer().expn_data()` and suggests to use
-    /// the `cx.outer_expn_data()`
-    ///
-    /// ### Why is this bad?
-    /// `cx.outer_expn_data()` is faster and more concise.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// expr.span.ctxt().outer().expn_data()
-    /// ```
-    ///
-    /// Use instead:
-    /// ```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()`"
-}
-
-declare_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);
-
-impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if is_lint_allowed(cx, OUTER_EXPN_EXPN_DATA, expr.hir_id) {
-            return;
-        }
-
-        let (method_names, arg_lists, spans) = method_calls(expr, 2);
-        let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect();
-        if let ["expn_data", "outer_expn"] = method_names.as_slice()
-            && let (self_arg, args) = arg_lists[1]
-            && args.is_empty()
-            && let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
-            && match_type(cx, self_ty, &paths::SYNTAX_CONTEXT)
-        {
-            span_lint_and_sugg(
-                cx,
-                OUTER_EXPN_EXPN_DATA,
-                spans[1].with_hi(expr.span.hi()),
-                "usage of `outer_expn().expn_data()`",
-                "try",
-                "outer_expn_data()".to_string(),
-                Applicability::MachineApplicable,
-            );
-        }
-    }
-}
diff --git a/clippy_lints/src/utils/internal_lints/produce_ice.rs b/clippy_lints/src/utils/internal_lints/produce_ice.rs
deleted file mode 100644
index 0a07919d659..00000000000
--- a/clippy_lints/src/utils/internal_lints/produce_ice.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-use rustc_ast::ast::NodeId;
-use rustc_ast::visit::FnKind;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_session::declare_lint_pass;
-use rustc_span::Span;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Not an actual lint. This lint is only meant for testing our customized internal compiler
-    /// error message by calling `panic`.
-    ///
-    /// ### Why is this bad?
-    /// ICE in large quantities can damage your teeth
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// 🍦🍦🍦🍦🍦
-    /// ```
-    pub PRODUCE_ICE,
-    internal,
-    "this message should not appear anywhere as we ICE before and don't emit the lint"
-}
-
-declare_lint_pass!(ProduceIce => [PRODUCE_ICE]);
-
-impl EarlyLintPass for ProduceIce {
-    fn check_fn(&mut self, ctx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) {
-        if is_trigger_fn(fn_kind) {
-            ctx.sess()
-                .dcx()
-                .span_delayed_bug(span, "Would you like some help with that?");
-        }
-    }
-}
-
-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::Closure(..) => false,
-    }
-}
diff --git a/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs b/clippy_lints/src/utils/internal_lints/slow_symbol_comparisons.rs
deleted file mode 100644
index b8bcb9b3756..00000000000
--- a/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/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
deleted file mode 100644
index 76b0a52621b..00000000000
--- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ /dev/null
@@ -1,301 +0,0 @@
-use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
-use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
-use rustc_ast::ast::LitKind;
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_errors::Applicability;
-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_middle::mir::ConstValue;
-use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
-use rustc_middle::ty::{self, Ty};
-use rustc_session::impl_lint_pass;
-use rustc_span::Span;
-use rustc_span::symbol::Symbol;
-
-use std::str;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for usage of def paths when a diagnostic item or a `LangItem` could be used.
-    ///
-    /// ### Why is this bad?
-    /// The path for an item is subject to change and is less efficient to look up than a
-    /// diagnostic item or a `LangItem`.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// utils::match_type(cx, ty, &paths::VEC)
-    /// ```
-    ///
-    /// Use instead:
-    /// ```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"
-}
-
-impl_lint_pass!(UnnecessaryDefPath => [UNNECESSARY_DEF_PATH]);
-
-#[derive(Default)]
-pub struct UnnecessaryDefPath {
-    array_def_ids: FxIndexSet<(DefId, Span)>,
-    linted_def_ids: FxHashSet<DefId>,
-}
-
-impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if is_lint_allowed(cx, UNNECESSARY_DEF_PATH, expr.hir_id) {
-            return;
-        }
-
-        match expr.kind {
-            ExprKind::Call(func, args) => self.check_call(cx, func, args, expr.span),
-            ExprKind::Array(elements) => self.check_array(cx, elements, expr.span),
-            _ => {},
-        }
-    }
-
-    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
-        for &(def_id, span) in &self.array_def_ids {
-            if self.linted_def_ids.contains(&def_id) {
-                continue;
-            }
-
-            let (msg, sugg) = if let Some(sym) = cx.tcx.get_diagnostic_name(def_id) {
-                ("diagnostic item", format!("sym::{sym}"))
-            } else if let Some(sym) = get_lang_item_name(cx, def_id) {
-                ("language item", format!("LangItem::{sym}"))
-            } else {
-                continue;
-            };
-
-            span_lint_and_help(
-                cx,
-                UNNECESSARY_DEF_PATH,
-                span,
-                format!("hardcoded path to a {msg}"),
-                None,
-                format!("convert all references to use `{sugg}`"),
-            );
-        }
-    }
-}
-
-impl UnnecessaryDefPath {
-    #[allow(clippy::too_many_lines)]
-    fn check_call(&mut self, cx: &LateContext<'_>, func: &Expr<'_>, args: &[Expr<'_>], span: Span) {
-        enum Item {
-            LangItem(&'static str),
-            DiagnosticItem(Symbol),
-        }
-        static PATHS: &[&[&str]] = &[
-            &["clippy_utils", "match_def_path"],
-            &["clippy_utils", "match_trait_method"],
-            &["clippy_utils", "ty", "match_type"],
-            &["clippy_utils", "is_expr_path_def_path"],
-        ];
-
-        if let [cx_arg, def_arg, args @ ..] = args
-            && let ExprKind::Path(path) = &func.kind
-            && let Some(id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-            && let Some(which_path) = match_any_def_paths(cx, id, PATHS)
-            && let item_arg = if which_path == 4 { &args[1] } else { &args[0] }
-            // Extract the path to the matched type
-            && let Some(segments) = path_to_matched_type(cx, item_arg)
-            && let segments = segments.iter().map(|sym| &**sym).collect::<Vec<_>>()
-            && let Some(def_id) = def_path_def_ids(cx.tcx, &segments[..]).next()
-        {
-            // Check if the target item is a diagnostic item or LangItem.
-            #[rustfmt::skip]
-            let (msg, item) = if let Some(item_name)
-                = cx.tcx.diagnostic_items(def_id.krate).id_to_name.get(&def_id)
-            {
-                (
-                    "use of a def path to a diagnostic item",
-                    Item::DiagnosticItem(*item_name),
-                )
-            } else if let Some(item_name) = get_lang_item_name(cx, def_id) {
-                (
-                    "use of a def path to a `LangItem`",
-                    Item::LangItem(item_name),
-                )
-            } else {
-                return;
-            };
-
-            let has_ctor = match cx.tcx.def_kind(def_id) {
-                DefKind::Struct => {
-                    let variant = cx.tcx.adt_def(def_id).non_enum_variant();
-                    variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
-                },
-                DefKind::Variant => {
-                    let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id);
-                    variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
-                },
-                _ => false,
-            };
-
-            let mut app = Applicability::MachineApplicable;
-            let cx_snip = snippet_with_applicability(cx, cx_arg.span, "..", &mut app);
-            let def_snip = snippet_with_applicability(cx, def_arg.span, "..", &mut app);
-            let (sugg, with_note) = match (which_path, item) {
-                // match_def_path
-                (0, Item::DiagnosticItem(item)) => (
-                    format!("{cx_snip}.tcx.is_diagnostic_item(sym::{item}, {def_snip})"),
-                    has_ctor,
-                ),
-                (0, Item::LangItem(item)) => (
-                    format!("{cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some({def_snip})"),
-                    has_ctor,
-                ),
-                // match_trait_method
-                (1, Item::DiagnosticItem(item)) => {
-                    (format!("is_trait_method({cx_snip}, {def_snip}, sym::{item})"), false)
-                },
-                // match_type
-                (2, Item::DiagnosticItem(item)) => (
-                    format!("is_type_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"),
-                    false,
-                ),
-                (2, Item::LangItem(item)) => (
-                    format!("is_type_lang_item({cx_snip}, {def_snip}, LangItem::{item})"),
-                    false,
-                ),
-                // is_expr_path_def_path
-                (3, Item::DiagnosticItem(item)) if has_ctor => (
-                    format!("is_res_diag_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), sym::{item})",),
-                    false,
-                ),
-                (3, Item::LangItem(item)) if has_ctor => (
-                    format!("is_res_lang_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), LangItem::{item})",),
-                    false,
-                ),
-                (3, Item::DiagnosticItem(item)) => (
-                    format!("is_path_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"),
-                    false,
-                ),
-                (3, Item::LangItem(item)) => (
-                    format!(
-                        "path_res({cx_snip}, {def_snip}).opt_def_id()\
-                            .map_or(false, |id| {cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some(id))",
-                    ),
-                    false,
-                ),
-                _ => return,
-            };
-
-            span_lint_and_then(cx, UNNECESSARY_DEF_PATH, span, msg, |diag| {
-                diag.span_suggestion(span, "try", sugg, app);
-                if with_note {
-                    diag.help(
-                        "if this `DefId` came from a constructor expression or pattern then the \
-                                parent `DefId` should be used instead",
-                    );
-                }
-            });
-
-            self.linted_def_ids.insert(def_id);
-        }
-    }
-
-    fn check_array(&mut self, cx: &LateContext<'_>, elements: &[Expr<'_>], span: Span) {
-        let Some(path) = path_from_array(elements) else { return };
-
-        for def_id in def_path_def_ids(cx.tcx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
-            self.array_def_ids.insert((def_id, span));
-        }
-    }
-}
-
-fn path_to_matched_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Vec<String>> {
-    match peel_hir_expr_refs(expr).0.kind {
-        ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
-            Res::Local(hir_id) => {
-                if let Node::LetStmt(LetStmt { init: Some(init), .. }) = cx.tcx.parent_hir_node(hir_id) {
-                    path_to_matched_type(cx, init)
-                } else {
-                    None
-                }
-            },
-            Res::Def(DefKind::Static { .. }, def_id) => read_mir_alloc_def_path(
-                cx,
-                cx.tcx.eval_static_initializer(def_id).ok()?.inner(),
-                cx.tcx.type_of(def_id).instantiate_identity(),
-            ),
-            Res::Def(DefKind::Const, def_id) => match cx.tcx.const_eval_poly(def_id).ok()? {
-                ConstValue::Indirect { alloc_id, offset } if offset.bytes() == 0 => {
-                    let alloc = cx.tcx.global_alloc(alloc_id).unwrap_memory();
-                    read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id).instantiate_identity())
-                },
-                _ => None,
-            },
-            _ => None,
-        },
-        ExprKind::Array(exprs) => path_from_array(exprs),
-        _ => None,
-    }
-}
-
-fn read_mir_alloc_def_path<'tcx>(cx: &LateContext<'tcx>, alloc: &'tcx Allocation, ty: Ty<'_>) -> Option<Vec<String>> {
-    let (alloc, ty) = if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() {
-        let &alloc = alloc.provenance().ptrs().values().next()?;
-        if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc.alloc_id()) {
-            (alloc.inner(), ty)
-        } else {
-            return None;
-        }
-    } else {
-        (alloc, ty)
-    };
-
-    if let ty::Array(ty, _) | ty::Slice(ty) = *ty.kind()
-        && let ty::Ref(_, ty, Mutability::Not) = *ty.kind()
-        && ty.is_str()
-    {
-        alloc
-            .provenance()
-            .ptrs()
-            .values()
-            .map(|&alloc| {
-                if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc.alloc_id()) {
-                    let alloc = alloc.inner();
-                    str::from_utf8(alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()))
-                        .ok()
-                        .map(ToOwned::to_owned)
-                } else {
-                    None
-                }
-            })
-            .collect()
-    } else {
-        None
-    }
-}
-
-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());
-                }
-            }
-
-            None
-        })
-        .collect()
-}
-
-fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static str> {
-    if let Some((lang_item, _)) = cx.tcx.lang_items().iter().find(|(_, id)| *id == def_id) {
-        Some(lang_item.variant_name())
-    } else {
-        None
-    }
-}
diff --git a/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs b/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs
deleted file mode 100644
index a5c4bf474f7..00000000000
--- a/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/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 4476cd1005e..16066dd96c0 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/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/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs
index 405310512df..5b3f60ad6ab 100644
--- a/clippy_lints/src/wildcard_imports.rs
+++ b/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/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs
index f6948be7f67..a97643e0eac 100644
--- a/clippy_lints/src/zero_sized_map_values.rs
+++ b/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/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs
index 7667db46968..39c1aab8967 100644
--- a/clippy_lints/src/zombie_processes.rs
+++ b/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>,
 }