about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--book/src/development/adding_lints.md12
-rw-r--r--book/src/development/defining_lints.md2
-rw-r--r--clippy_config/src/types.rs24
-rw-r--r--clippy_dev/src/new_lint.rs4
-rw-r--r--clippy_lints/Cargo.toml1
-rw-r--r--clippy_lints/src/allow_attributes.rs34
-rw-r--r--clippy_lints/src/arc_with_non_send_sync.rs22
-rw-r--r--clippy_lints/src/attrs.rs125
-rw-r--r--clippy_lints/src/blocks_in_if_conditions.rs17
-rw-r--r--clippy_lints/src/booleans.rs21
-rw-r--r--clippy_lints/src/borrow_deref_ref.rs105
-rw-r--r--clippy_lints/src/cargo/multiple_crate_versions.rs53
-rw-r--r--clippy_lints/src/cargo/wildcard_dependencies.rs25
-rw-r--r--clippy_lints/src/casts/cast_sign_loss.rs25
-rw-r--r--clippy_lints/src/casts/cast_slice_different_sizes.rs37
-rw-r--r--clippy_lints/src/casts/cast_slice_from_raw_parts.rs57
-rw-r--r--clippy_lints/src/casts/char_lit_as_u8.rs50
-rw-r--r--clippy_lints/src/casts/ptr_cast_constness.rs53
-rw-r--r--clippy_lints/src/casts/unnecessary_cast.rs98
-rw-r--r--clippy_lints/src/checked_conversions.rs111
-rw-r--r--clippy_lints/src/collapsible_if.rs85
-rw-r--r--clippy_lints/src/copy_iterator.rs38
-rw-r--r--clippy_lints/src/crate_in_macro_def.rs74
-rw-r--r--clippy_lints/src/create_dir.rs31
-rw-r--r--clippy_lints/src/declared_lints.rs2
-rw-r--r--clippy_lints/src/default.rs175
-rw-r--r--clippy_lints/src/default_constructed_unit_structs.rs44
-rw-r--r--clippy_lints/src/default_numeric_fallback.rs122
-rw-r--r--clippy_lints/src/dereference.rs283
-rw-r--r--clippy_lints/src/derivable_impls.rs122
-rw-r--r--clippy_lints/src/derive.rs229
-rw-r--r--clippy_lints/src/disallowed_names.rs4
-rw-r--r--clippy_lints/src/doc.rs39
-rw-r--r--clippy_lints/src/empty_drop.rs50
-rw-r--r--clippy_lints/src/endian_bytes.rs34
-rw-r--r--clippy_lints/src/exhaustive_items.rs58
-rw-r--r--clippy_lints/src/exit.rs21
-rw-r--r--clippy_lints/src/explicit_write.rs25
-rw-r--r--clippy_lints/src/fallible_impl_from.rs68
-rw-r--r--clippy_lints/src/float_literal.rs108
-rw-r--r--clippy_lints/src/floating_point_arithmetic.rs450
-rw-r--r--clippy_lints/src/format_args.rs81
-rw-r--r--clippy_lints/src/format_impl.rs115
-rw-r--r--clippy_lints/src/formatting.rs209
-rw-r--r--clippy_lints/src/from_str_radix_10.rs64
-rw-r--r--clippy_lints/src/functions/impl_trait_in_params.rs66
-rw-r--r--clippy_lints/src/functions/misnamed_getters.rs30
-rw-r--r--clippy_lints/src/functions/result.rs99
-rw-r--r--clippy_lints/src/if_let_mutex.rs19
-rw-r--r--clippy_lints/src/implicit_hasher.rs68
-rw-r--r--clippy_lints/src/implicit_saturating_add.rs85
-rw-r--r--clippy_lints/src/implicit_saturating_sub.rs142
-rw-r--r--clippy_lints/src/inconsistent_struct_constructor.rs84
-rw-r--r--clippy_lints/src/index_refutable_slice.rs56
-rw-r--r--clippy_lints/src/instant_subtraction.rs32
-rw-r--r--clippy_lints/src/large_const_arrays.rs66
-rw-r--r--clippy_lints/src/large_include_file.rs56
-rw-r--r--clippy_lints/src/len_zero.rs59
-rw-r--r--clippy_lints/src/let_if_seq.rs159
-rw-r--r--clippy_lints/src/let_with_type_underscore.rs38
-rw-r--r--clippy_lints/src/lib.rs186
-rw-r--r--clippy_lints/src/lifetimes.rs25
-rw-r--r--clippy_lints/src/literal_representation.rs111
-rw-r--r--clippy_lints/src/loops/explicit_counter_loop.rs99
-rw-r--r--clippy_lints/src/loops/manual_find.rs177
-rw-r--r--clippy_lints/src/loops/manual_flatten.rs94
-rw-r--r--clippy_lints/src/loops/manual_memcpy.rs76
-rw-r--r--clippy_lints/src/loops/missing_spin_loop.rs46
-rw-r--r--clippy_lints/src/loops/mut_range_bound.rs37
-rw-r--r--clippy_lints/src/loops/needless_range_loop.rs169
-rw-r--r--clippy_lints/src/loops/same_item_push.rs117
-rw-r--r--clippy_lints/src/loops/single_element_loop.rs53
-rw-r--r--clippy_lints/src/loops/utils.rs25
-rw-r--r--clippy_lints/src/loops/while_immutable_condition.rs27
-rw-r--r--clippy_lints/src/loops/while_let_on_iterator.rs89
-rw-r--r--clippy_lints/src/macro_use.rs37
-rw-r--r--clippy_lints/src/main_recursion.rs29
-rw-r--r--clippy_lints/src/manual_async_fn.rs177
-rw-r--r--clippy_lints/src/manual_bits.rs82
-rw-r--r--clippy_lints/src/manual_let_else.rs116
-rw-r--r--clippy_lints/src/manual_strip.rs169
-rw-r--r--clippy_lints/src/map_unit_fn.rs19
-rw-r--r--clippy_lints/src/match_result_ok.rs53
-rw-r--r--clippy_lints/src/matches/collapsible_match.rs94
-rw-r--r--clippy_lints/src/matches/infallible_destructuring_match.rs61
-rw-r--r--clippy_lints/src/matches/manual_filter.rs26
-rw-r--r--clippy_lints/src/matches/manual_unwrap_or.rs103
-rw-r--r--clippy_lints/src/matches/manual_utils.rs46
-rw-r--r--clippy_lints/src/matches/match_as_ref.rs43
-rw-r--r--clippy_lints/src/matches/match_like_matches.rs135
-rw-r--r--clippy_lints/src/matches/match_on_vec_items.rs49
-rw-r--r--clippy_lints/src/matches/match_same_arms.rs28
-rw-r--r--clippy_lints/src/matches/match_str_case_mismatch.rs45
-rw-r--r--clippy_lints/src/matches/match_wild_err_arm.rs27
-rw-r--r--clippy_lints/src/matches/redundant_pattern_match.rs31
-rw-r--r--clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs37
-rw-r--r--clippy_lints/src/matches/single_match.rs90
-rw-r--r--clippy_lints/src/matches/try_err.rs162
-rw-r--r--clippy_lints/src/mem_replace.rs100
-rw-r--r--clippy_lints/src/methods/bind_instead_of_map.rs91
-rw-r--r--clippy_lints/src/methods/bytecount.rs76
-rw-r--r--clippy_lints/src/methods/bytes_count_to_len.rs38
-rw-r--r--clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs90
-rw-r--r--clippy_lints/src/methods/chars_cmp.rs51
-rw-r--r--clippy_lints/src/methods/chars_cmp_with_unwrap.rs45
-rw-r--r--clippy_lints/src/methods/err_expect.rs31
-rw-r--r--clippy_lints/src/methods/extend_with_drain.rs53
-rw-r--r--clippy_lints/src/methods/filetype_is_file.rs29
-rw-r--r--clippy_lints/src/methods/filter_map.rs162
-rw-r--r--clippy_lints/src/methods/from_iter_instead_of_collect.rs112
-rw-r--r--clippy_lints/src/methods/get_first.rs64
-rw-r--r--clippy_lints/src/methods/implicit_clone.rs55
-rw-r--r--clippy_lints/src/methods/inefficient_to_string.rs62
-rw-r--r--clippy_lints/src/methods/into_iter_on_ref.rs33
-rw-r--r--clippy_lints/src/methods/iter_cloned_collect.rs34
-rw-r--r--clippy_lints/src/methods/iter_kv_map.rs98
-rw-r--r--clippy_lints/src/methods/iter_next_slice.rs54
-rw-r--r--clippy_lints/src/methods/iter_skip_next.rs22
-rw-r--r--clippy_lints/src/methods/manual_ok_or.rs45
-rw-r--r--clippy_lints/src/methods/manual_saturating_arithmetic.rs19
-rw-r--r--clippy_lints/src/methods/manual_str_repeat.rs72
-rw-r--r--clippy_lints/src/methods/map_clone.rs89
-rw-r--r--clippy_lints/src/methods/map_collect_result_unit.rs41
-rw-r--r--clippy_lints/src/methods/map_identity.rs32
-rw-r--r--clippy_lints/src/methods/mod.rs68
-rw-r--r--clippy_lints/src/methods/mut_mutex_lock.rs33
-rw-r--r--clippy_lints/src/methods/no_effect_replace.rs19
-rw-r--r--clippy_lints/src/methods/ok_expect.rs30
-rw-r--r--clippy_lints/src/methods/option_as_ref_deref.rs39
-rw-r--r--clippy_lints/src/methods/option_map_or_none.rs40
-rw-r--r--clippy_lints/src/methods/or_fun_call.rs88
-rw-r--r--clippy_lints/src/methods/path_buf_push_overwrite.rs43
-rw-r--r--clippy_lints/src/methods/range_zip_with_len.rs36
-rw-r--r--clippy_lints/src/methods/search_is_some.rs101
-rw-r--r--clippy_lints/src/methods/single_char_pattern.rs36
-rw-r--r--clippy_lints/src/methods/str_splitn.rs51
-rw-r--r--clippy_lints/src/methods/suspicious_map.rs37
-rw-r--r--clippy_lints/src/methods/suspicious_splitn.rs56
-rw-r--r--clippy_lints/src/methods/suspicious_to_owned.rs66
-rw-r--r--clippy_lints/src/methods/uninit_assumed_init.rs25
-rw-r--r--clippy_lints/src/methods/unnecessary_fallible_conversions.rs38
-rw-r--r--clippy_lints/src/methods/unnecessary_fold.rs85
-rw-r--r--clippy_lints/src/methods/unnecessary_iter_cloned.rs121
-rw-r--r--clippy_lints/src/methods/unnecessary_join.rs34
-rw-r--r--clippy_lints/src/methods/unnecessary_sort_by.rs112
-rw-r--r--clippy_lints/src/methods/unnecessary_to_owned.rs310
-rw-r--r--clippy_lints/src/methods/useless_asref.rs13
-rw-r--r--clippy_lints/src/methods/utils.rs62
-rw-r--r--clippy_lints/src/methods/vec_resize_to_zero.rs52
-rw-r--r--clippy_lints/src/methods/zst_offset.rs13
-rw-r--r--clippy_lints/src/misc.rs122
-rw-r--r--clippy_lints/src/mismatching_type_param_order.rs100
-rw-r--r--clippy_lints/src/missing_doc.rs19
-rw-r--r--clippy_lints/src/missing_enforced_import_rename.rs34
-rw-r--r--clippy_lints/src/mixed_read_write_in_expression.rs13
-rw-r--r--clippy_lints/src/module_style.rs5
-rw-r--r--clippy_lints/src/needless_arbitrary_self_type.rs91
-rw-r--r--clippy_lints/src/needless_continue.rs28
-rw-r--r--clippy_lints/src/needless_for_each.rs94
-rw-r--r--clippy_lints/src/needless_late_init.rs45
-rw-r--r--clippy_lints/src/needless_parens_on_range_literals.rs28
-rw-r--r--clippy_lints/src/needless_pass_by_value.rs200
-rw-r--r--clippy_lints/src/needless_question_mark.rs45
-rw-r--r--clippy_lints/src/neg_cmp_op_on_partial_ord.rs64
-rw-r--r--clippy_lints/src/neg_multiply.rs44
-rw-r--r--clippy_lints/src/new_without_default.rs123
-rw-r--r--clippy_lints/src/no_effect.rs133
-rw-r--r--clippy_lints/src/non_copy_const.rs30
-rw-r--r--clippy_lints/src/non_octal_unix_permissions.rs51
-rw-r--r--clippy_lints/src/non_send_fields_in_send_ty.rs129
-rw-r--r--clippy_lints/src/nonstandard_macro_braces.rs115
-rw-r--r--clippy_lints/src/operators/assign_op_pattern.rs68
-rw-r--r--clippy_lints/src/operators/const_comparisons.rs141
-rw-r--r--clippy_lints/src/operators/float_cmp.rs15
-rw-r--r--clippy_lints/src/operators/float_equality_without_abs.rs60
-rw-r--r--clippy_lints/src/operators/modulo_arithmetic.rs16
-rw-r--r--clippy_lints/src/operators/op_ref.rs57
-rw-r--r--clippy_lints/src/operators/ptr_eq.rs31
-rw-r--r--clippy_lints/src/option_if_let_else.rs143
-rw-r--r--clippy_lints/src/overflow_check_conditional.rs61
-rw-r--r--clippy_lints/src/partialeq_ne_impl.rs35
-rw-r--r--clippy_lints/src/pass_by_ref_or_value.rs39
-rw-r--r--clippy_lints/src/precedence.rs37
-rw-r--r--clippy_lints/src/question_mark.rs151
-rw-r--r--clippy_lints/src/ranges.rs210
-rw-r--r--clippy_lints/src/raw_strings.rs2
-rw-r--r--clippy_lints/src/rc_clone_in_vec_init.rs36
-rw-r--r--clippy_lints/src/redundant_clone.rs114
-rw-r--r--clippy_lints/src/redundant_closure_call.rs53
-rw-r--r--clippy_lints/src/redundant_locals.rs48
-rw-r--r--clippy_lints/src/redundant_pub_crate.rs43
-rw-r--r--clippy_lints/src/redundant_slicing.rs142
-rw-r--r--clippy_lints/src/ref_option_ref.rs49
-rw-r--r--clippy_lints/src/reference.rs95
-rw-r--r--clippy_lints/src/regex.rs12
-rw-r--r--clippy_lints/src/return_self_not_must_use.rs54
-rw-r--r--clippy_lints/src/returns.rs78
-rw-r--r--clippy_lints/src/same_name_method.rs37
-rw-r--r--clippy_lints/src/self_named_constructors.rs30
-rw-r--r--clippy_lints/src/semicolon_if_nothing_returned.rs46
-rw-r--r--clippy_lints/src/size_of_in_element_count.rs75
-rw-r--r--clippy_lints/src/slow_vector_initialization.rs110
-rw-r--r--clippy_lints/src/strings.rs276
-rw-r--r--clippy_lints/src/strlen_on_c_strings.rs78
-rw-r--r--clippy_lints/src/suspicious_doc_comments.rs25
-rw-r--r--clippy_lints/src/suspicious_operation_groupings.rs101
-rw-r--r--clippy_lints/src/suspicious_trait_impl.rs51
-rw-r--r--clippy_lints/src/swap.rs70
-rw-r--r--clippy_lints/src/tests_outside_test_module.rs26
-rw-r--r--clippy_lints/src/to_digit_is_some.rs97
-rw-r--r--clippy_lints/src/trailing_empty_array.rs22
-rw-r--r--clippy_lints/src/trait_bounds.rs327
-rw-r--r--clippy_lints/src/transmute/mod.rs79
-rw-r--r--clippy_lints/src/transmute/transmute_float_to_int.rs17
-rw-r--r--clippy_lints/src/transmute/transmute_ref_to_ref.rs110
-rw-r--r--clippy_lints/src/transmute/transmute_undefined_repr.rs14
-rw-r--r--clippy_lints/src/types/borrowed_box.rs145
-rw-r--r--clippy_lints/src/types/box_collection.rs42
-rw-r--r--clippy_lints/src/types/mod.rs2
-rw-r--r--clippy_lints/src/types/option_option.rs31
-rw-r--r--clippy_lints/src/types/rc_mutex.rs31
-rw-r--r--clippy_lints/src/types/utils.rs17
-rw-r--r--clippy_lints/src/types/vec_box.rs84
-rw-r--r--clippy_lints/src/uninit_vec.rs72
-rw-r--r--clippy_lints/src/unit_return_expecting_ord.rs83
-rw-r--r--clippy_lints/src/unit_types/unit_arg.rs35
-rw-r--r--clippy_lints/src/unnamed_address.rs86
-rw-r--r--clippy_lints/src/unnecessary_owned_empty_strings.rs75
-rw-r--r--clippy_lints/src/unnecessary_self_imports.rs60
-rw-r--r--clippy_lints/src/unnecessary_wraps.rs37
-rw-r--r--clippy_lints/src/unused_self.rs37
-rw-r--r--clippy_lints/src/unused_unit.rs76
-rw-r--r--clippy_lints/src/unwrap.rs192
-rw-r--r--clippy_lints/src/unwrap_in_result.rs13
-rw-r--r--clippy_lints/src/use_self.rs204
-rw-r--r--clippy_lints/src/useless_conversion.rs108
-rw-r--r--clippy_lints/src/utils/internal_lints.rs1
-rw-r--r--clippy_lints/src/utils/internal_lints/collapsible_calls.rs77
-rw-r--r--clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs31
-rw-r--r--clippy_lints/src/utils/internal_lints/if_chain_style.rs166
-rw-r--r--clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs91
-rw-r--r--clippy_lints/src/utils/internal_lints/invalid_paths.rs23
-rw-r--r--clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs17
-rw-r--r--clippy_lints/src/utils/internal_lints/metadata_collector.rs120
-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.rs33
-rw-r--r--clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs191
-rw-r--r--clippy_lints/src/vec.rs45
-rw-r--r--clippy_lints/src/wildcard_imports.rs106
-rw-r--r--clippy_lints/src/zero_div_zero.rs48
-rw-r--r--clippy_lints/src/zero_sized_map_values.rs34
-rw-r--r--clippy_utils/Cargo.toml1
-rw-r--r--clippy_utils/src/consts.rs42
-rw-r--r--clippy_utils/src/higher.rs77
-rw-r--r--clippy_utils/src/hir_utils.rs116
-rw-r--r--clippy_utils/src/lib.rs391
-rw-r--r--clippy_utils/src/paths.rs1
-rw-r--r--clippy_utils/src/ty.rs5
-rw-r--r--src/driver.rs2
-rw-r--r--tests/ui-internal/if_chain_style.rs97
-rw-r--r--tests/ui-internal/if_chain_style.stderr86
-rw-r--r--tests/ui/arc_with_non_send_sync.rs6
-rw-r--r--tests/ui/arc_with_non_send_sync.stderr32
-rw-r--r--tests/ui/explicit_auto_deref.fixed45
-rw-r--r--tests/ui/explicit_auto_deref.rs45
-rw-r--r--tests/ui/explicit_auto_deref.stderr32
-rw-r--r--tests/ui/manual_let_else.rs113
-rw-r--r--tests/ui/manual_let_else.stderr172
-rw-r--r--tests/ui/map_identity.fixed42
-rw-r--r--tests/ui/map_identity.rs42
-rw-r--r--tests/ui/map_identity.stderr32
-rw-r--r--tests/ui/needless_borrow.fixed51
-rw-r--r--tests/ui/needless_borrow.rs51
-rw-r--r--tests/ui/needless_borrow.stderr26
-rw-r--r--tests/ui/unnecessary_fallible_conversions.stderr3
-rw-r--r--tests/ui/unnecessary_fallible_conversions_unfixable.stderr11
-rw-r--r--tests/ui/vec_box_sized.fixed57
-rw-r--r--tests/ui/vec_box_sized.rs37
-rw-r--r--tests/ui/vec_box_sized.stderr32
280 files changed, 9533 insertions, 10149 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 04af1b98b55..b1a59238c82 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -146,16 +146,10 @@ For example, the [`else_if_without_else`][else_if_without_else] lint is register
 pub mod else_if_without_else;
 // ...
 
-pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
+pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     // ...
     store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
     // ...
-
-    store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
-        // ...
-        LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE),
-        // ...
-    ]);
 }
 ```
 
diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md
index 55c0e105b30..1803fc2d2f3 100644
--- a/book/src/development/adding_lints.md
+++ b/book/src/development/adding_lints.md
@@ -270,7 +270,7 @@ When using `cargo dev new_lint`, the lint is automatically registered and
 nothing more has to be done.
 
 When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
-pass may have to be registered manually in the `register_plugins` function in
+pass may have to be registered manually in the `register_lints` function in
 `clippy_lints/src/lib.rs`:
 
 ```rust,ignore
@@ -436,7 +436,7 @@ need to ensure that the MSRV configured for the project is >= the MSRV of the
 required Rust feature. If multiple features are required, just use the one with
 a lower MSRV.
 
-First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`].
+First, add an MSRV alias for the required feature in [`clippy_config::msrvs`].
 This can be accessed later as `msrvs::STR_STRIP_PREFIX`, for example.
 
 ```rust
@@ -506,7 +506,7 @@ fn msrv_1_45() {
 ```
 
 As a last step, the lint should be added to the lint documentation. This is done
-in `clippy_lints/src/utils/conf.rs`:
+in `clippy_config/src/conf.rs`:
 
 ```rust
 define_Conf! {
@@ -516,7 +516,7 @@ define_Conf! {
 }
 ```
 
-[`clippy_utils::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/msrvs/index.html
+[`clippy_config::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html
 
 ## Author lint
 
@@ -657,7 +657,7 @@ Adding a configuration to a lint can be useful for
 thresholds or to constrain some behavior that can be seen as a false positive
 for some users. Adding a configuration is done in the following steps:
 
-1. Adding a new configuration entry to [`clippy_lints::utils::conf`] like this:
+1. Adding a new configuration entry to [`clippy_config::conf`] like this:
 
    ```rust,ignore
    /// Lint: LINT_NAME.
@@ -736,7 +736,7 @@ for some users. Adding a configuration is done in the following steps:
 
    Run `cargo collect-metadata` to generate documentation changes for the book.
 
-[`clippy_lints::utils::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/conf.rs
+[`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs
 [`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
 [`tests/ui`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui
 [`tests/ui-toml`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui-toml
diff --git a/book/src/development/defining_lints.md b/book/src/development/defining_lints.md
index 7c4aa5d4523..54f77b00190 100644
--- a/book/src/development/defining_lints.md
+++ b/book/src/development/defining_lints.md
@@ -186,7 +186,7 @@ However, sometimes we might want to declare a new lint by hand. In this case,
 we'd use `cargo dev update_lints` command afterwards.
 
 When a lint is manually declared, we might need to register the lint pass
-manually in the `register_plugins` function in `clippy_lints/src/lib.rs`:
+manually in the `register_lints` function in `clippy_lints/src/lib.rs`:
 
 ```rust
 store.register_late_pass(|_| Box::new(foo_functions::FooFunctions));
diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs
index e898221ffa7..df48cc3f5e3 100644
--- a/clippy_config/src/types.rs
+++ b/clippy_config/src/types.rs
@@ -1,7 +1,6 @@
 use serde::de::{self, Deserializer, Visitor};
 use serde::{ser, Deserialize, Serialize};
 use std::fmt;
-use std::hash::{Hash, Hasher};
 
 #[derive(Clone, Debug, Deserialize)]
 pub struct Rename {
@@ -33,32 +32,19 @@ impl DisallowedPath {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
 pub enum MatchLintBehaviour {
     AllTypes,
     WellKnownTypes,
     Never,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Debug)]
 pub struct MacroMatcher {
     pub name: String,
-    pub braces: (String, String),
+    pub braces: (char, char),
 }
 
-impl Hash for MacroMatcher {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        self.name.hash(state);
-    }
-}
-
-impl PartialEq for MacroMatcher {
-    fn eq(&self, other: &Self) -> bool {
-        self.name == other.name
-    }
-}
-impl Eq for MacroMatcher {}
-
 impl<'de> Deserialize<'de> for MacroMatcher {
     fn deserialize<D>(deser: D) -> Result<Self, D::Error>
     where
@@ -83,7 +69,7 @@ impl<'de> Deserialize<'de> for MacroMatcher {
                 V: de::MapAccess<'de>,
             {
                 let mut name = None;
-                let mut brace: Option<String> = None;
+                let mut brace: Option<char> = None;
                 while let Some(key) = map.next_key()? {
                     match key {
                         Field::Name => {
@@ -104,7 +90,7 @@ impl<'de> Deserialize<'de> for MacroMatcher {
                 let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?;
                 Ok(MacroMatcher {
                     name,
-                    braces: [("(", ")"), ("{", "}"), ("[", "]")]
+                    braces: [('(', ')'), ('{', '}'), ('[', ']')]
                         .into_iter()
                         .find(|b| b.0 == brace)
                         .map(|(o, c)| (o.to_owned(), c.to_owned()))
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index eeea53ce46f..ddc20f7f37f 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -320,8 +320,8 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
                 extract_msrv_attr!({context_import});
             }}
 
-            // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
-            // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
+            // TODO: Add MSRV level to `clippy_config/src/msrvs.rs` if needed.
+            // TODO: Update msrv config comment in `clippy_config/src/conf.rs`
         "#
         )
     } else {
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index 4bc27fd48e2..a4116603688 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -14,7 +14,6 @@ cargo_metadata = "0.15.3"
 clippy_config = { path = "../clippy_config" }
 clippy_utils = { path = "../clippy_utils" }
 declare_clippy_lint = { path = "../declare_clippy_lint" }
-if_chain = "1.0"
 itertools = "0.10.1"
 quine-mc_cluskey = "0.2"
 regex-syntax = "0.7"
diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs
index e3f4cf79d31..98299e1e4bd 100644
--- a/clippy_lints/src/allow_attributes.rs
+++ b/clippy_lints/src/allow_attributes.rs
@@ -52,24 +52,22 @@ declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]);
 impl LateLintPass<'_> for AllowAttribute {
     // Separate each crate's features.
     fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) {
-        if_chain! {
-            if !in_external_macro(cx.sess(), attr.span);
-            if cx.tcx.features().lint_reasons;
-            if let AttrStyle::Outer = attr.style;
-            if let Some(ident) = attr.ident();
-            if ident.name == rustc_span::symbol::sym::allow;
-            if !is_from_proc_macro(cx, &attr);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    ALLOW_ATTRIBUTES,
-                    ident.span,
-                    "#[allow] attribute found",
-                    "replace it with",
-                    "expect".into(),
-                    Applicability::MachineApplicable,
-                );
-            }
+        if !in_external_macro(cx.sess(), attr.span)
+            && cx.tcx.features().lint_reasons
+            && let AttrStyle::Outer = attr.style
+            && let Some(ident) = attr.ident()
+            && ident.name == rustc_span::symbol::sym::allow
+            && !is_from_proc_macro(cx, &attr)
+        {
+            span_lint_and_sugg(
+                cx,
+                ALLOW_ATTRIBUTES,
+                ident.span,
+                "#[allow] attribute found",
+                "replace it with",
+                "expect".into(),
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs
index 192bc7d9ddc..9799e703afe 100644
--- a/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/clippy_lints/src/arc_with_non_send_sync.rs
@@ -14,7 +14,9 @@ declare_clippy_lint! {
     /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`.
     ///
     /// ### Why is this bad?
-    /// `Arc<T>` is only `Send`/`Sync` when `T` is [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E),
+    /// `Arc<T>` is an Atomic `RC<T>` and guarantees that updates to the reference counter are
+    /// Atomic. This is useful in multiprocessing scenarios. To send an `Arc<T>` across processes
+    /// and make use of the atomic ref counter, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E),
     /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
     ///
     /// ### Example
@@ -34,7 +36,7 @@ declare_clippy_lint! {
     #[clippy::version = "1.72.0"]
     pub ARC_WITH_NON_SEND_SYNC,
     suspicious,
-    "using `Arc` with a type that does not implement `Send` or `Sync`"
+    "using `Arc` with a type that does not implement `Send` and `Sync`"
 }
 declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]);
 
@@ -61,19 +63,25 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
                 cx,
                 ARC_WITH_NON_SEND_SYNC,
                 expr.span,
-                "usage of an `Arc` that is not `Send` or `Sync`",
+                "usage of an `Arc` that is not `Send` and `Sync`",
                 |diag| {
                     with_forced_trimmed_paths!({
+                        diag.note(format!("`Arc<{arg_ty}>` is not `Send` and `Sync` as:"));
+
                         if !is_send {
-                            diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`"));
+                            diag.note(format!("- the trait `Send` is not implemented for `{arg_ty}`"));
                         }
                         if !is_sync {
-                            diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`"));
+                            diag.note(format!("- the trait `Sync` is not implemented for `{arg_ty}`"));
                         }
 
-                        diag.note(format!("required for `{ty}` to implement `Send` and `Sync`"));
+                        diag.help("consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types");
+
+                        diag.note("if you intend to use `Arc` with `Send` and `Sync` traits");
 
-                        diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`");
+                        diag.note(format!(
+                            "wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `{arg_ty}`"
+                        ));
                     });
                 },
             );
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index 64bfa8d904c..240ff859764 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -5,7 +5,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::macros::{is_panic, macro_backtrace};
 use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
-use if_chain::if_chain;
 use rustc_ast::token::{Token, TokenKind};
 use rustc_ast::tokenstream::TokenTree;
 use rustc_ast::{
@@ -471,13 +470,11 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
                     return;
                 }
                 for item in items {
-                    if_chain! {
-                        if let NestedMetaItem::MetaItem(mi) = &item;
-                        if let MetaItemKind::NameValue(lit) = &mi.kind;
-                        if mi.has_name(sym::since);
-                        then {
-                            check_semver(cx, item.span(), lit);
-                        }
+                    if let NestedMetaItem::MetaItem(mi) = &item
+                        && let MetaItemKind::NameValue(lit) = &mi.kind
+                        && mi.has_name(sym::since)
+                    {
+                        check_semver(cx, item.span(), lit);
                     }
                 }
             }
@@ -580,15 +577,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
 
 /// Returns the lint name if it is clippy lint.
 fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> {
-    if_chain! {
-        if let Some(meta_item) = lint.meta_item();
-        if meta_item.path.segments.len() > 1;
-        if let tool_name = meta_item.path.segments[0].ident;
-        if tool_name.name == sym::clippy;
-        then {
-            let lint_name = meta_item.path.segments.last().unwrap().ident.name;
-            return Some(lint_name);
-        }
+    if let Some(meta_item) = lint.meta_item()
+        && meta_item.path.segments.len() > 1
+        && let tool_name = meta_item.path.segments[0].ident
+        && tool_name.name == sym::clippy
+    {
+        let lint_name = meta_item.path.segments.last().unwrap().ident.name;
+        return Some(lint_name);
     }
     None
 }
@@ -857,18 +852,17 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
 }
 
 fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) {
-    if_chain! {
-        if msrv.meets(msrvs::TOOL_ATTRIBUTES);
+    if msrv.meets(msrvs::TOOL_ATTRIBUTES)
         // check cfg_attr
-        if attr.has_name(sym::cfg_attr);
-        if let Some(items) = attr.meta_item_list();
-        if items.len() == 2;
+        && attr.has_name(sym::cfg_attr)
+        && let Some(items) = attr.meta_item_list()
+        && items.len() == 2
         // check for `rustfmt`
-        if let Some(feature_item) = items[0].meta_item();
-        if feature_item.has_name(sym::rustfmt);
+        && let Some(feature_item) = items[0].meta_item()
+        && feature_item.has_name(sym::rustfmt)
         // check for `rustfmt_skip` and `rustfmt::skip`
-        if let Some(skip_item) = &items[1].meta_item();
-        if skip_item.has_name(sym!(rustfmt_skip))
+        && let Some(skip_item) = &items[1].meta_item()
+        && (skip_item.has_name(sym!(rustfmt_skip))
             || skip_item
                 .path
                 .segments
@@ -876,21 +870,20 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
                 .expect("empty path in attribute")
                 .ident
                 .name
-                == sym::skip;
+                == sym::skip)
         // Only lint outer attributes, because custom inner attributes are unstable
         // Tracking issue: https://github.com/rust-lang/rust/issues/54726
-        if attr.style == AttrStyle::Outer;
-        then {
-            span_lint_and_sugg(
-                cx,
-                DEPRECATED_CFG_ATTR,
-                attr.span,
-                "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes",
-                "use",
-                "#[rustfmt::skip]".to_string(),
-                Applicability::MachineApplicable,
-            );
-        }
+        && attr.style == AttrStyle::Outer
+    {
+        span_lint_and_sugg(
+            cx,
+            DEPRECATED_CFG_ATTR,
+            attr.span,
+            "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes",
+            "use",
+            "#[rustfmt::skip]".to_string(),
+            Applicability::MachineApplicable,
+        );
     }
 }
 
@@ -990,12 +983,10 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
                         mismatched.extend(find_mismatched_target_os(list));
                     },
                     MetaItemKind::Word => {
-                        if_chain! {
-                            if let Some(ident) = meta.ident();
-                            if let Some(os) = find_os(ident.name.as_str());
-                            then {
-                                mismatched.push((os, ident.span));
-                            }
+                        if let Some(ident) = meta.ident()
+                            && let Some(os) = find_os(ident.name.as_str())
+                        {
+                            mismatched.push((os, ident.span));
                         }
                     },
                     MetaItemKind::NameValue(..) => {},
@@ -1006,30 +997,28 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
         mismatched
     }
 
-    if_chain! {
-        if attr.has_name(sym::cfg);
-        if let Some(list) = attr.meta_item_list();
-        let mismatched = find_mismatched_target_os(&list);
-        if !mismatched.is_empty();
-        then {
-            let mess = "operating system used in target family position";
-
-            span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| {
-                // Avoid showing the unix suggestion multiple times in case
-                // we have more than one mismatch for unix-like systems
-                let mut unix_suggested = false;
-
-                for (os, span) in mismatched {
-                    let sugg = format!("target_os = \"{os}\"");
-                    diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
-
-                    if !unix_suggested && is_unix(os) {
-                        diag.help("did you mean `unix`?");
-                        unix_suggested = true;
-                    }
+    if attr.has_name(sym::cfg)
+        && let Some(list) = attr.meta_item_list()
+        && let mismatched = find_mismatched_target_os(&list)
+        && !mismatched.is_empty()
+    {
+        let mess = "operating system used in target family position";
+
+        span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| {
+            // Avoid showing the unix suggestion multiple times in case
+            // we have more than one mismatch for unix-like systems
+            let mut unix_suggested = false;
+
+            for (os, span) in mismatched {
+                let sugg = format!("target_os = \"{os}\"");
+                diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
+
+                if !unix_suggested && is_unix(os) {
+                    diag.help("did you mean `unix`?");
+                    unix_suggested = true;
                 }
-            });
-        }
+            }
+        });
     }
 }
 
diff --git a/clippy_lints/src/blocks_in_if_conditions.rs b/clippy_lints/src/blocks_in_if_conditions.rs
index 04bf541a5bd..28bd3fc7011 100644
--- a/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/clippy_lints/src/blocks_in_if_conditions.rs
@@ -4,7 +4,6 @@ use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::{for_each_expr, Descend};
 use clippy_utils::{get_parent_expr, higher};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BlockCheckMode, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -114,15 +113,13 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
                 let _: Option<!> = for_each_expr(cond, |e| {
                     if let ExprKind::Closure(closure) = e.kind {
                         // do not lint if the closure is called using an iterator (see #1141)
-                        if_chain! {
-                            if let Some(parent) = get_parent_expr(cx, e);
-                            if let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind;
-                            let caller = cx.typeck_results().expr_ty(self_arg);
-                            if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
-                            if implements_trait(cx, caller, iter_id, &[]);
-                            then {
-                                return ControlFlow::Continue(Descend::No);
-                            }
+                        if let Some(parent) = get_parent_expr(cx, e)
+                            && let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind
+                            && let caller = cx.typeck_results().expr_ty(self_arg)
+                            && let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
+                            && implements_trait(cx, caller, iter_id, &[])
+                        {
+                            return ControlFlow::Continue(Descend::No);
                         }
 
                         let body = cx.tcx.hir().body(closure.body);
diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index 37ce65676c7..66fd64c1cd0 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::eq_expr_value;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
@@ -152,17 +151,15 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
                 return Ok(Bool::Term(n as u8));
             }
 
-            if_chain! {
-                if let ExprKind::Binary(e_binop, e_lhs, e_rhs) = &e.kind;
-                if implements_ord(self.cx, e_lhs);
-                if let ExprKind::Binary(expr_binop, expr_lhs, expr_rhs) = &expr.kind;
-                if negate(e_binop.node) == Some(expr_binop.node);
-                if eq_expr_value(self.cx, e_lhs, expr_lhs);
-                if eq_expr_value(self.cx, e_rhs, expr_rhs);
-                then {
-                    #[expect(clippy::cast_possible_truncation)]
-                    return Ok(Bool::Not(Box::new(Bool::Term(n as u8))));
-                }
+            if let ExprKind::Binary(e_binop, e_lhs, e_rhs) = &e.kind
+                && implements_ord(self.cx, e_lhs)
+                && let ExprKind::Binary(expr_binop, expr_lhs, expr_rhs) = &expr.kind
+                && negate(e_binop.node) == Some(expr_binop.node)
+                && eq_expr_value(self.cx, e_lhs, expr_lhs)
+                && eq_expr_value(self.cx, e_rhs, expr_rhs)
+            {
+                #[expect(clippy::cast_possible_truncation)]
+                return Ok(Bool::Not(Box::new(Bool::Term(n as u8))));
             }
         }
         let n = self.terminals.len();
diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs
index 739ce8f67c2..789cd3b6c21 100644
--- a/clippy_lints/src/borrow_deref_ref.rs
+++ b/clippy_lints/src/borrow_deref_ref.rs
@@ -49,69 +49,62 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
 
 impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
-        if_chain! {
-            if !e.span.from_expansion();
-            if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
-            if !addrof_target.span.from_expansion();
-            if let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind;
-            if !deref_target.span.from_expansion();
-            if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
-            let ref_ty = cx.typeck_results().expr_ty(deref_target);
-            if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
-            if !is_from_proc_macro(cx, e);
-            then{
-
-                if let Some(parent_expr) = get_parent_expr(cx, e){
-                    if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) &&
-                       !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) {
-                        return;
-                    }
+        if !e.span.from_expansion()
+            && let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind
+            && !addrof_target.span.from_expansion()
+            && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind
+            && !deref_target.span.from_expansion()
+            && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..))
+            && let ref_ty = cx.typeck_results().expr_ty(deref_target)
+            && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind()
+            && !is_from_proc_macro(cx, e)
+        {
+            if let Some(parent_expr) = get_parent_expr(cx, e) {
+                if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..))
+                    && !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id)
+                {
+                    return;
+                }
 
-                    // modification to `&mut &*x` is different from `&mut x`
-                    if matches!(deref_target.kind, ExprKind::Path(..)
-                                             | ExprKind::Field(..)
-                                             | ExprKind::Index(..)
-                                             | ExprKind::Unary(UnOp::Deref, ..))
-                     && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) {
-                       return;
-                    }
+                // modification to `&mut &*x` is different from `&mut x`
+                if matches!(
+                    deref_target.kind,
+                    ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..)
+                ) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _))
+                {
+                    return;
                 }
+            }
 
-                span_lint_and_then(
-                    cx,
-                    BORROW_DEREF_REF,
-                    e.span,
-                    "deref on an immutable reference",
-                    |diag| {
-                        diag.span_suggestion(
-                            e.span,
-                            "if you would like to reborrow, try removing `&*`",
-                            snippet_opt(cx, deref_target.span).unwrap(),
-                            Applicability::MachineApplicable
-                        );
+            span_lint_and_then(
+                cx,
+                BORROW_DEREF_REF,
+                e.span,
+                "deref on an immutable reference",
+                |diag| {
+                    diag.span_suggestion(
+                        e.span,
+                        "if you would like to reborrow, try removing `&*`",
+                        snippet_opt(cx, deref_target.span).unwrap(),
+                        Applicability::MachineApplicable,
+                    );
 
-                        // 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;
-                            }
+                    // 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;
                         }
-
-                        diag.span_suggestion(
-                            e.span,
-                            "if you would like to deref, try using `&**`",
-                            format!(
-                                "&**{}",
-                                &snippet_opt(cx, deref_target.span).unwrap(),
-                             ),
-                            Applicability::MaybeIncorrect
-                        );
-
                     }
-                );
 
-            }
+                    diag.span_suggestion(
+                        e.span,
+                        "if you would like to deref, try using `&**`",
+                        format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()),
+                        Applicability::MaybeIncorrect,
+                    );
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs
index f9b17d45e9f..473646d00d5 100644
--- a/clippy_lints/src/cargo/multiple_crate_versions.rs
+++ b/clippy_lints/src/cargo/multiple_crate_versions.rs
@@ -2,7 +2,6 @@
 
 use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId};
 use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_lint::LateContext;
@@ -15,31 +14,33 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
     let mut packages = metadata.packages.clone();
     packages.sort_by(|a, b| a.name.cmp(&b.name));
 
-    if_chain! {
-        if let Some(resolve) = &metadata.resolve;
-        if let Some(local_id) = packages
-            .iter()
-            .find_map(|p| if p.name == local_name.as_str() { Some(&p.id) } else { None });
-        then {
-            for (name, group) in &packages.iter().group_by(|p| p.name.clone()) {
-                let group: Vec<&Package> = group.collect();
-
-                if group.len() <= 1 {
-                    continue;
-                }
-
-                if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) {
-                    let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect();
-                    versions.sort();
-                    let versions = versions.iter().join(", ");
-
-                    span_lint(
-                        cx,
-                        MULTIPLE_CRATE_VERSIONS,
-                        DUMMY_SP,
-                        &format!("multiple versions for dependency `{name}`: {versions}"),
-                    );
-                }
+    if let Some(resolve) = &metadata.resolve
+        && let Some(local_id) = packages.iter().find_map(|p| {
+            if p.name == local_name.as_str() {
+                Some(&p.id)
+            } else {
+                None
+            }
+        })
+    {
+        for (name, group) in &packages.iter().group_by(|p| p.name.clone()) {
+            let group: Vec<&Package> = group.collect();
+
+            if group.len() <= 1 {
+                continue;
+            }
+
+            if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) {
+                let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect();
+                versions.sort();
+                let versions = versions.iter().join(", ");
+
+                span_lint(
+                    cx,
+                    MULTIPLE_CRATE_VERSIONS,
+                    DUMMY_SP,
+                    &format!("multiple versions for dependency `{name}`: {versions}"),
+                );
             }
         }
     }
diff --git a/clippy_lints/src/cargo/wildcard_dependencies.rs b/clippy_lints/src/cargo/wildcard_dependencies.rs
index 7fa6acbf557..3b7546dfd31 100644
--- a/clippy_lints/src/cargo/wildcard_dependencies.rs
+++ b/clippy_lints/src/cargo/wildcard_dependencies.rs
@@ -1,6 +1,5 @@
 use cargo_metadata::Metadata;
 use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
 use rustc_lint::LateContext;
 use rustc_span::source_map::DUMMY_SP;
 
@@ -9,19 +8,17 @@ use super::WILDCARD_DEPENDENCIES;
 pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
     for dep in &metadata.packages[0].dependencies {
         // VersionReq::any() does not work
-        if_chain! {
-            if let Ok(wildcard_ver) = semver::VersionReq::parse("*");
-            if let Some(ref source) = dep.source;
-            if !source.starts_with("git");
-            if dep.req == wildcard_ver;
-            then {
-                span_lint(
-                    cx,
-                    WILDCARD_DEPENDENCIES,
-                    DUMMY_SP,
-                    &format!("wildcard dependency for `{}`", dep.name),
-                );
-            }
+        if let Ok(wildcard_ver) = semver::VersionReq::parse("*")
+            && let Some(ref source) = dep.source
+            && !source.starts_with("git")
+            && dep.req == wildcard_ver
+        {
+            span_lint(
+                cx,
+                WILDCARD_DEPENDENCIES,
+                DUMMY_SP,
+                &format!("wildcard dependency for `{}`", dep.name),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs
index a83dfd94dc2..bd12ee40628 100644
--- a/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/clippy_lints/src/casts/cast_sign_loss.rs
@@ -1,7 +1,6 @@
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{method_chain_args, sext};
-use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
@@ -28,13 +27,11 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
 
             // Don't lint for positive constants.
             let const_val = constant(cx, cx.typeck_results(), cast_op);
-            if_chain! {
-                if let Some(Constant::Int(n)) = const_val;
-                if let ty::Int(ity) = *cast_from.kind();
-                if sext(cx.tcx, n, ity) >= 0;
-                then {
-                    return false;
-                }
+            if let Some(Constant::Int(n)) = const_val
+                && let ty::Int(ity) = *cast_from.kind()
+                && sext(cx.tcx, n, ity) >= 0
+            {
+                return false;
             }
 
             // Don't lint for the result of methods that always return non-negative values.
@@ -42,13 +39,11 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
                 let mut method_name = path.ident.name.as_str();
                 let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
 
-                if_chain! {
-                    if method_name == "unwrap";
-                    if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]);
-                    if let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind;
-                    then {
-                        method_name = inner_path.ident.name.as_str();
-                    }
+                if method_name == "unwrap"
+                    && let Some(arglist) = method_chain_args(cast_op, &["unwrap"])
+                    && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind
+                {
+                    method_name = inner_path.ident.name.as_str();
                 }
 
                 if allowed_methods.iter().any(|&name| method_name == name) {
diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs
index d1410402913..2a9f7fec172 100644
--- a/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -1,7 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source;
-use if_chain::if_chain;
 use rustc_ast::Mutability;
 use rustc_hir::{Expr, ExprKind, Node};
 use rustc_lint::LateContext;
@@ -69,26 +68,24 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
 
 fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let map = cx.tcx.hir();
-    if_chain! {
-        if let Some(parent_id) = map.opt_parent_id(expr.hir_id);
-        if let Some(parent) = map.find(parent_id);
-        then {
-            let expr = match parent {
-                Node::Block(block) => {
-                    if let Some(parent_expr) = block.expr {
-                        parent_expr
-                    } else {
-                        return false;
-                    }
-                },
-                Node::Expr(expr) => expr,
-                _ => return false,
-            };
+    if let Some(parent_id) = map.opt_parent_id(expr.hir_id)
+        && let Some(parent) = map.find(parent_id)
+    {
+        let expr = match parent {
+            Node::Block(block) => {
+                if let Some(parent_expr) = block.expr {
+                    parent_expr
+                } else {
+                    return false;
+                }
+            },
+            Node::Expr(expr) => expr,
+            _ => return false,
+        };
 
-            matches!(expr.kind, ExprKind::Cast(..))
-        } else {
-            false
-        }
+        matches!(expr.kind, ExprKind::Cast(..))
+    } else {
+        false
     }
 }
 
diff --git a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
index badadf2c9f6..3db1e3e6d97 100644
--- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
+++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
@@ -1,7 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind};
@@ -25,34 +24,32 @@ fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option<RawPartsKind> {
 }
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: &Msrv) {
-    if_chain! {
-        if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS);
-        if let ty::RawPtr(ptrty) = cast_to.kind();
-        if let ty::Slice(_) = ptrty.ty.kind();
-        if let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind;
-        if let ExprKind::Path(ref qpath) = fun.kind;
-        if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
-        if let Some(rpk) = raw_parts_kind(cx, fun_def_id);
-        let ctxt = expr.span.ctxt();
-        if cast_expr.span.ctxt() == ctxt;
-        then {
-            let func = match rpk {
-                RawPartsKind::Immutable => "from_raw_parts",
-                RawPartsKind::Mutable => "from_raw_parts_mut"
-            };
-            let span = expr.span;
-            let mut applicability = Applicability::MachineApplicable;
-            let ptr = snippet_with_context(cx, ptr_arg.span, ctxt, "ptr", &mut applicability).0;
-            let len = snippet_with_context(cx, len_arg.span, ctxt, "len", &mut applicability).0;
-            span_lint_and_sugg(
-                cx,
-                CAST_SLICE_FROM_RAW_PARTS,
-                span,
-                &format!("casting the result of `{func}` to {cast_to}"),
-                "replace with",
-                format!("core::ptr::slice_{func}({ptr}, {len})"),
-                applicability
-            );
-        }
+    if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS)
+        && let ty::RawPtr(ptrty) = cast_to.kind()
+        && let ty::Slice(_) = ptrty.ty.kind()
+        && let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind
+        && let ExprKind::Path(ref qpath) = fun.kind
+        && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
+        && let Some(rpk) = raw_parts_kind(cx, fun_def_id)
+        && let ctxt = expr.span.ctxt()
+        && cast_expr.span.ctxt() == ctxt
+    {
+        let func = match rpk {
+            RawPartsKind::Immutable => "from_raw_parts",
+            RawPartsKind::Mutable => "from_raw_parts_mut",
+        };
+        let span = expr.span;
+        let mut applicability = Applicability::MachineApplicable;
+        let ptr = snippet_with_context(cx, ptr_arg.span, ctxt, "ptr", &mut applicability).0;
+        let len = snippet_with_context(cx, len_arg.span, ctxt, "len", &mut applicability).0;
+        span_lint_and_sugg(
+            cx,
+            CAST_SLICE_FROM_RAW_PARTS,
+            span,
+            &format!("casting the result of `{func}` to {cast_to}"),
+            "replace with",
+            format!("core::ptr::slice_{func}({ptr}, {len})"),
+            applicability,
+        );
     }
 }
diff --git a/clippy_lints/src/casts/char_lit_as_u8.rs b/clippy_lints/src/casts/char_lit_as_u8.rs
index 82e07c98a7e..a7d3868f76c 100644
--- a/clippy_lints/src/casts/char_lit_as_u8.rs
+++ b/clippy_lints/src/casts/char_lit_as_u8.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -10,32 +9,31 @@ use rustc_middle::ty::{self, UintTy};
 use super::CHAR_LIT_AS_U8;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Cast(e, _) = &expr.kind;
-        if let ExprKind::Lit(l) = &e.kind;
-        if let LitKind::Char(c) = l.node;
-        if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(expr).kind();
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability);
+    if let ExprKind::Cast(e, _) = &expr.kind
+        && let ExprKind::Lit(l) = &e.kind
+        && let LitKind::Char(c) = l.node
+        && ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(expr).kind()
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability);
 
-            span_lint_and_then(
-                cx,
-                CHAR_LIT_AS_U8,
-                expr.span,
-                "casting a character literal to `u8` truncates",
-                |diag| {
-                    diag.note("`char` is four bytes wide, but `u8` is a single byte");
+        span_lint_and_then(
+            cx,
+            CHAR_LIT_AS_U8,
+            expr.span,
+            "casting a character literal to `u8` truncates",
+            |diag| {
+                diag.note("`char` is four bytes wide, but `u8` is a single byte");
 
-                    if c.is_ascii() {
-                        diag.span_suggestion(
-                            expr.span,
-                            "use a byte literal instead",
-                            format!("b{snippet}"),
-                            applicability,
-                        );
-                    }
-            });
-        }
+                if c.is_ascii() {
+                    diag.span_suggestion(
+                        expr.span,
+                        "use a byte literal instead",
+                        format!("b{snippet}"),
+                        applicability,
+                    );
+                }
+            },
+        );
     }
 }
diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs
index 0172e933649..ff069860a11 100644
--- a/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -1,7 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
@@ -17,29 +16,35 @@ pub(super) fn check<'tcx>(
     cast_to: Ty<'tcx>,
     msrv: &Msrv,
 ) {
-    if_chain! {
-        if msrv.meets(msrvs::POINTER_CAST_CONSTNESS);
-        if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind();
-        if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind();
-        if matches!((from_mutbl, to_mutbl),
-            (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not));
-        if from_ty == to_ty;
-        then {
-            let sugg = Sugg::hir(cx, cast_expr, "_");
-            let constness = match *to_mutbl {
-                Mutability::Not => "const",
-                Mutability::Mut => "mut",
-            };
+    if msrv.meets(msrvs::POINTER_CAST_CONSTNESS)
+        && let ty::RawPtr(TypeAndMut {
+            mutbl: from_mutbl,
+            ty: from_ty,
+        }) = cast_from.kind()
+        && let ty::RawPtr(TypeAndMut {
+            mutbl: to_mutbl,
+            ty: to_ty,
+        }) = cast_to.kind()
+        && matches!(
+            (from_mutbl, to_mutbl),
+            (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)
+        )
+        && from_ty == to_ty
+    {
+        let sugg = Sugg::hir(cx, cast_expr, "_");
+        let constness = match *to_mutbl {
+            Mutability::Not => "const",
+            Mutability::Mut => "mut",
+        };
 
-            span_lint_and_sugg(
-                cx,
-                PTR_CAST_CONSTNESS,
-                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,
-            );
-        }
+        span_lint_and_sugg(
+            cx,
+            PTR_CAST_CONSTNESS,
+            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,
+        );
     }
 }
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 61bfce07e1a..849920bb76d 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -3,7 +3,6 @@ use clippy_utils::numeric_literal::NumericLiteral;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::visitors::{for_each_expr, Visitable};
 use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
-use if_chain::if_chain;
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -25,40 +24,40 @@ pub(super) fn check<'tcx>(
 ) -> bool {
     let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
 
-    if_chain! {
-        if let ty::RawPtr(..) = cast_from.kind();
+    if let ty::RawPtr(..) = cast_from.kind()
         // check both mutability and type are the same
-        if cast_from.kind() == cast_to.kind();
-        if let ExprKind::Cast(_, cast_to_hir) = expr.kind;
+        && cast_from.kind() == cast_to.kind()
+        && let ExprKind::Cast(_, cast_to_hir) = expr.kind
         // Ignore casts to e.g. type aliases and infer types
         // - p as pointer_alias
         // - p as _
-        if let TyKind::Ptr(to_pointee) = cast_to_hir.kind;
-        then {
-            match to_pointee.ty.kind {
-                // Ignore casts to pointers that are aliases or cfg dependant, e.g.
-                // - p as *const std::ffi::c_char (alias)
-                // - p as *const std::os::raw::c_char (cfg dependant)
-                TyKind::Path(qpath) => {
-                    if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) {
-                        return false;
-                    }
-                },
-                // Ignore `p as *const _`
-                TyKind::Infer => return false,
-                _ => {},
-            }
-
-            span_lint_and_sugg(
-                cx,
-                UNNECESSARY_CAST,
-                expr.span,
-                &format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"),
-                "try",
-                cast_str.clone(),
-                Applicability::MaybeIncorrect,
-            );
+        && let TyKind::Ptr(to_pointee) = cast_to_hir.kind
+    {
+        match to_pointee.ty.kind {
+            // Ignore casts to pointers that are aliases or cfg dependant, e.g.
+            // - p as *const std::ffi::c_char (alias)
+            // - p as *const std::os::raw::c_char (cfg dependant)
+            TyKind::Path(qpath) => {
+                if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) {
+                    return false;
+                }
+            },
+            // Ignore `p as *const _`
+            TyKind::Infer => return false,
+            _ => {},
         }
+
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_CAST,
+            expr.span,
+            &format!(
+                "casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"
+            ),
+            "try",
+            cast_str.clone(),
+            Applicability::MaybeIncorrect,
+        );
     }
 
     // skip cast of local that is a type alias
@@ -86,14 +85,12 @@ pub(super) fn check<'tcx>(
     }
 
     // skip cast to non-primitive type
-    if_chain! {
-        if let ExprKind::Cast(_, cast_to) = expr.kind;
-        if let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind;
-        if let Res::PrimTy(_) = path.res;
-        then {}
-        else {
-            return false;
-        }
+    if let ExprKind::Cast(_, cast_to) = expr.kind
+        && let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind
+        && let Res::PrimTy(_) = path.res
+    {
+    } else {
+        return false;
     }
 
     // skip cast of fn call that returns type alias
@@ -106,18 +103,19 @@ pub(super) fn check<'tcx>(
     if let Some(lit) = get_numeric_literal(cast_expr) {
         let literal_str = &cast_str;
 
-        if_chain! {
-            if let LitKind::Int(n, _) = lit.node;
-            if let Some(src) = snippet_opt(cx, cast_expr.span);
-            if cast_to.is_floating_point();
-            if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node);
-            let from_nbits = 128 - n.leading_zeros();
-            let to_nbits = fp_ty_mantissa_nbits(cast_to);
-            if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal();
-            then {
-                lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
-                return true
-            }
+        if let LitKind::Int(n, _) = lit.node
+            && let Some(src) = snippet_opt(cx, cast_expr.span)
+            && cast_to.is_floating_point()
+            && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
+            && let from_nbits = 128 - n.leading_zeros()
+            && let to_nbits = fp_ty_mantissa_nbits(cast_to)
+            && from_nbits != 0
+            && to_nbits != 0
+            && from_nbits <= to_nbits
+            && num_lit.is_decimal()
+        {
+            lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
+            return true;
         }
 
         match lit.node {
diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs
index d31c2268a65..69fa0821e3f 100644
--- a/clippy_lints/src/checked_conversions.rs
+++ b/clippy_lints/src/checked_conversions.rs
@@ -4,7 +4,6 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -55,20 +54,17 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
             return;
         }
 
-        let result = if_chain! {
-            if !in_constant(cx, item.hir_id);
-            if !in_external_macro(cx.sess(), item.span);
-            if let ExprKind::Binary(op, left, right) = &item.kind;
-
-            then {
-                match op.node {
-                    BinOpKind::Ge | BinOpKind::Le => single_check(item),
-                    BinOpKind::And => double_check(cx, left, right),
-                    _ => None,
-                }
-            } else {
-                None
+        let result = if !in_constant(cx, item.hir_id)
+            && !in_external_macro(cx.sess(), item.span)
+            && let ExprKind::Binary(op, left, right) = &item.kind
+        {
+            match op.node {
+                BinOpKind::Ge | BinOpKind::Le => single_check(item),
+                BinOpKind::And => double_check(cx, left, right),
+                _ => None,
             }
+        } else {
+            None
         };
 
         if let Some(cv) = result {
@@ -193,16 +189,13 @@ impl ConversionType {
 
 /// Check for `expr <= (to_type::MAX as from_type)`
 fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
-    if_chain! {
-         if let ExprKind::Binary(ref op, left, right) = &expr.kind;
-         if let Some((candidate, check)) = normalize_le_ge(op, left, right);
-         if let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX");
-
-         then {
-             Conversion::try_new(candidate, from, to)
-         } else {
-            None
-        }
+    if let ExprKind::Binary(ref op, left, right) = &expr.kind
+        && let Some((candidate, check)) = normalize_le_ge(op, left, right)
+        && let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX")
+    {
+        Conversion::try_new(candidate, from, to)
+    } else {
+        None
     }
 }
 
@@ -243,33 +236,27 @@ fn get_types_from_cast<'a>(
 ) -> Option<(&'a str, &'a str)> {
     // `to_type::max_value() as from_type`
     // or `to_type::MAX as from_type`
-    let call_from_cast: Option<(&Expr<'_>, &str)> = if_chain! {
+    let call_from_cast: Option<(&Expr<'_>, &str)> = if let ExprKind::Cast(limit, from_type) = &expr.kind
         // to_type::max_value(), from_type
-        if let ExprKind::Cast(limit, from_type) = &expr.kind;
-        if let TyKind::Path(ref from_type_path) = &from_type.kind;
-        if let Some(from_sym) = int_ty_to_sym(from_type_path);
-
-        then {
-            Some((limit, from_sym))
-        } else {
-            None
-        }
+        && let TyKind::Path(ref from_type_path) = &from_type.kind
+        && let Some(from_sym) = int_ty_to_sym(from_type_path)
+    {
+        Some((limit, from_sym))
+    } else {
+        None
     };
 
     // `from_type::from(to_type::max_value())`
     let limit_from: Option<(&Expr<'_>, &str)> = call_from_cast.or_else(|| {
-        if_chain! {
+        if let ExprKind::Call(from_func, [limit]) = &expr.kind
             // `from_type::from, to_type::max_value()`
-            if let ExprKind::Call(from_func, [limit]) = &expr.kind;
             // `from_type::from`
-            if let ExprKind::Path(ref path) = &from_func.kind;
-            if let Some(from_sym) = get_implementing_type(path, INTS, "from");
-
-            then {
-                Some((limit, from_sym))
-            } else {
-                None
-            }
+            && let ExprKind::Path(ref path) = &from_func.kind
+            && let Some(from_sym) = get_implementing_type(path, INTS, "from")
+        {
+            Some((limit, from_sym))
+        } else {
+            None
         }
     });
 
@@ -298,31 +285,27 @@ fn get_types_from_cast<'a>(
 
 /// Gets the type which implements the called function
 fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function: &str) -> Option<&'a str> {
-    if_chain! {
-        if let QPath::TypeRelative(ty, path) = &path;
-        if path.ident.name.as_str() == function;
-        if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind;
-        if let [int] = tp.segments;
-        then {
-            let name = int.ident.name.as_str();
-            candidates.iter().find(|c| &name == *c).copied()
-        } else {
-            None
-        }
+    if let QPath::TypeRelative(ty, path) = &path
+        && path.ident.name.as_str() == function
+        && let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind
+        && let [int] = tp.segments
+    {
+        let name = int.ident.name.as_str();
+        candidates.iter().find(|c| &name == *c).copied()
+    } else {
+        None
     }
 }
 
 /// Gets the type as a string, if it is a supported integer
 fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
-    if_chain! {
-        if let QPath::Resolved(_, path) = *path;
-        if let [ty] = path.segments;
-        then {
-            let name = ty.ident.name.as_str();
-            INTS.iter().find(|c| &name == *c).copied()
-        } else {
-            None
-        }
+    if let QPath::Resolved(_, path) = *path
+        && let [ty] = path.segments
+    {
+        let name = ty.ident.name.as_str();
+        INTS.iter().find(|c| &name == *c).copied()
+    } else {
+        None
     }
 }
 
diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs
index d21ef195d9b..e5aaf88ab6c 100644
--- a/clippy_lints/src/collapsible_if.rs
+++ b/clippy_lints/src/collapsible_if.rs
@@ -15,7 +15,6 @@
 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 if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -121,49 +120,55 @@ fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
 }
 
 fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) {
-    if_chain! {
-        if let ast::ExprKind::Block(ref block, _) = else_.kind;
-        if !block_starts_with_comment(cx, block);
-        if let Some(else_) = expr_block(block);
-        if else_.attrs.is_empty();
-        if !else_.span.from_expansion();
-        if let ast::ExprKind::If(..) = else_.kind;
-        then {
-            // 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 };
+    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,
-            );
-        }
+        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_chain! {
-        if !block_starts_with_comment(cx, then);
-        if let Some(inner) = expr_block(then);
-        if inner.attrs.is_empty();
-        if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind;
+    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 { .. } }`.
-        if !matches!(check_inner.kind, ast::ExprKind::Let(..));
-        let ctxt = expr.span.ctxt();
-        if inner.span.ctxt() == ctxt;
-        then {
-            span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this `if` statement can be collapsed", |diag| {
+        && !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);
@@ -177,8 +182,8 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
                     ),
                     app, // snippet
                 );
-            });
-        }
+            },
+        );
     }
 }
 
diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs
index 5d04ad0112d..db850edd640 100644
--- a/clippy_lints/src/copy_iterator.rs
+++ b/clippy_lints/src/copy_iterator.rs
@@ -5,8 +5,6 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
-use if_chain::if_chain;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for types that implement `Copy` as well as
@@ -38,25 +36,23 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
 
 impl<'tcx> LateLintPass<'tcx> for CopyIterator {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if_chain! {
-            if let ItemKind::Impl(Impl {
-                of_trait: Some(ref trait_ref),
-                ..
-            }) = item.kind;
-            let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            if is_copy(cx, ty);
-            if let Some(trait_id) = trait_ref.trait_def_id();
-            if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
-            then {
-                span_lint_and_note(
-                    cx,
-                    COPY_ITERATOR,
-                    item.span,
-                    "you are implementing `Iterator` on a `Copy` type",
-                    None,
-                    "consider implementing `IntoIterator` instead",
-                );
-            }
+        if let ItemKind::Impl(Impl {
+            of_trait: Some(ref trait_ref),
+            ..
+        }) = item.kind
+            && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
+            && is_copy(cx, ty)
+            && let Some(trait_id) = trait_ref.trait_def_id()
+            && cx.tcx.is_diagnostic_item(sym::Iterator, trait_id)
+        {
+            span_lint_and_note(
+                cx,
+                COPY_ITERATOR,
+                item.span,
+                "you are implementing `Iterator` on a `Copy` type",
+                None,
+                "consider implementing `IntoIterator` instead",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs
index a2005638d24..637d5aae1be 100644
--- a/clippy_lints/src/crate_in_macro_def.rs
+++ b/clippy_lints/src/crate_in_macro_def.rs
@@ -53,35 +53,31 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]);
 
 impl EarlyLintPass for CrateInMacroDef {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if_chain! {
-            if item.attrs.iter().any(is_macro_export);
-            if let ItemKind::MacroDef(macro_def) = &item.kind;
-            let tts = macro_def.body.tokens.clone();
-            if let Some(span) = contains_unhygienic_crate_reference(&tts);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    CRATE_IN_MACRO_DEF,
-                    span,
-                    "`crate` references the macro call's crate",
-                    "to reference the macro definition's crate, use",
-                    String::from("$crate"),
-                    Applicability::MachineApplicable,
-                );
-            }
+        if item.attrs.iter().any(is_macro_export)
+            && let ItemKind::MacroDef(macro_def) = &item.kind
+            && let tts = macro_def.body.tokens.clone()
+            && let Some(span) = contains_unhygienic_crate_reference(&tts)
+        {
+            span_lint_and_sugg(
+                cx,
+                CRATE_IN_MACRO_DEF,
+                span,
+                "`crate` references the macro call's crate",
+                "to reference the macro definition's crate, use",
+                String::from("$crate"),
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
 
 fn is_macro_export(attr: &Attribute) -> bool {
-    if_chain! {
-        if let AttrKind::Normal(normal) = &attr.kind;
-        if let [segment] = normal.item.path.segments.as_slice();
-        then {
-            segment.ident.name == sym::macro_export
-        } else {
-            false
-        }
+    if let AttrKind::Normal(normal) = &attr.kind
+        && let [segment] = normal.item.path.segments.as_slice()
+    {
+        segment.ident.name == sym::macro_export
+    } else {
+        false
     }
 }
 
@@ -89,14 +85,12 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
     let mut prev_is_dollar = false;
     let mut cursor = tts.trees();
     while let Some(curr) = cursor.next() {
-        if_chain! {
-            if !prev_is_dollar;
-            if let Some(span) = is_crate_keyword(curr);
-            if let Some(next) = cursor.look_ahead(0);
-            if is_token(next, &TokenKind::ModSep);
-            then {
-                return Some(span);
-            }
+        if !prev_is_dollar
+            && let Some(span) = is_crate_keyword(curr)
+            && let Some(next) = cursor.look_ahead(0)
+            && is_token(next, &TokenKind::ModSep)
+        {
+            return Some(span);
         }
         if let TokenTree::Delimited(_, _, tts) = &curr {
             let span = contains_unhygienic_crate_reference(tts);
@@ -110,10 +104,18 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
 }
 
 fn is_crate_keyword(tt: &TokenTree) -> Option<Span> {
-    if_chain! {
-        if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }, _) = tt;
-        if symbol.as_str() == "crate";
-        then { Some(*span) } else { None }
+    if let TokenTree::Token(
+        Token {
+            kind: TokenKind::Ident(symbol, _),
+            span,
+        },
+        _,
+    ) = tt
+        && symbol.as_str() == "crate"
+    {
+        Some(*span)
+    } else {
+        None
     }
 }
 
diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs
index 2bca695c43b..97b736dfd8f 100644
--- a/clippy_lints/src/create_dir.rs
+++ b/clippy_lints/src/create_dir.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -33,22 +32,20 @@ declare_lint_pass!(CreateDir => [CREATE_DIR]);
 
 impl LateLintPass<'_> for CreateDir {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Call(func, [arg, ..]) = expr.kind;
-            if let ExprKind::Path(ref path) = func.kind;
-            if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
-            if cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    CREATE_DIR,
-                    expr.span,
-                    "calling `std::fs::create_dir` where there may be a better way",
-                    "consider calling `std::fs::create_dir_all` instead",
-                    format!("create_dir_all({})", snippet(cx, arg.span, "..")),
-                    Applicability::MaybeIncorrect,
-                )
-            }
+        if let ExprKind::Call(func, [arg, ..]) = expr.kind
+            && let ExprKind::Path(ref path) = func.kind
+            && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id)
+        {
+            span_lint_and_sugg(
+                cx,
+                CREATE_DIR,
+                expr.span,
+                "calling `std::fs::create_dir` where there may be a better way",
+                "consider calling `std::fs::create_dir_all` instead",
+                format!("create_dir_all({})", snippet(cx, arg.span, "..")),
+                Applicability::MaybeIncorrect,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 1a646ba38c3..04dcccede08 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -10,8 +10,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     #[cfg(feature = "internal")]
     crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO,
     #[cfg(feature = "internal")]
-    crate::utils::internal_lints::if_chain_style::IF_CHAIN_STYLE_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,
diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs
index c74b2b8831e..b325449c5a3 100644
--- a/clippy_lints/src/default.rs
+++ b/clippy_lints/src/default.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{has_drop, is_copy};
 use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro};
-use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -81,33 +80,31 @@ impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]);
 
 impl<'tcx> LateLintPass<'tcx> for Default {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if !expr.span.from_expansion();
+        if !expr.span.from_expansion()
             // Avoid cases already linted by `field_reassign_with_default`
-            if !self.reassigned_linted.contains(&expr.span);
-            if let ExprKind::Call(path, ..) = expr.kind;
-            if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
-            if let ExprKind::Path(ref qpath) = path.kind;
-            if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
-            if cx.tcx.is_diagnostic_item(sym::default_fn, def_id);
-            if !is_update_syntax_base(cx, expr);
+            && !self.reassigned_linted.contains(&expr.span)
+            && let ExprKind::Call(path, ..) = expr.kind
+            && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
+            && !is_update_syntax_base(cx, expr)
             // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
-            if let QPath::Resolved(None, _path) = qpath;
-            let expr_ty = cx.typeck_results().expr_ty(expr);
-            if let ty::Adt(def, ..) = expr_ty.kind();
-            if !is_from_proc_macro(cx, expr);
-            then {
-                let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
-                span_lint_and_sugg(
-                    cx,
-                    DEFAULT_TRAIT_ACCESS,
-                    expr.span,
-                    &format!("calling `{replacement}` is more clear than this expression"),
-                    "try",
-                    replacement,
-                    Applicability::Unspecified, // First resolve the TODO above
-                );
-            }
+            && let QPath::Resolved(None, _path) = qpath
+            && let expr_ty = cx.typeck_results().expr_ty(expr)
+            && let ty::Adt(def, ..) = expr_ty.kind()
+            && !is_from_proc_macro(cx, expr)
+        {
+            let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
+            span_lint_and_sugg(
+                cx,
+                DEFAULT_TRAIT_ACCESS,
+                expr.span,
+                &format!("calling `{replacement}` is more clear than this expression"),
+                "try",
+                replacement,
+                Applicability::Unspecified, // First resolve the TODO above
+            );
         }
     }
 
@@ -124,38 +121,36 @@ impl<'tcx> LateLintPass<'tcx> for Default {
             // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
             // `default` method of the `Default` trait, and store statement index in current block being
             // checked and the name of the bound variable
-            let (local, variant, binding_name, binding_type, span) = if_chain! {
+            let (local, variant, binding_name, binding_type, span) = if let StmtKind::Local(local) = stmt.kind
                 // only take `let ...` statements
-                if let StmtKind::Local(local) = stmt.kind;
-                if let Some(expr) = local.init;
-                if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
-                if !expr.span.from_expansion();
+                && let Some(expr) = local.init
+                && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
+                && !expr.span.from_expansion()
                 // only take bindings to identifiers
-                if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
+                && let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind
                 // only when assigning `... = Default::default()`
-                if is_expr_default(expr, cx);
-                let binding_type = cx.typeck_results().node_type(binding_id);
-                if let Some(adt) = binding_type.ty_adt_def();
-                if adt.is_struct();
-                let variant = adt.non_enum_variant();
-                if adt.did().is_local() || !variant.is_field_list_non_exhaustive();
-                let module_did = cx.tcx.parent_module(stmt.hir_id);
-                if variant
+                && is_expr_default(expr, cx)
+                && let binding_type = cx.typeck_results().node_type(binding_id)
+                && let Some(adt) = binding_type.ty_adt_def()
+                && adt.is_struct()
+                && let variant = adt.non_enum_variant()
+                && (adt.did().is_local() || !variant.is_field_list_non_exhaustive())
+                && let module_did = cx.tcx.parent_module(stmt.hir_id)
+                && variant
                     .fields
                     .iter()
-                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx));
-                let all_fields_are_copy = variant
+                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx))
+                && let all_fields_are_copy = variant
                     .fields
                     .iter()
                     .all(|field| {
                         is_copy(cx, cx.tcx.type_of(field.did).instantiate_identity())
-                    });
-                if !has_drop(cx, binding_type) || all_fields_are_copy;
-                then {
-                    (local, variant, ident.name, binding_type, expr.span)
-                } else {
-                    continue;
-                }
+                    })
+                && (!has_drop(cx, binding_type) || all_fields_are_copy)
+            {
+                (local, variant, ident.name, binding_type, expr.span)
+            } else {
+                continue;
             };
 
             let init_ctxt = local.span.ctxt();
@@ -216,21 +211,19 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                     .join(", ");
 
                 // give correct suggestion if generics are involved (see #6944)
-                let binding_type = if_chain! {
-                    if let ty::Adt(adt_def, args) = binding_type.kind();
-                    if !args.is_empty();
-                    then {
-                        let adt_def_ty_name = cx.tcx.item_name(adt_def.did());
-                        let generic_args = args.iter().collect::<Vec<_>>();
-                        let tys_str = generic_args
-                            .iter()
-                            .map(ToString::to_string)
-                            .collect::<Vec<_>>()
-                            .join(", ");
-                        format!("{adt_def_ty_name}::<{}>", &tys_str)
-                    } else {
-                        binding_type.to_string()
-                    }
+                let binding_type = if let ty::Adt(adt_def, args) = binding_type.kind()
+                    && !args.is_empty()
+                {
+                    let adt_def_ty_name = cx.tcx.item_name(adt_def.did());
+                    let generic_args = args.iter().collect::<Vec<_>>();
+                    let tys_str = generic_args
+                        .iter()
+                        .map(ToString::to_string)
+                        .collect::<Vec<_>>()
+                        .join(", ");
+                    format!("{adt_def_ty_name}::<{}>", &tys_str)
+                } else {
+                    binding_type.to_string()
                 };
 
                 let sugg = if ext_with_default {
@@ -260,48 +253,42 @@ impl<'tcx> LateLintPass<'tcx> for Default {
 
 /// Checks if the given expression is the `default` method belonging to the `Default` trait.
 fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
-    if_chain! {
-        if let ExprKind::Call(fn_expr, _) = &expr.kind;
-        if let ExprKind::Path(qpath) = &fn_expr.kind;
-        if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
-        then {
-            // right hand side of assignment is `Default::default`
-            cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
-        } else {
-            false
-        }
+    if let ExprKind::Call(fn_expr, _) = &expr.kind
+        && let ExprKind::Path(qpath) = &fn_expr.kind
+        && let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id)
+    {
+        // right hand side of assignment is `Default::default`
+        cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
+    } else {
+        false
     }
 }
 
 /// Returns the reassigned field and the assigning expression (right-hand side of assign).
 fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
-    if_chain! {
+    if let StmtKind::Semi(later_expr) = this.kind
         // only take assignments
-        if let StmtKind::Semi(later_expr) = this.kind;
-        if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind;
+        && let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind
         // only take assignments to fields where the left-hand side field is a field of
         // the same binding as the previous statement
-        if let ExprKind::Field(binding, field_ident) = assign_lhs.kind;
-        if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind;
-        if let Some(second_binding_name) = path.segments.last();
-        if second_binding_name.ident.name == binding_name;
-        then {
-            Some((field_ident, assign_rhs))
-        } else {
-            None
-        }
+        && let ExprKind::Field(binding, field_ident) = assign_lhs.kind
+        && let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind
+        && let Some(second_binding_name) = path.segments.last()
+        && second_binding_name.ident.name == binding_name
+    {
+        Some((field_ident, assign_rhs))
+    } else {
+        None
     }
 }
 
 /// Returns whether `expr` is the update syntax base: `Foo { a: 1, .. base }`
 fn is_update_syntax_base<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    if_chain! {
-        if let Some(parent) = get_parent_expr(cx, expr);
-        if let ExprKind::Struct(_, _, Some(base)) = parent.kind;
-        then {
-            base.hir_id == expr.hir_id
-        } else {
-            false
-        }
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let ExprKind::Struct(_, _, Some(base)) = parent.kind
+    {
+        base.hir_id == expr.hir_id
+    } else {
+        false
     }
 }
diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs
index bf070432ef9..b90d01b765a 100644
--- a/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/clippy_lints/src/default_constructed_unit_structs.rs
@@ -56,32 +56,30 @@ fn is_alias(ty: hir::Ty<'_>) -> bool {
 
 impl LateLintPass<'_> for DefaultConstructedUnitStructs {
     fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
-        if_chain!(
+        if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind
             // make sure we have a call to `Default::default`
-            if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind;
-            if let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind;
+            && let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind
             // make sure this isn't a type alias:
             // `<Foo as Bar>::Assoc` cannot be used as a constructor
-            if !is_alias(*base);
-            if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
-            if cx.tcx.is_diagnostic_item(sym::default_fn, def_id);
+            && !is_alias(*base)
+            && let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id)
+            && cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
             // make sure we have a struct with no fields (unit struct)
-            if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
-            if def.is_struct();
-            if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant();
-            if !var.is_field_list_non_exhaustive();
-            if !expr.span.from_expansion() && !qpath.span().from_expansion();
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    DEFAULT_CONSTRUCTED_UNIT_STRUCTS,
-                    expr.span.with_lo(qpath.qself_span().hi()),
-                    "use of `default` to create a unit struct",
-                    "remove this call to `default`",
-                    String::new(),
-                    Applicability::MachineApplicable,
-                )
-            }
-        );
+            && let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind()
+            && def.is_struct()
+            && 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()
+        {
+            span_lint_and_sugg(
+                cx,
+                DEFAULT_CONSTRUCTED_UNIT_STRUCTS,
+                expr.span.with_lo(qpath.qself_span().hi()),
+                "use of `default` to create a unit struct",
+                "remove this call to `default`",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
+        };
     }
 }
diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs
index b296ea20f9c..fb29703957d 100644
--- a/clippy_lints/src/default_numeric_fallback.rs
+++ b/clippy_lints/src/default_numeric_fallback.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::{get_parent_node, numeric_literal};
-use if_chain::if_chain;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
@@ -82,40 +81,40 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
 
     /// Check whether a passed literal has potential to cause fallback or not.
     fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
-        if_chain! {
-                if !in_external_macro(self.cx.sess(), lit.span);
-                if matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false)));
-                if matches!(lit.node,
-                            LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed));
-                then {
-                    let (suffix, is_float) = match lit_ty.kind() {
-                        ty::Int(IntTy::I32) => ("i32", false),
-                        ty::Float(FloatTy::F64) => ("f64", true),
-                        // Default numeric fallback never results in other types.
-                        _ => return,
-                    };
-
-                    let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
-                        src
-                    } else {
-                        match lit.node {
-                            LitKind::Int(src, _) => format!("{src}"),
-                            LitKind::Float(src, _) => format!("{src}"),
-                            _ => return,
-                        }
-                    };
-                    let sugg = numeric_literal::format(&src, Some(suffix), is_float);
-                    span_lint_hir_and_then(
-                        self.cx,
-                        DEFAULT_NUMERIC_FALLBACK,
-                        emit_hir_id,
-                        lit.span,
-                        "default numeric fallback might occur",
-                        |diag| {
-                            diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
-                        }
-                    );
+        if !in_external_macro(self.cx.sess(), lit.span)
+            && matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false)))
+            && matches!(
+                lit.node,
+                LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)
+            )
+        {
+            let (suffix, is_float) = match lit_ty.kind() {
+                ty::Int(IntTy::I32) => ("i32", false),
+                ty::Float(FloatTy::F64) => ("f64", true),
+                // Default numeric fallback never results in other types.
+                _ => return,
+            };
+
+            let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
+                src
+            } else {
+                match lit.node {
+                    LitKind::Int(src, _) => format!("{src}"),
+                    LitKind::Float(src, _) => format!("{src}"),
+                    _ => return,
                 }
+            };
+            let sugg = numeric_literal::format(&src, Some(suffix), is_float);
+            span_lint_hir_and_then(
+                self.cx,
+                DEFAULT_NUMERIC_FALLBACK,
+                emit_hir_id,
+                lit.span,
+                "default numeric fallback might occur",
+                |diag| {
+                    diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
+                },
+            );
         }
     }
 }
@@ -149,36 +148,33 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
 
             ExprKind::Struct(_, fields, base) => {
                 let ty = self.cx.typeck_results().expr_ty(expr);
-                if_chain! {
-                    if let Some(adt_def) = ty.ty_adt_def();
-                    if adt_def.is_struct();
-                    if let Some(variant) = adt_def.variants().iter().next();
-                    then {
-                        let fields_def = &variant.fields;
-
-                        // Push field type then visit each field expr.
-                        for field in *fields {
-                            let bound =
-                                fields_def
-                                    .iter()
-                                    .find_map(|f_def| {
-                                        if f_def.ident(self.cx.tcx) == field.ident
-                                            { Some(self.cx.tcx.type_of(f_def.did).instantiate_identity()) }
-                                        else { None }
-                                    });
-                            self.ty_bounds.push(bound.into());
-                            self.visit_expr(field.expr);
-                            self.ty_bounds.pop();
-                        }
-
-                        // Visit base with no bound.
-                        if let Some(base) = base {
-                            self.ty_bounds.push(ExplicitTyBound(false));
-                            self.visit_expr(base);
-                            self.ty_bounds.pop();
-                        }
-                        return;
+                if let Some(adt_def) = ty.ty_adt_def()
+                    && adt_def.is_struct()
+                    && let Some(variant) = adt_def.variants().iter().next()
+                {
+                    let fields_def = &variant.fields;
+
+                    // Push field type then visit each field expr.
+                    for field in *fields {
+                        let bound = fields_def.iter().find_map(|f_def| {
+                            if f_def.ident(self.cx.tcx) == field.ident {
+                                Some(self.cx.tcx.type_of(f_def.did).instantiate_identity())
+                            } else {
+                                None
+                            }
+                        });
+                        self.ty_bounds.push(bound.into());
+                        self.visit_expr(field.expr);
+                        self.ty_bounds.pop();
+                    }
+
+                    // Visit base with no bound.
+                    if let Some(base) = base {
+                        self.ty_bounds.push(ExplicitTyBound(false));
+                        self.visit_expr(base);
+                        self.ty_bounds.pop();
                     }
+                    return;
                 }
             },
 
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 6c109a51f83..afca8850ac5 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -1,10 +1,11 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
+use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs};
 use clippy_utils::{
     expr_use_ctxt, get_parent_expr, get_parent_node, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
 };
+use core::mem;
 use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
@@ -170,9 +171,7 @@ pub struct Dereferencing<'tcx> {
 
 #[derive(Debug)]
 struct StateData<'tcx> {
-    /// Span of the top level expression
-    span: Span,
-    hir_id: HirId,
+    first_expr: &'tcx Expr<'tcx>,
     adjusted_ty: Ty<'tcx>,
 }
 
@@ -198,6 +197,7 @@ enum State {
     },
     ExplicitDerefField {
         name: Symbol,
+        derefs_manually_drop: bool,
     },
     Reborrow {
         mutability: Mutability,
@@ -242,7 +242,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
         // Stop processing sub expressions when a macro call is seen
         if expr.span.from_expansion() {
             if let Some((state, data)) = self.state.take() {
-                report(cx, expr, state, data);
+                report(cx, expr, state, data, cx.typeck_results());
             }
             return;
         }
@@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
         let Some((kind, sub_expr)) = try_parse_ref_op(cx.tcx, typeck, expr) else {
             // The whole chain of reference operations has been seen
             if let Some((state, data)) = self.state.take() {
-                report(cx, expr, state, data);
+                report(cx, expr, state, data, typeck);
             }
             return;
         };
@@ -272,14 +272,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                     (Some(use_cx), RefOp::Deref) => {
                         let sub_ty = typeck.expr_ty(sub_expr);
                         if let ExprUseNode::FieldAccess(name) = use_cx.node
-                            && adjusted_ty.ty_adt_def().map_or(true, |adt| !adt.is_union())
+                            && !use_cx.moved_before_use
                             && !ty_contains_field(sub_ty, name.name)
                         {
                             self.state = Some((
-                                State::ExplicitDerefField { name: name.name },
+                                State::ExplicitDerefField {
+                                    name: name.name,
+                                    derefs_manually_drop: is_manually_drop(sub_ty),
+                                },
                                 StateData {
-                                    span: expr.span,
-                                    hir_id: expr.hir_id,
+                                    first_expr: expr,
                                     adjusted_ty,
                                 },
                             ));
@@ -293,8 +295,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             self.state = Some((
                                 State::ExplicitDeref { mutability: None },
                                 StateData {
-                                    span: expr.span,
-                                    hir_id: expr.hir_id,
+                                    first_expr: expr,
                                     adjusted_ty,
                                 },
                             ));
@@ -313,8 +314,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                                 mutbl,
                             },
                             StateData {
-                                span: expr.span,
-                                hir_id: expr.hir_id,
+                                first_expr: expr,
                                 adjusted_ty,
                             },
                         ));
@@ -342,8 +342,18 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             TyCoercionStability::for_defined_ty(cx, ty, use_cx.node.is_return())
                         });
                         let can_auto_borrow = match use_cx.node {
-                            ExprUseNode::Callee => true,
-                            ExprUseNode::FieldAccess(_) => adjusted_ty.ty_adt_def().map_or(true, |adt| !adt.is_union()),
+                            ExprUseNode::FieldAccess(_)
+                                if !use_cx.moved_before_use && matches!(sub_expr.kind, ExprKind::Field(..)) =>
+                            {
+                                // `DerefMut` will not be automatically applied to `ManuallyDrop<_>`
+                                // field expressions when the base type is a union and the parent
+                                // expression is also a field access.
+                                //
+                                // e.g. `&mut x.y.z` where `x` is a union, and accessing `z` requires a
+                                // deref through `ManuallyDrop<_>` will not compile.
+                                !adjust_derefs_manually_drop(use_cx.adjustments, expr_ty)
+                            },
+                            ExprUseNode::Callee | ExprUseNode::FieldAccess(_) => true,
                             ExprUseNode::MethodArg(hir_id, _, 0) if !use_cx.moved_before_use => {
                                 // Check for calls to trait methods where the trait is implemented
                                 // on a reference.
@@ -357,11 +367,8 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                                         .tcx
                                         .erase_regions(use_cx.adjustments.last().map_or(expr_ty, |a| a.target))
                                     && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
-                                    && let args = cx
-                                        .typeck_results()
-                                        .node_args_opt(hir_id)
-                                        .map(|args| &args[1..])
-                                        .unwrap_or_default()
+                                    && let args =
+                                        typeck.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default()
                                     && let impl_ty =
                                         if cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder().inputs()[0]
                                             .is_ref()
@@ -436,14 +443,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                                     count: deref_count - required_refs,
                                     msg,
                                     stability,
-                                    for_field_access: match use_cx.node {
-                                        ExprUseNode::FieldAccess(name) => Some(name.name),
-                                        _ => None,
+                                    for_field_access: if let ExprUseNode::FieldAccess(name) = use_cx.node
+                                        && !use_cx.moved_before_use
+                                    {
+                                        Some(name.name)
+                                    } else {
+                                        None
                                     },
                                 }),
                                 StateData {
-                                    span: expr.span,
-                                    hir_id: expr.hir_id,
+                                    first_expr: expr,
                                     adjusted_ty: use_cx.adjustments.last().map_or(expr_ty, |a| a.target),
                                 },
                             ));
@@ -455,8 +464,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             self.state = Some((
                                 State::Borrow { mutability },
                                 StateData {
-                                    span: expr.span,
-                                    hir_id: expr.hir_id,
+                                    first_expr: expr,
                                     adjusted_ty: use_cx.adjustments.last().map_or(expr_ty, |a| a.target),
                                 },
                             ));
@@ -501,13 +509,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
             (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf(mutability)) => {
                 let adjusted_ty = data.adjusted_ty;
                 let stability = state.stability;
-                report(cx, expr, State::DerefedBorrow(state), data);
+                report(cx, expr, State::DerefedBorrow(state), data, typeck);
                 if stability.is_deref_stable() {
                     self.state = Some((
                         State::Borrow { mutability },
                         StateData {
-                            span: expr.span,
-                            hir_id: expr.hir_id,
+                            first_expr: expr,
                             adjusted_ty,
                         },
                     ));
@@ -517,15 +524,18 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                 let adjusted_ty = data.adjusted_ty;
                 let stability = state.stability;
                 let for_field_access = state.for_field_access;
-                report(cx, expr, State::DerefedBorrow(state), data);
+                report(cx, expr, State::DerefedBorrow(state), data, typeck);
                 if let Some(name) = for_field_access
-                    && !ty_contains_field(typeck.expr_ty(sub_expr), name)
+                    && let sub_expr_ty = typeck.expr_ty(sub_expr)
+                    && !ty_contains_field(sub_expr_ty, name)
                 {
                     self.state = Some((
-                        State::ExplicitDerefField { name },
+                        State::ExplicitDerefField {
+                            name,
+                            derefs_manually_drop: is_manually_drop(sub_expr_ty),
+                        },
                         StateData {
-                            span: expr.span,
-                            hir_id: expr.hir_id,
+                            first_expr: expr,
                             adjusted_ty,
                         },
                     ));
@@ -535,8 +545,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                     self.state = Some((
                         State::ExplicitDeref { mutability: None },
                         StateData {
-                            span: parent.span,
-                            hir_id: parent.hir_id,
+                            first_expr: parent,
                             adjusted_ty,
                         },
                     ));
@@ -566,13 +575,28 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
             (state @ Some((State::ExplicitDeref { .. }, _)), RefOp::Deref) => {
                 self.state = state;
             },
-            (Some((State::ExplicitDerefField { name }, data)), RefOp::Deref)
-                if !ty_contains_field(typeck.expr_ty(sub_expr), name) =>
+            (
+                Some((
+                    State::ExplicitDerefField {
+                        name,
+                        derefs_manually_drop,
+                    },
+                    data,
+                )),
+                RefOp::Deref,
+            ) if let sub_expr_ty = typeck.expr_ty(sub_expr)
+                && !ty_contains_field(sub_expr_ty, name) =>
             {
-                self.state = Some((State::ExplicitDerefField { name }, data));
+                self.state = Some((
+                    State::ExplicitDerefField {
+                        name,
+                        derefs_manually_drop: derefs_manually_drop || is_manually_drop(sub_expr_ty),
+                    },
+                    data,
+                ));
             },
 
-            (Some((state, data)), _) => report(cx, expr, state, data),
+            (Some((state, data)), _) => report(cx, expr, state, data, typeck),
         }
     }
 
@@ -597,26 +621,24 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                 return;
             }
 
-            if_chain! {
-                if !pat.span.from_expansion();
-                if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
+            if !pat.span.from_expansion()
+                && let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind()
                 // only lint immutable refs, because borrowed `&mut T` cannot be moved out
-                if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
-                then {
-                    let mut app = Applicability::MachineApplicable;
-                    let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
-                    self.current_body = self.current_body.or(cx.enclosing_body);
-                    self.ref_locals.insert(
-                        id,
-                        Some(RefPat {
-                            always_deref: true,
-                            spans: vec![pat.span],
-                            app,
-                            replacements: vec![(pat.span, snip.into())],
-                            hir_id: pat.hir_id,
-                        }),
-                    );
-                }
+                && let ty::Ref(_, _, Mutability::Not) = *tam.kind()
+            {
+                let mut app = Applicability::MachineApplicable;
+                let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
+                self.current_body = self.current_body.or(cx.enclosing_body);
+                self.ref_locals.insert(
+                    id,
+                    Some(RefPat {
+                        always_deref: true,
+                        spans: vec![pat.span],
+                        app,
+                        replacements: vec![(pat.span, snip.into())],
+                        hir_id: pat.hir_id,
+                    }),
+                );
             }
         }
     }
@@ -689,6 +711,14 @@ fn try_parse_ref_op<'tcx>(
     }
 }
 
+// Checks if the adjustments contains a deref of `ManuallyDrop<_>`
+fn adjust_derefs_manually_drop<'tcx>(adjustments: &'tcx [Adjustment<'tcx>], mut ty: Ty<'tcx>) -> bool {
+    adjustments.iter().any(|a| {
+        let ty = mem::replace(&mut ty, a.target);
+        matches!(a.kind, Adjust::Deref(Some(ref op)) if op.mutbl == Mutability::Mut) && is_manually_drop(ty)
+    })
+}
+
 // Checks whether the type for a deref call actually changed the type, not just the mutability of
 // the reference.
 fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
@@ -898,7 +928,13 @@ fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool {
 }
 
 #[expect(clippy::needless_pass_by_value, clippy::too_many_lines)]
-fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData<'tcx>) {
+fn report<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'_>,
+    state: State,
+    data: StateData<'tcx>,
+    typeck: &'tcx TypeckResults<'tcx>,
+) {
     match state {
         State::DerefMethod {
             ty_changed_count,
@@ -906,8 +942,9 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             mutbl,
         } => {
             let mut app = Applicability::MachineApplicable;
-            let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
-            let ty = cx.typeck_results().expr_ty(expr);
+            let (expr_str, _expr_is_macro_call) =
+                snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
+            let ty = typeck.expr_ty(expr);
             let (_, ref_count) = peel_mid_ty_refs(ty);
             let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
                 // a deref call changing &T -> &U requires two deref operators the first time
@@ -947,7 +984,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             span_lint_and_sugg(
                 cx,
                 EXPLICIT_DEREF_METHODS,
-                data.span,
+                data.first_expr.span,
                 match mutbl {
                     Mutability::Not => "explicit `deref` method call",
                     Mutability::Mut => "explicit `deref_mut` method call",
@@ -959,26 +996,34 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
         },
         State::DerefedBorrow(state) => {
             let mut app = Applicability::MachineApplicable;
-            let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
-            span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| {
-                let (precedence, calls_field) = match get_parent_node(cx.tcx, data.hir_id) {
-                    Some(Node::Expr(e)) => match e.kind {
-                        ExprKind::Call(callee, _) if callee.hir_id != data.hir_id => (0, false),
-                        ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))),
-                        _ => (e.precedence().order(), false),
-                    },
-                    _ => (0, false),
-                };
-                let sugg = if !snip_is_macro
-                    && (calls_field || expr.precedence().order() < precedence)
-                    && !has_enclosing_paren(&snip)
-                {
-                    format!("({snip})")
-                } else {
-                    snip.into()
-                };
-                diag.span_suggestion(data.span, "change this to", sugg, app);
-            });
+            let (snip, snip_is_macro) =
+                snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
+            span_lint_hir_and_then(
+                cx,
+                NEEDLESS_BORROW,
+                data.first_expr.hir_id,
+                data.first_expr.span,
+                state.msg,
+                |diag| {
+                    let (precedence, calls_field) = match get_parent_node(cx.tcx, data.first_expr.hir_id) {
+                        Some(Node::Expr(e)) => match e.kind {
+                            ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
+                            ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))),
+                            _ => (e.precedence().order(), false),
+                        },
+                        _ => (0, false),
+                    };
+                    let sugg = if !snip_is_macro
+                        && (calls_field || expr.precedence().order() < precedence)
+                        && !has_enclosing_paren(&snip)
+                    {
+                        format!("({snip})")
+                    } else {
+                        snip.into()
+                    };
+                    diag.span_suggestion(data.first_expr.span, "change this to", sugg, app);
+                },
+            );
         },
         State::ExplicitDeref { mutability } => {
             if matches!(
@@ -996,7 +1041,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             }
 
             let (prefix, precedence) = if let Some(mutability) = mutability
-                && !cx.typeck_results().expr_ty(expr).is_ref()
+                && !typeck.expr_ty(expr).is_ref()
             {
                 let prefix = match mutability {
                     Mutability::Not => "&",
@@ -1009,53 +1054,61 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             span_lint_hir_and_then(
                 cx,
                 EXPLICIT_AUTO_DEREF,
-                data.hir_id,
-                data.span,
+                data.first_expr.hir_id,
+                data.first_expr.span,
                 "deref which would be done by auto-deref",
                 |diag| {
                     let mut app = Applicability::MachineApplicable;
-                    let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
+                    let (snip, snip_is_macro) =
+                        snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
                     let sugg =
                         if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) {
                             format!("{prefix}({snip})")
                         } else {
                             format!("{prefix}{snip}")
                         };
-                    diag.span_suggestion(data.span, "try", sugg, app);
+                    diag.span_suggestion(data.first_expr.span, "try", sugg, app);
                 },
             );
         },
-        State::ExplicitDerefField { .. } => {
-            if matches!(
-                expr.kind,
-                ExprKind::Block(..)
-                    | ExprKind::ConstBlock(_)
-                    | ExprKind::If(..)
-                    | ExprKind::Loop(..)
-                    | ExprKind::Match(..)
-            ) && data.adjusted_ty.is_sized(cx.tcx, cx.param_env)
-            {
-                // Rustc bug: auto deref doesn't work on block expression when targeting sized types.
-                return;
-            }
-
-            if let ExprKind::Field(parent_expr, _) = expr.kind
-                && let ty::Adt(adt, _) = cx.typeck_results().expr_ty(parent_expr).kind()
-                && adt.is_union()
-            {
-                // Auto deref does not apply on union field
-                return;
-            }
+        State::ExplicitDerefField {
+            derefs_manually_drop, ..
+        } => {
+            let (snip_span, needs_parens) = if matches!(expr.kind, ExprKind::Field(..))
+                && (derefs_manually_drop
+                    || adjust_derefs_manually_drop(
+                        typeck.expr_adjustments(data.first_expr),
+                        typeck.expr_ty(data.first_expr),
+                    )) {
+                // `DerefMut` will not be automatically applied to `ManuallyDrop<_>`
+                // field expressions when the base type is a union and the parent
+                // expression is also a field access.
+                //
+                // e.g. `&mut x.y.z` where `x` is a union, and accessing `z` requires a
+                // deref through `ManuallyDrop<_>` will not compile.
+                let parent_id = cx.tcx.hir().parent_id(expr.hir_id);
+                if parent_id == data.first_expr.hir_id {
+                    return;
+                }
+                (cx.tcx.hir().get(parent_id).expect_expr().span, true)
+            } else {
+                (expr.span, false)
+            };
             span_lint_hir_and_then(
                 cx,
                 EXPLICIT_AUTO_DEREF,
-                data.hir_id,
-                data.span,
+                data.first_expr.hir_id,
+                data.first_expr.span,
                 "deref which would be done by auto-deref",
                 |diag| {
                     let mut app = Applicability::MachineApplicable;
-                    let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0;
-                    diag.span_suggestion(data.span, "try", snip.into_owned(), app);
+                    let snip = snippet_with_context(cx, snip_span, data.first_expr.span.ctxt(), "..", &mut app).0;
+                    let sugg = if needs_parens {
+                        format!("({snip})")
+                    } else {
+                        snip.into_owned()
+                    };
+                    diag.span_suggestion(data.first_expr.span, "try", sugg, app);
                 },
             );
         },
diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index a450becc647..9db56fa8ad0 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -148,83 +148,65 @@ fn check_struct<'tcx>(
 }
 
 fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) {
-    if_chain! {
-        if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind;
-        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res;
-        if let variant_id = cx.tcx.parent(id);
-        if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id);
-        if variant_def.fields.is_empty();
-        if !variant_def.is_field_list_non_exhaustive();
-
-        then {
-            let enum_span = cx.tcx.def_span(adt_def.did());
-            let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
-            let variant_span = cx.tcx.def_span(variant_def.def_id);
-            let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
-            span_lint_and_then(
-                cx,
-                DERIVABLE_IMPLS,
+    if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind
+        && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res
+        && let variant_id = cx.tcx.parent(id)
+        && let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id)
+        && variant_def.fields.is_empty()
+        && !variant_def.is_field_list_non_exhaustive()
+    {
+        let enum_span = cx.tcx.def_span(adt_def.did());
+        let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
+        let variant_span = cx.tcx.def_span(variant_def.def_id);
+        let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
+        span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
+            diag.span_suggestion_hidden(
                 item.span,
-                "this `impl` can be derived",
-                |diag| {
-                    diag.span_suggestion_hidden(
-                        item.span,
-                        "remove the manual implementation...",
-                        String::new(),
-                        Applicability::MachineApplicable
-                    );
-                    diag.span_suggestion(
-                        enum_span.shrink_to_lo(),
-                        "...and instead derive it...",
-                        format!(
-                            "#[derive(Default)]\n{indent}",
-                            indent = " ".repeat(indent_enum),
-                        ),
-                        Applicability::MachineApplicable
-                    );
-                    diag.span_suggestion(
-                        variant_span.shrink_to_lo(),
-                        "...and mark the default variant",
-                        format!(
-                            "#[default]\n{indent}",
-                            indent = " ".repeat(indent_variant),
-                        ),
-                        Applicability::MachineApplicable
-                    );
-                }
+                "remove the manual implementation...",
+                String::new(),
+                Applicability::MachineApplicable,
             );
-        }
+            diag.span_suggestion(
+                enum_span.shrink_to_lo(),
+                "...and instead derive it...",
+                format!("#[derive(Default)]\n{indent}", indent = " ".repeat(indent_enum),),
+                Applicability::MachineApplicable,
+            );
+            diag.span_suggestion(
+                variant_span.shrink_to_lo(),
+                "...and mark the default variant",
+                format!("#[default]\n{indent}", indent = " ".repeat(indent_variant),),
+                Applicability::MachineApplicable,
+            );
+        });
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if_chain! {
-            if let ItemKind::Impl(Impl {
-                of_trait: Some(ref trait_ref),
-                items: [child],
-                self_ty,
-                ..
-            }) = item.kind;
-            if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
-            if !item.span.from_expansion();
-            if let Some(def_id) = trait_ref.trait_def_id();
-            if cx.tcx.is_diagnostic_item(sym::Default, def_id);
-            if let impl_item_hir = child.id.hir_id();
-            if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
-            if let ImplItemKind::Fn(_, b) = &impl_item.kind;
-            if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
-            if let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind();
-            if let attrs = cx.tcx.hir().attrs(item.hir_id());
-            if !attrs.iter().any(|attr| attr.doc_str().is_some());
-            if cx.tcx.hir().attrs(impl_item_hir).is_empty();
-
-            then {
-                if adt_def.is_struct() {
-                    check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));
-                } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
-                    check_enum(cx, item, func_expr, adt_def);
-                }
+        if let ItemKind::Impl(Impl {
+            of_trait: Some(ref trait_ref),
+            items: [child],
+            self_ty,
+            ..
+        }) = item.kind
+            && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
+            && !item.span.from_expansion()
+            && let Some(def_id) = trait_ref.trait_def_id()
+            && cx.tcx.is_diagnostic_item(sym::Default, def_id)
+            && let impl_item_hir = child.id.hir_id()
+            && let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir)
+            && let ImplItemKind::Fn(_, b) = &impl_item.kind
+            && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
+            && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
+            && let attrs = cx.tcx.hir().attrs(item.hir_id())
+            && !attrs.iter().any(|attr| attr.doc_str().is_some())
+            && cx.tcx.hir().attrs(impl_item_hir).is_empty()
+        {
+            if adt_def.is_struct() {
+                check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));
+            } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
+                check_enum(cx, item, func_expr, adt_def);
             }
         }
     }
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 6aaa9e39b8b..9807823ada3 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
 use clippy_utils::{is_lint_allowed, match_def_path, paths};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
@@ -233,42 +232,37 @@ fn check_hash_peq<'tcx>(
     ty: Ty<'tcx>,
     hash_is_automatically_derived: bool,
 ) {
-    if_chain! {
-        if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait();
-        if let Some(def_id) = trait_ref.trait_def_id();
-        if cx.tcx.is_diagnostic_item(sym::Hash, def_id);
-        then {
-            // 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);
-
-                if !hash_is_automatically_derived || peq_is_automatically_derived {
-                    return;
-                }
-
-                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
-
-                // Only care about `impl PartialEq<Foo> for Foo`
-                // For `impl PartialEq<B> for A, input_types is [A, B]
-                if trait_ref.instantiate_identity().args.type_at(1) == ty {
-                    span_lint_and_then(
-                        cx,
-                        DERIVED_HASH_WITH_MANUAL_EQ,
-                        span,
-                        "you are deriving `Hash` but have implemented `PartialEq` explicitly",
-                        |diag| {
-                            if let Some(local_def_id) = impl_id.as_local() {
-                                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
-                                diag.span_note(
-                                    cx.tcx.hir().span(hir_id),
-                                    "`PartialEq` implemented here"
-                                );
-                            }
+    if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait()
+        && let Some(def_id) = trait_ref.trait_def_id()
+        && cx.tcx.is_diagnostic_item(sym::Hash, def_id)
+    {
+        // 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);
+
+            if !hash_is_automatically_derived || peq_is_automatically_derived {
+                return;
+            }
+
+            let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
+
+            // Only care about `impl PartialEq<Foo> for Foo`
+            // For `impl PartialEq<B> for A, input_types is [A, B]
+            if trait_ref.instantiate_identity().args.type_at(1) == ty {
+                span_lint_and_then(
+                    cx,
+                    DERIVED_HASH_WITH_MANUAL_EQ,
+                    span,
+                    "you are deriving `Hash` but have implemented `PartialEq` explicitly",
+                    |diag| {
+                        if let Some(local_def_id) = impl_id.as_local() {
+                            let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
+                            diag.span_note(cx.tcx.hir().span(hir_id), "`PartialEq` implemented here");
                         }
-                    );
-                }
-            });
-        }
+                    },
+                );
+            }
+        });
     }
 }
 
@@ -280,49 +274,38 @@ fn check_ord_partial_ord<'tcx>(
     ty: Ty<'tcx>,
     ord_is_automatically_derived: bool,
 ) {
-    if_chain! {
-        if let Some(ord_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Ord);
-        if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait();
-        if let Some(def_id) = &trait_ref.trait_def_id();
-        if *def_id == ord_trait_def_id;
-        then {
-            // 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);
-
-                if partial_ord_is_automatically_derived == ord_is_automatically_derived {
-                    return;
-                }
-
-                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
-
-                // Only care about `impl PartialOrd<Foo> for Foo`
-                // For `impl PartialOrd<B> for A, input_types is [A, B]
-                if trait_ref.instantiate_identity().args.type_at(1) == ty {
-                    let mess = if partial_ord_is_automatically_derived {
-                        "you are implementing `Ord` explicitly but have derived `PartialOrd`"
-                    } else {
-                        "you are deriving `Ord` but have implemented `PartialOrd` explicitly"
-                    };
-
-                    span_lint_and_then(
-                        cx,
-                        DERIVE_ORD_XOR_PARTIAL_ORD,
-                        span,
-                        mess,
-                        |diag| {
-                            if let Some(local_def_id) = impl_id.as_local() {
-                                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
-                                diag.span_note(
-                                    cx.tcx.hir().span(hir_id),
-                                    "`PartialOrd` implemented here"
-                                );
-                            }
-                        }
-                    );
-                }
-            });
-        }
+    if let Some(ord_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Ord)
+        && let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait()
+        && let Some(def_id) = &trait_ref.trait_def_id()
+        && *def_id == ord_trait_def_id
+    {
+        // 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);
+
+            if partial_ord_is_automatically_derived == ord_is_automatically_derived {
+                return;
+            }
+
+            let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
+
+            // Only care about `impl PartialOrd<Foo> for Foo`
+            // For `impl PartialOrd<B> for A, input_types is [A, B]
+            if trait_ref.instantiate_identity().args.type_at(1) == ty {
+                let mess = if partial_ord_is_automatically_derived {
+                    "you are implementing `Ord` explicitly but have derived `PartialOrd`"
+                } else {
+                    "you are deriving `Ord` but have implemented `PartialOrd` explicitly"
+                };
+
+                span_lint_and_then(cx, DERIVE_ORD_XOR_PARTIAL_ORD, span, mess, |diag| {
+                    if let Some(local_def_id) = impl_id.as_local() {
+                        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
+                        diag.span_note(cx.tcx.hir().span(hir_id), "`PartialOrd` implemented here");
+                    }
+                });
+            }
+        });
     }
 }
 
@@ -395,27 +378,27 @@ fn check_unsafe_derive_deserialize<'tcx>(
         visitor.has_unsafe
     }
 
-    if_chain! {
-        if let Some(trait_def_id) = trait_ref.trait_def_id();
-        if match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE);
-        if let ty::Adt(def, _) = ty.kind();
-        if let Some(local_def_id) = def.did().as_local();
-        let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
-        if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
-        if cx.tcx.inherent_impls(def.did())
+    if let Some(trait_def_id) = trait_ref.trait_def_id()
+        && match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE)
+        && let ty::Adt(def, _) = ty.kind()
+        && let Some(local_def_id) = def.did().as_local()
+        && let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id)
+        && !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id)
+        && cx
+            .tcx
+            .inherent_impls(def.did())
             .iter()
             .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
-            .any(|imp| has_unsafe(cx, imp));
-        then {
-            span_lint_and_help(
-                cx,
-                UNSAFE_DERIVE_DESERIALIZE,
-                item.span,
-                "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`",
-                None,
-                "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html"
-            );
-        }
+            .any(|imp| has_unsafe(cx, imp))
+    {
+        span_lint_and_help(
+            cx,
+            UNSAFE_DERIVE_DESERIALIZE,
+            item.span,
+            "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`",
+            None,
+            "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html",
+        );
     }
 }
 
@@ -432,12 +415,10 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
             return;
         }
 
-        if_chain! {
-            if let Some(header) = kind.header();
-            if header.unsafety == Unsafety::Unsafe;
-            then {
-                self.has_unsafe = true;
-            }
+        if let Some(header) = kind.header()
+            && header.unsafety == Unsafety::Unsafe
+        {
+            self.has_unsafe = true;
         }
 
         walk_fn(self, kind, decl, body_id, id);
@@ -464,30 +445,28 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
 
 /// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint.
 fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) {
-    if_chain! {
-        if let ty::Adt(adt, args) = ty.kind();
-        if cx.tcx.visibility(adt.did()).is_public();
-        if let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq);
-        if let Some(def_id) = trait_ref.trait_def_id();
-        if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id);
-        let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id);
-        if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]);
+    if let ty::Adt(adt, args) = ty.kind()
+        && cx.tcx.visibility(adt.did()).is_public()
+        && let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq)
+        && let Some(def_id) = trait_ref.trait_def_id()
+        && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
+        && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
+        && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])
         // If all of our fields implement `Eq`, we can implement `Eq` too
-        if adt
+        && adt
             .all_fields()
             .map(|f| f.ty(cx.tcx, args))
-            .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]));
-        then {
-            span_lint_and_sugg(
-                cx,
-                DERIVE_PARTIAL_EQ_WITHOUT_EQ,
-                span.ctxt().outer_expn_data().call_site,
-                "you are deriving `PartialEq` and can implement `Eq`",
-                "consider deriving `Eq` as well",
-                "PartialEq, Eq".to_string(),
-                Applicability::MachineApplicable,
-            )
-        }
+            .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]))
+    {
+        span_lint_and_sugg(
+            cx,
+            DERIVE_PARTIAL_EQ_WITHOUT_EQ,
+            span.ctxt().outer_expn_data().call_site,
+            "you are deriving `PartialEq` and can implement `Eq`",
+            "consider deriving `Eq` as well",
+            "PartialEq, Eq".to_string(),
+            Applicability::MachineApplicable,
+        );
     }
 }
 
diff --git a/clippy_lints/src/disallowed_names.rs b/clippy_lints/src/disallowed_names.rs
index 5e46b29b639..a1dd4805b9c 100644
--- a/clippy_lints/src/disallowed_names.rs
+++ b/clippy_lints/src/disallowed_names.rs
@@ -31,9 +31,9 @@ pub struct DisallowedNames {
 }
 
 impl DisallowedNames {
-    pub fn new(disallow: FxHashSet<String>) -> Self {
+    pub fn new(disallowed_names: &[String]) -> Self {
         Self {
-            disallow,
+            disallow: disallowed_names.iter().cloned().collect(),
             test_modules_deep: 0,
         }
     }
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index d4a698521ac..6a12baa4201 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -4,7 +4,6 @@ use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{is_entrypoint_fn, method_chain_args, return_ty};
-use if_chain::if_chain;
 use pulldown_cmark::Event::{
     Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
 };
@@ -269,9 +268,9 @@ pub struct DocMarkdown {
 }
 
 impl DocMarkdown {
-    pub fn new(valid_idents: FxHashSet<String>) -> Self {
+    pub fn new(valid_idents: &[String]) -> Self {
         Self {
-            valid_idents,
+            valid_idents: valid_idents.iter().cloned().collect(),
             in_trait_impl: false,
         }
     }
@@ -428,25 +427,21 @@ fn lint_for_missing_headers(
                 span,
                 "docs for function returning `Result` missing `# Errors` section",
             );
-        } else {
-            if_chain! {
-                if let Some(body_id) = body_id;
-                if let Some(future) = cx.tcx.lang_items().future_trait();
-                let typeck = cx.tcx.typeck_body(body_id);
-                let body = cx.tcx.hir().body(body_id);
-                let ret_ty = typeck.expr_ty(body.value);
-                if implements_trait(cx, ret_ty, future, &[]);
-                if let ty::Coroutine(_, subs, _) = ret_ty.kind();
-                if is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result);
-                then {
-                    span_lint(
-                        cx,
-                        MISSING_ERRORS_DOC,
-                        span,
-                        "docs for function returning `Result` missing `# Errors` section",
-                    );
-                }
-            }
+        } else if let Some(body_id) = body_id
+            && let Some(future) = cx.tcx.lang_items().future_trait()
+            && let typeck = cx.tcx.typeck_body(body_id)
+            && let body = cx.tcx.hir().body(body_id)
+            && let ret_ty = typeck.expr_ty(body.value)
+            && implements_trait(cx, ret_ty, future, &[])
+            && let ty::Coroutine(_, subs, _) = ret_ty.kind()
+            && is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result)
+        {
+            span_lint(
+                cx,
+                MISSING_ERRORS_DOC,
+                span,
+                "docs for function returning `Result` missing `# Errors` section",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/empty_drop.rs b/clippy_lints/src/empty_drop.rs
index 5fcdca7cf36..17be95780cc 100644
--- a/clippy_lints/src/empty_drop.rs
+++ b/clippy_lints/src/empty_drop.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::peel_blocks;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
@@ -36,31 +35,30 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]);
 
 impl LateLintPass<'_> for EmptyDrop {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        if_chain! {
-            if let ItemKind::Impl(Impl {
-                of_trait: Some(ref trait_ref),
-                items: [child],
-                ..
-            }) = item.kind;
-            if trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait();
-            if let impl_item_hir = child.id.hir_id();
-            if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
-            if let ImplItemKind::Fn(_, b) = &impl_item.kind;
-            if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
-            let func_expr = peel_blocks(func_expr);
-            if let ExprKind::Block(block, _) = func_expr.kind;
-            if block.stmts.is_empty() && block.expr.is_none();
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    EMPTY_DROP,
-                    item.span,
-                    "empty drop implementation",
-                    "try removing this impl",
-                    String::new(),
-                    Applicability::MaybeIncorrect
-                );
-            }
+        if let ItemKind::Impl(Impl {
+            of_trait: Some(ref trait_ref),
+            items: [child],
+            ..
+        }) = item.kind
+            && trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
+            && let impl_item_hir = child.id.hir_id()
+            && let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir)
+            && let ImplItemKind::Fn(_, b) = &impl_item.kind
+            && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
+            && let func_expr = peel_blocks(func_expr)
+            && let ExprKind::Block(block, _) = func_expr.kind
+            && block.stmts.is_empty()
+            && block.expr.is_none()
+        {
+            span_lint_and_sugg(
+                cx,
+                EMPTY_DROP,
+                item.span,
+                "empty drop implementation",
+                "try removing this impl",
+                String::new(),
+                Applicability::MaybeIncorrect,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs
index affd0822120..6f5a0cb8801 100644
--- a/clippy_lints/src/endian_bytes.rs
+++ b/clippy_lints/src/endian_bytes.rs
@@ -114,27 +114,23 @@ impl LateLintPass<'_> for EndianBytes {
             return;
         }
 
-        if_chain! {
-            if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind;
-            if args.is_empty();
-            let ty = cx.typeck_results().expr_ty(receiver);
-            if ty.is_primitive_ty();
-            if maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty);
-            then {
-                return;
-            }
+        if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind
+            && args.is_empty()
+            && let ty = cx.typeck_results().expr_ty(receiver)
+            && ty.is_primitive_ty()
+            && maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty)
+        {
+            return;
         }
 
-        if_chain! {
-            if let ExprKind::Call(function, ..) = expr.kind;
-            if let ExprKind::Path(qpath) = function.kind;
-            if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id();
-            if let Some(function_name) = cx.get_def_path(def_id).last();
-            let ty = cx.typeck_results().expr_ty(expr);
-            if ty.is_primitive_ty();
-            then {
-                maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty);
-            }
+        if let ExprKind::Call(function, ..) = expr.kind
+            && let ExprKind::Path(qpath) = function.kind
+            && let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id()
+            && let Some(function_name) = cx.get_def_path(def_id).last()
+            && let ty = cx.typeck_results().expr_ty(expr)
+            && ty.is_primitive_ty()
+        {
+            maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty);
         }
     }
 }
diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs
index f976cfd3f22..b7e62e082e4 100644
--- a/clippy_lints/src/exhaustive_items.rs
+++ b/clippy_lints/src/exhaustive_items.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::indent_of;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -71,40 +70,31 @@ declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS, EXHAUSTIVE_STRUCTS]);
 
 impl LateLintPass<'_> for ExhaustiveItems {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        if_chain! {
-            if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind;
-            if cx.effective_visibilities.is_exported(item.owner_id.def_id);
-            let attrs = cx.tcx.hir().attrs(item.hir_id());
-            if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
-            then {
-                let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
-                    if v.fields().iter().any(|f| {
-                        !cx.tcx.visibility(f.def_id).is_public()
-                    }) {
-                        // skip structs with private fields
-                        return;
-                    }
-                    (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive")
-                } else {
-                    (EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive")
-                };
-                let suggestion_span = item.span.shrink_to_lo();
-                let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
-                span_lint_and_then(
-                    cx,
-                    lint,
-                    item.span,
-                    msg,
-                    |diag| {
-                        let sugg = format!("#[non_exhaustive]\n{indent}");
-                        diag.span_suggestion(suggestion_span,
-                                             "try adding #[non_exhaustive]",
-                                             sugg,
-                                             Applicability::MaybeIncorrect);
-                    }
+        if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind
+            && cx.effective_visibilities.is_exported(item.owner_id.def_id)
+            && let attrs = cx.tcx.hir().attrs(item.hir_id())
+            && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
+        {
+            let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
+                if v.fields().iter().any(|f| !cx.tcx.visibility(f.def_id).is_public()) {
+                    // skip structs with private fields
+                    return;
+                }
+                (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive")
+            } else {
+                (EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive")
+            };
+            let suggestion_span = item.span.shrink_to_lo();
+            let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
+            span_lint_and_then(cx, lint, item.span, msg, |diag| {
+                let sugg = format!("#[non_exhaustive]\n{indent}");
+                diag.span_suggestion(
+                    suggestion_span,
+                    "try adding #[non_exhaustive]",
+                    sugg,
+                    Applicability::MaybeIncorrect,
                 );
-
-            }
+            });
         }
     }
 }
diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs
index e14b1c556ec..07d025f68c3 100644
--- a/clippy_lints/src/exit.rs
+++ b/clippy_lints/src/exit.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_entrypoint_fn;
-use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -42,19 +41,17 @@ declare_lint_pass!(Exit => [EXIT]);
 
 impl<'tcx> LateLintPass<'tcx> for Exit {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Call(path_expr, _args) = e.kind;
-            if let ExprKind::Path(ref path) = path_expr.kind;
-            if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id();
-            if cx.tcx.is_diagnostic_item(sym::process_exit, def_id);
-            let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
-            if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent);
+        if let ExprKind::Call(path_expr, _args) = e.kind
+            && let ExprKind::Path(ref path) = path_expr.kind
+            && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
+            && let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id
+            && let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent)
             // If the next item up is a function we check if it is an entry point
             // and only then emit a linter warning
-            if !is_entrypoint_fn(cx, parent.to_def_id());
-            then {
-                span_lint(cx, EXIT, e.span, "usage of `process::exit`");
-            }
+            && !is_entrypoint_fn(cx, parent.to_def_id())
+        {
+            span_lint(cx, EXIT, e.span, "usage of `process::exit`");
         }
     }
 }
diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs
index 4b5bcb06a1e..08cb2114a2b 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::{find_format_args, format_args_inputs_span};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_expn_of, path_def_id};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
@@ -101,30 +100,28 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
 /// If `kind` is a block that looks like `{ let result = $expr; result }` then
 /// returns $expr. Otherwise returns `kind`.
 fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) -> &'tcx ExprKind<'hir> {
-    if_chain! {
-        if let ExprKind::Block(block, _label @ None) = kind;
-        if let Block {
+    if let ExprKind::Block(block, _label @ None) = kind
+        && let Block {
             stmts: [Stmt { kind: StmtKind::Local(local), .. }],
             expr: Some(expr_end_of_block),
             rules: BlockCheckMode::DefaultBlock,
             ..
-        } = block;
+        } = block
 
         // Find id of the local that expr_end_of_block resolves to
-        if let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind;
-        if let Res::Local(expr_res) = expr_path.res;
-        if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res);
+        && let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind
+        && let Res::Local(expr_res) = expr_path.res
+        && let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res)
 
         // Find id of the local we found in the block
-        if let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind;
+        && let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind
 
         // If those two are the same hir id
-        if res_pat.hir_id == local_hir_id;
+        && res_pat.hir_id == local_hir_id
 
-        if let Some(init) = local.init;
-        then {
-            return &init.kind;
-        }
+        && let Some(init) = local.init
+    {
+        return &init.kind;
     }
     kind
 }
diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs
index efb69476b94..753f75d83a8 100644
--- a/clippy_lints/src/fallible_impl_from.rs
+++ b/clippy_lints/src/fallible_impl_from.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use clippy_utils::method_chain_args;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
@@ -53,13 +52,13 @@ declare_lint_pass!(FallibleImplFrom => [FALLIBLE_IMPL_FROM]);
 impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
         // check for `impl From<???> for ..`
-        if_chain! {
-            if let hir::ItemKind::Impl(impl_) = &item.kind;
-            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
-            if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id);
-            then {
-                lint_impl_body(cx, item.span, impl_.items);
-            }
+        if let hir::ItemKind::Impl(impl_) = &item.kind
+            && let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
+            && cx
+                .tcx
+                .is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id)
+        {
+            lint_impl_body(cx, item.span, impl_.items);
         }
     }
 }
@@ -98,34 +97,33 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl
     }
 
     for impl_item in impl_items {
-        if_chain! {
-            if impl_item.ident.name == sym::from;
-            if let ImplItemKind::Fn(_, body_id) =
-                cx.tcx.hir().impl_item(impl_item.id).kind;
-            then {
-                // check the body for `begin_panic` or `unwrap`
-                let body = cx.tcx.hir().body(body_id);
-                let mut fpu = FindPanicUnwrap {
-                    lcx: cx,
-                    typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id),
-                    result: Vec::new(),
-                };
-                fpu.visit_expr(body.value);
+        if impl_item.ident.name == sym::from
+            && let ImplItemKind::Fn(_, body_id) = cx.tcx.hir().impl_item(impl_item.id).kind
+        {
+            // check the body for `begin_panic` or `unwrap`
+            let body = cx.tcx.hir().body(body_id);
+            let mut fpu = FindPanicUnwrap {
+                lcx: cx,
+                typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id),
+                result: Vec::new(),
+            };
+            fpu.visit_expr(body.value);
 
-                // if we've found one, lint
-                if !fpu.result.is_empty() {
-                    span_lint_and_then(
-                        cx,
-                        FALLIBLE_IMPL_FROM,
-                        impl_span,
-                        "consider implementing `TryFrom` instead",
-                        move |diag| {
-                            diag.help(
-                                "`From` is intended for infallible conversions only. \
-                                Use `TryFrom` if there's a possibility for the conversion to fail");
-                            diag.span_note(fpu.result, "potential failure(s)");
-                        });
-                }
+            // if we've found one, lint
+            if !fpu.result.is_empty() {
+                span_lint_and_then(
+                    cx,
+                    FALLIBLE_IMPL_FROM,
+                    impl_span,
+                    "consider implementing `TryFrom` instead",
+                    move |diag| {
+                        diag.help(
+                            "`From` is intended for infallible conversions only. \
+                            Use `TryFrom` if there's a possibility for the conversion to fail",
+                        );
+                        diag.span_note(fpu.result, "potential failure(s)");
+                    },
+                );
             }
         }
     }
diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs
index 506a1191747..663c33e8cee 100644
--- a/clippy_lints/src/float_literal.rs
+++ b/clippy_lints/src/float_literal.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal;
-use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -64,73 +63,70 @@ declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]);
 impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         let ty = cx.typeck_results().expr_ty(expr);
-        if_chain! {
-            if let ty::Float(fty) = *ty.kind();
-            if let hir::ExprKind::Lit(lit) = expr.kind;
-            if let LitKind::Float(sym, lit_float_ty) = lit.node;
-            then {
-                let sym_str = sym.as_str();
-                let formatter = FloatFormat::new(sym_str);
-                // Try to bail out if the float is for sure fine.
-                // If its within the 2 decimal digits of being out of precision we
-                // check if the parsed representation is the same as the string
-                // since we'll need the truncated string anyway.
-                let digits = count_digits(sym_str);
-                let max = max_digits(fty);
-                let type_suffix = match lit_float_ty {
-                    LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"),
-                    LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
-                    LitFloatType::Unsuffixed => None
-                };
-                let (is_whole, is_inf, mut float_str) = match fty {
-                    FloatTy::F32 => {
-                        let value = sym_str.parse::<f32>().unwrap();
+        if let ty::Float(fty) = *ty.kind()
+            && let hir::ExprKind::Lit(lit) = expr.kind
+            && let LitKind::Float(sym, lit_float_ty) = lit.node
+        {
+            let sym_str = sym.as_str();
+            let formatter = FloatFormat::new(sym_str);
+            // Try to bail out if the float is for sure fine.
+            // If its within the 2 decimal digits of being out of precision we
+            // check if the parsed representation is the same as the string
+            // since we'll need the truncated string anyway.
+            let digits = count_digits(sym_str);
+            let max = max_digits(fty);
+            let type_suffix = match lit_float_ty {
+                LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"),
+                LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
+                LitFloatType::Unsuffixed => None,
+            };
+            let (is_whole, is_inf, mut float_str) = match fty {
+                FloatTy::F32 => {
+                    let value = sym_str.parse::<f32>().unwrap();
 
-                        (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
-                    },
-                    FloatTy::F64 => {
-                        let value = sym_str.parse::<f64>().unwrap();
+                    (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
+                },
+                FloatTy::F64 => {
+                    let value = sym_str.parse::<f64>().unwrap();
 
+                    (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
+                },
+            };
 
-                        (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
-                    },
-                };
-
-                if is_inf {
-                    return;
-                }
-
-                if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') {
-                    // Normalize the literal by stripping the fractional portion
-                    if sym_str.split('.').next().unwrap() != float_str {
-                        // If the type suffix is missing the suggestion would be
-                        // incorrectly interpreted as an integer so adding a `.0`
-                        // suffix to prevent that.
-                        if type_suffix.is_none() {
-                            float_str.push_str(".0");
-                        }
+            if is_inf {
+                return;
+            }
 
-                        span_lint_and_sugg(
-                            cx,
-                            LOSSY_FLOAT_LITERAL,
-                            expr.span,
-                            "literal cannot be represented as the underlying type without loss of precision",
-                            "consider changing the type or replacing it with",
-                            numeric_literal::format(&float_str, type_suffix, true),
-                            Applicability::MachineApplicable,
-                        );
+            if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') {
+                // Normalize the literal by stripping the fractional portion
+                if sym_str.split('.').next().unwrap() != float_str {
+                    // If the type suffix is missing the suggestion would be
+                    // incorrectly interpreted as an integer so adding a `.0`
+                    // suffix to prevent that.
+                    if type_suffix.is_none() {
+                        float_str.push_str(".0");
                     }
-                } else if digits > max as usize && float_str.len() < sym_str.len() {
+
                     span_lint_and_sugg(
                         cx,
-                        EXCESSIVE_PRECISION,
+                        LOSSY_FLOAT_LITERAL,
                         expr.span,
-                        "float has excessive precision",
-                        "consider changing the type or truncating it to",
+                        "literal cannot be represented as the underlying type without loss of precision",
+                        "consider changing the type or replacing it with",
                         numeric_literal::format(&float_str, type_suffix, true),
                         Applicability::MachineApplicable,
                     );
                 }
+            } else if digits > max as usize && float_str.len() < sym_str.len() {
+                span_lint_and_sugg(
+                    cx,
+                    EXCESSIVE_PRECISION,
+                    expr.span,
+                    "float has excessive precision",
+                    "consider changing the type or truncating it to",
+                    numeric_literal::format(&float_str, type_suffix, true),
+                    Applicability::MachineApplicable,
+                );
             }
         }
     }
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index 09a9d9924de..d522873472b 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{
     eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, numeric_literal, peel_blocks, sugg,
 };
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -133,30 +132,25 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
         expr = inner_expr;
     }
 
-    if_chain! {
+    if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind()
         // if the expression is a float literal and it is unsuffixed then
         // add a suffix so the suggestion is valid and unambiguous
-        if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind();
-        if let ExprKind::Lit(lit) = &expr.kind;
-        if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
-        then {
-            let op = format!(
-                "{suggestion}{}{}",
-                // Check for float literals without numbers following the decimal
-                // separator such as `2.` and adds a trailing zero
-                if sym.as_str().ends_with('.') {
-                    "0"
-                } else {
-                    ""
-                },
-                float_ty.name_str()
-            ).into();
-
-            suggestion = match suggestion {
-                Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
-                _ => Sugg::NonParen(op)
-            };
-        }
+        && let ExprKind::Lit(lit) = &expr.kind
+        && let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node
+    {
+        let op = format!(
+            "{suggestion}{}{}",
+            // Check for float literals without numbers following the decimal
+            // separator such as `2.` and adds a trailing zero
+            if sym.as_str().ends_with('.') { "0" } else { "" },
+            float_ty.name_str()
+        )
+        .into();
+
+        suggestion = match suggestion {
+            Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
+            _ => Sugg::NonParen(op),
+        };
     }
 
     suggestion.maybe_par()
@@ -359,35 +353,59 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
     ) = receiver.kind
     {
         // check if expression of the form x * x + y * y
-        if_chain! {
-            if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lmul_lhs, lmul_rhs) = add_lhs.kind;
-            if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, rmul_lhs, rmul_rhs) = add_rhs.kind;
-            if eq_expr_value(cx, lmul_lhs, lmul_rhs);
-            if eq_expr_value(cx, rmul_lhs, rmul_rhs);
-            then {
-                return Some(format!("{}.hypot({})", Sugg::hir(cx, lmul_lhs, "..").maybe_par(), Sugg::hir(cx, rmul_lhs, "..")));
-            }
+        if let ExprKind::Binary(
+            Spanned {
+                node: BinOpKind::Mul, ..
+            },
+            lmul_lhs,
+            lmul_rhs,
+        ) = add_lhs.kind
+            && let ExprKind::Binary(
+                Spanned {
+                    node: BinOpKind::Mul, ..
+                },
+                rmul_lhs,
+                rmul_rhs,
+            ) = add_rhs.kind
+            && eq_expr_value(cx, lmul_lhs, lmul_rhs)
+            && eq_expr_value(cx, rmul_lhs, rmul_rhs)
+        {
+            return Some(format!(
+                "{}.hypot({})",
+                Sugg::hir(cx, lmul_lhs, "..").maybe_par(),
+                Sugg::hir(cx, rmul_lhs, "..")
+            ));
         }
 
         // check if expression of the form x.powi(2) + y.powi(2)
-        if_chain! {
-            if let ExprKind::MethodCall(
-                PathSegment { ident: lmethod_name, .. },
-                largs_0, [largs_1, ..],
-                _
-            ) = &add_lhs.kind;
-            if let ExprKind::MethodCall(
-                PathSegment { ident: rmethod_name, .. },
-                rargs_0, [rargs_1, ..],
-                _
-            ) = &add_rhs.kind;
-            if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
-            if let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1);
-            if let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1);
-            if Int(2) == lvalue && Int(2) == rvalue;
-            then {
-                return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, "..")));
-            }
+        if let ExprKind::MethodCall(
+            PathSegment {
+                ident: lmethod_name, ..
+            },
+            largs_0,
+            [largs_1, ..],
+            _,
+        ) = &add_lhs.kind
+            && let ExprKind::MethodCall(
+                PathSegment {
+                    ident: rmethod_name, ..
+                },
+                rargs_0,
+                [rargs_1, ..],
+                _,
+            ) = &add_rhs.kind
+            && lmethod_name.as_str() == "powi"
+            && rmethod_name.as_str() == "powi"
+            && let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1)
+            && let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1)
+            && Int(2) == lvalue
+            && Int(2) == rvalue
+        {
+            return Some(format!(
+                "{}.hypot({})",
+                Sugg::hir(cx, largs_0, "..").maybe_par(),
+                Sugg::hir(cx, rargs_0, "..")
+            ));
         }
     }
 
@@ -411,39 +429,44 @@ fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
 // TODO: Lint expressions of the form `x.exp() - y` where y > 1
 // and suggest usage of `x.exp_m1() - (y - 1)` instead
 fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind;
-        if cx.typeck_results().expr_ty(lhs).is_floating_point();
-        if let Some(value) = constant(cx, cx.typeck_results(), rhs);
-        if F32(1.0) == value || F64(1.0) == value;
-        if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
-        if cx.typeck_results().expr_ty(self_arg).is_floating_point();
-        if path.ident.name.as_str() == "exp";
-        then {
-            span_lint_and_sugg(
-                cx,
-                IMPRECISE_FLOPS,
-                expr.span,
-                "(e.pow(x) - 1) can be computed more accurately",
-                "consider using",
-                format!(
-                    "{}.exp_m1()",
-                    Sugg::hir(cx, self_arg, "..").maybe_par()
-                ),
-                Applicability::MachineApplicable,
-            );
-        }
+    if let ExprKind::Binary(
+        Spanned {
+            node: BinOpKind::Sub, ..
+        },
+        lhs,
+        rhs,
+    ) = expr.kind
+        && cx.typeck_results().expr_ty(lhs).is_floating_point()
+        && let Some(value) = constant(cx, cx.typeck_results(), rhs)
+        && (F32(1.0) == value || F64(1.0) == value)
+        && let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind
+        && cx.typeck_results().expr_ty(self_arg).is_floating_point()
+        && path.ident.name.as_str() == "exp"
+    {
+        span_lint_and_sugg(
+            cx,
+            IMPRECISE_FLOPS,
+            expr.span,
+            "(e.pow(x) - 1) can be computed more accurately",
+            "consider using",
+            format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_par()),
+            Applicability::MachineApplicable,
+        );
     }
 }
 
 fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
-    if_chain! {
-        if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lhs, rhs) = &expr.kind;
-        if cx.typeck_results().expr_ty(lhs).is_floating_point();
-        if cx.typeck_results().expr_ty(rhs).is_floating_point();
-        then {
-            return Some((lhs, rhs));
-        }
+    if let ExprKind::Binary(
+        Spanned {
+            node: BinOpKind::Mul, ..
+        },
+        lhs,
+        rhs,
+    ) = &expr.kind
+        && cx.typeck_results().expr_ty(lhs).is_floating_point()
+        && cx.typeck_results().expr_ty(rhs).is_floating_point()
+    {
+        return Some((lhs, rhs));
     }
 
     None
@@ -553,60 +576,72 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a
 }
 
 fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if let Some(higher::If { cond, then, r#else: Some(r#else) }) = higher::If::hir(expr);
-        let if_body_expr = peel_blocks(then);
-        let else_body_expr = peel_blocks(r#else);
-        if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr);
-        then {
-            let positive_abs_sugg = (
-                "manual implementation of `abs` method",
-                format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_par()),
-            );
-            let negative_abs_sugg = (
-                "manual implementation of negation of `abs` method",
-                format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_par()),
-            );
-            let sugg = if is_testing_positive(cx, cond, body) {
-                if if_expr_positive {
-                    positive_abs_sugg
-                } else {
-                    negative_abs_sugg
-                }
-            } else if is_testing_negative(cx, cond, body) {
-                if if_expr_positive {
-                    negative_abs_sugg
-                } else {
-                    positive_abs_sugg
-                }
+    if let Some(higher::If {
+        cond,
+        then,
+        r#else: Some(r#else),
+    }) = higher::If::hir(expr)
+        && let if_body_expr = peel_blocks(then)
+        && let else_body_expr = peel_blocks(r#else)
+        && let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr)
+    {
+        let positive_abs_sugg = (
+            "manual implementation of `abs` method",
+            format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_par()),
+        );
+        let negative_abs_sugg = (
+            "manual implementation of negation of `abs` method",
+            format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_par()),
+        );
+        let sugg = if is_testing_positive(cx, cond, body) {
+            if if_expr_positive {
+                positive_abs_sugg
             } else {
-                return;
-            };
-            span_lint_and_sugg(
-                cx,
-                SUBOPTIMAL_FLOPS,
-                expr.span,
-                sugg.0,
-                "try",
-                sugg.1,
-                Applicability::MachineApplicable,
-            );
-        }
+                negative_abs_sugg
+            }
+        } else if is_testing_negative(cx, cond, body) {
+            if if_expr_positive {
+                negative_abs_sugg
+            } else {
+                positive_abs_sugg
+            }
+        } else {
+            return;
+        };
+        span_lint_and_sugg(
+            cx,
+            SUBOPTIMAL_FLOPS,
+            expr.span,
+            sugg.0,
+            "try",
+            sugg.1,
+            Applicability::MachineApplicable,
+        );
     }
 }
 
 fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
-    if_chain! {
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind;
-        if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind;
-        then {
-            return method_name_a.as_str() == method_name_b.as_str() &&
-                args_a.len() == args_b.len() &&
-                (
-                    ["ln", "log2", "log10"].contains(&method_name_a.as_str()) ||
-                    method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])
-                );
-        }
+    if let ExprKind::MethodCall(
+        PathSegment {
+            ident: method_name_a, ..
+        },
+        _,
+        args_a,
+        _,
+    ) = expr_a.kind
+        && let ExprKind::MethodCall(
+            PathSegment {
+                ident: method_name_b, ..
+            },
+            _,
+            args_b,
+            _,
+        ) = expr_b.kind
+    {
+        return method_name_a.as_str() == method_name_b.as_str()
+            && args_a.len() == args_b.len()
+            && (["ln", "log2", "log10"].contains(&method_name_a.as_str())
+                || method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0]));
     }
 
     false
@@ -614,103 +649,98 @@ fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>
 
 fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
     // check if expression of the form x.logN() / y.logN()
-    if_chain! {
-        if let ExprKind::Binary(
-            Spanned {
-                node: BinOpKind::Div, ..
-            },
-            lhs,
-            rhs,
-        ) = &expr.kind;
-        if are_same_base_logs(cx, lhs, rhs);
-        if let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind;
-        if let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind;
-        then {
-            span_lint_and_sugg(
-                cx,
-                SUBOPTIMAL_FLOPS,
-                expr.span,
-                "log base can be expressed more clearly",
-                "consider using",
-                format!("{}.log({})", Sugg::hir(cx, largs_self, "..").maybe_par(), Sugg::hir(cx, rargs_self, ".."),),
-                Applicability::MachineApplicable,
-            );
-        }
+    if let ExprKind::Binary(
+        Spanned {
+            node: BinOpKind::Div, ..
+        },
+        lhs,
+        rhs,
+    ) = &expr.kind
+        && are_same_base_logs(cx, lhs, rhs)
+        && let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind
+        && let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind
+    {
+        span_lint_and_sugg(
+            cx,
+            SUBOPTIMAL_FLOPS,
+            expr.span,
+            "log base can be expressed more clearly",
+            "consider using",
+            format!(
+                "{}.log({})",
+                Sugg::hir(cx, largs_self, "..").maybe_par(),
+                Sugg::hir(cx, rargs_self, ".."),
+            ),
+            Applicability::MachineApplicable,
+        );
     }
 }
 
 fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Binary(
-            Spanned {
-                node: BinOpKind::Div, ..
-            },
-            div_lhs,
-            div_rhs,
-        ) = &expr.kind;
-        if let ExprKind::Binary(
+    if let ExprKind::Binary(
+        Spanned {
+            node: BinOpKind::Div, ..
+        },
+        div_lhs,
+        div_rhs,
+    ) = &expr.kind
+        && let ExprKind::Binary(
             Spanned {
                 node: BinOpKind::Mul, ..
             },
             mul_lhs,
             mul_rhs,
-        ) = &div_lhs.kind;
-        if let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs);
-        if let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs);
-        then {
-            // TODO: also check for constant values near PI/180 or 180/PI
-            if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
-               (F32(180_f32) == lvalue || F64(180_f64) == lvalue)
+        ) = &div_lhs.kind
+        && let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs)
+        && let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs)
+    {
+        // TODO: also check for constant values near PI/180 or 180/PI
+        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());
+            if let ExprKind::Lit(literal) = mul_lhs.kind
+                && let ast::LitKind::Float(ref value, float_type) = literal.node
+                && float_type == ast::LitFloatType::Unsuffixed
             {
-                let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
-                if_chain! {
-                    if let ExprKind::Lit(literal) = mul_lhs.kind;
-                    if let ast::LitKind::Float(ref value, float_type) = literal.node;
-                    if float_type == ast::LitFloatType::Unsuffixed;
-                    then {
-                        if value.as_str().ends_with('.') {
-                            proposal = format!("{}0_f64.to_degrees()", Sugg::hir(cx, mul_lhs, ".."));
-                        } else {
-                            proposal = format!("{}_f64.to_degrees()", Sugg::hir(cx, mul_lhs, ".."));
-                        }
-                    }
+                if value.as_str().ends_with('.') {
+                    proposal = format!("{}0_f64.to_degrees()", Sugg::hir(cx, mul_lhs, ".."));
+                } else {
+                    proposal = format!("{}_f64.to_degrees()", Sugg::hir(cx, mul_lhs, ".."));
                 }
-                span_lint_and_sugg(
-                    cx,
-                    SUBOPTIMAL_FLOPS,
-                    expr.span,
-                    "conversion to degrees can be done more accurately",
-                    "consider using",
-                    proposal,
-                    Applicability::MachineApplicable,
-                );
-            } else if
-                (F32(180_f32) == rvalue || F64(180_f64) == rvalue) &&
-                (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue)
+            }
+            span_lint_and_sugg(
+                cx,
+                SUBOPTIMAL_FLOPS,
+                expr.span,
+                "conversion to degrees can be done more accurately",
+                "consider using",
+                proposal,
+                Applicability::MachineApplicable,
+            );
+        } 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());
+            if let ExprKind::Lit(literal) = mul_lhs.kind
+                && let ast::LitKind::Float(ref value, float_type) = literal.node
+                && float_type == ast::LitFloatType::Unsuffixed
             {
-                let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par());
-                if_chain! {
-                    if let ExprKind::Lit(literal) = mul_lhs.kind;
-                    if let ast::LitKind::Float(ref value, float_type) = literal.node;
-                    if float_type == ast::LitFloatType::Unsuffixed;
-                    then {
-                        if value.as_str().ends_with('.') {
-                            proposal = format!("{}0_f64.to_radians()", Sugg::hir(cx, mul_lhs, ".."));
-                        } else {
-                            proposal = format!("{}_f64.to_radians()", Sugg::hir(cx, mul_lhs, ".."));
-                        }
-                    }
+                if value.as_str().ends_with('.') {
+                    proposal = format!("{}0_f64.to_radians()", Sugg::hir(cx, mul_lhs, ".."));
+                } else {
+                    proposal = format!("{}_f64.to_radians()", Sugg::hir(cx, mul_lhs, ".."));
                 }
-                span_lint_and_sugg(
-                    cx,
-                    SUBOPTIMAL_FLOPS,
-                    expr.span,
-                    "conversion to radians can be done more accurately",
-                    "consider using",
-                    proposal,
-                    Applicability::MachineApplicable,
-                );
             }
+            span_lint_and_sugg(
+                cx,
+                SUBOPTIMAL_FLOPS,
+                expr.span,
+                "conversion to radians can be done more accurately",
+                "consider using",
+                proposal,
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs
index 3c1f2d9d5dc..c9868255dcf 100644
--- a/clippy_lints/src/format_args.rs
+++ b/clippy_lints/src/format_args.rs
@@ -8,7 +8,6 @@ use clippy_utils::macros::{
 };
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{implements_trait, is_type_lang_item};
-use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_ast::{
     FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
@@ -404,49 +403,43 @@ fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symb
 }
 
 fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) {
-    if_chain! {
-        if !value.span.from_expansion();
-        if let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind;
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id);
-        if is_diag_trait_item(cx, method_def_id, sym::ToString);
-        let receiver_ty = cx.typeck_results().expr_ty(receiver);
-        if let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display);
-        let (n_needed_derefs, target) =
-            count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter());
-        if implements_trait(cx, target, display_trait_id, &[]);
-        if let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait();
-        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
-        then {
-            let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]);
-            if n_needed_derefs == 0 && !needs_ref {
-                span_lint_and_sugg(
-                    cx,
-                    TO_STRING_IN_FORMAT_ARGS,
-                    to_string_span.with_lo(receiver.span.hi()),
-                    &format!(
-                        "`to_string` applied to a type that implements `Display` in `{name}!` args"
-                    ),
-                    "remove this",
-                    String::new(),
-                    Applicability::MachineApplicable,
-                );
-            } else {
-                span_lint_and_sugg(
-                    cx,
-                    TO_STRING_IN_FORMAT_ARGS,
-                    value.span,
-                    &format!(
-                        "`to_string` applied to a type that implements `Display` in `{name}!` args"
-                    ),
-                    "use this",
-                    format!(
-                        "{}{:*>n_needed_derefs$}{receiver_snippet}",
-                        if needs_ref { "&" } else { "" },
-                        ""
-                    ),
-                    Applicability::MachineApplicable,
-                );
-            }
+    if !value.span.from_expansion()
+        && let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind
+        && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id)
+        && is_diag_trait_item(cx, method_def_id, sym::ToString)
+        && let receiver_ty = cx.typeck_results().expr_ty(receiver)
+        && let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display)
+        && let (n_needed_derefs, target) =
+            count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter())
+        && implements_trait(cx, target, display_trait_id, &[])
+        && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait()
+        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+    {
+        let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]);
+        if n_needed_derefs == 0 && !needs_ref {
+            span_lint_and_sugg(
+                cx,
+                TO_STRING_IN_FORMAT_ARGS,
+                to_string_span.with_lo(receiver.span.hi()),
+                &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
+                "remove this",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            span_lint_and_sugg(
+                cx,
+                TO_STRING_IN_FORMAT_ARGS,
+                value.span,
+                &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
+                "use this",
+                format!(
+                    "{}{:*>n_needed_derefs$}{receiver_snippet}",
+                    if needs_ref { "&" } else { "" },
+                    ""
+                ),
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index 08ee7032c09..ec87629a344 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/clippy_lints/src/format_impl.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::macros::{find_format_arg_expr, find_format_args, 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 if_chain::if_chain;
 use rustc_ast::{FormatArgsPiece, FormatTrait};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
@@ -141,27 +140,25 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl {
 }
 
 fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
+    if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind
         // Get the hir_id of the object we are calling the method on
-        if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind;
         // Is the method to_string() ?
-        if path.ident.name == sym::to_string;
+        && path.ident.name == sym::to_string
         // Is the method a part of the ToString trait? (i.e. not to_string() implemented
         // separately)
-        if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if is_diag_trait_item(cx, expr_def_id, sym::ToString);
+        && let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && is_diag_trait_item(cx, expr_def_id, sym::ToString)
         // Is the method is called on self
-        if let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind;
-        if let [segment] = path.segments;
-        if segment.ident.name == kw::SelfLower;
-        then {
-            span_lint(
-                cx,
-                RECURSIVE_FORMAT_IMPL,
-                expr.span,
-                "using `self.to_string` in `fmt::Display` implementation will cause infinite recursion",
-            );
-        }
+        && let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind
+        && let [segment] = path.segments
+        && segment.ident.name == kw::SelfLower
+    {
+        span_lint(
+            cx,
+            RECURSIVE_FORMAT_IMPL,
+            expr.span,
+            "using `self.to_string` in `fmt::Display` implementation will cause infinite recursion",
+        );
     }
 }
 
@@ -215,55 +212,53 @@ fn check_format_arg_self(cx: &LateContext<'_>, span: Span, arg: &Expr<'_>, impl_
 }
 
 fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTraitNames) {
-    if_chain! {
-        if let Some(macro_call) = root_macro_call_first_node(cx, expr);
-        if let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id);
-        then {
-            let replacement = match name {
-                sym::print_macro | sym::eprint_macro => "write",
-                sym::println_macro | sym::eprintln_macro => "writeln",
-                _ => return,
-            };
+    if let Some(macro_call) = root_macro_call_first_node(cx, expr)
+        && let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id)
+    {
+        let replacement = match name {
+            sym::print_macro | sym::eprint_macro => "write",
+            sym::println_macro | sym::eprintln_macro => "writeln",
+            _ => return,
+        };
 
-            let name = name.as_str().strip_suffix("_macro").unwrap();
+        let name = name.as_str().strip_suffix("_macro").unwrap();
 
-            span_lint_and_sugg(
-                cx,
-                PRINT_IN_FORMAT_IMPL,
-                macro_call.span,
-                &format!("use of `{name}!` in `{}` impl", impl_trait.name),
-                "replace with",
-                if let Some(formatter_name) = impl_trait.formatter_name {
-                    format!("{replacement}!({formatter_name}, ..)")
-                } else {
-                    format!("{replacement}!(..)")
-                },
-                Applicability::HasPlaceholders,
-            );
-        }
+        span_lint_and_sugg(
+            cx,
+            PRINT_IN_FORMAT_IMPL,
+            macro_call.span,
+            &format!("use of `{name}!` in `{}` impl", impl_trait.name),
+            "replace with",
+            if let Some(formatter_name) = impl_trait.formatter_name {
+                format!("{replacement}!({formatter_name}, ..)")
+            } else {
+                format!("{replacement}!(..)")
+            },
+            Applicability::HasPlaceholders,
+        );
     }
 }
 
 fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option<FormatTraitNames> {
-    if_chain! {
-        if impl_item.ident.name == sym::fmt;
-        if let ImplItemKind::Fn(_, body_id) = impl_item.kind;
-        if let Some(Impl { of_trait: Some(trait_ref),..}) = get_parent_as_impl(cx.tcx, impl_item.hir_id());
-        if let Some(did) = trait_ref.trait_def_id();
-        if let Some(name) = cx.tcx.get_diagnostic_name(did);
-        if matches!(name, sym::Debug | sym::Display);
-        then {
-            let body = cx.tcx.hir().body(body_id);
-            let formatter_name = body.params.get(1)
-                .and_then(|param| param.pat.simple_ident())
-                .map(|ident| ident.name);
+    if impl_item.ident.name == sym::fmt
+        && let ImplItemKind::Fn(_, body_id) = impl_item.kind
+        && let Some(Impl {
+            of_trait: Some(trait_ref),
+            ..
+        }) = get_parent_as_impl(cx.tcx, impl_item.hir_id())
+        && let Some(did) = trait_ref.trait_def_id()
+        && let Some(name) = cx.tcx.get_diagnostic_name(did)
+        && matches!(name, sym::Debug | sym::Display)
+    {
+        let body = cx.tcx.hir().body(body_id);
+        let formatter_name = body
+            .params
+            .get(1)
+            .and_then(|param| param.pat.simple_ident())
+            .map(|ident| ident.name);
 
-            Some(FormatTraitNames {
-                name,
-                formatter_name,
-            })
-        } else {
-            None
-        }
+        Some(FormatTraitNames { name, formatter_name })
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs
index 10ddc3bda34..a1db7b63b17 100644
--- a/clippy_lints/src/formatting.rs
+++ b/clippy_lints/src/formatting.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
 use clippy_utils::is_span_if;
 use clippy_utils::source::snippet_opt;
-use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -168,93 +167,84 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
 
 /// Implementation of the `SUSPICIOUS_UNARY_OP_FORMATTING` lint.
 fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
-    if_chain! {
-        if let ExprKind::Binary(ref binop, ref lhs, ref rhs) = expr.kind;
-        if !lhs.span.from_expansion() && !rhs.span.from_expansion();
+    if let ExprKind::Binary(ref binop, ref lhs, ref rhs) = expr.kind
+        && !lhs.span.from_expansion() && !rhs.span.from_expansion()
         // span between BinOp LHS and RHS
-        let binop_span = lhs.span.between(rhs.span);
+        && let binop_span = lhs.span.between(rhs.span)
         // if RHS is an UnOp
-        if let ExprKind::Unary(op, ref un_rhs) = rhs.kind;
+        && let ExprKind::Unary(op, ref un_rhs) = rhs.kind
         // from UnOp operator to UnOp operand
-        let unop_operand_span = rhs.span.until(un_rhs.span);
-        if let Some(binop_snippet) = snippet_opt(cx, binop_span);
-        if let Some(unop_operand_snippet) = snippet_opt(cx, unop_operand_span);
-        let binop_str = BinOpKind::to_string(&binop.node);
+        && let unop_operand_span = rhs.span.until(un_rhs.span)
+        && let Some(binop_snippet) = snippet_opt(cx, binop_span)
+        && let Some(unop_operand_snippet) = snippet_opt(cx, unop_operand_span)
+        && let binop_str = BinOpKind::to_string(&binop.node)
         // no space after BinOp operator and space after UnOp operator
-        if binop_snippet.ends_with(binop_str) && unop_operand_snippet.ends_with(' ');
-        then {
-            let unop_str = UnOp::to_string(op);
-            let eqop_span = lhs.span.between(un_rhs.span);
-            span_lint_and_help(
-                cx,
-                SUSPICIOUS_UNARY_OP_FORMATTING,
-                eqop_span,
-                &format!(
-                    "by not having a space between `{binop_str}` and `{unop_str}` it looks like \
-                     `{binop_str}{unop_str}` is a single operator"
-                ),
-                None,
-                &format!(
-                    "put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"
-                ),
-            );
-        }
+        && binop_snippet.ends_with(binop_str) && unop_operand_snippet.ends_with(' ')
+    {
+        let unop_str = UnOp::to_string(op);
+        let eqop_span = lhs.span.between(un_rhs.span);
+        span_lint_and_help(
+            cx,
+            SUSPICIOUS_UNARY_OP_FORMATTING,
+            eqop_span,
+            &format!(
+                "by not having a space between `{binop_str}` and `{unop_str}` it looks like \
+                 `{binop_str}{unop_str}` is a single operator"
+            ),
+            None,
+            &format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"),
+        );
     }
 }
 
 /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else`.
 fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
-    if_chain! {
-        if let ExprKind::If(_, then, Some(else_)) = &expr.kind;
-        if is_block(else_) || is_if(else_);
-        if !then.span.from_expansion() && !else_.span.from_expansion();
-        if !in_external_macro(cx.sess(), expr.span);
+    if let ExprKind::If(_, then, Some(else_)) = &expr.kind
+        && (is_block(else_) || is_if(else_))
+        && !then.span.from_expansion() && !else_.span.from_expansion()
+        && !in_external_macro(cx.sess(), expr.span)
 
         // workaround for rust-lang/rust#43081
-        if expr.span.lo().0 != 0 && expr.span.hi().0 != 0;
+        && expr.span.lo().0 != 0 && expr.span.hi().0 != 0
 
         // this will be a span from the closing ‘}’ of the “then” block (excluding) to
         // the “if” of the “else if” block (excluding)
-        let else_span = then.span.between(else_.span);
+        && let else_span = then.span.between(else_.span)
 
         // the snippet should look like " else \n    " with maybe comments anywhere
         // it’s bad when there is a ‘\n’ after the “else”
-        if let Some(else_snippet) = snippet_opt(cx, else_span);
-        if let Some((pre_else, post_else)) = else_snippet.split_once("else");
-        if let Some((_, post_else_post_eol)) = post_else.split_once('\n');
-
-        then {
-            // Allow allman style braces `} \n else \n {`
-            if_chain! {
-                if is_block(else_);
-                if let Some((_, pre_else_post_eol)) = pre_else.split_once('\n');
-                // Exactly one eol before and after the else
-                if !pre_else_post_eol.contains('\n');
-                if !post_else_post_eol.contains('\n');
-                then {
-                    return;
-                }
-            }
-
-            // Don't warn if the only thing inside post_else_post_eol is a comment block.
-            let trimmed_post_else_post_eol = post_else_post_eol.trim();
-            if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") {
-                return
-            }
+        && let Some(else_snippet) = snippet_opt(cx, else_span)
+        && let Some((pre_else, post_else)) = else_snippet.split_once("else")
+        && let Some((_, post_else_post_eol)) = post_else.split_once('\n')
+    {
+        // Allow allman style braces `} \n else \n {`
+        if is_block(else_)
+            && let Some((_, pre_else_post_eol)) = pre_else.split_once('\n')
+            // Exactly one eol before and after the else
+            && !pre_else_post_eol.contains('\n')
+            && !post_else_post_eol.contains('\n')
+        {
+            return;
+        }
 
-            let else_desc = if is_if(else_) { "if" } else { "{..}" };
-            span_lint_and_note(
-                cx,
-                SUSPICIOUS_ELSE_FORMATTING,
-                else_span,
-                &format!("this is an `else {else_desc}` but the formatting might hide it"),
-                None,
-                &format!(
-                    "to remove this lint, remove the `else` or remove the new line between \
-                     `else` and `{else_desc}`",
-                ),
-            );
+        // Don't warn if the only thing inside post_else_post_eol is a comment block.
+        let trimmed_post_else_post_eol = post_else_post_eol.trim();
+        if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") {
+            return;
         }
+
+        let else_desc = if is_if(else_) { "if" } else { "{..}" };
+        span_lint_and_note(
+            cx,
+            SUSPICIOUS_ELSE_FORMATTING,
+            else_span,
+            &format!("this is an `else {else_desc}` but the formatting might hide it"),
+            None,
+            &format!(
+                "to remove this lint, remove the `else` or remove the new line between \
+                 `else` and `{else_desc}`",
+            ),
+        );
     }
 }
 
@@ -272,61 +262,56 @@ fn indentation(cx: &EarlyContext<'_>, span: Span) -> usize {
 fn check_array(cx: &EarlyContext<'_>, expr: &Expr) {
     if let ExprKind::Array(ref array) = expr.kind {
         for element in array {
-            if_chain! {
-                if let ExprKind::Binary(ref op, ref lhs, _) = element.kind;
-                if has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span);
-                let space_span = lhs.span.between(op.span);
-                if let Some(space_snippet) = snippet_opt(cx, space_span);
-                let lint_span = lhs.span.with_lo(lhs.span.hi());
-                if space_snippet.contains('\n');
-                if indentation(cx, op.span) <= indentation(cx, lhs.span);
-                then {
-                    span_lint_and_note(
-                        cx,
-                        POSSIBLE_MISSING_COMMA,
-                        lint_span,
-                        "possibly missing a comma here",
-                        None,
-                        "to remove this lint, add a comma or write the expr in a single line",
-                    );
-                }
+            if let ExprKind::Binary(ref op, ref lhs, _) = element.kind
+                && has_unary_equivalent(op.node)
+                && lhs.span.eq_ctxt(op.span)
+                && let space_span = lhs.span.between(op.span)
+                && let Some(space_snippet) = snippet_opt(cx, space_span)
+                && let lint_span = lhs.span.with_lo(lhs.span.hi())
+                && space_snippet.contains('\n')
+                && indentation(cx, op.span) <= indentation(cx, lhs.span)
+            {
+                span_lint_and_note(
+                    cx,
+                    POSSIBLE_MISSING_COMMA,
+                    lint_span,
+                    "possibly missing a comma here",
+                    None,
+                    "to remove this lint, add a comma or write the expr in a single line",
+                );
             }
         }
     }
 }
 
 fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
-    if_chain! {
-        if !first.span.from_expansion() && !second.span.from_expansion();
-        if matches!(first.kind, ExprKind::If(..));
-        if is_block(second) || is_if(second);
+    if !first.span.from_expansion() && !second.span.from_expansion()
+        && matches!(first.kind, ExprKind::If(..))
+        && (is_block(second) || is_if(second))
 
         // Proc-macros can give weird spans. Make sure this is actually an `if`.
-        if is_span_if(cx, first.span);
+        && is_span_if(cx, first.span)
 
         // If there is a line break between the two expressions, don't lint.
         // If there is a non-whitespace character, this span came from a proc-macro.
-        let else_span = first.span.between(second.span);
-        if let Some(else_snippet) = snippet_opt(cx, else_span);
-        if !else_snippet.chars().any(|c| c == '\n' || !c.is_whitespace());
-        then {
-            let (looks_like, next_thing) = if is_if(second) {
-                ("an `else if`", "the second `if`")
-            } else {
-                ("an `else {..}`", "the next block")
-            };
+        && let else_span = first.span.between(second.span)
+        && let Some(else_snippet) = snippet_opt(cx, else_span)
+        && !else_snippet.chars().any(|c| c == '\n' || !c.is_whitespace())
+    {
+        let (looks_like, next_thing) = if is_if(second) {
+            ("an `else if`", "the second `if`")
+        } else {
+            ("an `else {..}`", "the next block")
+        };
 
-            span_lint_and_note(
-                cx,
-                SUSPICIOUS_ELSE_FORMATTING,
-                else_span,
-                &format!("this looks like {looks_like} but the `else` is missing"),
-                None,
-                &format!(
-                    "to remove this lint, add the missing `else` or add a new line before {next_thing}",
-                ),
-            );
-        }
+        span_lint_and_note(
+            cx,
+            SUSPICIOUS_ELSE_FORMATTING,
+            else_span,
+            &format!("this looks like {looks_like} but the `else` is missing"),
+            None,
+            &format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",),
+        );
     }
 }
 
diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs
index 74a60b6a0d2..18d11ccc0b5 100644
--- a/clippy_lints/src/from_str_radix_10.rs
+++ b/clippy_lints/src/from_str_radix_10.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_integer_literal;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -46,52 +45,41 @@ declare_lint_pass!(FromStrRadix10 => [FROM_STR_RADIX_10]);
 
 impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) {
-        if_chain! {
-            if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind;
-            if let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind;
+        if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind
+            && let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind
 
             // check if the first part of the path is some integer primitive
-            if let TyKind::Path(ty_qpath) = &ty.kind;
-            let ty_res = cx.qpath_res(ty_qpath, ty.hir_id);
-            if let def::Res::PrimTy(prim_ty) = ty_res;
-            if matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_));
+            && let TyKind::Path(ty_qpath) = &ty.kind
+            && let ty_res = cx.qpath_res(ty_qpath, ty.hir_id)
+            && let def::Res::PrimTy(prim_ty) = ty_res
+            && matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_))
 
             // check if the second part of the path indeed calls the associated
             // function `from_str_radix`
-            if pathseg.ident.name.as_str() == "from_str_radix";
+            && pathseg.ident.name.as_str() == "from_str_radix"
 
             // check if the second argument is a primitive `10`
-            if is_integer_literal(radix, 10);
+            && is_integer_literal(radix, 10)
+        {
+            let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
+                let ty = cx.typeck_results().expr_ty(expr);
+                if is_ty_stringish(cx, ty) { expr } else { &src }
+            } else {
+                &src
+            };
 
-            then {
-                let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
-                    let ty = cx.typeck_results().expr_ty(expr);
-                    if is_ty_stringish(cx, ty) {
-                        expr
-                    } else {
-                        &src
-                    }
-                } else {
-                    &src
-                };
+            let sugg =
+                Sugg::hir_with_applicability(cx, expr, "<string>", &mut Applicability::MachineApplicable).maybe_par();
 
-                let sugg = Sugg::hir_with_applicability(
-                    cx,
-                    expr,
-                    "<string>",
-                    &mut Applicability::MachineApplicable
-                ).maybe_par();
-
-                span_lint_and_sugg(
-                    cx,
-                    FROM_STR_RADIX_10,
-                    exp.span,
-                    "this call to `from_str_radix` can be replaced with a call to `str::parse`",
-                    "try",
-                    format!("{sugg}.parse::<{}>()", prim_ty.name_str()),
-                    Applicability::MaybeIncorrect
-                );
-            }
+            span_lint_and_sugg(
+                cx,
+                FROM_STR_RADIX_10,
+                exp.span,
+                "this call to `from_str_radix` can be replaced with a call to `str::parse`",
+                "try",
+                format!("{sugg}.parse::<{}>()", prim_ty.name_str()),
+                Applicability::MaybeIncorrect,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/functions/impl_trait_in_params.rs b/clippy_lints/src/functions/impl_trait_in_params.rs
index ee66c841ed2..4afff8a2434 100644
--- a/clippy_lints/src/functions/impl_trait_in_params.rs
+++ b/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -52,54 +52,48 @@ fn report(
 }
 
 pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
-    if_chain! {
-        if let FnKind::ItemFn(ident, generics, _) = kind;
-        if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public();
-        if !is_in_test_function(cx.tcx, hir_id);
-        then {
-            for param in generics.params {
-                if param.is_impl_trait() {
-                    report(cx, param, ident, generics, body.params[0].span);
-                };
-            }
+    if let FnKind::ItemFn(ident, generics, _) = kind
+        && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public()
+        && !is_in_test_function(cx.tcx, hir_id)
+    {
+        for param in generics.params {
+            if param.is_impl_trait() {
+                report(cx, param, ident, generics, body.params[0].span);
+            };
         }
     }
 }
 
 pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
-    if_chain! {
-        if let ImplItemKind::Fn(_, body_id) = impl_item.kind;
-        if let hir::Node::Item(item) = cx.tcx.hir().get_parent(impl_item.hir_id());
-        if let hir::ItemKind::Impl(impl_) = item.kind;
-        if let hir::Impl { of_trait, .. } = *impl_;
-        if of_trait.is_none();
-        let body = cx.tcx.hir().body(body_id);
-        if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public();
-        if !is_in_test_function(cx.tcx, impl_item.hir_id());
-        then {
-            for param in impl_item.generics.params {
-                if param.is_impl_trait() {
-                    report(cx, param, &impl_item.ident, impl_item.generics, body.params[0].span);
-                }
+    if let ImplItemKind::Fn(_, body_id) = impl_item.kind
+        && let hir::Node::Item(item) = cx.tcx.hir().get_parent(impl_item.hir_id())
+        && let hir::ItemKind::Impl(impl_) = item.kind
+        && let hir::Impl { of_trait, .. } = *impl_
+        && of_trait.is_none()
+        && let body = cx.tcx.hir().body(body_id)
+        && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public()
+        && !is_in_test_function(cx.tcx, impl_item.hir_id())
+    {
+        for param in impl_item.generics.params {
+            if param.is_impl_trait() {
+                report(cx, param, &impl_item.ident, impl_item.generics, body.params[0].span);
             }
         }
     }
 }
 
 pub(super) fn check_trait_item(cx: &LateContext<'_>, trait_item: &TraitItem<'_>, avoid_breaking_exported_api: bool) {
-    if_chain! {
-        if !avoid_breaking_exported_api;
-        if let TraitItemKind::Fn(_, _) = trait_item.kind;
-        if let hir::Node::Item(item) = cx.tcx.hir().get_parent(trait_item.hir_id());
+    if !avoid_breaking_exported_api
+        && let TraitItemKind::Fn(_, _) = trait_item.kind
+        && let hir::Node::Item(item) = cx.tcx.hir().get_parent(trait_item.hir_id())
         // ^^ (Will always be a trait)
-        if !item.vis_span.is_empty(); // Is public
-        if !is_in_test_function(cx.tcx, trait_item.hir_id());
-        then {
-            for param in trait_item.generics.params {
-                if param.is_impl_trait() {
-                    let sp = trait_item.ident.span.with_hi(trait_item.ident.span.hi() + BytePos(1));
-                    report(cx, param, &trait_item.ident, trait_item.generics, sp.shrink_to_hi());
-                }
+        && !item.vis_span.is_empty() // Is public
+        && !is_in_test_function(cx.tcx, trait_item.hir_id())
+    {
+        for param in trait_item.generics.params {
+            if param.is_impl_trait() {
+                let sp = trait_item.ident.span.with_hi(trait_item.ident.span.hi() + BytePos(1));
+                report(cx, param, &trait_item.ident, trait_item.generics, sp.shrink_to_hi());
             }
         }
     }
diff --git a/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs
index 18f7368dafb..bf96c0d62b0 100644
--- a/clippy_lints/src/functions/misnamed_getters.rs
+++ b/clippy_lints/src/functions/misnamed_getters.rs
@@ -43,15 +43,13 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
     // Body must be &(mut) <self_data>.name
     // self_data is not necessarily self, to also lint sub-getters, etc…
 
-    let block_expr = if_chain! {
-        if let ExprKind::Block(block,_) = body.value.kind;
-        if block.stmts.is_empty();
-        if let Some(block_expr) = block.expr;
-        then {
-            block_expr
-        } else {
-            return;
-        }
+    let block_expr = if let ExprKind::Block(block, _) = body.value.kind
+        && block.stmts.is_empty()
+        && let Some(block_expr) = block.expr
+    {
+        block_expr
+    } else {
+        return;
     };
     let expr_span = block_expr.span;
 
@@ -61,14 +59,12 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
     } else {
         block_expr
     };
-    let (self_data, used_ident) = if_chain! {
-        if let ExprKind::Field(self_data, ident) = expr.kind;
-        if ident.name.as_str() != name;
-        then {
-            (self_data, ident)
-        } else {
-            return;
-        }
+    let (self_data, used_ident) = if let ExprKind::Field(self_data, ident) = expr.kind
+        && ident.name.as_str() != name
+    {
+        (self_data, ident)
+    } else {
+        return;
     };
 
     let mut used_field = None;
diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs
index 485235514de..47db107d669 100644
--- a/clippy_lints/src/functions/result.rs
+++ b/clippy_lints/src/functions/result.rs
@@ -86,59 +86,60 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
 }
 
 fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
-    if_chain! {
-        if let Adt(adt, subst) = err_ty.kind();
-        if let Some(local_def_id) = err_ty.ty_adt_def().expect("already checked this is adt").did().as_local();
-        if let Some(hir::Node::Item(item)) = cx
-            .tcx
-            .hir()
-            .find_by_def_id(local_def_id);
-        if let hir::ItemKind::Enum(ref def, _) = item.kind;
-        then {
-            let variants_size = AdtVariantInfo::new(cx, *adt, subst);
-            if let Some((first_variant, variants)) = variants_size.split_first()
-                && first_variant.size >= large_err_threshold
-            {
-                span_lint_and_then(
-                    cx,
-                    RESULT_LARGE_ERR,
-                    hir_ty_span,
-                    "the `Err`-variant returned from this function is very large",
-                    |diag| {
-                        diag.span_label(
-                            def.variants[first_variant.ind].span,
-                            format!("the largest variant contains at least {} bytes", variants_size[0].size),
-                        );
+    if let Adt(adt, subst) = err_ty.kind()
+        && let Some(local_def_id) = err_ty
+            .ty_adt_def()
+            .expect("already checked this is adt")
+            .did()
+            .as_local()
+        && let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(local_def_id)
+        && let hir::ItemKind::Enum(ref def, _) = item.kind
+    {
+        let variants_size = AdtVariantInfo::new(cx, *adt, subst);
+        if let Some((first_variant, variants)) = variants_size.split_first()
+            && first_variant.size >= large_err_threshold
+        {
+            span_lint_and_then(
+                cx,
+                RESULT_LARGE_ERR,
+                hir_ty_span,
+                "the `Err`-variant returned from this function is very large",
+                |diag| {
+                    diag.span_label(
+                        def.variants[first_variant.ind].span,
+                        format!("the largest variant contains at least {} bytes", variants_size[0].size),
+                    );
 
-                        for variant in variants {
-                            if variant.size >= large_err_threshold {
-                                let variant_def = &def.variants[variant.ind];
-                                diag.span_label(
-                                    variant_def.span,
-                                    format!("the variant `{}` contains at least {} bytes", variant_def.ident, variant.size),
-                                );
-                            }
+                    for variant in variants {
+                        if variant.size >= large_err_threshold {
+                            let variant_def = &def.variants[variant.ind];
+                            diag.span_label(
+                                variant_def.span,
+                                format!(
+                                    "the variant `{}` contains at least {} bytes",
+                                    variant_def.ident, variant.size
+                                ),
+                            );
                         }
-
-                        diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
                     }
-                );
-            }
+
+                    diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
+                },
+            );
         }
-        else {
-            let ty_size = approx_ty_size(cx, err_ty);
-            if ty_size >= large_err_threshold {
-                span_lint_and_then(
-                    cx,
-                    RESULT_LARGE_ERR,
-                    hir_ty_span,
-                    "the `Err`-variant returned from this function is very large",
-                    |diag: &mut Diagnostic| {
-                        diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
-                        diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
-                    },
-                );
-            }
+    } else {
+        let ty_size = approx_ty_size(cx, err_ty);
+        if ty_size >= large_err_threshold {
+            span_lint_and_then(
+                cx,
+                RESULT_LARGE_ERR,
+                hir_ty_span,
+                "the `Err`-variant returned from this function is very large",
+                |diag: &mut Diagnostic| {
+                    diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
+                    diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs
index e614a8f694f..644b9cdaeb2 100644
--- a/clippy_lints/src/if_let_mutex.rs
+++ b/clippy_lints/src/if_let_mutex.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{higher, SpanlessEq};
-use if_chain::if_chain;
 use rustc_errors::Diagnostic;
 use rustc_hir::intravisit::{self as visit, Visitor};
 use rustc_hir::{Expr, ExprKind};
@@ -127,15 +126,13 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
 }
 
 fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
-    if_chain! {
-        if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
-        if path.ident.as_str() == "lock";
-        let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
-        if is_type_diagnostic_item(cx, ty, sym::Mutex);
-        then {
-            Some(self_arg)
-        } else {
-            None
-        }
+    if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
+        && path.ident.as_str() == "lock"
+        && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
+        && is_type_diagnostic_item(cx, ty, sym::Mutex)
+    {
+        Some(self_arg)
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index a1fcce18ff6..4545f6e42e3 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -13,8 +13,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::sym;
 
-use if_chain::if_chain;
-
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_opt};
 use clippy_utils::ty::is_type_diagnostic_item;
@@ -337,42 +335,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't
     }
 
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Call(fun, args) = e.kind;
-            if let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind;
-            if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind;
-            if let Some(ty_did) = ty_path.res.opt_def_id();
-            then {
-                if self.target.ty() != self.maybe_typeck_results.unwrap().expr_ty(e) {
-                    return;
-                }
+        if let ExprKind::Call(fun, args) = e.kind
+            && let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind
+            && let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind
+            && let Some(ty_did) = ty_path.res.opt_def_id()
+        {
+            if self.target.ty() != self.maybe_typeck_results.unwrap().expr_ty(e) {
+                return;
+            }
 
-                if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) {
-                    if method.ident.name == sym::new {
-                        self.suggestions
-                            .insert(e.span, "HashMap::default()".to_string());
-                    } else if method.ident.name == sym!(with_capacity) {
-                        self.suggestions.insert(
-                            e.span,
-                            format!(
-                                "HashMap::with_capacity_and_hasher({}, Default::default())",
-                                snippet(self.cx, args[0].span, "capacity"),
-                            ),
-                        );
-                    }
-                } else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) {
-                    if method.ident.name == sym::new {
-                        self.suggestions
-                            .insert(e.span, "HashSet::default()".to_string());
-                    } else if method.ident.name == sym!(with_capacity) {
-                        self.suggestions.insert(
-                            e.span,
-                            format!(
-                                "HashSet::with_capacity_and_hasher({}, Default::default())",
-                                snippet(self.cx, args[0].span, "capacity"),
-                            ),
-                        );
-                    }
+            if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) {
+                if method.ident.name == sym::new {
+                    self.suggestions.insert(e.span, "HashMap::default()".to_string());
+                } else if method.ident.name == sym!(with_capacity) {
+                    self.suggestions.insert(
+                        e.span,
+                        format!(
+                            "HashMap::with_capacity_and_hasher({}, Default::default())",
+                            snippet(self.cx, args[0].span, "capacity"),
+                        ),
+                    );
+                }
+            } else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) {
+                if method.ident.name == sym::new {
+                    self.suggestions.insert(e.span, "HashSet::default()".to_string());
+                } else if method.ident.name == sym!(with_capacity) {
+                    self.suggestions.insert(
+                        e.span,
+                        format!(
+                            "HashSet::with_capacity_and_hasher({}, Default::default())",
+                            snippet(self.cx, args[0].span, "capacity"),
+                        ),
+                    );
                 }
             }
         }
diff --git a/clippy_lints/src/implicit_saturating_add.rs b/clippy_lints/src/implicit_saturating_add.rs
index 24f62490f96..f2fac9a29cb 100644
--- a/clippy_lints/src/implicit_saturating_add.rs
+++ b/clippy_lints/src/implicit_saturating_add.rs
@@ -2,7 +2,6 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
 use clippy_utils::source::snippet_with_context;
-use if_chain::if_chain;
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
@@ -40,42 +39,58 @@ declare_lint_pass!(ImplicitSaturatingAdd => [IMPLICIT_SATURATING_ADD]);
 
 impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if_chain! {
-            if let ExprKind::If(cond, then, None) = expr.kind;
-            if let ExprKind::DropTemps(expr1) = cond.kind;
-            if let Some((c, op_node, l)) = get_const(cx, expr1);
-            if let BinOpKind::Ne | BinOpKind::Lt = op_node;
-            if let ExprKind::Block(block, None) = then.kind;
-            if let Block {
+        if let ExprKind::If(cond, then, None) = expr.kind
+            && let ExprKind::DropTemps(expr1) = cond.kind
+            && let Some((c, op_node, l)) = get_const(cx, expr1)
+            && let BinOpKind::Ne | BinOpKind::Lt = op_node
+            && let ExprKind::Block(block, None) = then.kind
+            && let Block {
                 stmts:
-                    [Stmt
-                        { kind: StmtKind::Expr(ex) | StmtKind::Semi(ex), .. }],
-                        expr: None, ..} |
-                        Block { stmts: [], expr: Some(ex), ..} = block;
-            if let ExprKind::AssignOp(op1, target, value) = ex.kind;
-            let ty = cx.typeck_results().expr_ty(target);
-            if Some(c) == get_int_max(ty);
-            let ctxt = expr.span.ctxt();
-            if ex.span.ctxt() == ctxt;
-            if expr1.span.ctxt() == ctxt;
-            if clippy_utils::SpanlessEq::new(cx).eq_expr(l, target);
-            if BinOpKind::Add == op1.node;
-            if let ExprKind::Lit(lit) = value.kind;
-            if let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node;
-            if block.expr.is_none();
-            then {
-                let mut app = Applicability::MachineApplicable;
-                let code = snippet_with_context(cx, target.span, ctxt, "_", &mut app).0;
-                let sugg = if let Some(parent) = get_parent_expr(cx, expr)
-                    && let ExprKind::If(_cond, _then, Some(else_)) = parent.kind
-                    && else_.hir_id == expr.hir_id
-                {
-                    format!("{{{code} = {code}.saturating_add(1); }}")
-                } else {
-                    format!("{code} = {code}.saturating_add(1);")
-                };
-                span_lint_and_sugg(cx, IMPLICIT_SATURATING_ADD, expr.span, "manual saturating add detected", "use instead", sugg, app);
+                    [
+                        Stmt {
+                            kind: StmtKind::Expr(ex) | StmtKind::Semi(ex),
+                            ..
+                        },
+                    ],
+                expr: None,
+                ..
             }
+            | Block {
+                stmts: [],
+                expr: Some(ex),
+                ..
+            } = block
+            && let ExprKind::AssignOp(op1, target, value) = ex.kind
+            && let ty = cx.typeck_results().expr_ty(target)
+            && Some(c) == get_int_max(ty)
+            && let ctxt = expr.span.ctxt()
+            && ex.span.ctxt() == ctxt
+            && expr1.span.ctxt() == ctxt
+            && clippy_utils::SpanlessEq::new(cx).eq_expr(l, target)
+            && BinOpKind::Add == op1.node
+            && let ExprKind::Lit(lit) = value.kind
+            && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
+            && block.expr.is_none()
+        {
+            let mut app = Applicability::MachineApplicable;
+            let code = snippet_with_context(cx, target.span, ctxt, "_", &mut app).0;
+            let sugg = if let Some(parent) = get_parent_expr(cx, expr)
+                && let ExprKind::If(_cond, _then, Some(else_)) = parent.kind
+                && else_.hir_id == expr.hir_id
+            {
+                format!("{{{code} = {code}.saturating_add(1); }}")
+            } else {
+                format!("{code} = {code}.saturating_add(1);")
+            };
+            span_lint_and_sugg(
+                cx,
+                IMPLICIT_SATURATING_ADD,
+                expr.span,
+                "manual saturating add detected",
+                "use instead",
+                sugg,
+                app,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 859404289d9..fc66f86ae86 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq};
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
@@ -46,83 +45,76 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
         if expr.span.from_expansion() {
             return;
         }
-        if_chain! {
-            if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr);
+        if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr)
 
             // Check if the conditional expression is a binary operation
-            if let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind;
+            && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind
 
             // Ensure that the binary operator is >, !=, or <
-            if BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node;
+            && (BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node)
 
             // Check if assign operation is done
-            if let Some(target) = subtracts_one(cx, then);
+            && let Some(target) = subtracts_one(cx, then)
 
             // Extracting out the variable name
-            if let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind;
-
-            then {
-                // Handle symmetric conditions in the if statement
-                let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
-                    if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node {
-                        (cond_left, cond_right)
-                    } else {
-                        return;
-                    }
-                } else if SpanlessEq::new(cx).eq_expr(cond_right, target) {
-                    if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node {
-                        (cond_right, cond_left)
-                    } else {
-                        return;
-                    }
+            && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind
+        {
+            // Handle symmetric conditions in the if statement
+            let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
+                if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node {
+                    (cond_left, cond_right)
                 } else {
                     return;
-                };
-
-                // Check if the variable in the condition statement is an integer
-                if !cx.typeck_results().expr_ty(cond_var).is_integral() {
+                }
+            } else if SpanlessEq::new(cx).eq_expr(cond_right, target) {
+                if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node {
+                    (cond_right, cond_left)
+                } else {
                     return;
                 }
+            } else {
+                return;
+            };
 
-                // Get the variable name
-                let var_name = ares_path.segments[0].ident.name.as_str();
-                match cond_num_val.kind {
-                    ExprKind::Lit(cond_lit) => {
-                        // Check if the constant is zero
-                        if let LitKind::Int(0, _) = cond_lit.node {
-                            if cx.typeck_results().expr_ty(cond_left).is_signed() {
-                            } else {
-                                print_lint_and_sugg(cx, var_name, expr);
-                            };
-                        }
-                    },
-                    ExprKind::Path(QPath::TypeRelative(_, name)) => {
-                        if_chain! {
-                            if name.ident.as_str() == "MIN";
-                            if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id);
-                            if let Some(impl_id) = cx.tcx.impl_of_method(const_id);
-                            if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
-                            if cx.tcx.type_of(impl_id).instantiate_identity().is_integral();
-                            then {
-                                print_lint_and_sugg(cx, var_name, expr)
-                            }
-                        }
-                    },
-                    ExprKind::Call(func, []) => {
-                        if_chain! {
-                            if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind;
-                            if name.ident.as_str() == "min_value";
-                            if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id);
-                            if let Some(impl_id) = cx.tcx.impl_of_method(func_id);
-                            if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
-                            if cx.tcx.type_of(impl_id).instantiate_identity().is_integral();
-                            then {
-                                print_lint_and_sugg(cx, var_name, expr)
-                            }
-                        }
-                    },
-                    _ => (),
-                }
+            // Check if the variable in the condition statement is an integer
+            if !cx.typeck_results().expr_ty(cond_var).is_integral() {
+                return;
+            }
+
+            // Get the variable name
+            let var_name = ares_path.segments[0].ident.name.as_str();
+            match cond_num_val.kind {
+                ExprKind::Lit(cond_lit) => {
+                    // Check if the constant is zero
+                    if let LitKind::Int(0, _) = cond_lit.node {
+                        if cx.typeck_results().expr_ty(cond_left).is_signed() {
+                        } else {
+                            print_lint_and_sugg(cx, var_name, expr);
+                        };
+                    }
+                },
+                ExprKind::Path(QPath::TypeRelative(_, name)) => {
+                    if name.ident.as_str() == "MIN"
+                        && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id)
+                        && let Some(impl_id) = cx.tcx.impl_of_method(const_id)
+                        && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
+                        && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
+                    {
+                        print_lint_and_sugg(cx, var_name, expr);
+                    }
+                },
+                ExprKind::Call(func, []) => {
+                    if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind
+                        && name.ident.as_str() == "min_value"
+                        && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id)
+                        && let Some(impl_id) = cx.tcx.impl_of_method(func_id)
+                        && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
+                        && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
+                    {
+                        print_lint_and_sugg(cx, var_name, expr);
+                    }
+                },
+                _ => (),
             }
         }
     }
@@ -135,18 +127,14 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp
             (BinOpKind::Sub == op1.node && is_integer_literal(value, 1)).then_some(target)
         },
         ExprKind::Assign(target, value, _) => {
-            if_chain! {
-                if let ExprKind::Binary(ref op1, left1, right1) = value.kind;
-                if BinOpKind::Sub == op1.node;
-
-                if SpanlessEq::new(cx).eq_expr(left1, target);
-
-                if is_integer_literal(right1, 1);
-                then {
-                    Some(target)
-                } else {
-                    None
-                }
+            if let ExprKind::Binary(ref op1, left1, right1) = value.kind
+                && BinOpKind::Sub == op1.node
+                && SpanlessEq::new(cx).eq_expr(left1, target)
+                && is_integer_literal(right1, 1)
+            {
+                Some(target)
+            } else {
+                None
             }
         },
         _ => None,
diff --git a/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs
index a84f7351ad6..f6e1281a291 100644
--- a/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, ExprKind};
@@ -66,54 +65,53 @@ declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRU
 
 impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if_chain! {
-            if !expr.span.from_expansion();
-            if let ExprKind::Struct(qpath, fields, base) = expr.kind;
-            let ty = cx.typeck_results().expr_ty(expr);
-            if let Some(adt_def) = ty.ty_adt_def();
-            if adt_def.is_struct();
-            if let Some(variant) = adt_def.variants().iter().next();
-            if fields.iter().all(|f| f.is_shorthand);
-            then {
-                let mut def_order_map = FxHashMap::default();
-                for (idx, field) in variant.fields.iter().enumerate() {
-                    def_order_map.insert(field.name, idx);
-                }
+        if !expr.span.from_expansion()
+            && let ExprKind::Struct(qpath, fields, base) = expr.kind
+            && let ty = cx.typeck_results().expr_ty(expr)
+            && let Some(adt_def) = ty.ty_adt_def()
+            && adt_def.is_struct()
+            && let Some(variant) = adt_def.variants().iter().next()
+            && fields.iter().all(|f| f.is_shorthand)
+        {
+            let mut def_order_map = FxHashMap::default();
+            for (idx, field) in variant.fields.iter().enumerate() {
+                def_order_map.insert(field.name, idx);
+            }
 
-                if is_consistent_order(fields, &def_order_map) {
-                    return;
-                }
+            if is_consistent_order(fields, &def_order_map) {
+                return;
+            }
 
-                let mut ordered_fields: Vec<_> = fields.iter().map(|f| f.ident.name).collect();
-                ordered_fields.sort_unstable_by_key(|id| def_order_map[id]);
+            let mut ordered_fields: Vec<_> = fields.iter().map(|f| f.ident.name).collect();
+            ordered_fields.sort_unstable_by_key(|id| def_order_map[id]);
 
-                let mut fields_snippet = String::new();
-                let (last_ident, idents) = ordered_fields.split_last().unwrap();
-                for ident in idents {
-                    let _: fmt::Result = write!(fields_snippet, "{ident}, ");
-                }
-                fields_snippet.push_str(&last_ident.to_string());
+            let mut fields_snippet = String::new();
+            let (last_ident, idents) = ordered_fields.split_last().unwrap();
+            for ident in idents {
+                let _: fmt::Result = write!(fields_snippet, "{ident}, ");
+            }
+            fields_snippet.push_str(&last_ident.to_string());
 
-                let base_snippet = if let Some(base) = base {
-                        format!(", ..{}", snippet(cx, base.span, ".."))
-                    } else {
-                        String::new()
-                    };
+            let base_snippet = if let Some(base) = base {
+                format!(", ..{}", snippet(cx, base.span, ".."))
+            } else {
+                String::new()
+            };
 
-                let sugg = format!("{} {{ {fields_snippet}{base_snippet} }}",
-                    snippet(cx, qpath.span(), ".."),
-                    );
+            let sugg = format!(
+                "{} {{ {fields_snippet}{base_snippet} }}",
+                snippet(cx, qpath.span(), ".."),
+            );
 
-                span_lint_and_sugg(
-                    cx,
-                    INCONSISTENT_STRUCT_CONSTRUCTOR,
-                    expr.span,
-                    "struct constructor field order is inconsistent with struct definition field order",
-                    "try",
-                    sugg,
-                    Applicability::MachineApplicable,
-                )
-            }
+            span_lint_and_sugg(
+                cx,
+                INCONSISTENT_STRUCT_CONSTRUCTOR,
+                expr.span,
+                "struct constructor field order is inconsistent with struct definition field order",
+                "try",
+                sugg,
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs
index c2f1f18e39d..fa6536db796 100644
--- a/clippy_lints/src/index_refutable_slice.rs
+++ b/clippy_lints/src/index_refutable_slice.rs
@@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLet;
 use clippy_utils::ty::is_copy;
 use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
-use if_chain::if_chain;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -70,20 +69,17 @@ impl_lint_pass!(IndexRefutableSlice => [INDEX_REFUTABLE_SLICE]);
 
 impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if_chain! {
-            if !expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some();
-            if let Some(IfLet {let_pat, if_then, ..}) = IfLet::hir(cx, expr);
-            if !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id);
-            if self.msrv.meets(msrvs::SLICE_PATTERNS);
-
-            let found_slices = find_slice_values(cx, let_pat);
-            if !found_slices.is_empty();
-            let filtered_slices = filter_lintable_slices(cx, found_slices, self.max_suggested_slice, if_then);
-            if !filtered_slices.is_empty();
-            then {
-                for slice in filtered_slices.values() {
-                    lint_slice(cx, slice);
-                }
+        if (!expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some())
+            && let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr)
+            && !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id)
+            && self.msrv.meets(msrvs::SLICE_PATTERNS)
+            && let found_slices = find_slice_values(cx, let_pat)
+            && !found_slices.is_empty()
+            && let filtered_slices = filter_lintable_slices(cx, found_slices, self.max_suggested_slice, if_then)
+            && !filtered_slices.is_empty()
+        {
+            for slice in filtered_slices.values() {
+                lint_slice(cx, slice);
             }
         }
     }
@@ -245,28 +241,26 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
                 max_suggested_slice,
             } = *self;
 
-            if_chain! {
+            if let Some(use_info) = slice_lint_info.get_mut(&local_id)
                 // Check if this is even a local we're interested in
-                if let Some(use_info) = slice_lint_info.get_mut(&local_id);
 
-                let map = cx.tcx.hir();
+                && let map = cx.tcx.hir()
 
                 // Checking for slice indexing
-                let parent_id = map.parent_id(expr.hir_id);
-                if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
-                if let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind;
-                if let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr);
-                if let Ok(index_value) = index_value.try_into();
-                if index_value < max_suggested_slice;
+                && let parent_id = map.parent_id(expr.hir_id)
+                && let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id)
+                && let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind
+                && let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr)
+                && let Ok(index_value) = index_value.try_into()
+                && index_value < max_suggested_slice
 
                 // Make sure that this slice index is read only
-                let maybe_addrof_id = map.parent_id(parent_id);
-                if let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id);
-                if let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind;
-                then {
-                    use_info.index_use.push((index_value, map.span(parent_expr.hir_id)));
-                    return;
-                }
+                && let maybe_addrof_id = map.parent_id(parent_id)
+                && let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id)
+                && let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind
+            {
+                use_info.index_use.push((index_value, map.span(parent_expr.hir_id)));
+                return;
             }
 
             // The slice was used for something other than indexing
diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs
index 32b2cb4385f..8e84c73666f 100644
--- a/clippy_lints/src/instant_subtraction.rs
+++ b/clippy_lints/src/instant_subtraction.rs
@@ -89,27 +89,17 @@ impl LateLintPass<'_> for InstantSubtraction {
             rhs,
         ) = expr.kind
         {
-            if_chain! {
-                if is_instant_now_call(cx, lhs);
-
-                if is_an_instant(cx, rhs);
-                if let Some(sugg) = Sugg::hir_opt(cx, rhs);
-
-                then {
-                    print_manual_instant_elapsed_sugg(cx, expr, sugg)
-                } else {
-                    if_chain! {
-                        if !expr.span.from_expansion();
-                        if self.msrv.meets(msrvs::TRY_FROM);
-
-                        if is_an_instant(cx, lhs);
-                        if is_a_duration(cx, rhs);
-
-                        then {
-                            print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr)
-                        }
-                    }
-                }
+            if is_instant_now_call(cx, lhs)
+                && is_an_instant(cx, rhs)
+                && let Some(sugg) = Sugg::hir_opt(cx, rhs)
+            {
+                print_manual_instant_elapsed_sugg(cx, expr, sugg);
+            } else if !expr.span.from_expansion()
+                && self.msrv.meets(msrvs::TRY_FROM)
+                && is_an_instant(cx, lhs)
+                && is_a_duration(cx, rhs)
+            {
+                print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
             }
         }
     }
diff --git a/clippy_lints/src/large_const_arrays.rs b/clippy_lints/src/large_const_arrays.rs
index a4f3d498345..7db088f986f 100644
--- a/clippy_lints/src/large_const_arrays.rs
+++ b/clippy_lints/src/large_const_arrays.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -47,43 +46,40 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]);
 
 impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if_chain! {
-            if !item.span.from_expansion();
-            if let ItemKind::Const(_, generics, _) = &item.kind;
+        if !item.span.from_expansion()
+            && let ItemKind::Const(_, generics, _) = &item.kind
             // Since static items may not have generics, skip generic const items.
             // FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it
             // doesn't account for empty where-clauses that only consist of keyword `where` IINM.
-            if generics.params.is_empty() && !generics.has_where_clause_predicates;
-            let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            if let ty::Array(element_type, cst) = ty.kind();
-            if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
-            if let Ok(element_count) = element_count.try_to_target_usize(cx.tcx);
-            if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
-            if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size);
-
-            then {
-                let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
-                let sugg_span = Span::new(
-                    hi_pos - BytePos::from_usize("const".len()),
-                    hi_pos,
-                    item.span.ctxt(),
-                    item.span.parent(),
-                );
-                span_lint_and_then(
-                    cx,
-                    LARGE_CONST_ARRAYS,
-                    item.span,
-                    "large array defined as const",
-                    |diag| {
-                        diag.span_suggestion(
-                            sugg_span,
-                            "make this a static item",
-                            "static",
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                );
-            }
+            && generics.params.is_empty() && !generics.has_where_clause_predicates
+            && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
+            && let ty::Array(element_type, cst) = ty.kind()
+            && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
+            && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
+            && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
+            && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size)
+        {
+            let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
+            let sugg_span = Span::new(
+                hi_pos - BytePos::from_usize("const".len()),
+                hi_pos,
+                item.span.ctxt(),
+                item.span.parent(),
+            );
+            span_lint_and_then(
+                cx,
+                LARGE_CONST_ARRAYS,
+                item.span,
+                "large array defined as const",
+                |diag| {
+                    diag.span_suggestion(
+                        sugg_span,
+                        "make this a static item",
+                        "static",
+                        Applicability::MachineApplicable,
+                    );
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs
index 566901de347..902b72ba5e4 100644
--- a/clippy_lints/src/large_include_file.rs
+++ b/clippy_lints/src/large_include_file.rs
@@ -50,37 +50,35 @@ impl_lint_pass!(LargeIncludeFile => [LARGE_INCLUDE_FILE]);
 
 impl LateLintPass<'_> for LargeIncludeFile {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
-        if_chain! {
-            if let Some(macro_call) = root_macro_call_first_node(cx, expr);
-            if !is_lint_allowed(cx, LARGE_INCLUDE_FILE, expr.hir_id);
-            if cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id)
-            || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id);
-            if let ExprKind::Lit(lit) = &expr.kind;
-            then {
-                let len = match &lit.node {
-                    // include_bytes
-                    LitKind::ByteStr(bstr, _) => bstr.len(),
-                    // include_str
-                    LitKind::Str(sym, _) => sym.as_str().len(),
-                    _ => return,
-                };
+        if let Some(macro_call) = root_macro_call_first_node(cx, expr)
+            && !is_lint_allowed(cx, LARGE_INCLUDE_FILE, expr.hir_id)
+            && (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id)
+                || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id))
+            && let ExprKind::Lit(lit) = &expr.kind
+        {
+            let len = match &lit.node {
+                // include_bytes
+                LitKind::ByteStr(bstr, _) => bstr.len(),
+                // include_str
+                LitKind::Str(sym, _) => sym.as_str().len(),
+                _ => return,
+            };
 
-                if len as u64 <= self.max_file_size {
-                    return;
-                }
-
-                span_lint_and_note(
-                    cx,
-                    LARGE_INCLUDE_FILE,
-                    expr.span,
-                    "attempted to include a large file",
-                    None,
-                    &format!(
-                        "the configuration allows a maximum size of {} bytes",
-                        self.max_file_size
-                    ),
-                );
+            if len as u64 <= self.max_file_size {
+                return;
             }
+
+            span_lint_and_note(
+                cx,
+                LARGE_INCLUDE_FILE,
+                expr.span,
+                "attempted to include a large file",
+                None,
+                &format!(
+                    "the configuration allows a maximum size of {} bytes",
+                    self.max_file_size
+                ),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 08f095859e5..305dd2c7f29 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -131,37 +130,33 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
-        if_chain! {
-            if item.ident.name == sym::len;
-            if let ImplItemKind::Fn(sig, _) = &item.kind;
-            if sig.decl.implicit_self.has_implicit_self();
-            if sig.decl.inputs.len() == 1;
-            if cx.effective_visibilities.is_exported(item.owner_id.def_id);
-            if matches!(sig.decl.output, FnRetTy::Return(_));
-            if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id());
-            if imp.of_trait.is_none();
-            if let TyKind::Path(ty_path) = &imp.self_ty.kind;
-            if let Some(ty_id) = cx.qpath_res(ty_path, imp.self_ty.hir_id).opt_def_id();
-            if let Some(local_id) = ty_id.as_local();
-            let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
-            if !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id);
-            if let Some(output) = parse_len_output(
-                cx,
-                cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder()
-            );
-            then {
-                let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
-                    Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
-                    Some(Node::Item(x)) => match x.kind {
-                        ItemKind::Struct(..) => (x.ident.name, "struct"),
-                        ItemKind::Enum(..) => (x.ident.name, "enum"),
-                        ItemKind::Union(..) => (x.ident.name, "union"),
-                        _ => (x.ident.name, "type"),
-                    }
-                    _ => return,
-                };
-                check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind)
-            }
+        if item.ident.name == sym::len
+            && let ImplItemKind::Fn(sig, _) = &item.kind
+            && sig.decl.implicit_self.has_implicit_self()
+            && sig.decl.inputs.len() == 1
+            && cx.effective_visibilities.is_exported(item.owner_id.def_id)
+            && matches!(sig.decl.output, FnRetTy::Return(_))
+            && let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id())
+            && imp.of_trait.is_none()
+            && let TyKind::Path(ty_path) = &imp.self_ty.kind
+            && 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.hir().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())
+        {
+            let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
+                Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
+                Some(Node::Item(x)) => match x.kind {
+                    ItemKind::Struct(..) => (x.ident.name, "struct"),
+                    ItemKind::Enum(..) => (x.ident.name, "enum"),
+                    ItemKind::Union(..) => (x.ident.name, "union"),
+                    _ => (x.ident.name, "type"),
+                },
+                _ => return,
+            };
+            check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind);
         }
     }
 
diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs
index 2f6f36c3960..da269ec61ff 100644
--- a/clippy_lints/src/let_if_seq.rs
+++ b/clippy_lints/src/let_if_seq.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::path_to_local_id;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::is_local_used;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{BindingAnnotation, Mutability};
@@ -61,76 +60,85 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
         let mut it = block.stmts.iter().peekable();
         while let Some(stmt) = it.next() {
-            if_chain! {
-                if let Some(expr) = it.peek();
-                if let hir::StmtKind::Local(local) = stmt.kind;
-                if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind;
-                if let hir::StmtKind::Expr(if_) = expr.kind;
-                if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind;
-                if !is_local_used(cx, *cond, canonical_id);
-                if let hir::ExprKind::Block(then, _) = then.kind;
-                if let Some(value) = check_assign(cx, canonical_id, then);
-                if !is_local_used(cx, value, canonical_id);
-                then {
-                    let span = stmt.span.to(if_.span);
+            if let Some(expr) = it.peek()
+                && let hir::StmtKind::Local(local) = stmt.kind
+                && let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind
+                && let hir::StmtKind::Expr(if_) = expr.kind
+                && let hir::ExprKind::If(
+                    hir::Expr {
+                        kind: hir::ExprKind::DropTemps(cond),
+                        ..
+                    },
+                    then,
+                    else_,
+                ) = if_.kind
+                && !is_local_used(cx, *cond, canonical_id)
+                && let hir::ExprKind::Block(then, _) = then.kind
+                && let Some(value) = check_assign(cx, canonical_id, then)
+                && !is_local_used(cx, value, canonical_id)
+            {
+                let span = stmt.span.to(if_.span);
 
-                    let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze(
-                        cx.tcx,
-                        cx.param_env,
-                    );
-                    if has_interior_mutability { return; }
+                let has_interior_mutability = !cx
+                    .typeck_results()
+                    .node_type(canonical_id)
+                    .is_freeze(cx.tcx, cx.param_env);
+                if has_interior_mutability {
+                    return;
+                }
 
-                    let (default_multi_stmts, default) = if let Some(else_) = else_ {
-                        if let hir::ExprKind::Block(else_, _) = else_.kind {
-                            if let Some(default) = check_assign(cx, canonical_id, else_) {
-                                (else_.stmts.len() > 1, default)
-                            } else if let Some(default) = local.init {
-                                (true, default)
-                            } else {
-                                continue;
-                            }
+                let (default_multi_stmts, default) = if let Some(else_) = else_ {
+                    if let hir::ExprKind::Block(else_, _) = else_.kind {
+                        if let Some(default) = check_assign(cx, canonical_id, else_) {
+                            (else_.stmts.len() > 1, default)
+                        } else if let Some(default) = local.init {
+                            (true, default)
                         } else {
                             continue;
                         }
-                    } else if let Some(default) = local.init {
-                        (false, default)
                     } else {
                         continue;
-                    };
+                    }
+                } else if let Some(default) = local.init {
+                    (false, default)
+                } else {
+                    continue;
+                };
 
-                    let mutability = match mode {
-                        BindingAnnotation(_, Mutability::Mut) => "<mut> ",
-                        _ => "",
-                    };
+                let mutability = match mode {
+                    BindingAnnotation(_, Mutability::Mut) => "<mut> ",
+                    _ => "",
+                };
 
-                    // FIXME: this should not suggest `mut` if we can detect that the variable is not
-                    // use mutably after the `if`
+                // FIXME: this should not suggest `mut` if we can detect that the variable is not
+                // use mutably after the `if`
 
-                    let sug = format!(
-                        "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
-                        name=ident.name,
-                        cond=snippet(cx, cond.span, "_"),
-                        then=if then.stmts.len() > 1 { " ..;" } else { "" },
-                        else=if default_multi_stmts { " ..;" } else { "" },
-                        value=snippet(cx, value.span, "<value>"),
-                        default=snippet(cx, default.span, "<default>"),
-                    );
-                    span_lint_and_then(cx,
-                                       USELESS_LET_IF_SEQ,
-                                       span,
-                                       "`if _ { .. } else { .. }` is an expression",
-                                       |diag| {
-                                           diag.span_suggestion(
-                                                span,
-                                                "it is more idiomatic to write",
-                                                sug,
-                                                Applicability::HasPlaceholders,
-                                            );
-                                           if !mutability.is_empty() {
-                                               diag.note("you might not need `mut` at all");
-                                           }
-                                       });
-                }
+                let sug = format!(
+                    "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
+                    name=ident.name,
+                    cond=snippet(cx, cond.span, "_"),
+                    then=if then.stmts.len() > 1 { " ..;" } else { "" },
+                    else=if default_multi_stmts { " ..;" } else { "" },
+                    value=snippet(cx, value.span, "<value>"),
+                    default=snippet(cx, default.span, "<default>"),
+                );
+                span_lint_and_then(
+                    cx,
+                    USELESS_LET_IF_SEQ,
+                    span,
+                    "`if _ { .. } else { .. }` is an expression",
+                    |diag| {
+                        diag.span_suggestion(
+                            span,
+                            "it is more idiomatic to write",
+                            sug,
+                            Applicability::HasPlaceholders,
+                        );
+                        if !mutability.is_empty() {
+                            diag.note("you might not need `mut` at all");
+                        }
+                    },
+                );
             }
         }
     }
@@ -141,20 +149,23 @@ fn check_assign<'tcx>(
     decl: hir::HirId,
     block: &'tcx hir::Block<'_>,
 ) -> Option<&'tcx hir::Expr<'tcx>> {
-    if_chain! {
-        if block.expr.is_none();
-        if let Some(expr) = block.stmts.iter().last();
-        if let hir::StmtKind::Semi(expr) = expr.kind;
-        if let hir::ExprKind::Assign(var, value, _) = expr.kind;
-        if path_to_local_id(var, decl);
-        then {
-            if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| is_local_used(cx, stmt, decl)) {
-                None
-            } else {
-                Some(value)
-            }
-        } else {
+    if block.expr.is_none()
+        && let Some(expr) = block.stmts.iter().last()
+        && let hir::StmtKind::Semi(expr) = expr.kind
+        && let hir::ExprKind::Assign(var, value, _) = expr.kind
+        && path_to_local_id(var, decl)
+    {
+        if block
+            .stmts
+            .iter()
+            .take(block.stmts.len() - 1)
+            .any(|stmt| is_local_used(cx, stmt, decl))
+        {
             None
+        } else {
+            Some(value)
         }
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs
index 79d728a021c..d4f410de957 100644
--- a/clippy_lints/src/let_with_type_underscore.rs
+++ b/clippy_lints/src/let_with_type_underscore.rs
@@ -27,27 +27,25 @@ declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]);
 
 impl LateLintPass<'_> for UnderscoreTyped {
     fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
-        if_chain! {
-            if !in_external_macro(cx.tcx.sess, local.span);
-            if let Some(ty) = local.ty; // Ensure that it has a type defined
-            if let TyKind::Infer = &ty.kind; // that type is '_'
-            if local.span.eq_ctxt(ty.span);
-            then {
-                // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized,
-                // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty`
-                if snippet(cx, ty.span, "_").trim() != "_" {
-                    return;
-                }
-
-                span_lint_and_help(
-                    cx,
-                    LET_WITH_TYPE_UNDERSCORE,
-                    local.span,
-                    "variable declared with type underscore",
-                    Some(ty.span.with_lo(local.pat.span.hi())),
-                    "remove the explicit type `_` declaration"
-                )
+        if !in_external_macro(cx.tcx.sess, local.span)
+            && let Some(ty) = local.ty // Ensure that it has a type defined
+            && let TyKind::Infer = &ty.kind // that type is '_'
+            && local.span.eq_ctxt(ty.span)
+        {
+            // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized,
+            // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty`
+            if snippet(cx, ty.span, "_").trim() != "_" {
+                return;
             }
+
+            span_lint_and_help(
+                cx,
+                LET_WITH_TYPE_UNDERSCORE,
+                local.span,
+                "variable declared with type underscore",
+                Some(ty.span.with_lo(local.pat.span.hi())),
+                "remove the explicit type `_` declaration",
+            );
         };
     }
 }
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index ab978a677c2..609ff3d051a 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -52,7 +52,6 @@ extern crate declare_clippy_lint;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::{Lint, LintId};
-use rustc_session::Session;
 
 #[cfg(feature = "internal")]
 pub mod deprecated_lints;
@@ -492,11 +491,83 @@ fn register_categories(store: &mut rustc_lint::LintStore) {
     groups.register(store);
 }
 
-/// Register all lints and lint groups with the rustc plugin registry
+/// Register all lints and lint groups with the rustc lint store
 ///
 /// Used in `./src/driver.rs`.
 #[expect(clippy::too_many_lines)]
-pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &'static Conf) {
+pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
+    let Conf {
+        ref absolute_paths_allowed_crates,
+        absolute_paths_max_segments,
+        accept_comment_above_attributes,
+        accept_comment_above_statement,
+        allow_dbg_in_tests,
+        allow_expect_in_tests,
+        allow_mixed_uninlined_format_args,
+        allow_one_hash_in_raw_strings,
+        allow_print_in_tests,
+        allow_private_module_inception,
+        allow_unwrap_in_tests,
+        ref allowed_dotfiles,
+        ref allowed_idents_below_min_chars,
+        ref allowed_scripts,
+        ref arithmetic_side_effects_allowed_binary,
+        ref arithmetic_side_effects_allowed_unary,
+        ref arithmetic_side_effects_allowed,
+        array_size_threshold,
+        avoid_breaking_exported_api,
+        ref await_holding_invalid_types,
+        cargo_ignore_publish,
+        cognitive_complexity_threshold,
+        ref disallowed_macros,
+        ref disallowed_methods,
+        ref disallowed_names,
+        ref disallowed_types,
+        ref doc_valid_idents,
+        enable_raw_pointer_heuristic_for_send,
+        enforce_iter_loop_reborrow,
+        ref enforced_import_renames,
+        enum_variant_name_threshold,
+        enum_variant_size_threshold,
+        excessive_nesting_threshold,
+        future_size_threshold,
+        ref ignore_interior_mutability,
+        large_error_threshold,
+        literal_representation_threshold,
+        matches_for_let_else,
+        max_fn_params_bools,
+        max_include_file_size,
+        max_struct_bools,
+        max_suggested_slice_pattern_length,
+        max_trait_bounds,
+        min_ident_chars_threshold,
+        missing_docs_in_crate_items,
+        ref msrv,
+        pass_by_value_size_limit,
+        semicolon_inside_block_ignore_singleline,
+        semicolon_outside_block_ignore_multiline,
+        single_char_binding_names_threshold,
+        stack_size_threshold,
+        ref standard_macro_braces,
+        struct_field_name_threshold,
+        suppress_restriction_lint_in_const,
+        too_large_for_stack,
+        too_many_arguments_threshold,
+        too_many_lines_threshold,
+        trivial_copy_size_limit,
+        type_complexity_threshold,
+        unnecessary_box_size,
+        unreadable_literal_lint_fractions,
+        upper_case_acronyms_aggressive,
+        vec_box_size_threshold,
+        verbose_bit_mask_threshold,
+        warn_on_all_wildcard_imports,
+
+        blacklisted_names: _,
+        cyclomatic_complexity_threshold: _,
+    } = *conf;
+    let msrv = || msrv.clone();
+
     register_removed_non_tool_lints(store);
     register_categories(store);
 
@@ -521,7 +592,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         store.register_late_pass(|_| {
             Box::new(utils::internal_lints::compiler_lint_functions::CompilerLintFunctions::new())
         });
-        store.register_late_pass(|_| Box::new(utils::internal_lints::if_chain_style::IfChainStyle));
         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()
@@ -537,9 +607,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         });
     }
 
-    let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
-    let arithmetic_side_effects_allowed_binary = conf.arithmetic_side_effects_allowed_binary.clone();
-    let arithmetic_side_effects_allowed_unary = conf.arithmetic_side_effects_allowed_unary.clone();
     store.register_late_pass(move |_| {
         Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(
             arithmetic_side_effects_allowed
@@ -557,16 +624,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::<utils::format_args_collector::FormatArgsCollector>::default());
     store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
     store.register_late_pass(|_| Box::new(utils::author::Author));
-    let await_holding_invalid_types = conf.await_holding_invalid_types.clone();
     store.register_late_pass(move |_| {
         Box::new(await_holding_invalid::AwaitHolding::new(
             await_holding_invalid_types.clone(),
         ))
     });
     store.register_late_pass(|_| Box::new(serde_api::SerdeApi));
-    let vec_box_size_threshold = conf.vec_box_size_threshold;
-    let type_complexity_threshold = conf.type_complexity_threshold;
-    let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
     store.register_late_pass(move |_| {
         Box::new(types::Types::new(
             vec_box_size_threshold,
@@ -599,19 +662,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
     store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
     store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
-
-    let msrv = || conf.msrv.clone();
-    let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
-    let allow_expect_in_tests = conf.allow_expect_in_tests;
-    let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
-    let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const;
     store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
-    let allowed_dotfiles = conf
-        .allowed_dotfiles
-        .iter()
-        .cloned()
-        .chain(methods::DEFAULT_ALLOWED_DOTFILES.iter().copied().map(ToOwned::to_owned))
-        .collect::<FxHashSet<_>>();
     store.register_late_pass(move |_| {
         Box::new(methods::Methods::new(
             avoid_breaking_exported_api,
@@ -622,7 +673,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv())));
-    let matches_for_let_else = conf.matches_for_let_else;
     store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv())));
     store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv())));
     store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv())));
@@ -639,7 +689,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv())));
     store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount));
     store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod));
-    let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length;
     store.register_late_pass(move |_| {
         Box::new(index_refutable_slice::IndexRefutableSlice::new(
             max_suggested_slice_pattern_length,
@@ -648,7 +697,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     store.register_late_pass(|_| Box::<shadow::Shadow>::default());
     store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
-    let enforce_iter_loop_reborrow = conf.enforce_iter_loop_reborrow;
     store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv(), enforce_iter_loop_reborrow)));
     store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
     store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
@@ -662,13 +710,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(no_effect::NoEffect));
     store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment));
     store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv())));
-    let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
     store.register_late_pass(move |_| {
         Box::new(cognitive_complexity::CognitiveComplexity::new(
             cognitive_complexity_threshold,
         ))
     });
-    let too_large_for_stack = conf.too_large_for_stack;
     store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack }));
     store.register_late_pass(move |_| {
         Box::new(vec::UselessVec {
@@ -684,18 +730,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
     store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
     store.register_late_pass(|_| Box::<regex::Regex>::default());
-    let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
     store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone())));
     store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));
     store.register_late_pass(|_| Box::new(format::UselessFormat));
     store.register_late_pass(|_| Box::new(swap::Swap));
     store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional));
     store.register_late_pass(|_| Box::<new_without_default::NewWithoutDefault>::default());
-    let disallowed_names = conf.disallowed_names.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone())));
-    let too_many_arguments_threshold = conf.too_many_arguments_threshold;
-    let too_many_lines_threshold = conf.too_many_lines_threshold;
-    let large_error_threshold = conf.large_error_threshold;
+    store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names)));
     store.register_late_pass(move |_| {
         Box::new(functions::Functions::new(
             too_many_arguments_threshold,
@@ -704,9 +745,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             avoid_breaking_exported_api,
         ))
     });
-    let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
-    let missing_docs_in_crate_items = conf.missing_docs_in_crate_items;
-    store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
+    store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents)));
     store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply));
     store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
     store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
@@ -716,17 +755,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk));
     store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl));
     store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount));
-    let enum_variant_size_threshold = conf.enum_variant_size_threshold;
     store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)));
     store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite));
     store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue));
-    let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
-        conf.trivial_copy_size_limit,
-        conf.pass_by_value_size_limit,
-        conf.avoid_breaking_exported_api,
-        &sess.target,
-    );
-    store.register_late_pass(move |_| Box::new(pass_by_ref_or_value));
+    store.register_late_pass(move |tcx| {
+        Box::new(pass_by_ref_or_value::PassByRefOrValue::new(
+            trivial_copy_size_limit,
+            pass_by_value_size_limit,
+            avoid_breaking_exported_api,
+            tcx.sess.target.pointer_width,
+        ))
+    });
     store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef));
     store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter));
     store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody));
@@ -746,7 +785,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             suppress_restriction_lint_in_const,
         ))
     });
-    let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
     store.register_late_pass(move |_| Box::new(non_copy_const::NonCopyConst::new(ignore_interior_mutability.clone())));
     store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
     store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
@@ -755,10 +793,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants));
     store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates));
     store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString));
-    let max_trait_bounds = conf.max_trait_bounds;
     store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv())));
     store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
-    let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
     store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
     store.register_early_pass(|| Box::new(reference::DerefAddrOf));
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
@@ -779,21 +815,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(redundant_else::RedundantElse));
     store.register_late_pass(|_| Box::new(create_dir::CreateDir));
     store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType));
-    let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
     store.register_early_pass(move || {
         Box::new(literal_representation::LiteralDigitGrouping::new(
-            literal_representation_lint_fraction_readability,
+            unreadable_literal_lint_fractions,
         ))
     });
-    let literal_representation_threshold = conf.literal_representation_threshold;
     store.register_early_pass(move || {
         Box::new(literal_representation::DecimalLiteralRepresentation::new(
             literal_representation_threshold,
         ))
     });
-    let enum_variant_name_threshold = conf.enum_variant_name_threshold;
-    let struct_field_name_threshold = conf.struct_field_name_threshold;
-    let allow_private_module_inception = conf.allow_private_module_inception;
     store.register_late_pass(move |_| {
         Box::new(item_name_repetitions::ItemNameRepetitions::new(
             enum_variant_name_threshold,
@@ -803,7 +834,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
-    let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
     store.register_late_pass(move |_| {
         Box::new(upper_case_acronyms::UpperCaseAcronyms::new(
             avoid_breaking_exported_api,
@@ -815,15 +845,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
     store.register_late_pass(|_| Box::new(exit::Exit));
     store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome));
-    let array_size_threshold = u128::from(conf.array_size_threshold);
-    store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
-    store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
+    store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold.into())));
+    store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold.into())));
     store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
     store.register_late_pass(|_| Box::new(as_conversions::AsConversions));
     store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
     store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default());
-    let max_fn_params_bools = conf.max_fn_params_bools;
-    let max_struct_bools = conf.max_struct_bools;
     store.register_late_pass(move |_| {
         Box::new(excessive_bools::ExcessiveBools::new(
             max_struct_bools,
@@ -831,36 +858,30 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
-    let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
     store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)));
     store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
     store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
     store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
     store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
-    let future_size_threshold = conf.future_size_threshold;
     store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(future_size_threshold)));
     store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex));
     store.register_late_pass(|_| Box::new(if_not_else::IfNotElse));
     store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality));
     store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn));
     store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn));
-    let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
     store.register_early_pass(move || {
         Box::new(non_expressive_names::NonExpressiveNames {
             single_char_binding_names_threshold,
         })
     });
-    let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(&macro_matcher)));
+    store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(standard_macro_braces)));
     store.register_late_pass(|_| Box::<macro_use::MacroUseImports>::default());
     store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch));
     store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult));
     store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned));
     store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync));
-    let disallowed_macros = conf.disallowed_macros.clone();
     store.register_late_pass(move |_| Box::new(disallowed_macros::DisallowedMacros::new(disallowed_macros.clone())));
-    let disallowed_methods = conf.disallowed_methods.clone();
     store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
@@ -875,36 +896,30 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison));
     store.register_early_pass(move || Box::new(module_style::ModStyle));
     store.register_late_pass(|_| Box::<unused_async::UnusedAsync>::default());
-    let disallowed_types = conf.disallowed_types.clone();
     store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone())));
-    let import_renames = conf.enforced_import_renames.clone();
     store.register_late_pass(move |_| {
         Box::new(missing_enforced_import_rename::ImportRename::new(
-            import_renames.clone(),
+            enforced_import_renames.clone(),
         ))
     });
-    let scripts = conf.allowed_scripts.clone();
-    store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts)));
+    store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(allowed_scripts)));
     store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings));
     store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors));
     store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator));
     store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert));
-    let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
     store.register_late_pass(move |_| {
         Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(
             enable_raw_pointer_heuristic_for_send,
         ))
     });
-    let accept_comment_above_statement = conf.accept_comment_above_statement;
-    let accept_comment_above_attributes = conf.accept_comment_above_attributes;
     store.register_late_pass(move |_| {
         Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(
             accept_comment_above_statement,
             accept_comment_above_attributes,
         ))
     });
-    let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args;
-    store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined)));
+    store
+        .register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined_format_args)));
     store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
     store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
     store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit));
@@ -914,11 +929,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv())));
     store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
     store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
-    let allow_dbg_in_tests = conf.allow_dbg_in_tests;
     store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
-    let allow_print_in_tests = conf.allow_print_in_tests;
     store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests)));
-    let cargo_ignore_publish = conf.cargo_ignore_publish;
     store.register_late_pass(move |_| {
         Box::new(cargo::Cargo {
             ignore_publish: cargo_ignore_publish,
@@ -929,7 +941,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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));
-    let max_include_file_size = conf.max_include_file_size;
     store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size)));
     store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace));
     store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
@@ -942,7 +953,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
     store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv())));
     store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv())));
-    let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
     store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
     store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
     store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
@@ -959,8 +969,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
     store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
     store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
-    let semicolon_inside_block_ignore_singleline = conf.semicolon_inside_block_ignore_singleline;
-    let semicolon_outside_block_ignore_multiline = conf.semicolon_outside_block_ignore_multiline;
     store.register_late_pass(move |_| {
         Box::new(semicolon_block::SemicolonBlock::new(
             semicolon_inside_block_ignore_singleline,
@@ -983,7 +991,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
     store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
     store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
-    let unnecessary_box_size = conf.unnecessary_box_size;
     store.register_late_pass(move |_| {
         Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(
             avoid_breaking_exported_api,
@@ -994,7 +1001,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
     store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
     store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
-    let excessive_nesting_threshold = conf.excessive_nesting_threshold;
     store.register_early_pass(move || {
         Box::new(excessive_nesting::ExcessiveNesting {
             excessive_nesting_threshold,
@@ -1010,15 +1016,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations));
     store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync));
     store.register_late_pass(|_| Box::new(needless_if::NeedlessIf));
-    let allowed_idents_below_min_chars = conf.allowed_idents_below_min_chars.clone();
-    let min_ident_chars_threshold = conf.min_ident_chars_threshold;
     store.register_late_pass(move |_| {
         Box::new(min_ident_chars::MinIdentChars {
             allowed_idents_below_min_chars: allowed_idents_below_min_chars.clone(),
             min_ident_chars_threshold,
         })
     });
-    let stack_size_threshold = conf.stack_size_threshold;
     store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold)));
     store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit));
     store.register_late_pass(move |_| {
@@ -1033,10 +1036,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(),
         })
     });
-    let needless_raw_string_hashes_allow_one = conf.allow_one_hash_in_raw_strings;
     store.register_early_pass(move || {
         Box::new(raw_strings::RawStrings {
-            needless_raw_string_hashes_allow_one,
+            allow_one_hash_in_raw_strings,
         })
     });
     store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns));
@@ -1045,8 +1047,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(manual_float_methods::ManualFloatMethods));
     store.register_late_pass(|_| Box::new(four_forward_slashes::FourForwardSlashes));
     store.register_late_pass(|_| Box::new(error_impl_error::ErrorImplError));
-    let absolute_paths_max_segments = conf.absolute_paths_max_segments;
-    let absolute_paths_allowed_crates = conf.absolute_paths_allowed_crates.clone();
     store.register_late_pass(move |_| {
         Box::new(absolute_paths::AbsolutePaths {
             absolute_paths_max_segments,
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index 4b89c0fa361..b190955d54c 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -310,20 +310,17 @@ fn elision_suggestions(
 
 // elision doesn't work for explicit self types, see rust-lang/rust#69064
 fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
-    if_chain! {
-        if let Some(ident) = ident;
-        if ident.name == kw::SelfLower;
-        if !func.implicit_self.has_implicit_self();
-
-        if let Some(self_ty) = func.inputs.first();
-        then {
-            let mut visitor = RefVisitor::new(cx);
-            visitor.visit_ty(self_ty);
-
-            !visitor.all_lts().is_empty()
-        } else {
-            false
-        }
+    if let Some(ident) = ident
+        && ident.name == kw::SelfLower
+        && !func.implicit_self.has_implicit_self()
+        && let Some(self_ty) = func.inputs.first()
+    {
+        let mut visitor = RefVisitor::new(cx);
+        visitor.visit_ty(self_ty);
+
+        !visitor.all_lts().is_empty()
+    } else {
+        false
     }
 }
 
diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index 2c14bb72a9e..8f34a9b1fed 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/clippy_lints/src/literal_representation.rs
@@ -4,7 +4,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::{NumericLiteral, Radix};
 use clippy_utils::source::snippet_opt;
-use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, LitKind};
 use rustc_ast::token;
 use rustc_errors::Applicability;
@@ -255,56 +254,48 @@ impl LiteralDigitGrouping {
     }
 
     fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
-        if_chain! {
-            if let Some(src) = snippet_opt(cx, span);
-            if let Ok(lit_kind) = LitKind::from_token_lit(lit);
-            if let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind);
-            then {
-                if !Self::check_for_mistyped_suffix(cx, span, &mut num_lit) {
-                    return;
-                }
+        if let Some(src) = snippet_opt(cx, span)
+            && let Ok(lit_kind) = LitKind::from_token_lit(lit)
+            && let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
+        {
+            if !Self::check_for_mistyped_suffix(cx, span, &mut num_lit) {
+                return;
+            }
+
+            if Self::is_literal_uuid_formatted(&num_lit) {
+                return;
+            }
 
-                if Self::is_literal_uuid_formatted(&num_lit) {
-                    return;
+            let result = (|| {
+                let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?;
+                if let Some(fraction) = num_lit.fraction {
+                    let fractional_group_size =
+                        Self::get_group_size(fraction.rsplit('_'), num_lit.radix, self.lint_fraction_readability)?;
+
+                    let consistent = Self::parts_consistent(
+                        integral_group_size,
+                        fractional_group_size,
+                        num_lit.integer.len(),
+                        fraction.len(),
+                    );
+                    if !consistent {
+                        return Err(WarningType::InconsistentDigitGrouping);
+                    };
                 }
 
-                let result = (|| {
-
-                    let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?;
-                    if let Some(fraction) = num_lit.fraction {
-                        let fractional_group_size = Self::get_group_size(
-                            fraction.rsplit('_'),
-                            num_lit.radix,
-                            self.lint_fraction_readability)?;
-
-                        let consistent = Self::parts_consistent(integral_group_size,
-                                                                fractional_group_size,
-                                                                num_lit.integer.len(),
-                                                                fraction.len());
-                        if !consistent {
-                            return Err(WarningType::InconsistentDigitGrouping);
-                        };
-                    }
+                Ok(())
+            })();
 
-                    Ok(())
-                })();
-
-
-                if let Err(warning_type) = result {
-                    let should_warn = match warning_type {
-                        | WarningType::UnreadableLiteral
-                        | WarningType::InconsistentDigitGrouping
-                        | WarningType::UnusualByteGroupings
-                        | WarningType::LargeDigitGroups => {
-                            !span.from_expansion()
-                        }
-                        WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => {
-                            true
-                        }
-                    };
-                    if should_warn {
-                        warning_type.display(num_lit.format(), cx, span);
-                    }
+            if let Err(warning_type) = result {
+                let should_warn = match warning_type {
+                    WarningType::UnreadableLiteral
+                    | WarningType::InconsistentDigitGrouping
+                    | WarningType::UnusualByteGroupings
+                    | WarningType::LargeDigitGroups => !span.from_expansion(),
+                    WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => true,
+                };
+                if should_warn {
+                    warning_type.display(num_lit.format(), cx, span);
                 }
             }
         }
@@ -478,20 +469,18 @@ impl DecimalLiteralRepresentation {
     }
     fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
         // Lint integral literals.
-        if_chain! {
-            if let Ok(lit_kind) = LitKind::from_token_lit(lit);
-            if let LitKind::Int(val, _) = lit_kind;
-            if let Some(src) = snippet_opt(cx, span);
-            if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind);
-            if num_lit.radix == Radix::Decimal;
-            if val >= u128::from(self.threshold);
-            then {
-                let hex = format!("{val:#X}");
-                let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
-                let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
-                    warning_type.display(num_lit.format(), cx, span);
-                });
-            }
+        if let Ok(lit_kind) = LitKind::from_token_lit(lit)
+            && let LitKind::Int(val, _) = lit_kind
+            && let Some(src) = snippet_opt(cx, span)
+            && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
+            && num_lit.radix == Radix::Decimal
+            && val >= u128::from(self.threshold)
+        {
+            let hex = format!("{val:#X}");
+            let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
+            let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
+                warning_type.display(num_lit.format(), cx, span);
+            });
         }
     }
 
diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs
index 1953ee8a717..277062a8490 100644
--- a/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -2,7 +2,6 @@ use super::{make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{get_enclosing_block, is_integer_const};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr};
 use rustc_hir::{Expr, Pat};
@@ -30,59 +29,57 @@ pub(super) fn check<'tcx>(
             let mut initialize_visitor = InitializeVisitor::new(cx, expr, id);
             walk_block(&mut initialize_visitor, block);
 
-            if_chain! {
-                if let Some((name, ty, initializer)) = initialize_visitor.get_result();
-                if is_integer_const(cx, initializer, 0);
-                then {
-                    let mut applicability = Applicability::MaybeIncorrect;
-                    let span = expr.span.with_hi(arg.span.hi());
+            if let Some((name, ty, initializer)) = initialize_visitor.get_result()
+                && is_integer_const(cx, initializer, 0)
+            {
+                let mut applicability = Applicability::MaybeIncorrect;
+                let span = expr.span.with_hi(arg.span.hi());
 
-                    let int_name = match ty.map(Ty::kind) {
-                        // usize or inferred
-                        Some(ty::Uint(UintTy::Usize)) | None => {
-                            span_lint_and_sugg(
-                                cx,
-                                EXPLICIT_COUNTER_LOOP,
-                                span,
-                                &format!("the variable `{name}` is used as a loop counter"),
-                                "consider using",
-                                format!(
-                                    "for ({name}, {}) in {}.enumerate()",
-                                    snippet_with_applicability(cx, pat.span, "item", &mut applicability),
-                                    make_iterator_snippet(cx, arg, &mut applicability),
-                                ),
-                                applicability,
-                            );
-                            return;
-                        }
-                        Some(ty::Int(int_ty)) => int_ty.name_str(),
-                        Some(ty::Uint(uint_ty)) => uint_ty.name_str(),
-                        _ => return,
-                    };
+                let int_name = match ty.map(Ty::kind) {
+                    // usize or inferred
+                    Some(ty::Uint(UintTy::Usize)) | None => {
+                        span_lint_and_sugg(
+                            cx,
+                            EXPLICIT_COUNTER_LOOP,
+                            span,
+                            &format!("the variable `{name}` is used as a loop counter"),
+                            "consider using",
+                            format!(
+                                "for ({name}, {}) in {}.enumerate()",
+                                snippet_with_applicability(cx, pat.span, "item", &mut applicability),
+                                make_iterator_snippet(cx, arg, &mut applicability),
+                            ),
+                            applicability,
+                        );
+                        return;
+                    },
+                    Some(ty::Int(int_ty)) => int_ty.name_str(),
+                    Some(ty::Uint(uint_ty)) => uint_ty.name_str(),
+                    _ => return,
+                };
 
-                    span_lint_and_then(
-                        cx,
-                        EXPLICIT_COUNTER_LOOP,
-                        span,
-                        &format!("the variable `{name}` is used as a loop counter"),
-                        |diag| {
-                            diag.span_suggestion(
-                                span,
-                                "consider using",
-                                format!(
-                                    "for ({name}, {}) in (0_{int_name}..).zip({})",
-                                    snippet_with_applicability(cx, pat.span, "item", &mut applicability),
-                                    make_iterator_snippet(cx, arg, &mut applicability),
-                                ),
-                                applicability,
-                            );
+                span_lint_and_then(
+                    cx,
+                    EXPLICIT_COUNTER_LOOP,
+                    span,
+                    &format!("the variable `{name}` is used as a loop counter"),
+                    |diag| {
+                        diag.span_suggestion(
+                            span,
+                            "consider using",
+                            format!(
+                                "for ({name}, {}) in (0_{int_name}..).zip({})",
+                                snippet_with_applicability(cx, pat.span, "item", &mut applicability),
+                                make_iterator_snippet(cx, arg, &mut applicability),
+                            ),
+                            applicability,
+                        );
 
-                            diag.note(format!(
-                                "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
-                            ));
-                        },
-                    );
-                }
+                        diag.note(format!(
+                            "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
+                        ));
+                    },
+                );
             }
         }
     }
diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs
index 0aaa66e6bce..c6c16f4673f 100644
--- a/clippy_lints/src/loops/manual_find.rs
+++ b/clippy_lints/src/loops/manual_find.rs
@@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::lang_items::LangItem;
@@ -23,77 +22,79 @@ pub(super) fn check<'tcx>(
     let inner_expr = peel_blocks_with_stmt(body);
     // Check for the specific case that the result is returned and optimize suggestion for that (more
     // cases can be added later)
-    if_chain! {
-        if let Some(higher::If { cond, then, r#else: None, }) = higher::If::hir(inner_expr);
-        if let Some(binding_id) = get_binding(pat);
-        if let ExprKind::Block(block, _) = then.kind;
-        if let [stmt] = block.stmts;
-        if let StmtKind::Semi(semi) = stmt.kind;
-        if let ExprKind::Ret(Some(ret_value)) = semi.kind;
-        if let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind;
-        if is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome);
-        if path_res(cx, inner_ret) == Res::Local(binding_id);
-        if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let mut snippet = make_iterator_snippet(cx, arg, &mut applicability);
-            // Checks if `pat` is a single reference to a binding (`&x`)
-            let is_ref_to_binding =
-                matches!(pat.kind, PatKind::Ref(inner, _) if matches!(inner.kind, PatKind::Binding(..)));
-            // If `pat` is not a binding or a reference to a binding (`x` or `&x`)
-            // we need to map it to the binding returned by the function (i.e. `.map(|(x, _)| x)`)
-            if !(matches!(pat.kind, PatKind::Binding(..)) || is_ref_to_binding) {
-                snippet.push_str(
-                    &format!(
-                        ".map(|{}| {})",
-                        snippet_with_applicability(cx, pat.span, "..", &mut applicability),
-                        snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability),
-                    )[..],
-                );
-            }
-            let ty = cx.typeck_results().expr_ty(inner_ret);
-            if cx.tcx.lang_items().copy_trait().map_or(false, |id| implements_trait(cx, ty, id, &[])) {
-                snippet.push_str(
-                    &format!(
-                        ".find(|{}{}| {})",
-                        "&".repeat(1 + usize::from(is_ref_to_binding)),
-                        snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability),
-                        snippet_with_applicability(cx, cond.span, "..", &mut applicability),
-                    )[..],
-                );
-                if is_ref_to_binding {
-                    snippet.push_str(".copied()");
-                }
-            } else {
-                applicability = Applicability::MaybeIncorrect;
-                snippet.push_str(
-                    &format!(
-                        ".find(|{}| {})",
-                        snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability),
-                        snippet_with_applicability(cx, cond.span, "..", &mut applicability),
-                    )[..],
-                );
+    if let Some(higher::If {
+        cond,
+        then,
+        r#else: None,
+    }) = higher::If::hir(inner_expr)
+        && let Some(binding_id) = get_binding(pat)
+        && let ExprKind::Block(block, _) = then.kind
+        && let [stmt] = block.stmts
+        && let StmtKind::Semi(semi) = stmt.kind
+        && let ExprKind::Ret(Some(ret_value)) = semi.kind
+        && 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)
+        && let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let mut snippet = make_iterator_snippet(cx, arg, &mut applicability);
+        // Checks if `pat` is a single reference to a binding (`&x`)
+        let is_ref_to_binding =
+            matches!(pat.kind, PatKind::Ref(inner, _) if matches!(inner.kind, PatKind::Binding(..)));
+        // If `pat` is not a binding or a reference to a binding (`x` or `&x`)
+        // we need to map it to the binding returned by the function (i.e. `.map(|(x, _)| x)`)
+        if !(matches!(pat.kind, PatKind::Binding(..)) || is_ref_to_binding) {
+            snippet.push_str(
+                &format!(
+                    ".map(|{}| {})",
+                    snippet_with_applicability(cx, pat.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability),
+                )[..],
+            );
+        }
+        let ty = cx.typeck_results().expr_ty(inner_ret);
+        if cx
+            .tcx
+            .lang_items()
+            .copy_trait()
+            .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+        {
+            snippet.push_str(
+                &format!(
+                    ".find(|{}{}| {})",
+                    "&".repeat(1 + usize::from(is_ref_to_binding)),
+                    snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, cond.span, "..", &mut applicability),
+                )[..],
+            );
+            if is_ref_to_binding {
+                snippet.push_str(".copied()");
             }
-            // Extends to `last_stmt` to include semicolon in case of `return None;`
-            let lint_span = span.to(last_stmt.span).to(last_ret.span);
-            span_lint_and_then(
-                cx,
-                MANUAL_FIND,
-                lint_span,
-                "manual implementation of `Iterator::find`",
-                |diag| {
-                    if applicability == Applicability::MaybeIncorrect {
-                        diag.note("you may need to dereference some variables");
-                    }
-                    diag.span_suggestion(
-                        lint_span,
-                        "replace with an iterator",
-                        snippet,
-                        applicability,
-                    );
-                },
+        } else {
+            applicability = Applicability::MaybeIncorrect;
+            snippet.push_str(
+                &format!(
+                    ".find(|{}| {})",
+                    snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability),
+                    snippet_with_applicability(cx, cond.span, "..", &mut applicability),
+                )[..],
             );
         }
+        // Extends to `last_stmt` to include semicolon in case of `return None;`
+        let lint_span = span.to(last_stmt.span).to(last_ret.span);
+        span_lint_and_then(
+            cx,
+            MANUAL_FIND,
+            lint_span,
+            "manual implementation of `Iterator::find`",
+            |diag| {
+                if applicability == Applicability::MaybeIncorrect {
+                    diag.note("you may need to dereference some variables");
+                }
+                diag.span_suggestion(lint_span, "replace with an iterator", snippet, applicability);
+            },
+        );
     }
 }
 
@@ -124,34 +125,30 @@ fn last_stmt_and_ret<'tcx>(
             if let Some(ret) = block.expr {
                 return Some((last_stmt, ret));
             }
-            if_chain! {
-                if let [.., snd_last, _] = block.stmts;
-                if let StmtKind::Semi(last_expr) = last_stmt.kind;
-                if let ExprKind::Ret(Some(ret)) = last_expr.kind;
-                then {
-                    return Some((snd_last, ret));
-                }
+            if let [.., snd_last, _] = block.stmts
+                && let StmtKind::Semi(last_expr) = last_stmt.kind
+                && let ExprKind::Ret(Some(ret)) = last_expr.kind
+            {
+                return Some((snd_last, ret));
             }
         }
         None
     }
     let mut parent_iter = cx.tcx.hir().parent_iter(expr.hir_id);
-    if_chain! {
+    if let Some((node_hir, Node::Stmt(..))) = parent_iter.next()
         // This should be the loop
-        if let Some((node_hir, Node::Stmt(..))) = parent_iter.next();
         // This should be the function body
-        if let Some((_, Node::Block(block))) = parent_iter.next();
-        if let Some((last_stmt, last_ret)) = extract(block);
-        if last_stmt.hir_id == node_hir;
-        if is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone);
-        if let Some((_, Node::Expr(_block))) = parent_iter.next();
+        && let Some((_, Node::Block(block))) = parent_iter.next()
+        && let Some((last_stmt, last_ret)) = extract(block)
+        && last_stmt.hir_id == node_hir
+        && is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone)
+        && let Some((_, Node::Expr(_block))) = parent_iter.next()
         // This includes the function header
-        if let Some((_, func)) = parent_iter.next();
-        if func.fn_kind().is_some();
-        then {
-            Some((block.stmts.last().unwrap(), last_ret))
-        } else {
-            None
-        }
+        && let Some((_, func)) = parent_iter.next()
+        && func.fn_kind().is_some()
+    {
+        Some((block.stmts.last().unwrap(), last_ret))
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs
index 559a2c03f14..de4e13bd84f 100644
--- a/clippy_lints/src/loops/manual_flatten.rs
+++ b/clippy_lints/src/loops/manual_flatten.rs
@@ -3,7 +3,6 @@ use super::MANUAL_FLATTEN;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, Pat, PatKind};
@@ -21,66 +20,51 @@ pub(super) fn check<'tcx>(
     span: Span,
 ) {
     let inner_expr = peel_blocks_with_stmt(body);
-    if_chain! {
-        if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None })
-            = higher::IfLet::hir(cx, inner_expr);
+    if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None })
+            = higher::IfLet::hir(cx, inner_expr)
         // Ensure match_expr in `if let` statement is the same as the pat from the for-loop
-        if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind;
-        if path_to_local_id(let_expr, pat_hir_id);
+        && let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind
+        && path_to_local_id(let_expr, pat_hir_id)
         // Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
-        if let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind;
-        if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id);
-        if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
-        let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id);
-        let ok_ctor = cx.tcx.lang_items().result_ok_variant() == Some(variant_id);
-        if some_ctor || ok_ctor;
+        && let PatKind::TupleStruct(ref qpath, _, _) = 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)
+        && let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id)
+        && let ok_ctor = cx.tcx.lang_items().result_ok_variant() == Some(variant_id)
+        && (some_ctor || ok_ctor)
         // Ensure expr in `if let` is not used afterwards
-        if !is_local_used(cx, if_then, pat_hir_id);
-        then {
-            let if_let_type = if some_ctor { "Some" } else { "Ok" };
-            // Prepare the error message
-            let msg = format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used");
+        && !is_local_used(cx, if_then, pat_hir_id)
+    {
+        let if_let_type = if some_ctor { "Some" } else { "Ok" };
+        // Prepare the error message
+        let msg =
+            format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used");
 
-            // Prepare the help message
-            let mut applicability = Applicability::MaybeIncorrect;
-            let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability);
-            let copied = match cx.typeck_results().expr_ty(let_expr).kind() {
-                ty::Ref(_, inner, _) => match inner.kind() {
-                    ty::Ref(..) => ".copied()",
-                    _ => ""
-                }
-                _ => ""
-            };
+        // Prepare the help message
+        let mut applicability = Applicability::MaybeIncorrect;
+        let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability);
+        let copied = match cx.typeck_results().expr_ty(let_expr).kind() {
+            ty::Ref(_, inner, _) => match inner.kind() {
+                ty::Ref(..) => ".copied()",
+                _ => "",
+            },
+            _ => "",
+        };
 
-            let sugg = format!("{arg_snippet}{copied}.flatten()");
+        let sugg = format!("{arg_snippet}{copied}.flatten()");
 
-            // If suggestion is not a one-liner, it won't be shown inline within the error message. In that case,
-            // it will be shown in the extra `help` message at the end, which is why the first `help_msg` needs
-            // to refer to the correct relative position of the suggestion.
-            let help_msg = if sugg.contains('\n') {
-                "remove the `if let` statement in the for loop and then..."
-            } else {
-                "...and remove the `if let` statement in the for loop"
-            };
+        // If suggestion is not a one-liner, it won't be shown inline within the error message. In that
+        // case, it will be shown in the extra `help` message at the end, which is why the first
+        // `help_msg` needs to refer to the correct relative position of the suggestion.
+        let help_msg = if sugg.contains('\n') {
+            "remove the `if let` statement in the for loop and then..."
+        } else {
+            "...and remove the `if let` statement in the for loop"
+        };
 
-            span_lint_and_then(
-                cx,
-                MANUAL_FLATTEN,
-                span,
-                &msg,
-                |diag| {
-                    diag.span_suggestion(
-                        arg.span,
-                        "try",
-                        sugg,
-                        applicability,
-                    );
-                    diag.span_help(
-                        inner_expr.span,
-                        help_msg,
-                    );
-                }
-            );
-        }
+        span_lint_and_then(cx, MANUAL_FLATTEN, span, &msg, |diag| {
+            diag.span_suggestion(arg.span, "try", sugg, applicability);
+            diag.span_help(inner_expr.span, help_msg);
+        });
     }
 }
diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs
index d3fd0e8639e..89f70519c20 100644
--- a/clippy_lints/src/loops/manual_memcpy.rs
+++ b/clippy_lints/src/loops/manual_memcpy.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::snippet;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_copy;
 use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::walk_block;
@@ -59,22 +58,31 @@ pub(super) fn check<'tcx>(
                 .map(|o| {
                     o.and_then(|(lhs, rhs)| {
                         let rhs = fetch_cloned_expr(rhs);
-                        if_chain! {
-                            if let ExprKind::Index(base_left, idx_left, _) = lhs.kind;
-                            if let ExprKind::Index(base_right, idx_right, _) = rhs.kind;
-                            if let Some(ty) = get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_left));
-                            if get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some();
-                            if let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts);
-                            if let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts);
+                        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()
+                            && let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts)
+                            && let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts)
 
                             // Source and destination must be different
-                            if path_to_local(base_left) != path_to_local(base_right);
-                            then {
-                                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
-                            }
+                            && 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
                         }
                     })
                 })
@@ -118,23 +126,19 @@ fn build_manual_memcpy_suggestion<'tcx>(
     }
 
     let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| {
-        if_chain! {
-            if let ExprKind::MethodCall(method, recv, [], _) = end.kind;
-            if method.ident.name == sym::len;
-            if path_to_local(recv) == path_to_local(base);
-            then {
-                if sugg.to_string() == end_str {
-                    sugg::EMPTY.into()
-                } else {
-                    sugg
-                }
+        if let ExprKind::MethodCall(method, recv, [], _) = end.kind
+            && method.ident.name == sym::len
+            && path_to_local(recv) == path_to_local(base)
+        {
+            if sugg.to_string() == end_str {
+                sugg::EMPTY.into()
             } else {
-                match limits {
-                    ast::RangeLimits::Closed => {
-                        sugg + &sugg::ONE.into()
-                    },
-                    ast::RangeLimits::HalfOpen => sugg,
-                }
+                sugg
+            }
+        } else {
+            match limits {
+                ast::RangeLimits::Closed => sugg + &sugg::ONE.into(),
+                ast::RangeLimits::HalfOpen => sugg,
             }
         }
     };
@@ -331,10 +335,12 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti
 }
 
 fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
-    if_chain! {
-        if let ExprKind::MethodCall(method, arg, [], _) = expr.kind;
-        if method.ident.name == sym::clone;
-        then { arg } else { expr }
+    if let ExprKind::MethodCall(method, arg, [], _) = expr.kind
+        && method.ident.name == sym::clone
+    {
+        arg
+    } else {
+        expr
     }
 }
 
diff --git a/clippy_lints/src/loops/missing_spin_loop.rs b/clippy_lints/src/loops/missing_spin_loop.rs
index 7b7d19c753f..e405829b2f4 100644
--- a/clippy_lints/src/loops/missing_spin_loop.rs
+++ b/clippy_lints/src/loops/missing_spin_loop.rs
@@ -31,26 +31,30 @@ fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
 }
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind;
-        if let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind;
-        if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name);
-        if let ty::Adt(def, _args) = cx.typeck_results().expr_ty(callee).kind();
-        if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did());
-        then {
-            span_lint_and_sugg(
-                cx,
-                MISSING_SPIN_LOOP,
-                body.span,
-                "busy-waiting loop should at least have a spin loop hint",
-                "try",
-                (if is_no_std_crate(cx) {
-                    "{ core::hint::spin_loop() }"
-                } else {
-                    "{ std::hint::spin_loop() }"
-                }).into(),
-                Applicability::MachineApplicable
-            );
-        }
+    if let ExprKind::Block(
+        Block {
+            stmts: [], expr: None, ..
+        },
+        _,
+    ) = body.kind
+        && let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind
+        && [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name)
+        && let ty::Adt(def, _args) = cx.typeck_results().expr_ty(callee).kind()
+        && cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did())
+    {
+        span_lint_and_sugg(
+            cx,
+            MISSING_SPIN_LOOP,
+            body.span,
+            "busy-waiting loop should at least have a spin loop hint",
+            "try",
+            (if is_no_std_crate(cx) {
+                "{ core::hint::spin_loop() }"
+            } else {
+                "{ std::hint::spin_loop() }"
+            })
+            .into(),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs
index b83d148b5f2..6e3477a1c76 100644
--- a/clippy_lints/src/loops/mut_range_bound.rs
+++ b/clippy_lints/src/loops/mut_range_bound.rs
@@ -1,7 +1,6 @@
 use super::MUT_RANGE_BOUND;
 use clippy_utils::diagnostics::span_lint_and_note;
 use clippy_utils::{get_enclosing_block, higher, path_to_local};
-use if_chain::if_chain;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@@ -12,19 +11,17 @@ use rustc_middle::ty;
 use rustc_span::source_map::Span;
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
-    if_chain! {
-        if let Some(higher::Range {
-            start: Some(start),
-            end: Some(end),
-            ..
-        }) = higher::Range::hir(arg);
-        let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end));
-        if mut_id_start.is_some() || mut_id_end.is_some();
-        then {
-            let (span_low, span_high) = check_for_mutation(cx, body, mut_id_start, mut_id_end);
-            mut_warn_with_span(cx, span_low);
-            mut_warn_with_span(cx, span_high);
-        }
+    if let Some(higher::Range {
+        start: Some(start),
+        end: Some(end),
+        ..
+    }) = higher::Range::hir(arg)
+        && let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end))
+        && (mut_id_start.is_some() || mut_id_end.is_some())
+    {
+        let (span_low, span_high) = check_for_mutation(cx, body, mut_id_start, mut_id_end);
+        mut_warn_with_span(cx, span_low);
+        mut_warn_with_span(cx, span_high);
     }
 }
 
@@ -42,13 +39,11 @@ fn mut_warn_with_span(cx: &LateContext<'_>, span: Option<Span>) {
 }
 
 fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId> {
-    if_chain! {
-        if let Some(hir_id) = path_to_local(bound);
-        if let Node::Pat(pat) = cx.tcx.hir().get(hir_id);
-        if let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind;
-        then {
-            return Some(hir_id);
-        }
+    if let Some(hir_id) = path_to_local(bound)
+        && let Node::Pat(pat) = cx.tcx.hir().get(hir_id)
+        && let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind
+    {
+        return Some(hir_id);
     }
     None
 }
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index c4af46b8fd3..e2be861a708 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::snippet;
 use clippy_utils::ty::has_iter_method;
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{DefKind, Res};
@@ -187,15 +186,13 @@ pub(super) fn check<'tcx>(
 }
 
 fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
-    if_chain! {
-        if let ExprKind::MethodCall(method, recv, [], _) = expr.kind;
-        if method.ident.name == sym::len;
-        if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind;
-        if path.segments.len() == 1;
-        if path.segments[0].ident.name == var;
-        then {
-            return true;
-        }
+    if let ExprKind::MethodCall(method, recv, [], _) = expr.kind
+        && method.ident.name == sym::len
+        && let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind
+        && path.segments.len() == 1
+        && path.segments[0].ident.name == var
+    {
+        return true;
     }
 
     false
@@ -207,17 +204,15 @@ fn is_end_eq_array_len<'tcx>(
     limits: ast::RangeLimits,
     indexed_ty: Ty<'tcx>,
 ) -> bool {
-    if_chain! {
-        if let ExprKind::Lit(lit) = end.kind;
-        if let ast::LitKind::Int(end_int, _) = lit.node;
-        if let ty::Array(_, arr_len_const) = indexed_ty.kind();
-        if let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env);
-        then {
-            return match limits {
-                ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
-                ast::RangeLimits::HalfOpen => end_int >= arr_len.into(),
-            };
-        }
+    if let ExprKind::Lit(lit) = end.kind
+        && let ast::LitKind::Int(end_int, _) = lit.node
+        && let ty::Array(_, arr_len_const) = indexed_ty.kind()
+        && let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env)
+    {
+        return match limits {
+            ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
+            ast::RangeLimits::HalfOpen => end_int >= arr_len.into(),
+        };
     }
 
     false
@@ -248,51 +243,49 @@ struct VarVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
     fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) -> bool {
-        if_chain! {
+        if let ExprKind::Path(ref seqpath) = seqexpr.kind
             // the indexed container is referenced by a name
-            if let ExprKind::Path(ref seqpath) = seqexpr.kind;
-            if let QPath::Resolved(None, seqvar) = *seqpath;
-            if seqvar.segments.len() == 1;
-            if is_local_used(self.cx, idx, self.var);
-            then {
-                if self.prefer_mutable {
-                    self.indexed_mut.insert(seqvar.segments[0].ident.name);
-                }
-                let index_used_directly = matches!(idx.kind, ExprKind::Path(_));
-                let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
-                match res {
-                    Res::Local(hir_id) => {
-                        let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
-                        let extent = self
-                            .cx
-                            .tcx
-                            .region_scope_tree(parent_def_id)
-                            .var_scope(hir_id.local_id)
-                            .unwrap();
-                        if index_used_directly {
-                            self.indexed_directly.insert(
-                                seqvar.segments[0].ident.name,
-                                (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
-                            );
-                        } else {
-                            self.indexed_indirectly
-                                .insert(seqvar.segments[0].ident.name, Some(extent));
-                        }
-                        return false; // no need to walk further *on the variable*
-                    },
-                    Res::Def(DefKind::Static(_) | DefKind::Const, ..) => {
-                        if index_used_directly {
-                            self.indexed_directly.insert(
-                                seqvar.segments[0].ident.name,
-                                (None, self.cx.typeck_results().node_type(seqexpr.hir_id)),
-                            );
-                        } else {
-                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
-                        }
-                        return false; // no need to walk further *on the variable*
-                    },
-                    _ => (),
-                }
+            && let QPath::Resolved(None, seqvar) = *seqpath
+            && seqvar.segments.len() == 1
+            && is_local_used(self.cx, idx, self.var)
+        {
+            if self.prefer_mutable {
+                self.indexed_mut.insert(seqvar.segments[0].ident.name);
+            }
+            let index_used_directly = matches!(idx.kind, ExprKind::Path(_));
+            let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
+            match res {
+                Res::Local(hir_id) => {
+                    let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
+                    let extent = self
+                        .cx
+                        .tcx
+                        .region_scope_tree(parent_def_id)
+                        .var_scope(hir_id.local_id)
+                        .unwrap();
+                    if index_used_directly {
+                        self.indexed_directly.insert(
+                            seqvar.segments[0].ident.name,
+                            (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
+                        );
+                    } else {
+                        self.indexed_indirectly
+                            .insert(seqvar.segments[0].ident.name, Some(extent));
+                    }
+                    return false; // no need to walk further *on the variable*
+                },
+                Res::Def(DefKind::Static(_) | DefKind::Const, ..) => {
+                    if index_used_directly {
+                        self.indexed_directly.insert(
+                            seqvar.segments[0].ident.name,
+                            (None, self.cx.typeck_results().node_type(seqexpr.hir_id)),
+                        );
+                    } else {
+                        self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
+                    }
+                    return false; // no need to walk further *on the variable*
+                },
+                _ => (),
             }
         }
         true
@@ -301,42 +294,36 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if_chain! {
+        if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind
             // a range index op
-            if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
-            if let Some(trait_id) = self
+            && let Some(trait_id) = self
                 .cx
                 .typeck_results()
                 .type_dependent_def_id(expr.hir_id)
-                .and_then(|def_id| self.cx.tcx.trait_of_item(def_id));
-            if (meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id))
-                || (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id));
-            if !self.check(args_1, args_0, expr);
-            then {
-                return;
-            }
+                .and_then(|def_id| self.cx.tcx.trait_of_item(def_id))
+            && ((meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id))
+                || (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id)))
+            && !self.check(args_1, args_0, expr)
+        {
+            return;
         }
 
-        if_chain! {
+        if let ExprKind::Index(seqexpr, idx, _) = expr.kind
             // an index op
-            if let ExprKind::Index(seqexpr, idx, _) = expr.kind;
-            if !self.check(idx, seqexpr, expr);
-            then {
-                return;
-            }
+            && !self.check(idx, seqexpr, expr)
+        {
+            return;
         }
 
-        if_chain! {
+        if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind
             // directly using a variable
-            if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind;
-            if let Res::Local(local_id) = path.res;
-            then {
-                if local_id == self.var {
-                    self.nonindex = true;
-                } else {
-                    // not the correct variable, but still a variable
-                    self.referenced.insert(path.segments[0].ident.name);
-                }
+            && let Res::Local(local_id) = path.res
+        {
+            if local_id == self.var {
+                self.nonindex = true;
+            } else {
+                // not the correct variable, but still a variable
+                self.referenced.insert(path.segments[0].ident.name);
             }
         }
 
diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs
index 5fffb27cda2..15e11fd386c 100644
--- a/clippy_lints/src/loops/same_item_push.rs
+++ b/clippy_lints/src/loops/same_item_push.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::path_to_local;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -44,54 +43,50 @@ pub(super) fn check<'tcx>(
     // Determine whether it is safe to lint the body
     let mut same_item_push_visitor = SameItemPushVisitor::new(cx);
     walk_expr(&mut same_item_push_visitor, body);
-    if_chain! {
-        if same_item_push_visitor.should_lint();
-        if let Some((vec, pushed_item, ctxt)) = same_item_push_visitor.vec_push;
-        let vec_ty = cx.typeck_results().expr_ty(vec);
-        let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
-        if cx
+    if same_item_push_visitor.should_lint()
+        && let Some((vec, pushed_item, ctxt)) = same_item_push_visitor.vec_push
+        && let vec_ty = cx.typeck_results().expr_ty(vec)
+        && let ty = vec_ty.walk().nth(1).unwrap().expect_ty()
+        && cx
             .tcx
             .lang_items()
             .clone_trait()
-            .map_or(false, |id| implements_trait(cx, ty, id, &[]));
-        then {
-            // Make sure that the push does not involve possibly mutating values
-            match pushed_item.kind {
-                ExprKind::Path(ref qpath) => {
-                    match cx.qpath_res(qpath, pushed_item.hir_id) {
-                        // immutable bindings that are initialized with literal or constant
-                        Res::Local(hir_id) => {
-                            let node = cx.tcx.hir().get(hir_id);
-                            if_chain! {
-                                if let Node::Pat(pat) = node;
-                                if let PatKind::Binding(bind_ann, ..) = pat.kind;
-                                if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut));
-                                let parent_node = cx.tcx.hir().parent_id(hir_id);
-                                if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
-                                if let Some(init) = parent_let_expr.init;
-                                then {
-                                    match init.kind {
-                                        // immutable bindings that are initialized with literal
-                                        ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
-                                        // immutable bindings that are initialized with constant
-                                        ExprKind::Path(ref path) => {
-                                            if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
-                                                emit_lint(cx, vec, pushed_item, ctxt);
-                                            }
-                                        }
-                                        _ => {},
+            .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+    {
+        // Make sure that the push does not involve possibly mutating values
+        match pushed_item.kind {
+            ExprKind::Path(ref qpath) => {
+                match cx.qpath_res(qpath, pushed_item.hir_id) {
+                    // immutable bindings that are initialized with literal or constant
+                    Res::Local(hir_id) => {
+                        let node = cx.tcx.hir().get(hir_id);
+                        if let Node::Pat(pat) = node
+                            && let PatKind::Binding(bind_ann, ..) = pat.kind
+                            && !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut))
+                            && let parent_node = cx.tcx.hir().parent_id(hir_id)
+                            && let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node)
+                            && let Some(init) = parent_let_expr.init
+                        {
+                            match init.kind {
+                                // immutable bindings that are initialized with literal
+                                ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
+                                // immutable bindings that are initialized with constant
+                                ExprKind::Path(ref path) => {
+                                    if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
+                                        emit_lint(cx, vec, pushed_item, ctxt);
                                     }
-                                }
+                                },
+                                _ => {},
                             }
-                        },
-                        // constant
-                        Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt),
-                        _ => {},
-                    }
-                },
-                ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
-                _ => {},
-            }
+                        }
+                    },
+                    // constant
+                    Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt),
+                    _ => {},
+                }
+            },
+            ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt),
+            _ => {},
         }
     }
 }
@@ -118,16 +113,14 @@ impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> {
     }
 
     fn should_lint(&self) -> bool {
-        if_chain! {
-            if !self.non_deterministic_expr;
-            if !self.multiple_pushes;
-            if let Some((vec, _, _)) = self.vec_push;
-            if let Some(hir_id) = path_to_local(vec);
-            then {
-                !self.used_locals.contains(&hir_id)
-            } else {
-                false
-            }
+        if !self.non_deterministic_expr
+            && !self.multiple_pushes
+            && let Some((vec, _, _)) = self.vec_push
+            && let Some(hir_id) = path_to_local(vec)
+        {
+            !self.used_locals.contains(&hir_id)
+        } else {
+            false
         }
     }
 }
@@ -180,18 +173,16 @@ fn get_vec_push<'tcx>(
     cx: &LateContext<'tcx>,
     stmt: &'tcx Stmt<'_>,
 ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, SyntaxContext)> {
-    if_chain! {
+    if let StmtKind::Semi(semi_stmt) = &stmt.kind
             // Extract method being called
-            if let StmtKind::Semi(semi_stmt) = &stmt.kind;
-            if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind;
+            && let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind
             // Figure out the parameters for the method call
-            if let Some(pushed_item) = args.first();
+            && let Some(pushed_item) = args.first()
             // Check that the method being called is push() on a Vec
-            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
-            if path.ident.name.as_str() == "push";
-            then {
-                return Some((self_expr, pushed_item, semi_stmt.span.ctxt()))
-            }
+            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec)
+            && path.ident.name.as_str() == "push"
+    {
+        return Some((self_expr, pushed_item, semi_stmt.span.ctxt()));
     }
     None
 }
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs
index dfb800ccf71..d860b297a02 100644
--- a/clippy_lints/src/loops/single_element_loop.rs
+++ b/clippy_lints/src/loops/single_element_loop.rs
@@ -2,7 +2,6 @@ use super::SINGLE_ELEMENT_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, snippet_with_applicability};
 use clippy_utils::visitors::contains_break_or_continue;
-use if_chain::if_chain;
 use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_ast::Mutability;
 use rustc_errors::Applicability;
@@ -66,36 +65,36 @@ pub(super) fn check<'tcx>(
         ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""),
         _ => return,
     };
-    if_chain! {
-        if let ExprKind::Block(block, _) = body.kind;
-        if !block.stmts.is_empty();
-        if !contains_break_or_continue(body);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
-            let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);
-            let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned();
-            block_str.remove(0);
-            block_str.pop();
-            let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0));
+    if let ExprKind::Block(block, _) = body.kind
+        && !block.stmts.is_empty()
+        && !contains_break_or_continue(body)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
+        let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);
+        let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned();
+        block_str.remove(0);
+        block_str.pop();
+        let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0));
 
-            // Reference iterator from `&(mut) []` or `[].iter(_mut)()`.
-            if !prefix.is_empty() && (
+        // Reference iterator from `&(mut) []` or `[].iter(_mut)()`.
+        if !prefix.is_empty()
+            && (
                 // Precedence of internal expression is less than or equal to precedence of `&expr`.
                 arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression)
-            ) {
-                arg_snip = format!("({arg_snip})").into();
-            }
-
-            span_lint_and_sugg(
-                cx,
-                SINGLE_ELEMENT_LOOP,
-                expr.span,
-                "for loop over a single element",
-                "try",
-                format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"),
-                applicability,
             )
+        {
+            arg_snip = format!("({arg_snip})").into();
         }
+
+        span_lint_and_sugg(
+            cx,
+            SINGLE_ELEMENT_LOOP,
+            expr.span,
+            "for loop over a single element",
+            "try",
+            format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"),
+            applicability,
+        );
     }
 }
diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs
index 0a2bd89eb3c..38fdca573c6 100644
--- a/clippy_lints/src/loops/utils.rs
+++ b/clippy_lints/src/loops/utils.rs
@@ -1,6 +1,5 @@
 use clippy_utils::ty::{has_iter_method, implements_trait};
 use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
-use if_chain::if_chain;
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor};
@@ -145,20 +144,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
 
     fn visit_local(&mut self, l: &'tcx Local<'_>) {
         // Look for declarations of the variable
-        if_chain! {
-            if l.pat.hir_id == self.var_id;
-            if let PatKind::Binding(.., ident, _) = l.pat.kind;
-            then {
-                let ty = l.ty.map(|_| self.cx.typeck_results().pat_ty(l.pat));
+        if l.pat.hir_id == self.var_id
+            && let PatKind::Binding(.., ident, _) = l.pat.kind
+        {
+            let ty = l.ty.map(|_| self.cx.typeck_results().pat_ty(l.pat));
 
-                self.state = l.init.map_or(InitializeVisitorState::Declared(ident.name, ty), |init| {
-                    InitializeVisitorState::Initialized {
-                        initializer: init,
-                        ty,
-                        name: ident.name,
-                    }
-                })
-            }
+            self.state = l.init.map_or(InitializeVisitorState::Declared(ident.name, ty), |init| {
+                InitializeVisitorState::Initialized {
+                    initializer: init,
+                    ty,
+                    name: ident.name,
+                }
+            });
         }
 
         walk_local(self, l);
diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs
index 7f24f3c5dc2..9fd9b7a1631 100644
--- a/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/clippy_lints/src/loops/while_immutable_condition.rs
@@ -2,7 +2,6 @@ use super::WHILE_IMMUTABLE_CONDITION;
 use clippy_utils::consts::constant;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::usage::mutated_variables;
-use if_chain::if_chain;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::intravisit::{walk_expr, Visitor};
@@ -95,20 +94,18 @@ struct VarCollectorVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
     fn insert_def_id(&mut self, ex: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Path(ref qpath) = ex.kind;
-            if let QPath::Resolved(None, _) = *qpath;
-            then {
-                match self.cx.qpath_res(qpath, ex.hir_id) {
-                    Res::Local(hir_id) => {
-                        self.ids.insert(hir_id);
-                    },
-                    Res::Def(DefKind::Static(_), def_id) => {
-                        let mutable = self.cx.tcx.is_mutable_static(def_id);
-                        self.def_ids.insert(def_id, mutable);
-                    },
-                    _ => {},
-                }
+        if let ExprKind::Path(ref qpath) = ex.kind
+            && let QPath::Resolved(None, _) = *qpath
+        {
+            match self.cx.qpath_res(qpath, ex.hir_id) {
+                Res::Local(hir_id) => {
+                    self.ids.insert(hir_id);
+                },
+                Res::Def(DefKind::Static(_), def_id) => {
+                    let mutable = self.cx.tcx.is_mutable_static(def_id);
+                    self.def_ids.insert(def_id, mutable);
+                },
+                _ => {},
             }
         }
     }
diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs
index 5153070cfe6..21b9efba54c 100644
--- a/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::visitors::is_res_used;
 use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_expr, Visitor};
@@ -15,59 +14,53 @@ use rustc_span::symbol::sym;
 use rustc_span::Symbol;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if_chain! {
-        if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr);
+    if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr)
         // check for `Some(..)` pattern
-        if let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind;
-        if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome);
+        && let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind
+        && is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome)
         // check for call to `Iterator::next`
-        if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
-        if method_name.ident.name == sym::next;
-        if is_trait_method(cx, let_expr, sym::Iterator);
-        if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr);
+        && let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind
+        && method_name.ident.name == sym::next
+        && is_trait_method(cx, let_expr, sym::Iterator)
+        && let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr)
         // get the loop containing the match expression
-        if !uses_iter(cx, &iter_expr_struct, if_then);
-        then {
-            (let_expr, iter_expr_struct, iter_expr, some_pat, expr)
+        && !uses_iter(cx, &iter_expr_struct, if_then)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let loop_var = if let Some(some_pat) = some_pat.first() {
+            if is_refutable(cx, some_pat) {
+                // Refutable patterns don't work with for loops.
+                return;
+            }
+            snippet_with_applicability(cx, some_pat.span, "..", &mut applicability)
         } else {
-            return;
-        }
-    };
-
-    let mut applicability = Applicability::MachineApplicable;
-    let loop_var = if let Some(some_pat) = some_pat.first() {
-        if is_refutable(cx, some_pat) {
-            // Refutable patterns don't work with for loops.
-            return;
-        }
-        snippet_with_applicability(cx, some_pat.span, "..", &mut applicability)
-    } else {
-        "_".into()
-    };
+            "_".into()
+        };
 
-    // If the iterator is a field or the iterator is accessed after the loop is complete it needs to be
-    // borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
-    // afterwards a mutable borrow of a field isn't necessary.
-    let by_ref = if cx.typeck_results().expr_ty(iter_expr).ref_mutability() == Some(Mutability::Mut)
-        || !iter_expr_struct.can_move
-        || !iter_expr_struct.fields.is_empty()
-        || needs_mutable_borrow(cx, &iter_expr_struct, loop_expr)
-    {
-        ".by_ref()"
-    } else {
-        ""
-    };
+        // If the iterator is a field or the iterator is accessed after the loop is complete it needs to be
+        // borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
+        // afterwards a mutable borrow of a field isn't necessary.
+        let by_ref = if cx.typeck_results().expr_ty(iter_expr).ref_mutability() == Some(Mutability::Mut)
+            || !iter_expr_struct.can_move
+            || !iter_expr_struct.fields.is_empty()
+            || needs_mutable_borrow(cx, &iter_expr_struct, expr)
+        {
+            ".by_ref()"
+        } else {
+            ""
+        };
 
-    let iterator = snippet_with_applicability(cx, iter_expr.span, "_", &mut applicability);
-    span_lint_and_sugg(
-        cx,
-        WHILE_LET_ON_ITERATOR,
-        expr.span.with_hi(scrutinee_expr.span.hi()),
-        "this loop could be written as a `for` loop",
-        "try",
-        format!("for {loop_var} in {iterator}{by_ref}"),
-        applicability,
-    );
+        let iterator = snippet_with_applicability(cx, iter_expr.span, "_", &mut applicability);
+        span_lint_and_sugg(
+            cx,
+            WHILE_LET_ON_ITERATOR,
+            expr.span.with_hi(let_expr.span.hi()),
+            "this loop could be written as a `for` loop",
+            "try",
+            format!("for {loop_var} in {iterator}{by_ref}"),
+            applicability,
+        );
+    }
 }
 
 #[derive(Debug)]
diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs
index 70c5182472a..6f1c5461dc0 100644
--- a/clippy_lints/src/macro_use.rs
+++ b/clippy_lints/src/macro_use.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet;
 use hir::def::{DefKind, Res};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
@@ -90,30 +89,26 @@ impl MacroUseImports {
 
 impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if_chain! {
-            if cx.sess().opts.edition >= Edition::Edition2018;
-            if let hir::ItemKind::Use(path, _kind) = &item.kind;
-            let hir_id = item.hir_id();
-            let attrs = cx.tcx.hir().attrs(hir_id);
-            if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use));
-            if let Some(id) = path.res.iter().find_map(|res| match res {
+        if cx.sess().opts.edition >= Edition::Edition2018
+            && let hir::ItemKind::Use(path, _kind) = &item.kind
+            && let hir_id = item.hir_id()
+            && let attrs = cx.tcx.hir().attrs(hir_id)
+            && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
+            && let Some(id) = path.res.iter().find_map(|res| match res {
                 Res::Def(DefKind::Mod, id) => Some(id),
                 _ => None,
-            });
-            if !id.is_local();
-            then {
-                for kid in cx.tcx.module_children(id) {
-                    if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
-                        let span = mac_attr.span;
-                        let def_path = cx.tcx.def_path_str(mac_id);
-                        self.imports.push((def_path, span, hir_id));
-                    }
-                }
-            } else {
-                if item.span.from_expansion() {
-                    self.push_unique_macro_pat_ty(cx, item.span);
+            })
+            && !id.is_local()
+        {
+            for kid in cx.tcx.module_children(id) {
+                if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
+                    let span = mac_attr.span;
+                    let def_path = cx.tcx.def_path_str(mac_id);
+                    self.imports.push((def_path, span, hir_id));
                 }
             }
+        } else if item.span.from_expansion() {
+            self.push_unique_macro_pat_ty(cx, item.span);
         }
     }
     fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
diff --git a/clippy_lints/src/main_recursion.rs b/clippy_lints/src/main_recursion.rs
index 20333c150e3..ea1d25d80e1 100644
--- a/clippy_lints/src/main_recursion.rs
+++ b/clippy_lints/src/main_recursion.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet;
 use clippy_utils::{is_entrypoint_fn, is_no_std_crate};
-use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -43,21 +42,19 @@ impl LateLintPass<'_> for MainRecursion {
             return;
         }
 
-        if_chain! {
-            if let ExprKind::Call(func, _) = &expr.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind;
-            if let Some(def_id) = path.res.opt_def_id();
-            if is_entrypoint_fn(cx, def_id);
-            then {
-                span_lint_and_help(
-                    cx,
-                    MAIN_RECURSION,
-                    func.span,
-                    &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
-                    None,
-                    "consider using another function for this recursion"
-                )
-            }
+        if let ExprKind::Call(func, _) = &expr.kind
+            && let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind
+            && let Some(def_id) = path.res.opt_def_id()
+            && is_entrypoint_fn(cx, def_id)
+        {
+            span_lint_and_help(
+                cx,
+                MAIN_RECURSION,
+                func.span,
+                &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
+                None,
+                "consider using another function for this recursion",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index 998de38a995..a5d91c949bc 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
@@ -47,61 +46,57 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
         span: Span,
         def_id: LocalDefId,
     ) {
-        if_chain! {
-            if let Some(header) = kind.header();
-            if !header.asyncness.is_async();
+        if let Some(header) = kind.header()
+            && !header.asyncness.is_async()
             // Check that this function returns `impl Future`
-            if let FnRetTy::Return(ret_ty) = decl.output;
-            if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
-            if let Some(output) = future_output_ty(trait_ref);
-            if captures_all_lifetimes(decl.inputs, &output_lifetimes);
+            && let FnRetTy::Return(ret_ty) = decl.output
+            && let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty)
+            && let Some(output) = future_output_ty(trait_ref)
+            && captures_all_lifetimes(decl.inputs, &output_lifetimes)
             // Check that the body of the function consists of one async block
-            if let ExprKind::Block(block, _) = body.value.kind;
-            if block.stmts.is_empty();
-            if let Some(closure_body) = desugared_async_block(cx, block);
-            if let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
-                cx.tcx.hir().get_by_def_id(def_id);
-            then {
-                let header_span = span.with_hi(ret_ty.span.hi());
-
-                span_lint_and_then(
-                    cx,
-                    MANUAL_ASYNC_FN,
-                    header_span,
-                    "this function can be simplified using the `async fn` syntax",
-                    |diag| {
-                        if_chain! {
-                            if let Some(vis_snip) = snippet_opt(cx, *vis_span);
-                            if let Some(header_snip) = snippet_opt(cx, header_span);
-                            if let Some(ret_pos) = position_before_rarrow(&header_snip);
-                            if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
-                            then {
-                                let header_snip = if vis_snip.is_empty() {
-                                    format!("async {}", &header_snip[..ret_pos])
-                                } else {
-                                    format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
-                                };
-
-                                let help = format!("make the function `async` and {ret_sugg}");
-                                diag.span_suggestion(
-                                    header_span,
-                                    help,
-                                    format!("{header_snip}{ret_snip}"),
-                                    Applicability::MachineApplicable
-                                );
-
-                                let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
-                                diag.span_suggestion(
-                                    block.span,
-                                    "move the body of the async block to the enclosing function",
-                                    body_snip,
-                                    Applicability::MachineApplicable
-                                );
-                            }
-                        }
-                    },
-                );
-            }
+            && let ExprKind::Block(block, _) = body.value.kind
+            && block.stmts.is_empty()
+            && let Some(closure_body) = desugared_async_block(cx, block)
+            && let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
+                cx.tcx.hir().get_by_def_id(def_id)
+        {
+            let header_span = span.with_hi(ret_ty.span.hi());
+
+            span_lint_and_then(
+                cx,
+                MANUAL_ASYNC_FN,
+                header_span,
+                "this function can be simplified using the `async fn` syntax",
+                |diag| {
+                    if let Some(vis_snip) = snippet_opt(cx, *vis_span)
+                        && let Some(header_snip) = snippet_opt(cx, header_span)
+                        && let Some(ret_pos) = position_before_rarrow(&header_snip)
+                        && let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
+                    {
+                        let header_snip = if vis_snip.is_empty() {
+                            format!("async {}", &header_snip[..ret_pos])
+                        } else {
+                            format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos])
+                        };
+
+                        let help = format!("make the function `async` and {ret_sugg}");
+                        diag.span_suggestion(
+                            header_span,
+                            help,
+                            format!("{header_snip}{ret_snip}"),
+                            Applicability::MachineApplicable,
+                        );
+
+                        let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
+                        diag.span_suggestion(
+                            block.span,
+                            "move the body of the async block to the enclosing function",
+                            body_snip,
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                },
+            );
         }
     }
 }
@@ -110,48 +105,44 @@ fn future_trait_ref<'tcx>(
     cx: &LateContext<'tcx>,
     ty: &'tcx Ty<'tcx>,
 ) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
-    if_chain! {
-        if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind;
-        let item = cx.tcx.hir().item(item_id);
-        if let ItemKind::OpaqueTy(opaque) = &item.kind;
-        if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
+    if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind
+        && let item = cx.tcx.hir().item(item_id)
+        && let ItemKind::OpaqueTy(opaque) = &item.kind
+        && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
             if let GenericBound::Trait(poly, _) = bound {
                 Some(&poly.trait_ref)
             } else {
                 None
             }
-        });
-        if trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait();
-        then {
-            let output_lifetimes = bounds
-                .iter()
-                .filter_map(|bound| {
-                    if let GenericArg::Lifetime(lt) = bound {
-                        Some(lt.res)
-                    } else {
-                        None
-                    }
-                })
-                .collect();
-
-            return Some((trait_ref, output_lifetimes));
-        }
+        })
+        && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
+    {
+        let output_lifetimes = bounds
+            .iter()
+            .filter_map(|bound| {
+                if let GenericArg::Lifetime(lt) = bound {
+                    Some(lt.res)
+                } else {
+                    None
+                }
+            })
+            .collect();
+
+        return Some((trait_ref, output_lifetimes));
     }
 
     None
 }
 
 fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> {
-    if_chain! {
-        if let Some(segment) = trait_ref.path.segments.last();
-        if let Some(args) = segment.args;
-        if args.bindings.len() == 1;
-        let binding = &args.bindings[0];
-        if binding.ident.name == sym::Output;
-        if let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind;
-        then {
-            return Some(output);
-        }
+    if let Some(segment) = trait_ref.path.segments.last()
+        && let Some(args) = segment.args
+        && args.bindings.len() == 1
+        && let binding = &args.bindings[0]
+        && binding.ident.name == sym::Output
+        && let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind
+    {
+        return Some(output);
     }
 
     None
@@ -181,17 +172,15 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
 }
 
 fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
-    if_chain! {
-        if let Some(block_expr) = block.expr;
-        if let Expr {
+    if let Some(block_expr) = block.expr
+        && let Expr {
             kind: ExprKind::Closure(&Closure { body, .. }),
             ..
-        } = block_expr;
-        let closure_body = cx.tcx.hir().body(body);
-        if closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block));
-        then {
-            return Some(closure_body);
-        }
+        } = block_expr
+        && let closure_body = cx.tcx.hir().body(body)
+        && closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block))
+    {
+        return Some(closure_body);
     }
 
     None
diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs
index cd614c8951c..69c65cf305c 100644
--- a/clippy_lints/src/manual_bits.rs
+++ b/clippy_lints/src/manual_bits.rs
@@ -53,32 +53,30 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits {
             return;
         }
 
-        if_chain! {
-            if let ExprKind::Binary(bin_op, left_expr, right_expr) = expr.kind;
-            if let BinOpKind::Mul = &bin_op.node;
-            if !in_external_macro(cx.sess(), expr.span);
-            let ctxt = expr.span.ctxt();
-            if left_expr.span.ctxt() == ctxt;
-            if right_expr.span.ctxt() == ctxt;
-            if let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr);
-            if matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_));
-            if let ExprKind::Lit(lit) = &other_expr.kind;
-            if let LitKind::Int(8, _) = lit.node;
-            then {
-                let mut app = Applicability::MachineApplicable;
-                let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0;
-                let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS"));
-
-                span_lint_and_sugg(
-                    cx,
-                    MANUAL_BITS,
-                    expr.span,
-                    "usage of `mem::size_of::<T>()` to obtain the size of `T` in bits",
-                    "consider using",
-                    sugg,
-                    app,
-                );
-            }
+        if let ExprKind::Binary(bin_op, left_expr, right_expr) = expr.kind
+            && let BinOpKind::Mul = &bin_op.node
+            && !in_external_macro(cx.sess(), expr.span)
+            && let ctxt = expr.span.ctxt()
+            && left_expr.span.ctxt() == ctxt
+            && right_expr.span.ctxt() == ctxt
+            && let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr)
+            && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_))
+            && let ExprKind::Lit(lit) = &other_expr.kind
+            && let LitKind::Int(8, _) = lit.node
+        {
+            let mut app = Applicability::MachineApplicable;
+            let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0;
+            let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS"));
+
+            span_lint_and_sugg(
+                cx,
+                MANUAL_BITS,
+                expr.span,
+                "usage of `mem::size_of::<T>()` to obtain the size of `T` in bits",
+                "consider using",
+                sugg,
+                app,
+            );
         }
     }
 
@@ -98,22 +96,22 @@ fn get_one_size_of_ty<'tcx>(
 }
 
 fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>)> {
-    if_chain! {
-        if let ExprKind::Call(count_func, _func_args) = expr.kind;
-        if let ExprKind::Path(ref count_func_qpath) = count_func.kind;
-
-        if let QPath::Resolved(_, count_func_path) = count_func_qpath;
-        if let Some(segment_zero) = count_func_path.segments.first();
-        if let Some(args) = segment_zero.args;
-        if let Some(GenericArg::Type(real_ty)) = args.args.first();
-
-        if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
-        if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id);
-        then {
-            cx.typeck_results().node_args(count_func.hir_id).types().next().map(|resolved_ty| (*real_ty, resolved_ty))
-        } else {
-            None
-        }
+    if let ExprKind::Call(count_func, _func_args) = expr.kind
+        && let ExprKind::Path(ref count_func_qpath) = count_func.kind
+        && let QPath::Resolved(_, count_func_path) = count_func_qpath
+        && let Some(segment_zero) = count_func_path.segments.first()
+        && let Some(args) = segment_zero.args
+        && let Some(GenericArg::Type(real_ty)) = args.args.first()
+        && let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id()
+        && cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id)
+    {
+        cx.typeck_results()
+            .node_args(count_func.hir_id)
+            .types()
+            .next()
+            .map(|resolved_ty| (*real_ty, resolved_ty))
+    } else {
+        None
     }
 }
 
diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs
index 170a040d4ae..01eccb56a0a 100644
--- a/clippy_lints/src/manual_let_else.rs
+++ b/clippy_lints/src/manual_let_else.rs
@@ -5,18 +5,15 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{Descend, Visitable};
-use clippy_utils::{is_lint_allowed, pat_and_expr_can_be_question_mark, peel_blocks};
+use clippy_utils::{is_lint_allowed, is_never_expr, pat_and_expr_can_be_question_mark, peel_blocks};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty};
+use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_tool_lint;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
-use std::ops::ControlFlow;
 use std::slice;
 
 declare_clippy_lint! {
@@ -51,7 +48,7 @@ declare_clippy_lint! {
 }
 
 impl<'tcx> QuestionMark {
-    pub(crate) fn check_manual_let_else(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
+    pub(crate) fn check_manual_let_else(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) {
         if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) {
             return;
         }
@@ -67,7 +64,7 @@ impl<'tcx> QuestionMark {
                 IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => {
                     if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then)
                         && let Some(if_else) = if_else
-                        && expr_diverges(cx, if_else)
+                        && is_never_expr(cx, if_else).is_some()
                         && let qm_allowed = is_lint_allowed(cx, QUESTION_MARK, stmt.hir_id)
                         && (qm_allowed || pat_and_expr_can_be_question_mark(cx, let_pat, if_else).is_none())
                     {
@@ -91,10 +88,9 @@ impl<'tcx> QuestionMark {
                         return;
                     }
                     let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes;
-                    let diverging_arm_opt = arms
-                        .iter()
-                        .enumerate()
-                        .find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types));
+                    let diverging_arm_opt = arms.iter().enumerate().find(|(_, arm)| {
+                        is_never_expr(cx, arm.body).is_some() && pat_allowed_for_else(cx, arm.pat, check_types)
+                    });
                     let Some((idx, diverging_arm)) = diverging_arm_opt else {
                         return;
                     };
@@ -272,104 +268,6 @@ fn replace_in_pattern(
     sn_pat.into_owned()
 }
 
-/// Check whether an expression is divergent. May give false negatives.
-fn expr_diverges(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    struct V<'cx, 'tcx> {
-        cx: &'cx LateContext<'tcx>,
-        res: ControlFlow<(), Descend>,
-    }
-    impl<'tcx> Visitor<'tcx> for V<'_, '_> {
-        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
-            fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
-                if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) {
-                    return ty.is_never();
-                }
-                false
-            }
-
-            if self.res.is_break() {
-                return;
-            }
-
-            // We can't just call is_never on expr and be done, because the type system
-            // sometimes coerces the ! type to something different before we can get
-            // our hands on it. So instead, we do a manual search. We do fall back to
-            // is_never in some places when there is no better alternative.
-            self.res = match e.kind {
-                ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()),
-                ExprKind::Call(call, _) => {
-                    if is_never(self.cx, e) || is_never(self.cx, call) {
-                        ControlFlow::Break(())
-                    } else {
-                        ControlFlow::Continue(Descend::Yes)
-                    }
-                },
-                ExprKind::MethodCall(..) => {
-                    if is_never(self.cx, e) {
-                        ControlFlow::Break(())
-                    } else {
-                        ControlFlow::Continue(Descend::Yes)
-                    }
-                },
-                ExprKind::If(if_expr, if_then, if_else) => {
-                    let else_diverges = if_else.map_or(false, |ex| expr_diverges(self.cx, ex));
-                    let diverges =
-                        expr_diverges(self.cx, if_expr) || (else_diverges && expr_diverges(self.cx, if_then));
-                    if diverges {
-                        ControlFlow::Break(())
-                    } else {
-                        ControlFlow::Continue(Descend::No)
-                    }
-                },
-                ExprKind::Match(match_expr, match_arms, _) => {
-                    let diverges = expr_diverges(self.cx, match_expr)
-                        || match_arms.iter().all(|arm| {
-                            let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(self.cx, g.body()));
-                            guard_diverges || expr_diverges(self.cx, arm.body)
-                        });
-                    if diverges {
-                        ControlFlow::Break(())
-                    } else {
-                        ControlFlow::Continue(Descend::No)
-                    }
-                },
-
-                // Don't continue into loops or labeled blocks, as they are breakable,
-                // and we'd have to start checking labels.
-                ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No),
-
-                // Default: descend
-                _ => ControlFlow::Continue(Descend::Yes),
-            };
-            if let ControlFlow::Continue(Descend::Yes) = self.res {
-                walk_expr(self, e);
-            }
-        }
-
-        fn visit_local(&mut self, local: &'tcx Local<'_>) {
-            // Don't visit the else block of a let/else statement as it will not make
-            // the statement divergent even though the else block is divergent.
-            if let Some(init) = local.init {
-                self.visit_expr(init);
-            }
-        }
-
-        // Avoid unnecessary `walk_*` calls.
-        fn visit_ty(&mut self, _: &'tcx Ty<'tcx>) {}
-        fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
-        fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
-        // Avoid monomorphising all `visit_*` functions.
-        fn visit_nested_item(&mut self, _: ItemId) {}
-    }
-
-    let mut v = V {
-        cx,
-        res: ControlFlow::Continue(Descend::Yes),
-    };
-    expr.visit(&mut v);
-    v.res.is_break()
-}
-
 fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: bool) -> bool {
     // Check whether the pattern contains any bindings, as the
     // binding might potentially be used in the body.
diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs
index 9a9e6af5084..b41bf2d767e 100644
--- a/clippy_lints/src/manual_strip.rs
+++ b/clippy_lints/src/manual_strip.rs
@@ -4,7 +4,6 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_expr, Visitor};
@@ -71,55 +70,61 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
             return;
         }
 
-        if_chain! {
-            if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
-            if let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind;
-            if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
-            if let ExprKind::Path(target_path) = &target_arg.kind;
-            then {
-                let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
-                    StripKind::Prefix
-                } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
-                    StripKind::Suffix
-                } else {
-                    return;
-                };
-                let target_res = cx.qpath_res(target_path, target_arg.hir_id);
-                if target_res == Res::Err {
-                    return;
-                };
-
-                if_chain! {
-                    if let Res::Local(hir_id) = target_res;
-                    if let Some(used_mutably) = mutated_variables(then, cx);
-                    if used_mutably.contains(&hir_id);
-                    then {
-                        return;
-                    }
-                }
-
-                let strippings = find_stripping(cx, strip_kind, target_res, pattern, then);
-                if !strippings.is_empty() {
+        if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr)
+            && let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind
+            && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id)
+            && let ExprKind::Path(target_path) = &target_arg.kind
+        {
+            let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
+                StripKind::Prefix
+            } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
+                StripKind::Suffix
+            } else {
+                return;
+            };
+            let target_res = cx.qpath_res(target_path, target_arg.hir_id);
+            if target_res == Res::Err {
+                return;
+            };
+
+            if let Res::Local(hir_id) = target_res
+                && let Some(used_mutably) = mutated_variables(then, cx)
+                && used_mutably.contains(&hir_id)
+            {
+                return;
+            }
 
-                    let kind_word = match strip_kind {
-                        StripKind::Prefix => "prefix",
-                        StripKind::Suffix => "suffix",
-                    };
+            let strippings = find_stripping(cx, strip_kind, target_res, pattern, then);
+            if !strippings.is_empty() {
+                let kind_word = match strip_kind {
+                    StripKind::Prefix => "prefix",
+                    StripKind::Suffix => "suffix",
+                };
 
-                    let test_span = expr.span.until(then.span);
-                    span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| {
+                let test_span = expr.span.until(then.span);
+                span_lint_and_then(
+                    cx,
+                    MANUAL_STRIP,
+                    strippings[0],
+                    &format!("stripping a {kind_word} manually"),
+                    |diag| {
                         diag.span_note(test_span, format!("the {kind_word} was tested here"));
                         multispan_sugg(
                             diag,
                             &format!("try using the `strip_{kind_word}` method"),
-                            vec![(test_span,
-                                  format!("if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
-                                          snippet(cx, target_arg.span, ".."),
-                                          snippet(cx, pattern.span, "..")))]
-                            .into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
+                            vec![(
+                                test_span,
+                                format!(
+                                    "if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
+                                    snippet(cx, target_arg.span, ".."),
+                                    snippet(cx, pattern.span, "..")
+                                ),
+                            )]
+                            .into_iter()
+                            .chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
                         );
-                    });
-                }
+                    },
+                );
             }
         }
     }
@@ -129,15 +134,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
 
 // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
 fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
-    if_chain! {
-        if let ExprKind::MethodCall(_, arg, [], _) = expr.kind;
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if match_def_path(cx, method_def_id, &paths::STR_LEN);
-        then {
-            Some(arg)
-        } else {
-            None
-        }
+    if let ExprKind::MethodCall(_, arg, [], _) = expr.kind
+        && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && match_def_path(cx, method_def_id, &paths::STR_LEN)
+    {
+        Some(arg)
+    } else {
+        None
     }
 }
 
@@ -201,36 +204,38 @@ fn find_stripping<'tcx>(
 
     impl<'a, 'tcx> Visitor<'tcx> for StrippingFinder<'a, 'tcx> {
         fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
-            if_chain! {
-                if is_ref_str(self.cx, ex);
-                let unref = peel_ref(ex);
-                if let ExprKind::Index(indexed, index, _) = &unref.kind;
-                if let Some(higher::Range { start, end, .. }) = higher::Range::hir(index);
-                if let ExprKind::Path(path) = &indexed.kind;
-                if self.cx.qpath_res(path, ex.hir_id) == self.target;
-                then {
-                    match (self.strip_kind, start, end) {
-                        (StripKind::Prefix, Some(start), None) => {
-                            if eq_pattern_length(self.cx, self.pattern, start) {
-                                self.results.push(ex.span);
-                                return;
-                            }
-                        },
-                        (StripKind::Suffix, None, Some(end)) => {
-                            if_chain! {
-                                if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind;
-                                if let Some(left_arg) = len_arg(self.cx, left);
-                                if let ExprKind::Path(left_path) = &left_arg.kind;
-                                if self.cx.qpath_res(left_path, left_arg.hir_id) == self.target;
-                                if eq_pattern_length(self.cx, self.pattern, right);
-                                then {
-                                    self.results.push(ex.span);
-                                    return;
-                                }
-                            }
-                        },
-                        _ => {}
-                    }
+            if is_ref_str(self.cx, ex)
+                && let unref = peel_ref(ex)
+                && let ExprKind::Index(indexed, index, _) = &unref.kind
+                && let Some(higher::Range { start, end, .. }) = higher::Range::hir(index)
+                && let ExprKind::Path(path) = &indexed.kind
+                && self.cx.qpath_res(path, ex.hir_id) == self.target
+            {
+                match (self.strip_kind, start, end) {
+                    (StripKind::Prefix, Some(start), None) => {
+                        if eq_pattern_length(self.cx, self.pattern, start) {
+                            self.results.push(ex.span);
+                            return;
+                        }
+                    },
+                    (StripKind::Suffix, None, Some(end)) => {
+                        if let ExprKind::Binary(
+                            Spanned {
+                                node: BinOpKind::Sub, ..
+                            },
+                            left,
+                            right,
+                        ) = end.kind
+                            && let Some(left_arg) = len_arg(self.cx, left)
+                            && let ExprKind::Path(left_path) = &left_arg.kind
+                            && self.cx.qpath_res(left_path, left_arg.hir_id) == self.target
+                            && eq_pattern_length(self.cx, self.pattern, right)
+                        {
+                            self.results.push(ex.span);
+                            return;
+                        }
+                    },
+                    _ => {},
                 }
             }
 
diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index 766beb980a5..5cef4d91b5b 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/clippy_lints/src/map_unit_fn.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{iter_input_pats, method_chain_args};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
@@ -164,16 +163,14 @@ fn unit_closure<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &hir::Expr<'_>,
 ) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
-    if_chain! {
-        if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind;
-        let body = cx.tcx.hir().body(body);
-        let body_expr = &body.value;
-        if fn_decl.inputs.len() == 1;
-        if is_unit_expression(cx, body_expr);
-        if let Some(binding) = iter_input_pats(fn_decl, body).next();
-        then {
-            return Some((binding, body_expr));
-        }
+    if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind
+        && let body = cx.tcx.hir().body(body)
+        && let body_expr = &body.value
+        && fn_decl.inputs.len() == 1
+        && is_unit_expression(cx, body_expr)
+        && let Some(binding) = iter_input_pats(fn_decl, body).next()
+    {
+        return Some((binding, body_expr));
     }
     None
 }
diff --git a/clippy_lints/src/match_result_ok.rs b/clippy_lints/src/match_result_ok.rs
index 841c020f2d3..bf035969477 100644
--- a/clippy_lints/src/match_result_ok.rs
+++ b/clippy_lints/src/match_result_ok.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{higher, is_res_lang_ctor};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -56,33 +55,31 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
                 return;
             };
 
-        if_chain! {
-            if let ExprKind::MethodCall(ok_path, recv, [], ..) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
-            if let PatKind::TupleStruct(ref pat_path, [ok_pat], _)  = let_pat.kind; //get operation
-            if ok_path.ident.as_str() == "ok";
-            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
-            if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome);
-            let ctxt = expr.span.ctxt();
-            if let_expr.span.ctxt() == ctxt;
-            if let_pat.span.ctxt() == ctxt;
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let some_expr_string = snippet_with_context(cx, ok_pat.span, ctxt, "", &mut applicability).0;
-                let trimmed_ok = snippet_with_context(cx, recv.span, ctxt, "", &mut applicability).0;
-                let sugg = format!(
-                    "{ifwhile} let Ok({some_expr_string}) = {}",
-                    trimmed_ok.trim().trim_end_matches('.'),
-                );
-                span_lint_and_sugg(
-                    cx,
-                    MATCH_RESULT_OK,
-                    expr.span.with_hi(let_expr.span.hi()),
-                    "matching on `Some` with `ok()` is redundant",
-                    &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),
-                    sugg,
-                    applicability,
-                );
-            }
+        if let ExprKind::MethodCall(ok_path, recv, [], ..) = let_expr.kind //check is expr.ok() has type Result<T,E>.ok(, _)
+            && let PatKind::TupleStruct(ref pat_path, [ok_pat], _)  = let_pat.kind //get operation
+            && ok_path.ident.as_str() == "ok"
+            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
+            && is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome)
+            && let ctxt = expr.span.ctxt()
+            && let_expr.span.ctxt() == ctxt
+            && let_pat.span.ctxt() == ctxt
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let some_expr_string = snippet_with_context(cx, ok_pat.span, ctxt, "", &mut applicability).0;
+            let trimmed_ok = snippet_with_context(cx, recv.span, ctxt, "", &mut applicability).0;
+            let sugg = format!(
+                "{ifwhile} let Ok({some_expr_string}) = {}",
+                trimmed_ok.trim().trim_end_matches('.'),
+            );
+            span_lint_and_sugg(
+                cx,
+                MATCH_RESULT_OK,
+                expr.span.with_hi(let_expr.span.hi()),
+                "matching on `Some` with `ok()` is redundant",
+                &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),
+                sugg,
+                applicability,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index 29b935fb61a..48fc5746b3c 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/clippy_lints/src/matches/collapsible_match.rs
@@ -5,7 +5,6 @@ use clippy_utils::visitors::is_local_used;
 use clippy_utils::{
     is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq,
 };
-use if_chain::if_chain;
 use rustc_errors::MultiSpan;
 use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{Arm, Expr, Guard, HirId, Let, Pat, PatKind};
@@ -40,76 +39,73 @@ fn check_arm<'tcx>(
     outer_else_body: Option<&'tcx Expr<'tcx>>,
 ) {
     let inner_expr = peel_blocks_with_stmt(outer_then_body);
-    if_chain! {
-        if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr);
-        if let Some((inner_scrutinee, inner_then_pat, inner_else_body)) = match inner {
+    if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr)
+        && let Some((inner_scrutinee, inner_then_pat, inner_else_body)) = match inner {
             IfLetOrMatch::IfLet(scrutinee, pat, _, els) => Some((scrutinee, pat, els)),
-            IfLetOrMatch::Match(scrutinee, arms, ..) => if_chain! {
+            IfLetOrMatch::Match(scrutinee, arms, ..) => if arms.len() == 2 && arms.iter().all(|a| a.guard.is_none())
                 // if there are more than two arms, collapsing would be non-trivial
-                if arms.len() == 2 && arms.iter().all(|a| a.guard.is_none());
                 // one of the arms must be "wild-like"
-                if let Some(wild_idx) = arms.iter().rposition(|a| arm_is_wild_like(cx, a));
-                then {
-                    let (then, els) = (&arms[1 - wild_idx], &arms[wild_idx]);
-                    Some((scrutinee, then.pat, Some(els.body)))
-                } else {
-                    None
-                }
+                && let Some(wild_idx) = arms.iter().rposition(|a| arm_is_wild_like(cx, a))
+            {
+                let (then, els) = (&arms[1 - wild_idx], &arms[wild_idx]);
+                Some((scrutinee, then.pat, Some(els.body)))
+            } else {
+                None
             },
-        };
-        if outer_pat.span.eq_ctxt(inner_scrutinee.span);
+        }
+        && outer_pat.span.eq_ctxt(inner_scrutinee.span)
         // match expression must be a local binding
         // match <local> { .. }
-        if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee));
-        if !pat_contains_or(inner_then_pat);
+        && let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee))
+        && !pat_contains_or(inner_then_pat)
         // the binding must come from the pattern of the containing match arm
         // ..<local>.. => match <local> { .. }
-        if let (Some(binding_span), is_innermost_parent_pat_struct)
-            = find_pat_binding_and_is_innermost_parent_pat_struct(outer_pat, binding_id);
+        && let (Some(binding_span), is_innermost_parent_pat_struct)
+            = find_pat_binding_and_is_innermost_parent_pat_struct(outer_pat, binding_id)
         // the "else" branches must be equal
-        if match (outer_else_body, inner_else_body) {
+        && match (outer_else_body, inner_else_body) {
             (None, None) => true,
             (None, Some(e)) | (Some(e), None) => is_unit_expr(e),
             (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b),
-        };
+        }
         // the binding must not be used in the if guard
-        if outer_guard.map_or(
+        && outer_guard.map_or(
             true,
             |(Guard::If(e) | Guard::IfLet(Let { init: e, .. }))| !is_local_used(cx, *e, binding_id)
-        );
+        )
         // ...or anywhere in the inner expression
-        if match inner {
+        && match inner {
             IfLetOrMatch::IfLet(_, _, body, els) => {
                 !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id))
             },
             IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)),
-        };
-        then {
-            let msg = format!(
-                "this `{}` can be collapsed into the outer `{}`",
-                if matches!(inner, IfLetOrMatch::Match(..)) { "match" } else { "if let" },
-                if outer_is_match { "match" } else { "if let" },
-            );
-            // collapsing patterns need an explicit field name in struct pattern matching
-            // ex: Struct {x: Some(1)}
-            let replace_msg = if is_innermost_parent_pat_struct {
-                format!(", prefixed by {}:", snippet(cx, binding_span, "their field name"))
+        }
+    {
+        let msg = format!(
+            "this `{}` can be collapsed into the outer `{}`",
+            if matches!(inner, IfLetOrMatch::Match(..)) {
+                "match"
             } else {
-                String::new()
-            };
-            span_lint_and_then(
-                cx,
-                COLLAPSIBLE_MATCH,
-                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}"));
-                    diag.span_help(help_span, "the outer pattern can be modified to include the inner pattern");
-                },
+                "if let"
+            },
+            if outer_is_match { "match" } else { "if let" },
+        );
+        // collapsing patterns need an explicit field name in struct pattern matching
+        // ex: Struct {x: Some(1)}
+        let replace_msg = if is_innermost_parent_pat_struct {
+            format!(", prefixed by {}:", snippet(cx, binding_span, "their field name"))
+        } else {
+            String::new()
+        };
+        span_lint_and_then(cx, COLLAPSIBLE_MATCH, 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}"));
+            diag.span_help(
+                help_span,
+                "the outer pattern can be modified to include the inner pattern",
             );
-        }
+        });
     }
 }
 
diff --git a/clippy_lints/src/matches/infallible_destructuring_match.rs b/clippy_lints/src/matches/infallible_destructuring_match.rs
index 3329f93b73c..c8a48246e67 100644
--- a/clippy_lints/src/matches/infallible_destructuring_match.rs
+++ b/clippy_lints/src/matches/infallible_destructuring_match.rs
@@ -8,38 +8,35 @@ use rustc_lint::LateContext;
 use super::INFALLIBLE_DESTRUCTURING_MATCH;
 
 pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool {
-    if_chain! {
-        if !local.span.from_expansion();
-        if let Some(expr) = local.init;
-        if let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind;
-        if arms.len() == 1 && arms[0].guard.is_none();
-        if let PatKind::TupleStruct(
-            QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind;
-        if args.len() == 1;
-        if let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind;
-        let body = peel_blocks(arms[0].body);
-        if path_to_local_id(body, arg);
-
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                INFALLIBLE_DESTRUCTURING_MATCH,
-                local.span,
-                "you seem to be trying to use `match` to destructure a single infallible pattern. \
-                Consider using `let`",
-                "try",
-                format!(
-                    "let {}({}{}) = {};",
-                    snippet_with_applicability(cx, variant_name.span, "..", &mut applicability),
-                    if binding.0 == ByRef::Yes { "ref " } else { "" },
-                    snippet_with_applicability(cx, local.pat.span, "..", &mut applicability),
-                    snippet_with_applicability(cx, target.span, "..", &mut applicability),
-                ),
-                applicability,
-            );
-            return true;
-        }
+    if !local.span.from_expansion()
+        && let Some(expr) = local.init
+        && let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind
+        && arms.len() == 1
+        && arms[0].guard.is_none()
+        && let PatKind::TupleStruct(QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind
+        && args.len() == 1
+        && let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind
+        && let body = peel_blocks(arms[0].body)
+        && path_to_local_id(body, arg)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            INFALLIBLE_DESTRUCTURING_MATCH,
+            local.span,
+            "you seem to be trying to use `match` to destructure a single infallible pattern. \
+            Consider using `let`",
+            "try",
+            format!(
+                "let {}({}{}) = {};",
+                snippet_with_applicability(cx, variant_name.span, "..", &mut applicability),
+                if binding.0 == ByRef::Yes { "ref " } else { "" },
+                snippet_with_applicability(cx, local.pat.span, "..", &mut applicability),
+                snippet_with_applicability(cx, target.span, "..", &mut applicability),
+            ),
+            applicability,
+        );
+        return true;
     }
     false
 }
diff --git a/clippy_lints/src/matches/manual_filter.rs b/clippy_lints/src/matches/manual_filter.rs
index cdb51c33aaf..619ec83127a 100644
--- a/clippy_lints/src/matches/manual_filter.rs
+++ b/clippy_lints/src/matches/manual_filter.rs
@@ -21,19 +21,19 @@ fn get_cond_expr<'tcx>(
     expr: &'tcx Expr<'_>,
     ctxt: SyntaxContext,
 ) -> Option<SomeExpr<'tcx>> {
-    if_chain! {
-        if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr);
-        if let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind;
-        if let PatKind::Binding(_,target, ..) = pat.kind;
-        if is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr)
-            || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr); // check that one expr resolves to `Some(x)`, the other to `None`
-        then {
-            return Some(SomeExpr {
-                    expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()),
-                    needs_unsafe_block: contains_unsafe_block(cx, expr),
-                    needs_negated: is_none_expr(cx, then_expr) // if the `then_expr` resolves to `None`, need to negate the cond
-                })
-            }
+    if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr)
+        && let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind
+        && let PatKind::Binding(_, target, ..) = pat.kind
+        && (is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr)
+            || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr))
+    // check that one expr resolves to `Some(x)`, the other to `None`
+    {
+        return Some(SomeExpr {
+            expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()),
+            needs_unsafe_block: contains_unsafe_block(cx, expr),
+            needs_negated: is_none_expr(cx, then_expr), /* if the `then_expr` resolves to `None`, need to negate the
+                                                         * cond */
+        });
     };
     None
 }
diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs
index b94501bf0ad..3e79cabd795 100644
--- a/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
 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, sugg};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::LangItem::{OptionNone, ResultErr};
@@ -16,65 +15,57 @@ use super::MANUAL_UNWRAP_OR;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
     let ty = cx.typeck_results().expr_ty(scrutinee);
-    if_chain! {
-        if let Some(ty_name) = 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
-        };
-        if let Some(or_arm) = applicable_or_arm(cx, arms);
-        if let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span);
-        if let Some(indent) = indent_of(cx, expr.span);
-        if constant_simple(cx, cx.typeck_results(), or_arm.body).is_some();
-        then {
-            let reindented_or_body =
-                reindent_multiline(or_body_snippet.into(), true, Some(indent));
+    if let Some(ty_name) = 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
+    } && let Some(or_arm) = applicable_or_arm(cx, arms)
+        && let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span)
+        && let Some(indent) = indent_of(cx, expr.span)
+        && constant_simple(cx, cx.typeck_results(), or_arm.body).is_some()
+    {
+        let reindented_or_body = reindent_multiline(or_body_snippet.into(), 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,
-            );
-        }
+        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,
+        );
     }
 }
 
 fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> {
-    if_chain! {
-        if arms.len() == 2;
-        if arms.iter().all(|arm| arm.guard.is_none());
-        if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
-            match arm.pat.kind {
-                PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.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];
-        if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind;
-        if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, unwrap_arm.pat.hir_id);
-        if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
-        if cx.tcx.lang_items().option_some_variant() == Some(variant_id)
-            || cx.tcx.lang_items().result_ok_variant() == Some(variant_id);
-        if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
-        if path_to_local_id(unwrap_arm.body, binding_hir_id);
-        if cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty();
-        if !contains_return_break_continue_macro(or_arm.body);
-        then {
-            Some(or_arm)
-        } else {
-            None
-        }
+    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::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.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]
+        && let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind
+        && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, unwrap_arm.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(unwrap_arm.body, binding_hir_id)
+        && cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty()
+        && !contains_return_break_continue_macro(or_arm.body)
+    {
+        Some(or_arm)
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs
index 781ee138c76..0627e458dfe 100644
--- a/clippy_lints/src/matches/manual_utils.rs
+++ b/clippy_lints/src/matches/manual_utils.rs
@@ -127,32 +127,30 @@ where
 
     let closure_expr_snip = some_expr.to_snippet_with_context(cx, expr_ctxt, &mut app);
     let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind {
-        if_chain! {
-            if !some_expr.needs_unsafe_block;
-            if let Some(func) = can_pass_as_func(cx, id, some_expr.expr);
-            if func.span.eq_ctxt(some_expr.expr.span);
-            then {
-                snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
-            } else {
-                if path_to_local_id(some_expr.expr, id)
-                    && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
-                    && binding_ref.is_some()
-                {
-                    return None;
-                }
+        if !some_expr.needs_unsafe_block
+            && let Some(func) = can_pass_as_func(cx, id, some_expr.expr)
+            && func.span.eq_ctxt(some_expr.expr.span)
+        {
+            snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
+        } else {
+            if path_to_local_id(some_expr.expr, id)
+                && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
+                && binding_ref.is_some()
+            {
+                return None;
+            }
 
-                // `ref` and `ref mut` annotations were handled earlier.
-                let annotation = if matches!(annotation, BindingAnnotation::MUT) {
-                    "mut "
-                } else {
-                    ""
-                };
+            // `ref` and `ref mut` annotations were handled earlier.
+            let annotation = if matches!(annotation, BindingAnnotation::MUT) {
+                "mut "
+            } else {
+                ""
+            };
 
-                if some_expr.needs_unsafe_block {
-                    format!("|{annotation}{some_binding}| unsafe {{ {closure_expr_snip} }}")
-                } else {
-                    format!("|{annotation}{some_binding}| {closure_expr_snip}")
-                }
+            if some_expr.needs_unsafe_block {
+                format!("|{annotation}{some_binding}| unsafe {{ {closure_expr_snip} }}")
+            } else {
+                format!("|{annotation}{some_binding}| {closure_expr_snip}")
             }
         }
     } else if !is_wild_none && explicit_ref.is_none() {
diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs
index d51cca040a2..3f737da92c0 100644
--- a/clippy_lints/src/matches/match_as_ref.rs
+++ b/clippy_lints/src/matches/match_as_ref.rs
@@ -26,18 +26,16 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
             let output_ty = cx.typeck_results().expr_ty(expr);
             let input_ty = cx.typeck_results().expr_ty(ex);
 
-            let cast = if_chain! {
-                if let ty::Adt(_, args) = input_ty.kind();
-                let input_ty = args.type_at(0);
-                if let ty::Adt(_, args) = output_ty.kind();
-                let output_ty = args.type_at(0);
-                if let ty::Ref(_, output_ty, _) = *output_ty.kind();
-                if input_ty != output_ty;
-                then {
-                    ".map(|x| x as _)"
-                } else {
-                    ""
-                }
+            let cast = if let ty::Adt(_, args) = input_ty.kind()
+                && let input_ty = args.type_at(0)
+                && let ty::Adt(_, args) = output_ty.kind()
+                && let output_ty = args.type_at(0)
+                && let ty::Ref(_, output_ty, _) = *output_ty.kind()
+                && input_ty != output_ty
+            {
+                ".map(|x| x as _)"
+            } else {
+                ""
             };
 
             let mut applicability = Applicability::MachineApplicable;
@@ -67,17 +65,16 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
 
 // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
 fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
-    if_chain! {
-        if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
-        if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome);
-        if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
-        if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
-        if is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome);
-        if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
-        if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
-        then {
-            return Some(mutabl)
-        }
+    if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind
+        && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome)
+        && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind
+        && let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind
+        && is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome)
+        && let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind
+        && path2.segments.len() == 1
+        && ident.name == path2.segments[0].ident.name
+    {
+        return Some(mutabl);
     }
     None
 }
diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs
index e2ddf11abe2..56123326fe4 100644
--- a/clippy_lints/src/matches/match_like_matches.rs
+++ b/clippy_lints/src/matches/match_like_matches.rs
@@ -76,79 +76,80 @@ where
             ),
         >,
 {
-    if_chain! {
-        if !span_contains_comment(cx.sess().source_map(), expr.span);
-        if iter.len() >= 2;
-        if cx.typeck_results().expr_ty(expr).is_bool();
-        if let Some((_, last_pat_opt, last_expr, _)) = iter.next_back();
-        let iter_without_last = iter.clone();
-        if let Some((first_attrs, _, first_expr, first_guard)) = iter.next();
-        if let Some(b0) = find_bool_lit(&first_expr.kind);
-        if let Some(b1) = find_bool_lit(&last_expr.kind);
-        if b0 != b1;
-        if first_guard.is_none() || iter.len() == 0;
-        if first_attrs.is_empty();
-        if iter
-            .all(|arm| {
-                find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty()
-            });
-        then {
-            if let Some(last_pat) = last_pat_opt {
-                if !is_wild(last_pat) {
-                    return false;
-                }
+    if !span_contains_comment(cx.sess().source_map(), expr.span)
+        && iter.len() >= 2
+        && cx.typeck_results().expr_ty(expr).is_bool()
+        && let Some((_, last_pat_opt, last_expr, _)) = iter.next_back()
+        && let iter_without_last = iter.clone()
+        && let Some((first_attrs, _, first_expr, first_guard)) = iter.next()
+        && let Some(b0) = find_bool_lit(&first_expr.kind)
+        && let Some(b1) = find_bool_lit(&last_expr.kind)
+        && b0 != b1
+        && (first_guard.is_none() || iter.len() == 0)
+        && first_attrs.is_empty()
+        && iter.all(|arm| find_bool_lit(&arm.2.kind).map_or(false, |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;
             }
+        }
 
-            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;
-                    }
+        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;
                 }
             }
+        }
 
-            // The suggestion may be incorrect, because some arms can have `cfg` attributes
-            // evaluated into `false` and so such arms will be stripped before.
-            let mut applicability = Applicability::MaybeIncorrect;
-            let pat = {
-                use itertools::Itertools as _;
-                iter_without_last
-                    .filter_map(|arm| {
-                        let pat_span = arm.1?.span;
-                        Some(snippet_with_applicability(cx, pat_span, "..", &mut applicability))
-                    })
-                    .join(" | ")
-            };
-            let pat_and_guard = if let Some(Guard::If(g)) = first_guard {
-                format!("{pat} if {}", snippet_with_applicability(cx, g.span, "..", &mut applicability))
-            } else {
-                pat
-            };
-
-            // 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;
-                }
-            };
-            span_lint_and_sugg(
-                cx,
-                MATCH_LIKE_MATCHES_MACRO,
-                expr.span,
-                &format!("{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" }),
-                "try",
-                format!(
-                    "{}matches!({}, {pat_and_guard})",
-                    if b0 { "" } else { "!" },
-                    snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
-                ),
-                applicability,
-            );
-            true
+        // The suggestion may be incorrect, because some arms can have `cfg` attributes
+        // evaluated into `false` and so such arms will be stripped before.
+        let mut applicability = Applicability::MaybeIncorrect;
+        let pat = {
+            use itertools::Itertools as _;
+            iter_without_last
+                .filter_map(|arm| {
+                    let pat_span = arm.1?.span;
+                    Some(snippet_with_applicability(cx, pat_span, "..", &mut applicability))
+                })
+                .join(" | ")
+        };
+        let pat_and_guard = if let Some(Guard::If(g)) = first_guard {
+            format!(
+                "{pat} if {}",
+                snippet_with_applicability(cx, g.span, "..", &mut applicability)
+            )
         } else {
-            false
-        }
+            pat
+        };
+
+        // 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;
+            }
+        };
+        span_lint_and_sugg(
+            cx,
+            MATCH_LIKE_MATCHES_MACRO,
+            expr.span,
+            &format!(
+                "{} expression looks like `matches!` macro",
+                if is_if_let { "if let .. else" } else { "match" }
+            ),
+            "try",
+            format!(
+                "{}matches!({}, {pat_and_guard})",
+                if b0 { "" } else { "!" },
+                snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
+            ),
+            applicability,
+        );
+        true
+    } else {
+        false
     }
 }
 
diff --git a/clippy_lints/src/matches/match_on_vec_items.rs b/clippy_lints/src/matches/match_on_vec_items.rs
index bd53ebd48c8..dd71560e169 100644
--- a/clippy_lints/src/matches/match_on_vec_items.rs
+++ b/clippy_lints/src/matches/match_on_vec_items.rs
@@ -1,7 +1,6 @@
 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 if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
@@ -10,39 +9,29 @@ use rustc_span::sym;
 use super::MATCH_ON_VEC_ITEMS;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) {
-    if_chain! {
-        if let Some(idx_expr) = is_vec_indexing(cx, scrutinee);
-        if let ExprKind::Index(vec, idx, _) = idx_expr.kind;
-
-        then {
-            // 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
-            );
-        }
+    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_chain! {
-        if let ExprKind::Index(array, index, _) = expr.kind;
-        if is_vector(cx, array);
-        if !is_full_range(cx, index);
-
-        then {
-            return Some(expr);
-        }
+    if let ExprKind::Index(array, index, _) = expr.kind
+        && is_vector(cx, array)
+        && !is_full_range(cx, index)
+    {
+        return Some(expr);
     }
 
     None
diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs
index 6fc79faddbe..745be671b86 100644
--- a/clippy_lints/src/matches/match_same_arms.rs
+++ b/clippy_lints/src/matches/match_same_arms.rs
@@ -66,25 +66,23 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
 
         let mut local_map: HirIdMap<HirId> = HirIdMap::default();
         let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
-            if_chain! {
-                if let Some(a_id) = path_to_local(a);
-                if let Some(b_id) = path_to_local(b);
-                let entry = match local_map.entry(a_id) {
+            if let Some(a_id) = path_to_local(a)
+                && let Some(b_id) = path_to_local(b)
+                && let entry = match local_map.entry(a_id) {
                     HirIdMapEntry::Vacant(entry) => entry,
                     // check if using the same bindings as before
                     HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
-                };
-                // the names technically don't have to match; this makes the lint more conservative
-                if cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id);
-                if cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b);
-                if pat_contains_local(lhs.pat, a_id);
-                if pat_contains_local(rhs.pat, b_id);
-                then {
-                    entry.insert(b_id);
-                    true
-                } else {
-                    false
                 }
+                // the names technically don't have to match; this makes the lint more conservative
+                && cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
+                && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
+                && pat_contains_local(lhs.pat, a_id)
+                && pat_contains_local(rhs.pat, b_id)
+            {
+                entry.insert(b_id);
+                true
+            } else {
+                false
             }
         };
         // Arms with a guard are ignored, those can’t always be merged together
diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs
index 675a85ae555..bd38648bcf1 100644
--- a/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -20,21 +20,16 @@ enum CaseMethod {
 }
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
-    if_chain! {
-        if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(scrutinee).kind();
-        if let ty::Str = ty.kind();
-        then {
-            let mut visitor = MatchExprVisitor {
-                cx,
-                case_method: None,
-            };
-
-            visitor.visit_expr(scrutinee);
-
-            if let Some(case_method) = visitor.case_method {
-                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 ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(scrutinee).kind()
+        && let ty::Str = ty.kind()
+    {
+        let mut visitor = MatchExprVisitor { cx, case_method: None };
+
+        visitor.visit_expr(scrutinee);
+
+        if let Some(case_method) = visitor.case_method {
+            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());
             }
         }
     }
@@ -88,17 +83,15 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
     };
 
     for arm in arms {
-        if_chain! {
-            if let PatKind::Lit(Expr {
-                                kind: ExprKind::Lit(lit),
-                                ..
-                            }) = arm.pat.kind;
-            if let LitKind::Str(symbol, _) = lit.node;
-            let input = symbol.as_str();
-            if !case_check(input);
-            then {
-                return Some((lit.span, symbol));
-            }
+        if let PatKind::Lit(Expr {
+            kind: ExprKind::Lit(lit),
+            ..
+        }) = arm.pat.kind
+            && let LitKind::Str(symbol, _) = lit.node
+            && let input = symbol.as_str()
+            && !case_check(input)
+        {
+            return Some((lit.span, symbol));
         }
     }
 
diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs
index a2903e52ae0..8a4c0ab9062 100644
--- a/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -34,20 +34,19 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
                             }
                         }
                     }
-                    if_chain! {
-                        if matching_wild;
-                        if let Some(macro_call) = root_macro_call(peel_blocks_with_stmt(arm.body).span);
-                        if is_panic(cx, macro_call.def_id);
-                        then {
-                            // `Err(_)` or `Err(_e)` arm with `panic!` found
-                            span_lint_and_note(cx,
-                                MATCH_WILD_ERR_ARM,
-                                arm.pat.span,
-                                &format!("`Err({ident_bind_name})` matches all errors"),
-                                None,
-                                "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable",
-                            );
-                        }
+                    if matching_wild
+                        && let Some(macro_call) = root_macro_call(peel_blocks_with_stmt(arm.body).span)
+                        && is_panic(cx, macro_call.def_id)
+                    {
+                        // `Err(_)` or `Err(_e)` arm with `panic!` found
+                        span_lint_and_note(
+                            cx,
+                            MATCH_WILD_ERR_ARM,
+                            arm.pat.span,
+                            &format!("`Err({ident_bind_name})` matches all errors"),
+                            None,
+                            "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable",
+                        );
                     }
                 }
             }
diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs
index 9a7c00823b6..2582f7edcf6 100644
--- a/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -5,7 +5,6 @@ use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
 use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr};
 use clippy_utils::{higher, is_expn_of, is_trait_method};
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -35,15 +34,13 @@ pub(super) fn check_if_let<'tcx>(
 
 // Extract the generic arguments out of a type
 fn try_get_generic_ty(ty: Ty<'_>, index: usize) -> Option<Ty<'_>> {
-    if_chain! {
-        if let ty::Adt(_, subs) = ty.kind();
-        if let Some(sub) = subs.get(index);
-        if let GenericArgKind::Type(sub_ty) = sub.unpack();
-        then {
-            Some(sub_ty)
-        } else {
-            None
-        }
+    if let ty::Adt(_, subs) = ty.kind()
+        && let Some(sub) = subs.get(index)
+        && let GenericArgKind::Type(sub_ty) = sub.unpack()
+    {
+        Some(sub_ty)
+    } else {
+        None
     }
 }
 
@@ -142,14 +139,12 @@ fn find_sugg_for_if_let<'tcx>(
     let needs_drop = needs_ordered_drop(cx, check_ty) || any_temporaries_need_ordered_drop(cx, let_expr);
 
     // check that `while_let_on_iterator` lint does not trigger
-    if_chain! {
-        if keyword == "while";
-        if let ExprKind::MethodCall(method_path, ..) = let_expr.kind;
-        if method_path.ident.name == sym::next;
-        if is_trait_method(cx, let_expr, sym::Iterator);
-        then {
-            return;
-        }
+    if keyword == "while"
+        && let ExprKind::MethodCall(method_path, ..) = let_expr.kind
+        && method_path.ident.name == sym::next
+        && is_trait_method(cx, let_expr, sym::Iterator)
+    {
+        return;
     }
 
     let result_expr = match &let_expr.kind {
diff --git a/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
index 4efe93d4b54..316b2f63e4e 100644
--- a/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
+++ b/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
@@ -6,25 +6,22 @@ use rustc_middle::ty;
 use super::REST_PAT_IN_FULLY_BOUND_STRUCTS;
 
 pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
-    if_chain! {
-        if !pat.span.from_expansion();
-        if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind;
-        if let Some(def_id) = path.res.opt_def_id();
-        let ty = cx.tcx.type_of(def_id).instantiate_identity();
-        if let ty::Adt(def, _) = ty.kind();
-        if def.is_struct() || def.is_union();
-        if fields.len() == def.non_enum_variant().fields.len();
-        if !def.non_enum_variant().is_field_list_non_exhaustive();
-
-        then {
-            span_lint_and_help(
-                cx,
-                REST_PAT_IN_FULLY_BOUND_STRUCTS,
-                pat.span,
-                "unnecessary use of `..` pattern in struct binding. All fields were already bound",
-                None,
-                "consider removing `..` from this binding",
-            );
-        }
+    if !pat.span.from_expansion()
+        && let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind
+        && let Some(def_id) = path.res.opt_def_id()
+        && let ty = cx.tcx.type_of(def_id).instantiate_identity()
+        && let ty::Adt(def, _) = ty.kind()
+        && (def.is_struct() || def.is_union())
+        && fields.len() == def.non_enum_variant().fields.len()
+        && !def.non_enum_variant().is_field_list_non_exhaustive()
+    {
+        span_lint_and_help(
+            cx,
+            REST_PAT_IN_FULLY_BOUND_STRUCTS,
+            pat.span,
+            "unnecessary use of `..` pattern in struct binding. All fields were already bound",
+            None,
+            "consider removing `..` from this binding",
+        );
     }
 }
diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index 48efd023017..86c414dafcc 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -89,50 +89,52 @@ fn report_single_pattern(
     });
 
     let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat);
-    let (msg, sugg) = if_chain! {
-        if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind;
-        let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex));
-        if let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait();
-        if let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait();
-        if ty.is_integral() || ty.is_char() || ty.is_str()
-            || (implements_trait(cx, ty, spe_trait_id, &[])
-                && implements_trait(cx, ty, pe_trait_id, &[ty.into()]));
-        then {
-            // scrutinee derives PartialEq and the pattern is a constant.
-            let pat_ref_count = match pat.kind {
-                // string literals are already a reference.
-                PatKind::Lit(Expr { kind: ExprKind::Lit(lit), .. }) if lit.node.is_str() => pat_ref_count + 1,
-                _ => pat_ref_count,
-            };
-            // References are only implicitly added to the pattern, so no overflow here.
-            // e.g. will work: match &Some(_) { Some(_) => () }
-            // will not: match Some(_) { &Some(_) => () }
-            let ref_count_diff = ty_ref_count - pat_ref_count;
-
-            // Try to remove address of expressions first.
-            let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff);
-            let ref_count_diff = ref_count_diff - removed;
-
-            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, ".."),
-                // PartialEq for different reference counts may not exist.
-                "&".repeat(ref_count_diff),
-                snippet(cx, arms[0].pat.span, ".."),
-                expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
-            );
-            (msg, sugg)
-        } else {
-            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, arms[0].pat.span, ".."),
-                snippet(cx, ex.span, ".."),
-                expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
-            );
-            (msg, sugg)
-        }
+    let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
+        && let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex))
+        && let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait()
+        && let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait()
+        && (ty.is_integral()
+            || ty.is_char()
+            || ty.is_str()
+            || (implements_trait(cx, ty, spe_trait_id, &[]) && implements_trait(cx, ty, pe_trait_id, &[ty.into()])))
+    {
+        // scrutinee derives PartialEq and the pattern is a constant.
+        let pat_ref_count = match pat.kind {
+            // string literals are already a reference.
+            PatKind::Lit(Expr {
+                kind: ExprKind::Lit(lit),
+                ..
+            }) if lit.node.is_str() => pat_ref_count + 1,
+            _ => pat_ref_count,
+        };
+        // References are only implicitly added to the pattern, so no overflow here.
+        // e.g. will work: match &Some(_) { Some(_) => () }
+        // will not: match Some(_) { &Some(_) => () }
+        let ref_count_diff = ty_ref_count - pat_ref_count;
+
+        // Try to remove address of expressions first.
+        let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff);
+        let ref_count_diff = ref_count_diff - removed;
+
+        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, ".."),
+            // PartialEq for different reference counts may not exist.
+            "&".repeat(ref_count_diff),
+            snippet(cx, arms[0].pat.span, ".."),
+            expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
+        );
+        (msg, sugg)
+    } else {
+        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, arms[0].pat.span, ".."),
+            snippet(cx, ex.span, ".."),
+            expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
+        );
+        (msg, sugg)
     };
 
     span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app);
diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs
index 0fd6f533db0..dd489fc250b 100644
--- a/clippy_lints/src/matches/try_err.rs
+++ b/clippy_lints/src/matches/try_err.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::ResultErr;
 use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
@@ -22,59 +21,57 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
     //         #[allow(unreachable_code)]
     //         val,
     // };
-    if_chain! {
-        if let ExprKind::Call(match_fun, [try_arg, ..]) = scrutinee.kind;
-        if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
-        if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..));
-        if let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind;
-        if is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr);
-        if let Some(return_ty) = find_return_type(cx, &expr.kind);
-        then {
-            let prefix;
-            let suffix;
-            let err_ty;
+    if let ExprKind::Call(match_fun, [try_arg, ..]) = scrutinee.kind
+        && let ExprKind::Path(ref match_fun_path) = match_fun.kind
+        && matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..))
+        && let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind
+        && is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr)
+        && let Some(return_ty) = find_return_type(cx, &expr.kind)
+    {
+        let prefix;
+        let suffix;
+        let err_ty;
 
-            if let Some(ty) = result_error_type(cx, return_ty) {
-                prefix = "Err(";
-                suffix = ")";
-                err_ty = ty;
-            } else if let Some(ty) = poll_result_error_type(cx, return_ty) {
-                prefix = "Poll::Ready(Err(";
-                suffix = "))";
-                err_ty = ty;
-            } else if let Some(ty) = poll_option_result_error_type(cx, return_ty) {
-                prefix = "Poll::Ready(Some(Err(";
-                suffix = ")))";
-                err_ty = ty;
-            } else {
-                return;
-            };
+        if let Some(ty) = result_error_type(cx, return_ty) {
+            prefix = "Err(";
+            suffix = ")";
+            err_ty = ty;
+        } else if let Some(ty) = poll_result_error_type(cx, return_ty) {
+            prefix = "Poll::Ready(Err(";
+            suffix = "))";
+            err_ty = ty;
+        } else if let Some(ty) = poll_option_result_error_type(cx, return_ty) {
+            prefix = "Poll::Ready(Some(Err(";
+            suffix = ")))";
+            err_ty = ty;
+        } else {
+            return;
+        };
 
-            let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
-            let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
-            let mut applicability = Applicability::MachineApplicable;
-            let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
-            let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
-                "" // already returns
-            } else {
-                "return "
-            };
-            let suggestion = if err_ty == expr_err_ty {
-                format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
-            } else {
-                format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
-            };
+        let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
+        let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
+        let mut applicability = Applicability::MachineApplicable;
+        let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
+        let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
+            "" // already returns
+        } else {
+            "return "
+        };
+        let suggestion = if err_ty == expr_err_ty {
+            format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
+        } else {
+            format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
+        };
 
-            span_lint_and_sugg(
-                cx,
-                TRY_ERR,
-                expr.span,
-                "returning an `Err(_)` with the `?` operator",
-                "try",
-                suggestion,
-                applicability,
-            );
-        }
+        span_lint_and_sugg(
+            cx,
+            TRY_ERR,
+            expr.span,
+            "returning an `Err(_)` with the `?` operator",
+            "try",
+            suggestion,
+            applicability,
+        );
     }
 }
 
@@ -92,51 +89,42 @@ fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> O
 
 /// Extracts the error type from Result<T, E>.
 fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-    if_chain! {
-        if let ty::Adt(_, subst) = ty.kind();
-        if is_type_diagnostic_item(cx, ty, sym::Result);
-        then {
-            Some(subst.type_at(1))
-        } else {
-            None
-        }
+    if let ty::Adt(_, subst) = ty.kind()
+        && is_type_diagnostic_item(cx, ty, sym::Result)
+    {
+        Some(subst.type_at(1))
+    } else {
+        None
     }
 }
 
 /// Extracts the error type from Poll<Result<T, E>>.
 fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-    if_chain! {
-        if let ty::Adt(def, subst) = ty.kind();
-        if cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did());
-        let ready_ty = subst.type_at(0);
-
-        if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
-        if cx.tcx.is_diagnostic_item(sym::Result, ready_def.did());
-        then {
-            Some(ready_subst.type_at(1))
-        } else {
-            None
-        }
+    if let ty::Adt(def, subst) = ty.kind()
+        && cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did())
+        && let ready_ty = subst.type_at(0)
+        && let ty::Adt(ready_def, ready_subst) = ready_ty.kind()
+        && cx.tcx.is_diagnostic_item(sym::Result, ready_def.did())
+    {
+        Some(ready_subst.type_at(1))
+    } else {
+        None
     }
 }
 
 /// Extracts the error type from Poll<Option<Result<T, E>>>.
 fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-    if_chain! {
-        if let ty::Adt(def, subst) = ty.kind();
-        if cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did());
-        let ready_ty = subst.type_at(0);
-
-        if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
-        if cx.tcx.is_diagnostic_item(sym::Option, ready_def.did());
-        let some_ty = ready_subst.type_at(0);
-
-        if let ty::Adt(some_def, some_subst) = some_ty.kind();
-        if cx.tcx.is_diagnostic_item(sym::Result, some_def.did());
-        then {
-            Some(some_subst.type_at(1))
-        } else {
-            None
-        }
+    if let ty::Adt(def, subst) = ty.kind()
+        && cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did())
+        && let ready_ty = subst.type_at(0)
+        && let ty::Adt(ready_def, ready_subst) = ready_ty.kind()
+        && cx.tcx.is_diagnostic_item(sym::Option, ready_def.did())
+        && let some_ty = ready_subst.type_at(0)
+        && let ty::Adt(some_def, some_subst) = some_ty.kind()
+        && cx.tcx.is_diagnostic_item(sym::Result, some_def.did())
+    {
+        Some(some_subst.type_at(1))
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index c6a1b45a9fa..13d6f511281 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/clippy_lints/src/mem_replace.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_non_aggregate_primitive_type;
 use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{Expr, ExprKind};
@@ -125,17 +124,37 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_sp
 }
 
 fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
-    if_chain! {
+    if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(src.hir_id)
         // check if replacement is mem::MaybeUninit::uninit().assume_init()
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(src.hir_id);
-        if cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id);
-        then {
+        && cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            MEM_REPLACE_WITH_UNINIT,
+            expr_span,
+            "replacing with `mem::MaybeUninit::uninit().assume_init()`",
+            "consider using",
+            format!(
+                "std::ptr::read({})",
+                snippet_with_applicability(cx, dest.span, "", &mut applicability)
+            ),
+            applicability,
+        );
+        return;
+    }
+
+    if let ExprKind::Call(repl_func, []) = src.kind
+        && let ExprKind::Path(ref repl_func_qpath) = repl_func.kind
+        && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id()
+    {
+        if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
                 cx,
                 MEM_REPLACE_WITH_UNINIT,
                 expr_span,
-                "replacing with `mem::MaybeUninit::uninit().assume_init()`",
+                "replacing with `mem::uninitialized()`",
                 "consider using",
                 format!(
                     "std::ptr::read({})",
@@ -143,40 +162,17 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
                 ),
                 applicability,
             );
-            return;
-        }
-    }
-
-    if_chain! {
-        if let ExprKind::Call(repl_func, []) = src.kind;
-        if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
-        if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
-        then {
-            if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
-                let mut applicability = Applicability::MachineApplicable;
-                span_lint_and_sugg(
-                    cx,
-                    MEM_REPLACE_WITH_UNINIT,
-                    expr_span,
-                    "replacing with `mem::uninitialized()`",
-                    "consider using",
-                    format!(
-                        "std::ptr::read({})",
-                        snippet_with_applicability(cx, dest.span, "", &mut applicability)
-                    ),
-                    applicability,
-                );
-            } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) &&
-                    !cx.typeck_results().expr_ty(src).is_primitive() {
-                span_lint_and_help(
-                    cx,
-                    MEM_REPLACE_WITH_UNINIT,
-                    expr_span,
-                    "replacing with `mem::zeroed()`",
-                    None,
-                    "consider using a default value or the `take_mut` crate instead",
-                );
-            }
+        } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id)
+            && !cx.typeck_results().expr_ty(src).is_primitive()
+        {
+            span_lint_and_help(
+                cx,
+                MEM_REPLACE_WITH_UNINIT,
+                expr_span,
+                "replacing with `mem::zeroed()`",
+                None,
+                "consider using a default value or the `take_mut` crate instead",
+            );
         }
     }
 }
@@ -222,21 +218,19 @@ impl MemReplace {
 
 impl<'tcx> LateLintPass<'tcx> for MemReplace {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
+        if let ExprKind::Call(func, [dest, src]) = expr.kind
             // Check that `expr` is a call to `mem::replace()`
-            if let ExprKind::Call(func, [dest, src]) = expr.kind;
-            if let ExprKind::Path(ref func_qpath) = func.kind;
-            if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
-            if cx.tcx.is_diagnostic_item(sym::mem_replace, def_id);
-            then {
-                // Check that second argument is `Option::None`
-                if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
-                    check_replace_option_with_none(cx, dest, expr.span);
-                } else if self.msrv.meets(msrvs::MEM_TAKE) {
-                    check_replace_with_default(cx, src, dest, expr.span);
-                }
-                check_replace_with_uninit(cx, src, dest, expr.span);
+            && 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 is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
+                check_replace_option_with_none(cx, dest, expr.span);
+            } else if self.msrv.meets(msrvs::MEM_TAKE) {
+                check_replace_with_default(cx, src, dest, expr.span);
             }
+            check_replace_with_uninit(cx, src, dest, expr.span);
         }
     }
     extract_msrv_attr!(LateContext);
diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs
index 3a8cc41748e..08bfa2e009b 100644
--- a/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and
 use clippy_utils::peel_blocks;
 use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::visitors::find_all_ret_expressions;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -70,57 +69,50 @@ pub(crate) trait BindInsteadOfMap {
         closure_expr: &hir::Expr<'_>,
         closure_args_span: Span,
     ) -> bool {
-        if_chain! {
-            if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind;
-            if let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind;
-            if Self::is_variant(cx, path.res);
-            if !contains_return(inner_expr);
-            if let Some(msg) = Self::lint_msg(cx);
-            then {
-                let mut app = Applicability::MachineApplicable;
-                let some_inner_snip = snippet_with_context(cx, inner_expr.span, closure_expr.span.ctxt(), "_", &mut app).0;
-
-                let closure_args_snip = snippet(cx, closure_args_span, "..");
-                let option_snip = snippet(cx, recv.span, "..");
-                let note = format!("{option_snip}.{}({closure_args_snip} {some_inner_snip})", Self::GOOD_METHOD_NAME);
-                span_lint_and_sugg(
-                    cx,
-                    BIND_INSTEAD_OF_MAP,
-                    expr.span,
-                    &msg,
-                    "try",
-                    note,
-                    app,
-                );
-                true
-            } else {
-                false
-            }
+        if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind
+            && let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind
+            && Self::is_variant(cx, path.res)
+            && !contains_return(inner_expr)
+            && let Some(msg) = Self::lint_msg(cx)
+        {
+            let mut app = Applicability::MachineApplicable;
+            let some_inner_snip = snippet_with_context(cx, inner_expr.span, closure_expr.span.ctxt(), "_", &mut app).0;
+
+            let closure_args_snip = snippet(cx, closure_args_span, "..");
+            let option_snip = snippet(cx, recv.span, "..");
+            let note = format!(
+                "{option_snip}.{}({closure_args_snip} {some_inner_snip})",
+                Self::GOOD_METHOD_NAME
+            );
+            span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, "try", note, app);
+            true
+        } else {
+            false
         }
     }
 
     fn lint_closure(cx: &LateContext<'_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) -> bool {
         let mut suggs = Vec::new();
         let can_sugg: bool = find_all_ret_expressions(cx, closure_expr, |ret_expr| {
-            if_chain! {
-                if !ret_expr.span.from_expansion();
-                if let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind;
-                if let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind;
-                if Self::is_variant(cx, path.res);
-                if !contains_return(arg);
-                then {
-                    suggs.push((ret_expr.span, arg.span.source_callsite()));
-                    true
-                } else {
-                    false
-                }
+            if !ret_expr.span.from_expansion()
+                && let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind
+                && let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind
+                && Self::is_variant(cx, path.res)
+                && !contains_return(arg)
+            {
+                suggs.push((ret_expr.span, arg.span.source_callsite()));
+                true
+            } else {
+                false
             }
         });
-        let (span, msg) = if_chain! {
-            if can_sugg;
-            if let hir::ExprKind::MethodCall(segment, ..) = expr.kind;
-            if let Some(msg) = Self::lint_msg(cx);
-            then { (segment.ident.span, msg) } else { return false; }
+        let (span, msg) = if can_sugg
+            && let hir::ExprKind::MethodCall(segment, ..) = expr.kind
+            && let Some(msg) = Self::lint_msg(cx)
+        {
+            (segment.ident.span, msg)
+        } else {
+            return false;
         };
         span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| {
             multispan_sugg_with_applicability(
@@ -139,11 +131,12 @@ pub(crate) trait BindInsteadOfMap {
 
     /// Lint use of `_.and_then(|x| Some(y))` for `Option`s
     fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
-        if_chain! {
-            if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
-            if let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM);
-            if adt.did() == cx.tcx.parent(vid);
-            then {} else { return false; }
+        if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def()
+            && let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)
+            && adt.did() == cx.tcx.parent(vid)
+        {
+        } else {
+            return false;
         }
 
         match arg.kind {
diff --git a/clippy_lints/src/methods/bytecount.rs b/clippy_lints/src/methods/bytecount.rs
index 35370355f83..4a2124c74a8 100644
--- a/clippy_lints/src/methods/bytecount.rs
+++ b/clippy_lints/src/methods/bytecount.rs
@@ -3,7 +3,6 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind};
 use rustc_lint::LateContext;
@@ -18,53 +17,50 @@ pub(super) fn check<'tcx>(
     filter_recv: &'tcx Expr<'_>,
     filter_arg: &'tcx Expr<'_>,
 ) {
-    if_chain! {
-        if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind;
-        let body = cx.tcx.hir().body(body);
-        if let [param] = body.params;
-        if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind;
-        if let ExprKind::Binary(ref op, l, r) = body.value.kind;
-        if op.node == BinOpKind::Eq;
-        if is_type_diagnostic_item(cx,
-                    cx.typeck_results().expr_ty(filter_recv).peel_refs(),
-                    sym::SliceIter);
-        let operand_is_arg = |expr| {
+    if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind
+        && let body = cx.tcx.hir().body(body)
+        && let [param] = body.params
+        && let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind
+        && let ExprKind::Binary(ref op, l, r) = body.value.kind
+        && op.node == BinOpKind::Eq
+        && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv).peel_refs(), sym::SliceIter)
+        && let operand_is_arg = (|expr| {
             let expr = peel_ref_operators(cx, peel_blocks(expr));
             path_to_local_id(expr, arg_id)
-        };
-        let needle = if operand_is_arg(l) {
+        })
+        && let needle = if operand_is_arg(l) {
             r
         } else if operand_is_arg(r) {
             l
         } else {
             return;
-        };
-        if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind();
-        if !is_local_used(cx, needle, arg_id);
-        then {
-            let haystack = if let ExprKind::MethodCall(path, receiver, [], _) =
-                    filter_recv.kind {
-                let p = path.ident.name;
-                if p == sym::iter || p == sym::iter_mut {
-                    receiver
-                } else {
-                    filter_recv
-                }
+        }
+        && ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind()
+        && !is_local_used(cx, needle, arg_id)
+    {
+        let haystack = if let ExprKind::MethodCall(path, receiver, [], _) = filter_recv.kind {
+            let p = path.ident.name;
+            if p == sym::iter || p == sym::iter_mut {
+                receiver
             } else {
                 filter_recv
-            };
-            let mut applicability = Applicability::MaybeIncorrect;
-            span_lint_and_sugg(
-                cx,
-                NAIVE_BYTECOUNT,
-                expr.span,
-                "you appear to be counting bytes the naive way",
-                "consider using the bytecount crate",
-                format!("bytecount::count({}, {})",
-                        snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
-                        snippet_with_applicability(cx, needle.span, "..", &mut applicability)),
-                applicability,
-            );
-        }
+            }
+        } else {
+            filter_recv
+        };
+        let mut applicability = Applicability::MaybeIncorrect;
+        span_lint_and_sugg(
+            cx,
+            NAIVE_BYTECOUNT,
+            expr.span,
+            "you appear to be counting bytes the naive way",
+            "consider using the bytecount crate",
+            format!(
+                "bytecount::count({}, {})",
+                snippet_with_applicability(cx, haystack.span, "..", &mut applicability),
+                snippet_with_applicability(cx, needle.span, "..", &mut applicability)
+            ),
+            applicability,
+        );
     };
 }
diff --git a/clippy_lints/src/methods/bytes_count_to_len.rs b/clippy_lints/src/methods/bytes_count_to_len.rs
index 649fc46e4ad..34159f2d150 100644
--- a/clippy_lints/src/methods/bytes_count_to_len.rs
+++ b/clippy_lints/src/methods/bytes_count_to_len.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_lang_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -14,23 +13,24 @@ pub(super) fn check<'tcx>(
     count_recv: &'tcx hir::Expr<'_>,
     bytes_recv: &'tcx hir::Expr<'_>,
 ) {
-    if_chain! {
-        if let Some(bytes_id) = cx.typeck_results().type_dependent_def_id(count_recv.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(bytes_id);
-        if cx.tcx.type_of(impl_id).instantiate_identity().is_str();
-        let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs();
-        if ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                BYTES_COUNT_TO_LEN,
-                expr.span,
-                "using long and hard to read `.bytes().count()`",
-                "consider calling `.len()` instead",
-                format!("{}.len()", snippet_with_applicability(cx, bytes_recv.span, "..", &mut applicability)),
-                applicability
-            );
-        }
+    if let Some(bytes_id) = cx.typeck_results().type_dependent_def_id(count_recv.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(bytes_id)
+        && cx.tcx.type_of(impl_id).instantiate_identity().is_str()
+        && let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs()
+        && (ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String))
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            BYTES_COUNT_TO_LEN,
+            expr.span,
+            "using long and hard to read `.bytes().count()`",
+            "consider calling `.len()` instead",
+            format!(
+                "{}.len()",
+                snippet_with_applicability(cx, bytes_recv.span, "..", &mut applicability)
+            ),
+            applicability,
+        );
     };
 }
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 d5897822eda..a37087d0abf 100644
--- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
 use clippy_utils::ty::is_type_lang_item;
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
@@ -27,51 +26,54 @@ pub(super) fn check<'tcx>(
         }
     }
 
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if cx.tcx.type_of(impl_id).instantiate_identity().is_str();
-        if let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = arg.kind;
-        if (2..=6).contains(&ext_literal.as_str().len());
-        let ext_str = ext_literal.as_str();
-        if ext_str.starts_with('.');
-        if ext_str.chars().skip(1).all(|c| c.is_uppercase() || c.is_ascii_digit())
-            || ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit());
-        let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
-        if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
-        then {
-            span_lint_and_then(
-                cx,
-                CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
-                recv.span.to(call_span),
-                "case-sensitive file extension comparison",
-                |diag| {
-                    diag.help("consider using a case-insensitive comparison instead");
-                    if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
-
-                        if !cx.typeck_results().expr_ty(recv).is_ref() {
-                            recv_source = format!("&{recv_source}");
-                        }
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && cx.tcx.type_of(impl_id).instantiate_identity().is_str()
+        && let ExprKind::Lit(Spanned {
+            node: LitKind::Str(ext_literal, ..),
+            ..
+        }) = arg.kind
+        && (2..=6).contains(&ext_literal.as_str().len())
+        && let ext_str = ext_literal.as_str()
+        && ext_str.starts_with('.')
+        && (ext_str.chars().skip(1).all(|c| c.is_uppercase() || c.is_ascii_digit())
+            || ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit()))
+        && let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs()
+        && (recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String))
+    {
+        span_lint_and_then(
+            cx,
+            CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
+            recv.span.to(call_span),
+            "case-sensitive file extension comparison",
+            |diag| {
+                diag.help("consider using a case-insensitive comparison instead");
+                if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
+                    if !cx.typeck_results().expr_ty(recv).is_ref() {
+                        recv_source = format!("&{recv_source}");
+                    }
 
-                        let suggestion_source = reindent_multiline(
-                            format!(
-                                "std::path::Path::new({})
-                                    .extension()
-                                    .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
-                                recv_source, ext_str.strip_prefix('.').unwrap()).into(),
-                            true,
-                            Some(indent_of(cx, call_span).unwrap_or(0) + 4)
-                        );
+                    let suggestion_source = reindent_multiline(
+                        format!(
+                            "std::path::Path::new({})
+                                .extension()
+                                .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
+                            recv_source,
+                            ext_str.strip_prefix('.').unwrap()
+                        )
+                        .into(),
+                        true,
+                        Some(indent_of(cx, call_span).unwrap_or(0) + 4),
+                    );
 
-                        diag.span_suggestion(
-                            recv.span.to(call_span),
-                            "use std::path::Path",
-                            suggestion_source,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
+                    diag.span_suggestion(
+                        recv.span.to(call_span),
+                        "use std::path::Path",
+                        suggestion_source,
+                        Applicability::MaybeIncorrect,
+                    );
                 }
-            );
-        }
+            },
+        );
     }
 }
diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs
index 0e41f3c2107..c99cec067bf 100644
--- a/clippy_lints/src/methods/chars_cmp.rs
+++ b/clippy_lints/src/methods/chars_cmp.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{method_chain_args, path_def_id};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, Lint};
@@ -15,34 +14,34 @@ pub(super) fn check(
     lint: &'static Lint,
     suggest: &str,
 ) -> bool {
-    if_chain! {
-        if let Some(args) = method_chain_args(info.chain, chain_methods);
-        if let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind;
-        if let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id));
-        if Some(id) == cx.tcx.lang_items().option_some_variant();
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let self_ty = cx.typeck_results().expr_ty_adjusted(args[0].0).peel_refs();
+    if let Some(args) = method_chain_args(info.chain, chain_methods)
+        && let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind
+        && let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id))
+        && Some(id) == cx.tcx.lang_items().option_some_variant()
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let self_ty = cx.typeck_results().expr_ty_adjusted(args[0].0).peel_refs();
 
-            if *self_ty.kind() != ty::Str {
-                return false;
-            }
+        if *self_ty.kind() != ty::Str {
+            return false;
+        }
 
-            span_lint_and_sugg(
-                cx,
-                lint,
-                info.expr.span,
-                &format!("you should use the `{suggest}` method"),
-                "like this",
-                format!("{}{}.{suggest}({})",
-                        if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
-                        snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
-                applicability,
-            );
+        span_lint_and_sugg(
+            cx,
+            lint,
+            info.expr.span,
+            &format!("you should use the `{suggest}` method"),
+            "like this",
+            format!(
+                "{}{}.{suggest}({})",
+                if info.eq { "" } else { "!" },
+                snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
+                snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)
+            ),
+            applicability,
+        );
 
-            return true;
-        }
+        return true;
     }
 
     false
diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
index c9d50a5b03d..d07e45434a7 100644
--- a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
+++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::method_chain_args;
 use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -15,28 +14,28 @@ pub(super) fn check(
     lint: &'static Lint,
     suggest: &str,
 ) -> bool {
-    if_chain! {
-        if let Some(args) = method_chain_args(info.chain, chain_methods);
-        if let hir::ExprKind::Lit(lit) = info.other.kind;
-        if let ast::LitKind::Char(c) = lit.node;
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                lint,
-                info.expr.span,
-                &format!("you should use the `{suggest}` method"),
-                "like this",
-                format!("{}{}.{suggest}('{}')",
-                        if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
-                        c.escape_default()),
-                applicability,
-            );
+    if let Some(args) = method_chain_args(info.chain, chain_methods)
+        && let hir::ExprKind::Lit(lit) = info.other.kind
+        && let ast::LitKind::Char(c) = lit.node
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            lint,
+            info.expr.span,
+            &format!("you should use the `{suggest}` method"),
+            "like this",
+            format!(
+                "{}{}.{suggest}('{}')",
+                if info.eq { "" } else { "!" },
+                snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
+                c.escape_default()
+            ),
+            applicability,
+        );
 
-            true
-        } else {
-            false
-        }
+        true
+    } else {
+        false
     }
 }
diff --git a/clippy_lints/src/methods/err_expect.rs b/clippy_lints/src/methods/err_expect.rs
index a8d4dd5e4f3..dc978c8a584 100644
--- a/clippy_lints/src/methods/err_expect.rs
+++ b/clippy_lints/src/methods/err_expect.rs
@@ -16,30 +16,27 @@ pub(super) fn check(
     err_span: Span,
     msrv: &Msrv,
 ) {
-    if_chain! {
-        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
+    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
         // Test the version to make sure the lint can be showed (expect_err has been
         // introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982)
-        if msrv.meets(msrvs::EXPECT_ERR);
+        && msrv.meets(msrvs::EXPECT_ERR)
 
         // Grabs the `Result<T, E>` type
-        let result_type = cx.typeck_results().expr_ty(recv);
+        && let result_type = cx.typeck_results().expr_ty(recv)
         // Tests if the T type in a `Result<T, E>` is not None
-        if let Some(data_type) = get_data_type(cx, result_type);
+        && let Some(data_type) = get_data_type(cx, result_type)
         // Tests if the T type in a `Result<T, E>` implements debug
-        if has_debug_impl(cx, data_type);
-
-        then {
-            span_lint_and_sugg(
-                cx,
-                ERR_EXPECT,
-                err_span.to(expect_span),
-                "called `.err().expect()` on a `Result` value",
-                "try",
-                "expect_err".to_string(),
-                Applicability::MachineApplicable
+        && has_debug_impl(cx, data_type)
+    {
+        span_lint_and_sugg(
+            cx,
+            ERR_EXPECT,
+            err_span.to(expect_span),
+            "called `.err().expect()` on a `Result` value",
+            "try",
+            "expect_err".to_string(),
+            Applicability::MachineApplicable,
         );
-        }
     };
 }
 
diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs
index 495b266529b..460ec7b3640 100644
--- a/clippy_lints/src/methods/extend_with_drain.rs
+++ b/clippy_lints/src/methods/extend_with_drain.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
@@ -11,35 +10,33 @@ use super::EXTEND_WITH_DRAIN;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) {
     let ty = cx.typeck_results().expr_ty(recv).peel_refs();
-    if_chain! {
-        if is_type_diagnostic_item(cx, ty, sym::Vec);
+    if is_type_diagnostic_item(cx, ty, sym::Vec)
         //check source object
-        if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind;
-        if src_method.ident.as_str() == "drain";
-        let src_ty = cx.typeck_results().expr_ty(drain_vec);
+        && let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind
+        && src_method.ident.as_str() == "drain"
+        && let src_ty = cx.typeck_results().expr_ty(drain_vec)
         //check if actual src type is mutable for code suggestion
-        let immutable = src_ty.is_mutable_ptr();
-        let src_ty = src_ty.peel_refs();
-        if is_type_diagnostic_item(cx, src_ty, sym::Vec);
+        && let immutable = src_ty.is_mutable_ptr()
+        && let src_ty = src_ty.peel_refs()
+        && is_type_diagnostic_item(cx, src_ty, sym::Vec)
         //check drain range
-        if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs();
-        if is_type_lang_item(cx, src_ty_range, LangItem::RangeFull);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                EXTEND_WITH_DRAIN,
-                expr.span,
-                "use of `extend` instead of `append` for adding the full range of a second vector",
-                "try",
-                format!(
-                    "{}.append({}{})",
-                    snippet_with_applicability(cx, recv.span, "..", &mut applicability),
-                    if immutable { "" } else { "&mut " },
-                    snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability)
-                ),
-                applicability,
-            );
-        }
+        && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs()
+        && is_type_lang_item(cx, src_ty_range, LangItem::RangeFull)
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            EXTEND_WITH_DRAIN,
+            expr.span,
+            "use of `extend` instead of `append` for adding the full range of a second vector",
+            "try",
+            format!(
+                "{}.append({}{})",
+                snippet_with_applicability(cx, recv.span, "..", &mut applicability),
+                if immutable { "" } else { "&mut " },
+                snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability)
+            ),
+            applicability,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs
index 3fef53739fb..15f21fa6ac0 100644
--- a/clippy_lints/src/methods/filetype_is_file.rs
+++ b/clippy_lints/src/methods/filetype_is_file.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::get_parent_expr;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
@@ -20,21 +19,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
     let verb: &str;
     let lint_unary: &str;
     let help_unary: &str;
-    if_chain! {
-        if let Some(parent) = get_parent_expr(cx, expr);
-        if let hir::ExprKind::Unary(op, _) = parent.kind;
-        if op == hir::UnOp::Not;
-        then {
-            lint_unary = "!";
-            verb = "denies";
-            help_unary = "";
-            span = parent.span;
-        } else {
-            lint_unary = "";
-            verb = "covers";
-            help_unary = "!";
-            span = expr.span;
-        }
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let hir::ExprKind::Unary(op, _) = parent.kind
+        && op == hir::UnOp::Not
+    {
+        lint_unary = "!";
+        verb = "denies";
+        help_unary = "";
+        span = parent.span;
+    } else {
+        lint_unary = "";
+        verb = "covers";
+        help_unary = "!";
+        span = expr.span;
     }
     let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files");
     let help_msg = format!("use `{help_unary}FileType::is_dir()` instead");
diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs
index 22b67923e50..e52974103b2 100644
--- a/clippy_lints/src/methods/filter_map.rs
+++ b/clippy_lints/src/methods/filter_map.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::{indent_of, reindent_multiline, snippet};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{higher, is_trait_method, path_to_local_id, peel_blocks, SpanlessEq};
 use hir::{Body, HirId, MatchSource, Pat};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -29,13 +28,11 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
             let arg_id = body.params[0].pat.hir_id;
             match closure_expr.kind {
                 hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
-                    if_chain! {
-                        if ident.name == method_name;
-                        if let hir::ExprKind::Path(path) = &receiver.kind;
-                        if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
-                        then {
-                            return arg_id == *local
-                        }
+                    if ident.name == method_name
+                        && let hir::ExprKind::Path(path) = &receiver.kind
+                        && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id)
+                    {
+                        return arg_id == *local;
                     }
                     false
                 },
@@ -139,11 +136,9 @@ impl<'tcx> OffendingFilterExpr<'tcx> {
                         && path_to_local_id(map_arg_peeled, map_param_id))
                     && let eq_fallback = (|a: &Expr<'_>, b: &Expr<'_>| {
                         // in `filter(|x| ..)`, replace `*x` with `x`
-                        let a_path = if_chain! {
-                            if !is_filter_param_ref;
-                            if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
-                            then { expr_path } else { a }
-                        };
+                        let a_path = if !is_filter_param_ref
+                            && let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind
+                        { expr_path } else { a };
                         // let the filter closure arg and the map closure arg be equal
                         path_to_local_id(a_path, filter_param_id)
                             && path_to_local_id(b, map_param_id)
@@ -305,87 +300,98 @@ pub(super) fn check(
         return;
     }
 
-    if_chain! {
-        if is_trait_method(cx, map_recv, sym::Iterator);
+    if is_trait_method(cx, map_recv, sym::Iterator)
 
         // filter(|x| ...is_some())...
-        if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
-        let filter_body = cx.tcx.hir().body(filter_body_id);
-        if let [filter_param] = filter_body.params;
+        && let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind
+        && let filter_body = cx.tcx.hir().body(filter_body_id)
+        && let [filter_param] = filter_body.params
         // optional ref pattern: `filter(|&x| ..)`
-        let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
+        && let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
             (ref_pat, true)
         } else {
             (filter_param.pat, false)
-        };
-
-        if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
-        if let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id);
+        }
 
-        if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
-        let map_body = cx.tcx.hir().body(map_body_id);
-        if let [map_param] = map_body.params;
-        if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
+        && let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind
+        && let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id)
 
-        if let Some(check_result) =
-            offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref);
+        && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind
+        && let map_body = cx.tcx.hir().body(map_body_id)
+        && let [map_param] = map_body.params
+        && let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind
 
-        then {
-            let span = filter_span.with_hi(expr.span.hi());
-            let (filter_name, lint) = if is_find {
-                ("find", MANUAL_FIND_MAP)
-            } else {
-                ("filter", MANUAL_FILTER_MAP)
-            };
-            let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
+        && let Some(check_result) =
+            offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref)
+    {
+        let span = filter_span.with_hi(expr.span.hi());
+        let (filter_name, lint) = if is_find {
+            ("find", MANUAL_FIND_MAP)
+        } else {
+            ("filter", MANUAL_FILTER_MAP)
+        };
+        let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
 
-            let (sugg, note_and_span, applicability) = match check_result {
-                CheckResult::Method { map_arg, method, side_effect_expr_span } => {
-                    let (to_opt, deref) = match method {
-                        CalledMethod::ResultIsOk => (".ok()", String::new()),
-                        CalledMethod::OptionIsSome => {
-                            let derefs = cx.typeck_results()
-                                .expr_adjustments(map_arg)
-                                .iter()
-                                .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
-                                .count();
+        let (sugg, note_and_span, applicability) = match check_result {
+            CheckResult::Method {
+                map_arg,
+                method,
+                side_effect_expr_span,
+            } => {
+                let (to_opt, deref) = match method {
+                    CalledMethod::ResultIsOk => (".ok()", String::new()),
+                    CalledMethod::OptionIsSome => {
+                        let derefs = cx
+                            .typeck_results()
+                            .expr_adjustments(map_arg)
+                            .iter()
+                            .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
+                            .count();
 
-                            ("", "*".repeat(derefs))
-                        }
-                    };
+                        ("", "*".repeat(derefs))
+                    },
+                };
 
-                    let sugg = format!(
-                        "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
-                        snippet(cx, map_arg.span, ".."),
-                    );
-                    let (note_and_span, applicability) = if let Some(span) = side_effect_expr_span {
-                        let note = "the suggestion might change the behavior of the program when merging `filter` and `map`, \
-                            because this expression potentially contains side effects and will only execute once";
+                let sugg = format!(
+                    "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
+                    snippet(cx, map_arg.span, ".."),
+                );
+                let (note_and_span, applicability) = if let Some(span) = side_effect_expr_span {
+                    let note = "the suggestion might change the behavior of the program when merging `filter` and `map`, \
+                        because this expression potentially contains side effects and will only execute once";
 
-                        (Some((note, span)), Applicability::MaybeIncorrect)
-                    } else {
-                        (None, Applicability::MachineApplicable)
-                    };
+                    (Some((note, span)), Applicability::MaybeIncorrect)
+                } else {
+                    (None, Applicability::MachineApplicable)
+                };
 
-                    (sugg, note_and_span, applicability)
-                }
-                CheckResult::PatternMatching { variant_span, variant_ident } => {
-                    let pat = snippet(cx, variant_span, "<pattern>");
+                (sugg, note_and_span, applicability)
+            },
+            CheckResult::PatternMatching {
+                variant_span,
+                variant_ident,
+            } => {
+                let pat = snippet(cx, variant_span, "<pattern>");
 
-                    (format!("{filter_name}_map(|{map_param_ident}| match {map_param_ident} {{ \
-                        {pat} => Some({variant_ident}), \
-                        _ => None \
-                    }})"), None, Applicability::MachineApplicable)
-                }
-            };
-            span_lint_and_then(cx, lint, span, &msg, |diag| {
-                diag.span_suggestion(span, "try", sugg, applicability);
+                (
+                    format!(
+                        "{filter_name}_map(|{map_param_ident}| match {map_param_ident} {{ \
+                    {pat} => Some({variant_ident}), \
+                    _ => None \
+                }})"
+                    ),
+                    None,
+                    Applicability::MachineApplicable,
+                )
+            },
+        };
+        span_lint_and_then(cx, lint, span, &msg, |diag| {
+            diag.span_suggestion(span, "try", sugg, applicability);
 
-                if let Some((note, span)) = note_and_span {
-                    diag.span_note(span, note);
-                }
-            });
-        }
+            if let Some((note, span)) = note_and_span {
+                diag.span_note(span, note);
+            }
+        });
     }
 }
 
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 4040d3a5fe1..917a8e33eb9 100644
--- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{is_path_diagnostic_item, sugg};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -12,28 +11,25 @@ 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<'_>) {
-    if_chain! {
-        if is_path_diagnostic_item(cx, func, sym::from_iter_fn);
-        let ty = cx.typeck_results().expr_ty(expr);
-        let arg_ty = cx.typeck_results().expr_ty(&args[0]);
-        if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
-
-        if implements_trait(cx, arg_ty, iter_id, &[]);
-        then {
-            // `expr` implements `FromIterator` trait
-            let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par();
-            let turbofish = extract_turbofish(cx, expr, ty);
-            let sugg = format!("{iter_expr}.collect::<{turbofish}>()");
-            span_lint_and_sugg(
-                cx,
-                FROM_ITER_INSTEAD_OF_COLLECT,
-                expr.span,
-                "usage of `FromIterator::from_iter`",
-                "use `.collect()` instead of `::from_iter()`",
-                sugg,
-                Applicability::MaybeIncorrect,
-            );
-        }
+    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 sugg = format!("{iter_expr}.collect::<{turbofish}>()");
+        span_lint_and_sugg(
+            cx,
+            FROM_ITER_INSTEAD_OF_COLLECT,
+            expr.span,
+            "usage of `FromIterator::from_iter`",
+            "use `.collect()` instead of `::from_iter()`",
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
     }
 }
 
@@ -43,41 +39,43 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
     }
 
     let call_site = expr.span.source_callsite();
-    if_chain! {
-        if let Some(snippet) = snippet_opt(cx, call_site);
-        let snippet_split = snippet.split("::").collect::<Vec<_>>();
-        if let Some((_, elements)) = snippet_split.split_last();
-
-        then {
-            if_chain! {
-                if let [type_specifier, _] = snippet_split.as_slice();
-                if let Some(type_specifier) = strip_angle_brackets(type_specifier);
-                if let Some((type_specifier, ..)) = type_specifier.split_once(" as ");
-                then {
-                    type_specifier.to_string()
-                } 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("::"))
-                    }
-                }
-            }
+    if let Some(snippet) = snippet_opt(cx, call_site)
+        && let snippet_split = snippet.split("::").collect::<Vec<_>>()
+        && let Some((_, elements)) = snippet_split.split_last()
+    {
+        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()
         } else {
-            ty.to_string()
+            // 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("::"))
+            }
         }
+    } else {
+        ty.to_string()
     }
 }
diff --git a/clippy_lints/src/methods/get_first.rs b/clippy_lints/src/methods/get_first.rs
index 2e1dd3ec649..e1f1e489355 100644
--- a/clippy_lints/src/methods/get_first.rs
+++ b/clippy_lints/src/methods/get_first.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -17,37 +16,38 @@ pub(super) fn check<'tcx>(
     recv: &'tcx hir::Expr<'_>,
     arg: &'tcx hir::Expr<'_>,
 ) {
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        let identity = cx.tcx.type_of(impl_id).instantiate_identity();
-        if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
-        then {
-            if identity.is_slice() {
-                let mut app = Applicability::MachineApplicable;
-                let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
-                span_lint_and_sugg(
-                    cx,
-                    GET_FIRST,
-                    expr.span,
-                    &format!("accessing first element with `{slice_name}.get(0)`"),
-                    "try",
-                    format!("{slice_name}.first()"),
-                    app,
-                );
-            } else if is_type_diagnostic_item(cx, identity, sym::VecDeque){
-                    let mut app = Applicability::MachineApplicable;
-                    let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
-                    span_lint_and_sugg(
-                        cx,
-                        GET_FIRST,
-                        expr.span,
-                        &format!("accessing first element with `{slice_name}.get(0)`"),
-                        "try",
-                        format!("{slice_name}.front()"),
-                        app,
-                    );
-            }
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && let identity = cx.tcx.type_of(impl_id).instantiate_identity()
+        && let hir::ExprKind::Lit(Spanned {
+            node: LitKind::Int(0, _),
+            ..
+        }) = arg.kind
+    {
+        if identity.is_slice() {
+            let mut app = Applicability::MachineApplicable;
+            let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
+            span_lint_and_sugg(
+                cx,
+                GET_FIRST,
+                expr.span,
+                &format!("accessing first element with `{slice_name}.get(0)`"),
+                "try",
+                format!("{slice_name}.first()"),
+                app,
+            );
+        } else if is_type_diagnostic_item(cx, identity, sym::VecDeque) {
+            let mut app = Applicability::MachineApplicable;
+            let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
+            span_lint_and_sugg(
+                cx,
+                GET_FIRST,
+                expr.span,
+                &format!("accessing first element with `{slice_name}.get(0)`"),
+                "try",
+                format!("{slice_name}.front()"),
+                app,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/methods/implicit_clone.rs b/clippy_lints/src/methods/implicit_clone.rs
index e91ce64d8c8..78a553eb8c0 100644
--- a/clippy_lints/src/methods/implicit_clone.rs
+++ b/clippy_lints/src/methods/implicit_clone.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
 use clippy_utils::{is_diag_item_method, is_diag_trait_item};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -11,34 +10,32 @@ use rustc_span::sym;
 use super::IMPLICIT_CLONE;
 
 pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
-    if_chain! {
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if is_clone_like(cx, method_name, method_def_id);
-        let return_type = cx.typeck_results().expr_ty(expr);
-        let input_type = cx.typeck_results().expr_ty(recv);
-        let (input_type, ref_count) = peel_mid_ty_refs(input_type);
-        if !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned));
-        if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()));
-        if return_type == input_type;
-        if let Some(clone_trait) = cx.tcx.lang_items().clone_trait();
-        if implements_trait(cx, return_type, clone_trait, &[]);
-        then {
-            let mut app = Applicability::MachineApplicable;
-            let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
-            span_lint_and_sugg(
-                cx,
-                IMPLICIT_CLONE,
-                expr.span,
-                &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"),
-                "consider using",
-                if ref_count > 1 {
-                    format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1))
-                } else {
-                    format!("{recv_snip}.clone()")
-                },
-                app,
-            );
-        }
+    if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && is_clone_like(cx, method_name, method_def_id)
+        && let return_type = cx.typeck_results().expr_ty(expr)
+        && let input_type = cx.typeck_results().expr_ty(recv)
+        && let (input_type, ref_count) = peel_mid_ty_refs(input_type)
+        && !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned))
+        && let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()))
+        && return_type == input_type
+        && let Some(clone_trait) = cx.tcx.lang_items().clone_trait()
+        && implements_trait(cx, return_type, clone_trait, &[])
+    {
+        let mut app = Applicability::MachineApplicable;
+        let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
+        span_lint_and_sugg(
+            cx,
+            IMPLICIT_CLONE,
+            expr.span,
+            &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"),
+            "consider using",
+            if ref_count > 1 {
+                format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1))
+            } else {
+                format!("{recv_snip}.clone()")
+            },
+            app,
+        );
     }
 }
 
diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs
index 6686d42c95f..efc3ddd20b4 100644
--- a/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/clippy_lints/src/methods/inefficient_to_string.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -18,37 +17,36 @@ pub fn check(
     receiver: &hir::Expr<'_>,
     args: &[hir::Expr<'_>],
 ) {
-    if_chain! {
-        if args.is_empty() && method_name == sym::to_string;
-        if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did);
-        if let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id);
-        let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver);
-        let self_ty = args.type_at(0);
-        let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty);
-        if deref_count >= 1;
-        if specializes_tostring(cx, deref_self_ty);
-        then {
-            span_lint_and_then(
-                cx,
-                INEFFICIENT_TO_STRING,
-                expr.span,
-                &format!("calling `to_string` on `{arg_ty}`"),
-                |diag| {
-                    diag.help(format!(
-                        "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`"
-                    ));
-                    let mut applicability = Applicability::MachineApplicable;
-                    let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability);
-                    diag.span_suggestion(
-                        expr.span,
-                        "try dereferencing the receiver",
-                        format!("({}{arg_snippet}).to_string()", "*".repeat(deref_count)),
-                        applicability,
-                    );
-                },
-            );
-        }
+    if args.is_empty()
+        && method_name == sym::to_string
+        && let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did)
+        && let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id)
+        && let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver)
+        && let self_ty = args.type_at(0)
+        && let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty)
+        && deref_count >= 1
+        && specializes_tostring(cx, deref_self_ty)
+    {
+        span_lint_and_then(
+            cx,
+            INEFFICIENT_TO_STRING,
+            expr.span,
+            &format!("calling `to_string` on `{arg_ty}`"),
+            |diag| {
+                diag.help(format!(
+                    "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`"
+                ));
+                let mut applicability = Applicability::MachineApplicable;
+                let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability);
+                diag.span_suggestion(
+                    expr.span,
+                    "try dereferencing the receiver",
+                    format!("({}{arg_snippet}).to_string()", "*".repeat(deref_count)),
+                    applicability,
+                );
+            },
+        );
     }
 }
 
diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs
index 8adf9e37059..5ca841df5d9 100644
--- a/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_trait_method;
 use clippy_utils::ty::has_iter_method;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -19,24 +18,20 @@ pub(super) fn check(
     receiver: &hir::Expr<'_>,
 ) {
     let self_ty = cx.typeck_results().expr_ty_adjusted(receiver);
-    if_chain! {
-        if let ty::Ref(..) = self_ty.kind();
-        if method_name == sym::into_iter;
-        if is_trait_method(cx, expr, sym::IntoIterator);
-        if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty);
-        then {
-            span_lint_and_sugg(
-                cx,
-                INTO_ITER_ON_REF,
-                method_span,
-                &format!(
-                    "this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",
-                ),
-                "call directly",
-                method_name.to_string(),
-                Applicability::MachineApplicable,
-            );
-        }
+    if let ty::Ref(..) = self_ty.kind()
+        && method_name == sym::into_iter
+        && is_trait_method(cx, expr, sym::IntoIterator)
+        && let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty)
+    {
+        span_lint_and_sugg(
+            cx,
+            INTO_ITER_ON_REF,
+            method_span,
+            &format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",),
+            "call directly",
+            method_name.to_string(),
+            Applicability::MachineApplicable,
+        );
     }
 }
 
diff --git a/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs
index bde6f92b076..dd741cd43f9 100644
--- a/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -1,7 +1,6 @@
 use crate::methods::utils::derefs_to_slice;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -10,22 +9,21 @@ 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_chain! {
-        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec);
-        if let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv));
-        if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite());
-
-        then {
-            span_lint_and_sugg(
-                cx,
-                ITER_CLONED_COLLECT,
-                to_replace,
-                &format!("called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
-                more readable"),
-                "try",
-                ".to_vec()".to_string(),
-                Applicability::MachineApplicable,
-            );
-        }
+    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec)
+        && let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv))
+        && let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite())
+    {
+        span_lint_and_sugg(
+            cx,
+            ITER_CLONED_COLLECT,
+            to_replace,
+            &format!(
+                "called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
+            more readable"
+            ),
+            "try",
+            ".to_vec()".to_string(),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs
index 625325d4cf5..c5dbb6ad98b 100644
--- a/clippy_lints/src/methods/iter_kv_map.rs
+++ b/clippy_lints/src/methods/iter_kv_map.rs
@@ -22,64 +22,54 @@ pub(super) fn check<'tcx>(
     recv: &'tcx Expr<'tcx>,  // hashmap
     m_arg: &'tcx Expr<'tcx>, // |(_, v)| v
 ) {
-    if_chain! {
-        if !expr.span.from_expansion();
-        if let ExprKind::Closure(c) = m_arg.kind;
-        if let Body {params: [p], value: body_expr, coroutine_kind: _ } = cx.tcx.hir().body(c.body);
-        if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
-
-        let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
+    if !expr.span.from_expansion()
+        && let ExprKind::Closure(c) = m_arg.kind
+        && let Body {
+            params: [p],
+            value: body_expr,
+            coroutine_kind: _,
+        } = cx.tcx.hir().body(c.body)
+        && let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind
+        && let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
             (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
             (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);
-        if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap);
-
-        then {
-            let mut applicability = rustc_errors::Applicability::MachineApplicable;
-            let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability);
-            let into_prefix = if map_type == "into_iter" {"into_"} else {""};
-
-            if_chain! {
-                if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
-                if let [local_ident] = path.segments;
-                if local_ident.ident.as_str() == bound_ident.as_str();
+        }
+        && let ty = cx.typeck_results().expr_ty(recv)
+        && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
+    {
+        let mut applicability = rustc_errors::Applicability::MachineApplicable;
+        let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability);
+        let into_prefix = if map_type == "into_iter" { "into_" } else { "" };
 
-                then {
-                    span_lint_and_sugg(
-                        cx,
-                        ITER_KV_MAP,
-                        expr.span,
-                        &format!("iterating on a map's {replacement_kind}s"),
-                        "try",
-                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"),
-                        applicability,
-                    );
-                } else {
-                    let ref_annotation = if annotation.0 == ByRef::Yes {
-                        "ref "
-                    } else {
-                        ""
-                    };
-                    let mut_annotation = if annotation.1 == Mutability::Mut {
-                        "mut "
-                    } else {
-                        ""
-                    };
-                    span_lint_and_sugg(
-                        cx,
-                        ITER_KV_MAP,
-                        expr.span,
-                        &format!("iterating on a map's {replacement_kind}s"),
-                        "try",
-                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
-                            snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
-                        applicability,
-                    );
-                }
-            }
+        if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind
+            && let [local_ident] = path.segments
+            && local_ident.ident.as_str() == bound_ident.as_str()
+        {
+            span_lint_and_sugg(
+                cx,
+                ITER_KV_MAP,
+                expr.span,
+                &format!("iterating on a map's {replacement_kind}s"),
+                "try",
+                format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"),
+                applicability,
+            );
+        } else {
+            let ref_annotation = if annotation.0 == ByRef::Yes { "ref " } else { "" };
+            let mut_annotation = if annotation.1 == Mutability::Mut { "mut " } else { "" };
+            span_lint_and_sugg(
+                cx,
+                ITER_KV_MAP,
+                expr.span,
+                &format!("iterating on a map's {replacement_kind}s"),
+                "try",
+                format!(
+                    "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
+                    snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)
+                ),
+                applicability,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/methods/iter_next_slice.rs b/clippy_lints/src/methods/iter_next_slice.rs
index 8f885e9f729..fd4650e1e45 100644
--- a/clippy_lints/src/methods/iter_next_slice.rs
+++ b/clippy_lints/src/methods/iter_next_slice.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, higher};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -26,29 +25,36 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal
 
     if derefs_to_slice(cx, caller_expr, cx.typeck_results().expr_ty(caller_expr)).is_some() {
         // caller is a Slice
-        if_chain! {
-            if let hir::ExprKind::Index(caller_var, index_expr, _) = &caller_expr.kind;
-            if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen })
-                = higher::Range::hir(index_expr);
-            if let hir::ExprKind::Lit(start_lit) = &start_expr.kind;
-            if let ast::LitKind::Int(start_idx, _) = start_lit.node;
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let suggest = if start_idx == 0 {
-                    format!("{}.first()", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability))
-                } else {
-                    format!("{}.get({start_idx})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability))
-                };
-                span_lint_and_sugg(
-                    cx,
-                    ITER_NEXT_SLICE,
-                    expr.span,
-                    "using `.iter().next()` on a Slice without end index",
-                    "try calling",
-                    suggest,
-                    applicability,
-                );
-            }
+        if let hir::ExprKind::Index(caller_var, index_expr, _) = &caller_expr.kind
+            && let Some(higher::Range {
+                start: Some(start_expr),
+                end: None,
+                limits: ast::RangeLimits::HalfOpen,
+            }) = higher::Range::hir(index_expr)
+            && let hir::ExprKind::Lit(start_lit) = &start_expr.kind
+            && let ast::LitKind::Int(start_idx, _) = start_lit.node
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let suggest = if start_idx == 0 {
+                format!(
+                    "{}.first()",
+                    snippet_with_applicability(cx, caller_var.span, "..", &mut applicability)
+                )
+            } else {
+                format!(
+                    "{}.get({start_idx})",
+                    snippet_with_applicability(cx, caller_var.span, "..", &mut applicability)
+                )
+            };
+            span_lint_and_sugg(
+                cx,
+                ITER_NEXT_SLICE,
+                expr.span,
+                "using `.iter().next()` on a Slice without end index",
+                "try calling",
+                suggest,
+                applicability,
+            );
         }
     } else if is_vec_or_array(cx, caller_expr) {
         // caller is a Vec or an Array
diff --git a/clippy_lints/src/methods/iter_skip_next.rs b/clippy_lints/src/methods/iter_skip_next.rs
index 39af52141bb..fbe20dfe54e 100644
--- a/clippy_lints/src/methods/iter_skip_next.rs
+++ b/clippy_lints/src/methods/iter_skip_next.rs
@@ -19,18 +19,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
             expr.span.trim_start(recv.span).unwrap(),
             "called `skip(..).next()` on an iterator",
             |diag| {
-                if_chain! {
-                    if let Some(id) = path_to_local(recv);
-                    if let Node::Pat(pat) = cx.tcx.hir().get(id);
-                    if let PatKind::Binding(ann, _, _, _)  = pat.kind;
-                    if ann != BindingAnnotation::MUT;
-                    then {
-                        application = Applicability::Unspecified;
-                        diag.span_help(
-                            pat.span,
-                            format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")),
-                        );
-                    }
+                if let Some(id) = path_to_local(recv)
+                    && let Node::Pat(pat) = cx.tcx.hir().get(id)
+                    && let PatKind::Binding(ann, _, _, _) = pat.kind
+                    && ann != BindingAnnotation::MUT
+                {
+                    application = Applicability::Unspecified;
+                    diag.span_help(
+                        pat.span,
+                        format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")),
+                    );
                 }
 
                 diag.span_suggestion(
diff --git a/clippy_lints/src/methods/manual_ok_or.rs b/clippy_lints/src/methods/manual_ok_or.rs
index 3031193e531..b1af0083e65 100644
--- a/clippy_lints/src/methods/manual_ok_or.rs
+++ b/clippy_lints/src/methods/manual_ok_or.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{ResultErr, ResultOk};
 use rustc_hir::{Expr, ExprKind, PatKind};
@@ -18,30 +17,26 @@ pub(super) fn check<'tcx>(
     or_expr: &'tcx Expr<'_>,
     map_expr: &'tcx Expr<'_>,
 ) {
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Option);
-        if let ExprKind::Call(err_path, [err_arg]) = or_expr.kind;
-        if is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr);
-        if is_ok_wrapping(cx, map_expr);
-        if let Some(recv_snippet) = snippet_opt(cx, recv.span);
-        if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span);
-        if let Some(indent) = indent_of(cx, expr.span);
-        then {
-            let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4));
-            span_lint_and_sugg(
-                cx,
-                MANUAL_OK_OR,
-                expr.span,
-                "this pattern reimplements `Option::ok_or`",
-                "replace with",
-                format!(
-                    "{recv_snippet}.ok_or({reindented_err_arg_snippet})"
-                ),
-                Applicability::MachineApplicable,
-            );
-        }
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Option)
+        && let ExprKind::Call(err_path, [err_arg]) = or_expr.kind
+        && is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr)
+        && is_ok_wrapping(cx, map_expr)
+        && let Some(recv_snippet) = snippet_opt(cx, recv.span)
+        && let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span)
+        && let Some(indent) = indent_of(cx, expr.span)
+    {
+        let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4));
+        span_lint_and_sugg(
+            cx,
+            MANUAL_OK_OR,
+            expr.span,
+            "this pattern reimplements `Option::ok_or`",
+            "replace with",
+            format!("{recv_snippet}.ok_or({reindented_err_arg_snippet})"),
+            Applicability::MachineApplicable,
+        );
     }
 }
 
diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 540425eef8c..04bdbc1ea25 100644
--- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{match_def_path, path_def_id};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -69,16 +68,14 @@ enum MinMax {
 
 fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
     // `T::max_value()` `T::min_value()` inherent methods
-    if_chain! {
-        if let hir::ExprKind::Call(func, args) = &expr.kind;
-        if args.is_empty();
-        if let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind;
-        then {
-            match segment.ident.as_str() {
-                "max_value" => return Some(MinMax::Max),
-                "min_value" => return Some(MinMax::Min),
-                _ => {}
-            }
+    if let hir::ExprKind::Call(func, args) = &expr.kind
+        && args.is_empty()
+        && let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind
+    {
+        match segment.ident.as_str() {
+            "max_value" => return Some(MinMax::Max),
+            "min_value" => return Some(MinMax::Min),
+            _ => {},
         }
     }
 
diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs
index ab13d30d845..61e74369cb0 100644
--- a/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/clippy_lints/src/methods/manual_str_repeat.rs
@@ -3,7 +3,6 @@ use clippy_utils::is_path_diagnostic_item;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
@@ -55,43 +54,42 @@ pub(super) fn check(
     take_self_arg: &Expr<'_>,
     take_arg: &Expr<'_>,
 ) {
-    if_chain! {
-        if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
-        if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat);
-        if is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String);
-        if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
-        if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
-        if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id);
-        if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg);
-        let ctxt = collect_expr.span.ctxt();
-        if ctxt == take_expr.span.ctxt();
-        if ctxt == take_self_arg.span.ctxt();
-        then {
-            let mut app = Applicability::MachineApplicable;
-            let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0;
+    if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind
+        && is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat)
+        && is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String)
+        && let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id)
+        && let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
+        && cx.tcx.trait_of_item(take_id) == Some(iter_trait_id)
+        && let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg)
+        && let ctxt = collect_expr.span.ctxt()
+        && ctxt == take_expr.span.ctxt()
+        && ctxt == take_self_arg.span.ctxt()
+    {
+        let mut app = Applicability::MachineApplicable;
+        let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0;
 
-            let val_str = match repeat_kind {
-                RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return,
-                RepeatKind::Char('\'') => r#""'""#.into(),
-                RepeatKind::Char('"') => r#""\"""#.into(),
-                RepeatKind::Char(_) =>
-                    match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) {
-                        Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])),
-                        s @ Cow::Borrowed(_) => s,
-                    },
-                RepeatKind::String =>
-                    Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app).maybe_par().to_string().into(),
-            };
+        let val_str = match repeat_kind {
+            RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return,
+            RepeatKind::Char('\'') => r#""'""#.into(),
+            RepeatKind::Char('"') => r#""\"""#.into(),
+            RepeatKind::Char(_) => match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) {
+                Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])),
+                s @ Cow::Borrowed(_) => s,
+            },
+            RepeatKind::String => Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app)
+                .maybe_par()
+                .to_string()
+                .into(),
+        };
 
-            span_lint_and_sugg(
-                cx,
-                MANUAL_STR_REPEAT,
-                collect_expr.span,
-                "manual implementation of `str::repeat` using iterators",
-                "try",
-                format!("{val_str}.repeat({count_snip})"),
-                app
-            )
-        }
+        span_lint_and_sugg(
+            cx,
+            MANUAL_STR_REPEAT,
+            collect_expr.span,
+            "manual implementation of `str::repeat` using iterators",
+            "try",
+            format!("{val_str}.repeat({count_snip})"),
+            app,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs
index e0f8cb1b955..cc6eeaa86e5 100644
--- a/clippy_lints/src/methods/map_clone.rs
+++ b/clippy_lints/src/methods/map_clone.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
 use clippy_utils::{is_diag_trait_item, peel_blocks};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -16,57 +15,55 @@ use rustc_span::{sym, Span};
 use super::MAP_CLONE;
 
 pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) {
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id);
-        if cx.tcx.impl_of_method(method_id)
-            .map_or(false, |id| is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Option))
-            || is_diag_trait_item(cx, method_id, sym::Iterator);
-        if let hir::ExprKind::Closure(&hir::Closure{ body, .. }) = arg.kind;
-        then {
-            let closure_body = cx.tcx.hir().body(body);
-            let closure_expr = peel_blocks(closure_body.value);
-            match closure_body.params[0].pat.kind {
-                hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
-                    hir::BindingAnnotation::NONE, .., name, None
-                ) = inner.kind {
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+        && (cx.tcx.impl_of_method(method_id).map_or(false, |id| {
+            is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Option)
+        }) || is_diag_trait_item(cx, method_id, sym::Iterator))
+        && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind
+    {
+        let closure_body = cx.tcx.hir().body(body);
+        let closure_expr = peel_blocks(closure_body.value);
+        match closure_body.params[0].pat.kind {
+            hir::PatKind::Ref(inner, hir::Mutability::Not) => {
+                if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) = inner.kind {
                     if ident_eq(name, closure_expr) {
                         lint_explicit_closure(cx, e.span, recv.span, true, msrv);
                     }
-                },
-                hir::PatKind::Binding(hir::BindingAnnotation::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);
-                                }
+                }
+            },
+            hir::PatKind::Binding(hir::BindingAnnotation::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);
                             }
-                        },
-                        hir::ExprKind::MethodCall(method, obj, [], _) => if_chain! {
-                            if ident_eq(name, obj) && method.ident.name == sym::clone;
-                            if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id);
-                            if let Some(trait_id) = cx.tcx.trait_of_item(fn_id);
-                            if cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id);
-                            // no autoderefs
-                            if !cx.typeck_results().expr_adjustments(obj).iter()
-                                .any(|a| matches!(a.kind, Adjust::Deref(Some(..))));
-                            then {
-                                let obj_ty = cx.typeck_results().expr_ty(obj);
-                                if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
-                                    if matches!(mutability, Mutability::Not) {
-                                        let copy = is_copy(cx, *ty);
-                                        lint_explicit_closure(cx, e.span, recv.span, copy, msrv);
-                                    }
-                                } else {
-                                    lint_needless_cloning(cx, e.span, recv.span);
+                        }
+                    },
+                    hir::ExprKind::MethodCall(method, obj, [], _) => {
+                        if ident_eq(name, obj) && method.ident.name == sym::clone
+                        && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
+                        && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
+                        && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+                        // no autoderefs
+                        && !cx.typeck_results().expr_adjustments(obj).iter()
+                            .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
+                        {
+                            let obj_ty = cx.typeck_results().expr_ty(obj);
+                            if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
+                                if matches!(mutability, Mutability::Not) {
+                                    let copy = is_copy(cx, *ty);
+                                    lint_explicit_closure(cx, e.span, recv.span, copy, msrv);
                                 }
+                            } else {
+                                lint_needless_cloning(cx, e.span, recv.span);
                             }
-                        },
-                        _ => {},
-                    }
-                },
-                _ => {},
-            }
+                        }
+                    },
+                    _ => {},
+                }
+            },
+            _ => {},
         }
     }
 }
diff --git a/clippy_lints/src/methods/map_collect_result_unit.rs b/clippy_lints/src/methods/map_collect_result_unit.rs
index 01cdd02e602..e944eac91e7 100644
--- a/clippy_lints/src/methods/map_collect_result_unit.rs
+++ b/clippy_lints/src/methods/map_collect_result_unit.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -13,26 +12,24 @@ use super::MAP_COLLECT_RESULT_UNIT;
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr<'_>, map_fn: &hir::Expr<'_>) {
     // return of collect `Result<(),_>`
     let collect_ret_ty = cx.typeck_results().expr_ty(expr);
-    if_chain! {
-        if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result);
-        if let ty::Adt(_, args) = collect_ret_ty.kind();
-        if let Some(result_t) = args.types().next();
-        if result_t.is_unit();
-        // get parts for snippet
-        then {
-            span_lint_and_sugg(
-                cx,
-                MAP_COLLECT_RESULT_UNIT,
-                expr.span,
-                "`.map().collect()` can be replaced with `.try_for_each()`",
-                "try",
-                format!(
-                    "{}.try_for_each({})",
-                    snippet(cx, iter.span, ".."),
-                    snippet(cx, map_fn.span, "..")
-                ),
-                Applicability::MachineApplicable,
-            );
-        }
+    if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result)
+        && let ty::Adt(_, args) = collect_ret_ty.kind()
+        && let Some(result_t) = args.types().next()
+        && result_t.is_unit()
+    // get parts for snippet
+    {
+        span_lint_and_sugg(
+            cx,
+            MAP_COLLECT_RESULT_UNIT,
+            expr.span,
+            "`.map().collect()` can be replaced with `.try_for_each()`",
+            "try",
+            format!(
+                "{}.try_for_each({})",
+                snippet(cx, iter.span, ".."),
+                snippet(cx, map_fn.span, "..")
+            ),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/map_identity.rs b/clippy_lints/src/methods/map_identity.rs
index 57581363cfa..d1072475843 100644
--- a/clippy_lints/src/methods/map_identity.rs
+++ b/clippy_lints/src/methods/map_identity.rs
@@ -19,22 +19,20 @@ pub(super) fn check(
 ) {
     let caller_ty = cx.typeck_results().expr_ty(caller);
 
-    if_chain! {
-        if is_trait_method(cx, expr, sym::Iterator)
-            || is_type_diagnostic_item(cx, caller_ty, sym::Result)
-            || is_type_diagnostic_item(cx, caller_ty, sym::Option);
-        if is_expr_untyped_identity_function(cx, map_arg);
-        if let Some(sugg_span) = expr.span.trim_start(caller.span);
-        then {
-            span_lint_and_sugg(
-                cx,
-                MAP_IDENTITY,
-                sugg_span,
-                "unnecessary map of the identity function",
-                &format!("remove the call to `{name}`"),
-                String::new(),
-                Applicability::MachineApplicable,
-            )
-        }
+    if (is_trait_method(cx, expr, sym::Iterator)
+        || is_type_diagnostic_item(cx, caller_ty, sym::Result)
+        || is_type_diagnostic_item(cx, caller_ty, sym::Option))
+        && is_expr_untyped_identity_function(cx, map_arg)
+        && let Some(sugg_span) = expr.span.trim_start(caller.span)
+    {
+        span_lint_and_sugg(
+            cx,
+            MAP_IDENTITY,
+            sugg_span,
+            "unnecessary map of the identity function",
+            &format!("remove the call to `{name}`"),
+            String::new(),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index a71a136eba5..57c3913944f 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -123,7 +123,6 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
 use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty};
-use if_chain::if_chain;
 pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -3698,8 +3697,10 @@ impl Methods {
         msrv: Msrv,
         allow_expect_in_tests: bool,
         allow_unwrap_in_tests: bool,
-        allowed_dotfiles: FxHashSet<String>,
+        mut allowed_dotfiles: FxHashSet<String>,
     ) -> Self {
+        allowed_dotfiles.extend(DEFAULT_ALLOWED_DOTFILES.iter().map(ToString::to_string));
+
         Self {
             avoid_breaking_exported_api,
             msrv,
@@ -3977,44 +3978,41 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             return;
         }
 
-        if_chain! {
-            if let TraitItemKind::Fn(ref sig, _) = item.kind;
-            if sig.decl.implicit_self.has_implicit_self();
-            if let Some(first_arg_hir_ty) = sig.decl.inputs.first();
-            if let Some(&first_arg_ty) = cx.tcx.fn_sig(item.owner_id)
+        if let TraitItemKind::Fn(ref sig, _) = item.kind
+            && sig.decl.implicit_self.has_implicit_self()
+            && let Some(first_arg_hir_ty) = sig.decl.inputs.first()
+            && let Some(&first_arg_ty) = cx
+                .tcx
+                .fn_sig(item.owner_id)
                 .instantiate_identity()
                 .inputs()
                 .skip_binder()
-                .first();
-            then {
-                let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty();
-                wrong_self_convention::check(
-                    cx,
-                    item.ident.name.as_str(),
-                    self_ty,
-                    first_arg_ty,
-                    first_arg_hir_ty.span,
-                    false,
-                    true,
-                );
-            }
-        }
-
-        if_chain! {
-            if item.ident.name == sym::new;
-            if let TraitItemKind::Fn(_, _) = item.kind;
-            let ret_ty = return_ty(cx, item.owner_id);
+                .first()
+        {
             let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty();
-            if !ret_ty.contains(self_ty);
+            wrong_self_convention::check(
+                cx,
+                item.ident.name.as_str(),
+                self_ty,
+                first_arg_ty,
+                first_arg_hir_ty.span,
+                false,
+                true,
+            );
+        }
 
-            then {
-                span_lint(
-                    cx,
-                    NEW_RET_NO_SELF,
-                    item.span,
-                    "methods called `new` usually return `Self`",
-                );
-            }
+        if item.ident.name == sym::new
+            && let TraitItemKind::Fn(_, _) = item.kind
+            && let ret_ty = return_ty(cx, item.owner_id)
+            && let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty()
+            && !ret_ty.contains(self_ty)
+        {
+            span_lint(
+                cx,
+                NEW_RET_NO_SELF,
+                item.span,
+                "methods called `new` usually return `Self`",
+            );
         }
     }
 
diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs
index 2855e23bf5b..1a0fce2876d 100644
--- a/clippy_lints/src/methods/mut_mutex_lock.rs
+++ b/clippy_lints/src/methods/mut_mutex_lock.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::expr_custom_deref_adjustment;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
@@ -11,22 +10,20 @@ use rustc_span::{sym, Span};
 use super::MUT_MUTEX_LOCK;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>, recv: &'tcx Expr<'tcx>, name_span: Span) {
-    if_chain! {
-        if matches!(expr_custom_deref_adjustment(cx, recv), None | Some(Mutability::Mut));
-        if let ty::Ref(_, _, Mutability::Mut) = cx.typeck_results().expr_ty(recv).kind();
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Mutex);
-        then {
-            span_lint_and_sugg(
-                cx,
-                MUT_MUTEX_LOCK,
-                name_span,
-                "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference",
-                "change this to",
-                "get_mut".to_owned(),
-                Applicability::MaybeIncorrect,
-            );
-        }
+    if matches!(expr_custom_deref_adjustment(cx, recv), None | Some(Mutability::Mut))
+        && let ty::Ref(_, _, Mutability::Mut) = cx.typeck_results().expr_ty(recv).kind()
+        && let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Mutex)
+    {
+        span_lint_and_sugg(
+            cx,
+            MUT_MUTEX_LOCK,
+            name_span,
+            "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference",
+            "change this to",
+            "get_mut".to_owned(),
+            Applicability::MaybeIncorrect,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/no_effect_replace.rs b/clippy_lints/src/methods/no_effect_replace.rs
index 01655e860c4..81df32bdee2 100644
--- a/clippy_lints/src/methods/no_effect_replace.rs
+++ b/clippy_lints/src/methods/no_effect_replace.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::SpanlessEq;
-use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_hir::{ExprKind, LangItem};
 use rustc_lint::LateContext;
@@ -19,17 +18,13 @@ pub(super) fn check<'tcx>(
         return;
     }
 
-    if_chain! {
-        if let ExprKind::Lit(spanned) = &arg1.kind;
-        if let Some(param1) = lit_string_value(&spanned.node);
-
-        if let ExprKind::Lit(spanned) = &arg2.kind;
-        if let LitKind::Str(param2, _) = &spanned.node;
-        if param1 == param2.as_str();
-
-        then {
-            span_lint(cx, NO_EFFECT_REPLACE, expr.span, "replacing text with itself");
-        }
+    if let ExprKind::Lit(spanned) = &arg1.kind
+        && let Some(param1) = lit_string_value(&spanned.node)
+        && let ExprKind::Lit(spanned) = &arg2.kind
+        && let LitKind::Str(param2, _) = &spanned.node
+        && param1 == param2.as_str()
+    {
+        span_lint(cx, NO_EFFECT_REPLACE, expr.span, "replacing text with itself");
     }
 
     if SpanlessEq::new(cx).eq_expr(arg1, arg2) {
diff --git a/clippy_lints/src/methods/ok_expect.rs b/clippy_lints/src/methods/ok_expect.rs
index f2ef42933df..e10bc0216e5 100644
--- a/clippy_lints/src/methods/ok_expect.rs
+++ b/clippy_lints/src/methods/ok_expect.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
@@ -10,23 +9,20 @@ use super::OK_EXPECT;
 
 /// lint use of `ok().expect()` for `Result`s
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
-    if_chain! {
+    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
         // lint if the caller of `ok()` is a `Result`
-        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
-        let result_type = cx.typeck_results().expr_ty(recv);
-        if let Some(error_type) = get_error_type(cx, result_type);
-        if has_debug_impl(cx, error_type);
-
-        then {
-            span_lint_and_help(
-                cx,
-                OK_EXPECT,
-                expr.span,
-                "called `ok().expect()` on a `Result` value",
-                None,
-                "you can call `expect()` directly on the `Result`",
-            );
-        }
+        && let result_type = cx.typeck_results().expr_ty(recv)
+        && let Some(error_type) = get_error_type(cx, result_type)
+        && has_debug_impl(cx, error_type)
+    {
+        span_lint_and_help(
+            cx,
+            OK_EXPECT,
+            expr.span,
+            "called `ok().expect()` on a `Result` value",
+            None,
+            "you can call `expect()` directly on the `Result`",
+        );
     }
 }
 
diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs
index 7b81d4571b2..15111006133 100644
--- a/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -58,34 +57,30 @@ pub(super) fn check(
 
             match &closure_expr.kind {
                 hir::ExprKind::MethodCall(_, receiver, [], _) => {
-                    if_chain! {
-                        if path_to_local_id(receiver, closure_body.params[0].pat.hir_id);
-                        let adj = cx
+                    if path_to_local_id(receiver, closure_body.params[0].pat.hir_id)
+                        && let adj = cx
                             .typeck_results()
                             .expr_adjustments(receiver)
                             .iter()
                             .map(|x| &x.kind)
-                            .collect::<Box<[_]>>();
-                        if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
-                        then {
-                            let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
-                            cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
-                                || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
-                                || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
-                        } else {
-                            false
-                        }
+                            .collect::<Box<[_]>>()
+                        && let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj
+                    {
+                        let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
+                        cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
+                            || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
+                            || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
+                    } else {
+                        false
                     }
                 },
                 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, inner) if same_mutability(m) => {
-                    if_chain! {
-                        if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind;
-                        if let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind;
-                        then {
-                            path_to_local_id(inner2, closure_body.params[0].pat.hir_id)
-                        } else {
-                            false
-                        }
+                    if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind
+                        && let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind
+                    {
+                        path_to_local_id(inner2, closure_body.params[0].pat.hir_id)
+                    } else {
+                        false
                     }
                 },
                 _ => false,
diff --git a/clippy_lints/src/methods/option_map_or_none.rs b/clippy_lints/src/methods/option_map_or_none.rs
index cb6a2306857..418e6a7d6a0 100644
--- a/clippy_lints/src/methods/option_map_or_none.rs
+++ b/clippy_lints/src/methods/option_map_or_none.rs
@@ -58,27 +58,25 @@ pub(super) fn check<'tcx>(
 
     if is_option {
         let self_snippet = snippet(cx, recv.span, "..");
-        if_chain! {
-            if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind;
-            let arg_snippet = snippet(cx, fn_decl_span, "..");
-            let body = cx.tcx.hir().body(body);
-            if let Some((func, [arg_char])) = reduce_unit_expression(body.value);
-            if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
-            if Some(id) == cx.tcx.lang_items().option_some_variant();
-            then {
-                let func_snippet = snippet(cx, arg_char.span, "..");
-                let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
-                   `map(..)` instead";
-                return span_lint_and_sugg(
-                    cx,
-                    OPTION_MAP_OR_NONE,
-                    expr.span,
-                    msg,
-                    "try using `map` instead",
-                    format!("{self_snippet}.map({arg_snippet} {func_snippet})"),
-                    Applicability::MachineApplicable,
-                );
-            }
+        if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind
+            && let arg_snippet = snippet(cx, fn_decl_span, "..")
+            && let body = cx.tcx.hir().body(body)
+            && let Some((func, [arg_char])) = reduce_unit_expression(body.value)
+            && let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id))
+            && Some(id) == cx.tcx.lang_items().option_some_variant()
+        {
+            let func_snippet = snippet(cx, arg_char.span, "..");
+            let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
+               `map(..)` instead";
+            return span_lint_and_sugg(
+                cx,
+                OPTION_MAP_OR_NONE,
+                expr.span,
+                msg,
+                "try using `map` instead",
+                format!("{self_snippet}.map({arg_snippet} {func_snippet})"),
+                Applicability::MachineApplicable,
+            );
         }
 
         let func_snippet = snippet(cx, map_arg.span, "..");
diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index b942346d5c3..dd669e49956 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/clippy_lints/src/methods/or_fun_call.rs
@@ -3,7 +3,6 @@ use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{expr_type_is_certain, implements_trait, is_type_diagnostic_item};
 use clippy_utils::{contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -131,54 +130,47 @@ pub(super) fn check<'tcx>(
             (sym::Result, true, &["or", "unwrap_or"], "else"),
         ];
 
-        if_chain! {
-            if KNOW_TYPES.iter().any(|k| k.2.contains(&name));
-
-            if switch_to_lazy_eval(cx, arg);
-            if !contains_return(arg);
-
-            let self_ty = cx.typeck_results().expr_ty(self_expr);
-
-            if let Some(&(_, fn_has_arguments, poss, suffix)) =
-                KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0));
-
-            if poss.contains(&name);
-
-            then {
-                let ctxt = span.ctxt();
-                let mut app = Applicability::HasPlaceholders;
-                let sugg = {
-                    let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) {
-                        (false, Some(fun_span)) => (fun_span, false),
-                        _ => (arg.span, true),
-                    };
-
-                    let snip = snippet_with_context(cx, snippet_span, ctxt, "..", &mut app).0;
-                    let snip = if use_lambda {
-                        let l_arg = if fn_has_arguments { "_" } else { "" };
-                        format!("|{l_arg}| {snip}")
-                    } else {
-                        snip.into_owned()
-                    };
-
-                    if let Some(f) = second_arg {
-                        let f = snippet_with_context(cx, f.span, ctxt, "..", &mut app).0;
-                        format!("{snip}, {f}")
-                    } else {
-                        snip
-                    }
+        if KNOW_TYPES.iter().any(|k| k.2.contains(&name))
+            && switch_to_lazy_eval(cx, arg)
+            && !contains_return(arg)
+            && let self_ty = cx.typeck_results().expr_ty(self_expr)
+            && let Some(&(_, fn_has_arguments, poss, suffix)) =
+                KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0))
+            && poss.contains(&name)
+        {
+            let ctxt = span.ctxt();
+            let mut app = Applicability::HasPlaceholders;
+            let sugg = {
+                let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) {
+                    (false, Some(fun_span)) => (fun_span, false),
+                    _ => (arg.span, true),
                 };
-                let span_replace_word = method_span.with_hi(span.hi());
-                span_lint_and_sugg(
-                    cx,
-                    OR_FUN_CALL,
-                    span_replace_word,
-                    &format!("use of `{name}` followed by a function call"),
-                    "try",
-                    format!("{name}_{suffix}({sugg})"),
-                    app,
-                );
-            }
+
+                let snip = snippet_with_context(cx, snippet_span, ctxt, "..", &mut app).0;
+                let snip = if use_lambda {
+                    let l_arg = if fn_has_arguments { "_" } else { "" };
+                    format!("|{l_arg}| {snip}")
+                } else {
+                    snip.into_owned()
+                };
+
+                if let Some(f) = second_arg {
+                    let f = snippet_with_context(cx, f.span, ctxt, "..", &mut app).0;
+                    format!("{snip}, {f}")
+                } else {
+                    snip
+                }
+            };
+            let span_replace_word = method_span.with_hi(span.hi());
+            span_lint_and_sugg(
+                cx,
+                OR_FUN_CALL,
+                span_replace_word,
+                &format!("use of `{name}` followed by a function call"),
+                "try",
+                format!("{name}_{suffix}({sugg})"),
+                app,
+            );
         }
     }
 
diff --git a/clippy_lints/src/methods/path_buf_push_overwrite.rs b/clippy_lints/src/methods/path_buf_push_overwrite.rs
index 1c07d2a3a59..04a27cc98f3 100644
--- a/clippy_lints/src/methods/path_buf_push_overwrite.rs
+++ b/clippy_lints/src/methods/path_buf_push_overwrite.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -11,27 +10,25 @@ use std::path::{Component, Path};
 use super::PATH_BUF_PUSH_OVERWRITE;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::PathBuf);
-        if let ExprKind::Lit(lit) = arg.kind;
-        if let LitKind::Str(ref path_lit, _) = lit.node;
-        if let pushed_path = Path::new(path_lit.as_str());
-        if let Some(pushed_path_lit) = pushed_path.to_str();
-        if pushed_path.has_root();
-        if let Some(root) = pushed_path.components().next();
-        if root == Component::RootDir;
-        then {
-            span_lint_and_sugg(
-                cx,
-                PATH_BUF_PUSH_OVERWRITE,
-                lit.span,
-                "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition",
-                "try",
-                format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')),
-                Applicability::MachineApplicable,
-            );
-        }
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::PathBuf)
+        && let ExprKind::Lit(lit) = arg.kind
+        && let LitKind::Str(ref path_lit, _) = lit.node
+        && let pushed_path = Path::new(path_lit.as_str())
+        && let Some(pushed_path_lit) = pushed_path.to_str()
+        && pushed_path.has_root()
+        && let Some(root) = pushed_path.components().next()
+        && root == Component::RootDir
+    {
+        span_lint_and_sugg(
+            cx,
+            PATH_BUF_PUSH_OVERWRITE,
+            lit.span,
+            "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition",
+            "try",
+            format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs
index f253d8de91f..1148628b084 100644
--- a/clippy_lints/src/methods/range_zip_with_len.rs
+++ b/clippy_lints/src/methods/range_zip_with_len.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet;
 use clippy_utils::{higher, is_integer_const, is_trait_method, SpanlessEq};
-use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -9,25 +8,26 @@ use rustc_span::sym;
 use super::RANGE_ZIP_WITH_LEN;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, zip_arg: &'tcx Expr<'_>) {
-    if_chain! {
-        if is_trait_method(cx, expr, sym::Iterator);
+    if is_trait_method(cx, expr, sym::Iterator)
         // range expression in `.zip()` call: `0..x.len()`
-        if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg);
-        if is_integer_const(cx, start, 0);
+        && let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg)
+        && is_integer_const(cx, start, 0)
         // `.len()` call
-        if let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind;
-        if len_path.ident.name == sym::len;
+        && let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind
+        && len_path.ident.name == sym::len
         // `.iter()` and `.len()` called on same `Path`
-        if let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind;
-        if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_recv.kind;
-        if SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments);
-        then {
-            span_lint(cx,
-                RANGE_ZIP_WITH_LEN,
-                expr.span,
-                &format!("it is more idiomatic to use `{}.iter().enumerate()`",
-                    snippet(cx, recv.span, "_"))
-            );
-        }
+        && let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind
+        && let ExprKind::Path(QPath::Resolved(_, len_path)) = len_recv.kind
+        && SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments)
+    {
+        span_lint(
+            cx,
+            RANGE_ZIP_WITH_LEN,
+            expr.span,
+            &format!(
+                "it is more idiomatic to use `{}.iter().enumerate()`",
+                snippet(cx, recv.span, "_")
+            ),
+        );
     }
 }
diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index 04ddaaa2f46..9b90a3df72f 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -3,7 +3,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::deref_closure_args;
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{is_trait_method, strip_pat_refs};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::PatKind;
@@ -35,29 +34,27 @@ pub(super) fn check<'tcx>(
             // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
             // suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
             let mut applicability = Applicability::MachineApplicable;
-            let any_search_snippet = if_chain! {
-                if search_method == "find";
-                if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind;
-                let closure_body = cx.tcx.hir().body(body);
-                if let Some(closure_arg) = closure_body.params.first();
-                then {
-                    if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
-                        Some(search_snippet.replacen('&', "", 1))
-                    } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind {
-                        // `find()` provides a reference to the item, but `any` does not,
-                        // so we should fix item usages for suggestion
-                        if let Some(closure_sugg) = deref_closure_args(cx, search_arg) {
-                            applicability = closure_sugg.applicability;
-                            Some(closure_sugg.suggestion)
-                        } else {
-                            Some(search_snippet.to_string())
-                        }
+            let any_search_snippet = if search_method == "find"
+                && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
+                && let closure_body = cx.tcx.hir().body(body)
+                && let Some(closure_arg) = closure_body.params.first()
+            {
+                if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
+                    Some(search_snippet.replacen('&', "", 1))
+                } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind {
+                    // `find()` provides a reference to the item, but `any` does not,
+                    // so we should fix item usages for suggestion
+                    if let Some(closure_sugg) = deref_closure_args(cx, search_arg) {
+                        applicability = closure_sugg.applicability;
+                        Some(closure_sugg.suggestion)
                     } else {
-                        None
+                        Some(search_snippet.to_string())
                     }
                 } else {
                     None
                 }
+            } else {
+                None
             };
             // add note if not multi-line
             if is_some {
@@ -110,41 +107,37 @@ pub(super) fn check<'tcx>(
                 self_ty.is_str()
             }
         };
-        if_chain! {
-            if is_string_or_str_slice(search_recv);
-            if is_string_or_str_slice(search_arg);
-            then {
-                let msg = format!("called `{option_check_method}()` after calling `find()` on a string");
-                match option_check_method {
-                    "is_some" => {
-                        let mut applicability = Applicability::MachineApplicable;
-                        let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
-                        span_lint_and_sugg(
-                            cx,
-                            SEARCH_IS_SOME,
-                            method_span.with_hi(expr.span.hi()),
-                            &msg,
-                            "use `contains()` instead",
-                            format!("contains({find_arg})"),
-                            applicability,
-                        );
-                    },
-                    "is_none" => {
-                        let string = snippet(cx, search_recv.span, "..");
-                        let mut applicability = Applicability::MachineApplicable;
-                        let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
-                        span_lint_and_sugg(
-                            cx,
-                            SEARCH_IS_SOME,
-                            expr.span,
-                            &msg,
-                            "use `!_.contains()` instead",
-                            format!("!{string}.contains({find_arg})"),
-                            applicability,
-                        );
-                    },
-                    _ => (),
-                }
+        if is_string_or_str_slice(search_recv) && is_string_or_str_slice(search_arg) {
+            let msg = format!("called `{option_check_method}()` after calling `find()` on a string");
+            match option_check_method {
+                "is_some" => {
+                    let mut applicability = Applicability::MachineApplicable;
+                    let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
+                    span_lint_and_sugg(
+                        cx,
+                        SEARCH_IS_SOME,
+                        method_span.with_hi(expr.span.hi()),
+                        &msg,
+                        "use `contains()` instead",
+                        format!("contains({find_arg})"),
+                        applicability,
+                    );
+                },
+                "is_none" => {
+                    let string = snippet(cx, search_recv.span, "..");
+                    let mut applicability = Applicability::MachineApplicable;
+                    let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
+                    span_lint_and_sugg(
+                        cx,
+                        SEARCH_IS_SOME,
+                        expr.span,
+                        &msg,
+                        "use `!_.contains()` instead",
+                        format!("!{string}.contains({find_arg})"),
+                        applicability,
+                    );
+                },
+                _ => (),
             }
         }
     }
diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs
index 4d704ec39eb..3983f0c0cab 100644
--- a/clippy_lints/src/methods/single_char_pattern.rs
+++ b/clippy_lints/src/methods/single_char_pattern.rs
@@ -1,6 +1,5 @@
 use super::utils::get_hint_if_single_char_arg;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -45,24 +44,23 @@ pub(super) fn check(
     args: &[hir::Expr<'_>],
 ) {
     for &(method, pos) in &PATTERN_METHODS {
-        if_chain! {
-            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind();
-            if ty.is_str();
-            if method_name.as_str() == method && args.len() > pos;
-            let arg = &args[pos];
-            let mut applicability = Applicability::MachineApplicable;
-            if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    SINGLE_CHAR_PATTERN,
-                    arg.span,
-                    "single-character string constant used as pattern",
-                    "try using a `char` instead",
-                    hint,
-                    applicability,
-                );
-            }
+        if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind()
+            && ty.is_str()
+            && method_name.as_str() == method
+            && args.len() > pos
+            && let arg = &args[pos]
+            && let mut applicability = Applicability::MachineApplicable
+            && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability)
+        {
+            span_lint_and_sugg(
+                cx,
+                SINGLE_CHAR_PATTERN,
+                arg.span,
+                "single-character string constant used as pattern",
+                "try using a `char` instead",
+                hint,
+                applicability,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs
index 9da61bca52c..0e7ad8fc996 100644
--- a/clippy_lints/src/methods/str_splitn.rs
+++ b/clippy_lints/src/methods/str_splitn.rs
@@ -6,7 +6,6 @@ use clippy_utils::usage::local_used_after_expr;
 use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
 use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
     BindingAnnotation, Expr, ExprKind, HirId, LangItem, Local, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind,
@@ -286,41 +285,35 @@ fn parse_iter_usage<'tcx>(
             match (name.ident.as_str(), args) {
                 ("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => (IterUsageKind::Nth(0), e.span),
                 ("next_tuple", []) => {
-                    return if_chain! {
-                        if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE);
-                        if let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind();
-                        if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did());
-                        if let ty::Tuple(subs) = subs.type_at(0).kind();
-                        if subs.len() == 2;
-                        then {
-                            Some(IterUsage {
-                                kind: IterUsageKind::NextTuple,
-                                span: e.span,
-                                unwrap_kind: None
-                            })
-                        } else {
-                            None
-                        }
+                    return if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE)
+                        && let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind()
+                        && cx.tcx.is_diagnostic_item(sym::Option, adt_def.did())
+                        && let ty::Tuple(subs) = subs.type_at(0).kind()
+                        && subs.len() == 2
+                    {
+                        Some(IterUsage {
+                            kind: IterUsageKind::NextTuple,
+                            span: e.span,
+                            unwrap_kind: None,
+                        })
+                    } else {
+                        None
                     };
                 },
                 ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
                     if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
                         let span = if name.ident.as_str() == "nth" {
                             e.span
+                        } else if let Some((_, Node::Expr(next_expr))) = iter.next()
+                            && let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind
+                            && next_name.ident.name == sym::next
+                            && next_expr.span.ctxt() == ctxt
+                            && let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id)
+                            && cx.tcx.trait_of_item(next_id) == Some(iter_id)
+                        {
+                            next_expr.span
                         } else {
-                            if_chain! {
-                                if let Some((_, Node::Expr(next_expr))) = iter.next();
-                                if let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind;
-                                if next_name.ident.name == sym::next;
-                                if next_expr.span.ctxt() == ctxt;
-                                if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id);
-                                if cx.tcx.trait_of_item(next_id) == Some(iter_id);
-                                then {
-                                    next_expr.span
-                                } else {
-                                    return None;
-                                }
-                            }
+                            return None;
                         };
                         (IterUsageKind::Nth(idx), span)
                     } else {
diff --git a/clippy_lints/src/methods/suspicious_map.rs b/clippy_lints/src/methods/suspicious_map.rs
index 0dc7fe2a2c5..ed49233acb7 100644
--- a/clippy_lints/src/methods/suspicious_map.rs
+++ b/clippy_lints/src/methods/suspicious_map.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::{expr_or_init, is_trait_method};
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -9,26 +8,24 @@ use rustc_span::sym;
 use super::SUSPICIOUS_MAP;
 
 pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
-    if_chain! {
-        if is_trait_method(cx, count_recv, sym::Iterator);
-        if let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind;
-        let closure_body = cx.tcx.hir().body(closure.body);
-        if !cx.typeck_results().expr_ty(closure_body.value).is_unit();
-        then {
-            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;
-                }
+    if is_trait_method(cx, count_recv, sym::Iterator)
+        && let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind
+        && 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) {
+            // A variable is used mutably inside of the closure. Suppress the lint.
+            if !map_mutated_vars.is_empty() {
+                return;
             }
-            span_lint_and_help(
-                cx,
-                SUSPICIOUS_MAP,
-                expr.span,
-                "this call to `map()` won't have an effect on the call to `count()`",
-                None,
-                "make sure you did not confuse `map` with `filter`, `for_each` or `inspect`",
-            );
         }
+        span_lint_and_help(
+            cx,
+            SUSPICIOUS_MAP,
+            expr.span,
+            "this call to `map()` won't have an effect on the call to `count()`",
+            None,
+            "make sure you did not confuse `map` with `filter`, `for_each` or `inspect`",
+        );
     }
 }
diff --git a/clippy_lints/src/methods/suspicious_splitn.rs b/clippy_lints/src/methods/suspicious_splitn.rs
index 3cb2719e4a0..c45212581ee 100644
--- a/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/clippy_lints/src/methods/suspicious_splitn.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_note;
-use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -8,41 +7,36 @@ use rustc_span::source_map::Spanned;
 use super::SUSPICIOUS_SPLITN;
 
 pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) {
-    if_chain! {
-        if count <= 1;
-        if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
-        if cx.tcx.impl_trait_ref(impl_id).is_none();
-        let self_ty = cx.tcx.type_of(impl_id).instantiate_identity();
-        if self_ty.is_slice() || self_ty.is_str();
-        then {
-            // Ignore empty slice and string literals when used with a literal count.
-            if matches!(self_arg.kind, ExprKind::Array([]))
-                || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
-            {
-                return;
-            }
+    if count <= 1
+        && let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(call_id)
+        && cx.tcx.impl_trait_ref(impl_id).is_none()
+        && let self_ty = cx.tcx.type_of(impl_id).instantiate_identity()
+        && (self_ty.is_slice() || self_ty.is_str())
+    {
+        // Ignore empty slice and string literals when used with a literal count.
+        if matches!(self_arg.kind, ExprKind::Array([]))
+            || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
+        {
+            return;
+        }
 
-            let (msg, note_msg) = if count == 0 {
-                (format!("`{method_name}` called with `0` splits"),
-                "the resulting iterator will always return `None`")
-            } else {
-                (format!("`{method_name}` called with `1` split"),
+        let (msg, note_msg) = if count == 0 {
+            (
+                format!("`{method_name}` called with `0` splits"),
+                "the resulting iterator will always return `None`",
+            )
+        } else {
+            (
+                format!("`{method_name}` called with `1` split"),
                 if self_ty.is_slice() {
                     "the resulting iterator will always return the entire slice followed by `None`"
                 } else {
                     "the resulting iterator will always return the entire string followed by `None`"
-                })
-            };
+                },
+            )
+        };
 
-            span_lint_and_note(
-                cx,
-                SUSPICIOUS_SPLITN,
-                expr.span,
-                &msg,
-                None,
-                note_msg,
-            );
-        }
+        span_lint_and_note(cx, SUSPICIOUS_SPLITN, expr.span, &msg, None, note_msg);
     }
 }
diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs
index 9eb8d6e6e78..60864902a48 100644
--- a/clippy_lints/src/methods/suspicious_to_owned.rs
+++ b/clippy_lints/src/methods/suspicious_to_owned.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_diag_trait_item;
 use clippy_utils::source::snippet_with_context;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -12,40 +11,37 @@ use rustc_span::sym;
 use super::SUSPICIOUS_TO_OWNED;
 
 pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -> bool {
-    if_chain! {
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if is_diag_trait_item(cx, method_def_id, sym::ToOwned);
-        let input_type = cx.typeck_results().expr_ty(expr);
-        if let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind();
-        if cx.tcx.is_diagnostic_item(sym::Cow, adt.did());
-
-        then {
-            let mut app = Applicability::MaybeIncorrect;
-            let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
-            span_lint_and_then(
-                cx,
-                SUSPICIOUS_TO_OWNED,
-                expr.span,
-                &with_forced_trimmed_paths!(format!(
-                    "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
-                )),
-                |diag| {
-                    diag.span_suggestion(
-                        expr.span,
-                        "depending on intent, either make the Cow an Owned variant",
-                        format!("{recv_snip}.into_owned()"),
-                        app
-                    );
-                    diag.span_suggestion(
-                        expr.span,
-                        "or clone the Cow itself",
-                        format!("{recv_snip}.clone()"),
-                        app
-                    );
-                }
-            );
-            return true;
-        }
+    if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && is_diag_trait_item(cx, method_def_id, sym::ToOwned)
+        && let input_type = cx.typeck_results().expr_ty(expr)
+        && let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind()
+        && cx.tcx.is_diagnostic_item(sym::Cow, adt.did())
+    {
+        let mut app = Applicability::MaybeIncorrect;
+        let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
+        span_lint_and_then(
+            cx,
+            SUSPICIOUS_TO_OWNED,
+            expr.span,
+            &with_forced_trimmed_paths!(format!(
+                "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
+            )),
+            |diag| {
+                diag.span_suggestion(
+                    expr.span,
+                    "depending on intent, either make the Cow an Owned variant",
+                    format!("{recv_snip}.into_owned()"),
+                    app,
+                );
+                diag.span_suggestion(
+                    expr.span,
+                    "or clone the Cow itself",
+                    format!("{recv_snip}.clone()"),
+                    app,
+                );
+            },
+        );
+        return true;
     }
     false
 }
diff --git a/clippy_lints/src/methods/uninit_assumed_init.rs b/clippy_lints/src/methods/uninit_assumed_init.rs
index bc9c518dbcf..1ee655d61e1 100644
--- a/clippy_lints/src/methods/uninit_assumed_init.rs
+++ b/clippy_lints/src/methods/uninit_assumed_init.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_path_diagnostic_item;
 use clippy_utils::ty::is_uninit_value_valid_for_ty;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -10,18 +9,16 @@ use super::UNINIT_ASSUMED_INIT;
 
 /// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter)
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
-    if_chain! {
-        if let hir::ExprKind::Call(callee, args) = recv.kind;
-        if args.is_empty();
-        if is_path_diagnostic_item(cx, callee, sym::maybe_uninit_uninit);
-        if !is_uninit_value_valid_for_ty(cx, cx.typeck_results().expr_ty_adjusted(expr));
-        then {
-            span_lint(
-                cx,
-                UNINIT_ASSUMED_INIT,
-                expr.span,
-                "this call for this type may be undefined behavior"
-            );
-        }
+    if let hir::ExprKind::Call(callee, args) = recv.kind
+        && args.is_empty()
+        && is_path_diagnostic_item(cx, callee, sym::maybe_uninit_uninit)
+        && !is_uninit_value_valid_for_ty(cx, cx.typeck_results().expr_ty_adjusted(expr))
+    {
+        span_lint(
+            cx,
+            UNINIT_ASSUMED_INIT,
+            expr.span,
+            "this call for this type may be undefined behavior",
+        );
     }
 }
diff --git a/clippy_lints/src/methods/unnecessary_fallible_conversions.rs b/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
index bb32b1bb7fc..89cf20c14fc 100644
--- a/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
+++ b/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
@@ -1,10 +1,11 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_parent_expr;
 use clippy_utils::ty::implements_trait;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_span::{sym, Span};
 
 use super::UNNECESSARY_FALLIBLE_CONVERSIONS;
@@ -42,6 +43,7 @@ fn check<'tcx>(
         // (else there would be conflicting impls, even with #![feature(spec)]), so we don't even need to check
         // what `<T as TryFrom<U>>::Error` is: it's always `Infallible`
         && implements_trait(cx, self_ty, from_into_trait, &[other_ty])
+        && let Some(other_ty) = other_ty.as_type()
     {
         let parent_unwrap_call = get_parent_expr(cx, expr).and_then(|parent| {
             if let ExprKind::MethodCall(path, .., span) = parent.kind
@@ -52,8 +54,7 @@ fn check<'tcx>(
                 None
             }
         });
-
-        let (sugg, span, applicability) = match kind {
+        let (source_ty, target_ty, sugg, span, applicability) = match kind {
             FunctionKind::TryIntoMethod if let Some(unwrap_span) = parent_unwrap_call => {
                 // Extend the span to include the unwrap/expect call:
                 // `foo.try_into().expect("..")`
@@ -63,24 +64,41 @@ fn check<'tcx>(
                 // so that can be machine-applicable
 
                 (
+                    self_ty,
+                    other_ty,
                     "into()",
                     primary_span.with_hi(unwrap_span.hi()),
                     Applicability::MachineApplicable,
                 )
             },
-            FunctionKind::TryFromFunction => ("From::from", primary_span, Applicability::Unspecified),
-            FunctionKind::TryIntoFunction => ("Into::into", primary_span, Applicability::Unspecified),
-            FunctionKind::TryIntoMethod => ("into", primary_span, Applicability::Unspecified),
+            FunctionKind::TryFromFunction => (
+                other_ty,
+                self_ty,
+                "From::from",
+                primary_span,
+                Applicability::Unspecified,
+            ),
+            FunctionKind::TryIntoFunction => (
+                self_ty,
+                other_ty,
+                "Into::into",
+                primary_span,
+                Applicability::Unspecified,
+            ),
+            FunctionKind::TryIntoMethod => (self_ty, other_ty, "into", primary_span, Applicability::Unspecified),
         };
 
-        span_lint_and_sugg(
+        span_lint_and_then(
             cx,
             UNNECESSARY_FALLIBLE_CONVERSIONS,
             span,
             "use of a fallible conversion when an infallible one could be used",
-            "use",
-            sugg.into(),
-            applicability,
+            |diag| {
+                with_forced_trimmed_paths!({
+                    diag.note(format!("converting `{source_ty}` to `{target_ty}` cannot fail"));
+                });
+                diag.span_suggestion(span, "use", sugg, applicability);
+            },
         );
     }
 }
diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs
index 6e23754bf46..7afd3802f7d 100644
--- a/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/clippy_lints/src/methods/unnecessary_fold.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_trait_method, path_to_local_id, peel_blocks, strip_pat_refs};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -61,57 +60,51 @@ fn check_fold_with_op(
     op: hir::BinOpKind,
     replacement: Replacement,
 ) {
-    if_chain! {
+    if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind
         // Extract the body of the closure passed to fold
-        if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind;
-        let closure_body = cx.tcx.hir().body(body);
-        let closure_expr = peel_blocks(closure_body.value);
+        && let closure_body = cx.tcx.hir().body(body)
+        && let closure_expr = peel_blocks(closure_body.value)
 
         // Check if the closure body is of the form `acc <op> some_expr(x)`
-        if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind;
-        if bin_op.node == op;
+        && let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind
+        && bin_op.node == op
 
         // Extract the names of the two arguments to the closure
-        if let [param_a, param_b] = closure_body.params;
-        if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind;
-        if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind;
+        && let [param_a, param_b] = closure_body.params
+        && let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind
+        && let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind
 
-        if path_to_local_id(left_expr, first_arg_id);
-        if replacement.has_args || path_to_local_id(right_expr, second_arg_id);
-
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-
-            let turbofish = if replacement.has_generic_return {
-                format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs())
-            } else {
-                String::new()
-            };
-
-            let sugg = if replacement.has_args {
-                format!(
-                    "{method}{turbofish}(|{second_arg_ident}| {r})",
-                    method = replacement.method_name,
-                    r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
-                )
-            } else {
-                format!(
-                    "{method}{turbofish}()",
-                    method = replacement.method_name,
-                )
-            };
-
-            span_lint_and_sugg(
-                cx,
-                UNNECESSARY_FOLD,
-                fold_span.with_hi(expr.span.hi()),
-                // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
-                "this `.fold` can be written more succinctly using another method",
-                "try",
-                sugg,
-                applicability,
-            );
-        }
+        && path_to_local_id(left_expr, first_arg_id)
+        && (replacement.has_args || path_to_local_id(right_expr, second_arg_id))
+    {
+        let mut applicability = Applicability::MachineApplicable;
+
+        let turbofish = if replacement.has_generic_return {
+            format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs())
+        } else {
+            String::new()
+        };
+
+        let sugg = if replacement.has_args {
+            format!(
+                "{method}{turbofish}(|{second_arg_ident}| {r})",
+                method = replacement.method_name,
+                r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
+            )
+        } else {
+            format!("{method}{turbofish}()", method = replacement.method_name,)
+        };
+
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_FOLD,
+            fold_span.with_hi(expr.span.hi()),
+            // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
+            "this `.fold` can be written more succinctly using another method",
+            "try",
+            sugg,
+            applicability,
+        );
     }
 }
 
diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 0c72c13a3ca..36497d59a5a 100644
--- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -13,15 +13,13 @@ use rustc_span::{sym, Symbol};
 use super::UNNECESSARY_TO_OWNED;
 
 pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>) -> bool {
-    if_chain! {
-        if let Some(parent) = get_parent_expr(cx, expr);
-        if let Some(callee_def_id) = fn_def_id(cx, parent);
-        if is_into_iter(cx, callee_def_id);
-        then {
-            check_for_loop_iter(cx, parent, method_name, receiver, false)
-        } else {
-            false
-        }
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let Some(callee_def_id) = fn_def_id(cx, parent)
+        && is_into_iter(cx, callee_def_id)
+    {
+        check_for_loop_iter(cx, parent, method_name, receiver, false)
+    } else {
+        false
     }
 }
 
@@ -36,65 +34,58 @@ pub fn check_for_loop_iter(
     receiver: &Expr<'_>,
     cloned_before_iter: bool,
 ) -> bool {
-    if_chain! {
-        if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent));
-        if let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent);
-        let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body);
-        if !clone_or_copy_needed;
-        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
-        then {
-            let snippet = if_chain! {
-                if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind;
-                if maybe_iter_method_name.ident.name == sym::iter;
-
-                if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
-                let receiver_ty = cx.typeck_results().expr_ty(receiver);
-                if implements_trait(cx, receiver_ty, iterator_trait_id, &[]);
-                if let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty);
-
-                if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator);
-                let collection_ty = cx.typeck_results().expr_ty(collection);
-                if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]);
-                if let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item");
-
-                if iter_item_ty == into_iter_item_ty;
-                if let Some(collection_snippet) = snippet_opt(cx, collection.span);
-                then {
-                    collection_snippet
+    if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent))
+        && let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent)
+        && let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body)
+        && !clone_or_copy_needed
+        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+    {
+        let snippet = if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind
+            && maybe_iter_method_name.ident.name == sym::iter
+            && let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
+            && let receiver_ty = cx.typeck_results().expr_ty(receiver)
+            && implements_trait(cx, receiver_ty, iterator_trait_id, &[])
+            && let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty)
+            && let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
+            && let collection_ty = cx.typeck_results().expr_ty(collection)
+            && implements_trait(cx, collection_ty, into_iterator_trait_id, &[])
+            && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item")
+            && iter_item_ty == into_iter_item_ty
+            && let Some(collection_snippet) = snippet_opt(cx, collection.span)
+        {
+            collection_snippet
+        } else {
+            receiver_snippet
+        };
+        span_lint_and_then(
+            cx,
+            UNNECESSARY_TO_OWNED,
+            expr.span,
+            &format!("unnecessary use of `{method_name}`"),
+            |diag| {
+                // If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to
+                // a `to_owned`-like function was removed, then the next suggestion may be
+                // incorrect. This is because the iterator that results from the call's removal
+                // could hold a reference to a resource that is used mutably. See
+                // https://github.com/rust-lang/rust-clippy/issues/8148.
+                let applicability = if cloned_before_iter {
+                    Applicability::MaybeIncorrect
                 } else {
-                    receiver_snippet
-                }
-            };
-            span_lint_and_then(
-                cx,
-                UNNECESSARY_TO_OWNED,
-                expr.span,
-                &format!("unnecessary use of `{method_name}`"),
-                |diag| {
-                    // If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to
-                    // a `to_owned`-like function was removed, then the next suggestion may be
-                    // incorrect. This is because the iterator that results from the call's removal
-                    // could hold a reference to a resource that is used mutably. See
-                    // https://github.com/rust-lang/rust-clippy/issues/8148.
-                    let applicability = if cloned_before_iter {
-                        Applicability::MaybeIncorrect
-                    } else {
-                        Applicability::MachineApplicable
-                    };
-                    diag.span_suggestion(expr.span, "use", snippet, applicability);
-                    for addr_of_expr in addr_of_exprs {
-                        match addr_of_expr.kind {
-                            ExprKind::AddrOf(_, _, referent) => {
-                                let span = addr_of_expr.span.with_hi(referent.span.lo());
-                                diag.span_suggestion(span, "remove this `&`", "", applicability);
-                            }
-                            _ => unreachable!(),
-                        }
+                    Applicability::MachineApplicable
+                };
+                diag.span_suggestion(expr.span, "use", snippet, applicability);
+                for addr_of_expr in addr_of_exprs {
+                    match addr_of_expr.kind {
+                        ExprKind::AddrOf(_, _, referent) => {
+                            let span = addr_of_expr.span.with_hi(referent.span.lo());
+                            diag.span_suggestion(span, "remove this `&`", "", applicability);
+                        },
+                        _ => unreachable!(),
                     }
                 }
-            );
-            return true;
-        }
+            },
+        );
+        return true;
     }
     false
 }
diff --git a/clippy_lints/src/methods/unnecessary_join.rs b/clippy_lints/src/methods/unnecessary_join.rs
index d0c62fb56dc..e2b389e96da 100644
--- a/clippy_lints/src/methods/unnecessary_join.rs
+++ b/clippy_lints/src/methods/unnecessary_join.rs
@@ -18,25 +18,23 @@ pub(super) fn check<'tcx>(
 ) {
     let applicability = Applicability::MachineApplicable;
     let collect_output_adjusted_type = cx.typeck_results().expr_ty_adjusted(join_self_arg);
-    if_chain! {
+    if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
         // the turbofish for collect is ::<Vec<String>>
-        if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind();
-        if let Slice(slice) = ref_type.kind();
-        if is_type_lang_item(cx, *slice, LangItem::String);
+        && let Slice(slice) = ref_type.kind()
+        && is_type_lang_item(cx, *slice, LangItem::String)
         // the argument for join is ""
-        if let ExprKind::Lit(spanned) = &join_arg.kind;
-        if let LitKind::Str(symbol, _) = spanned.node;
-        if symbol.is_empty();
-        then {
-            span_lint_and_sugg(
-                cx,
-                UNNECESSARY_JOIN,
-                span.with_hi(expr.span.hi()),
-                r#"called `.collect::<Vec<String>>().join("")` on an iterator"#,
-                "try using",
-                "collect::<String>()".to_owned(),
-                applicability,
-            );
-        }
+        && let ExprKind::Lit(spanned) = &join_arg.kind
+        && let LitKind::Str(symbol, _) = spanned.node
+        && symbol.is_empty()
+    {
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_JOIN,
+            span.with_hi(expr.span.hi()),
+            r#"called `.collect::<Vec<String>>().join("")` on an iterator"#,
+            "try using",
+            "collect::<String>()".to_owned(),
+            applicability,
+        );
     }
 }
diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs
index 79bff39379c..4949ccd770e 100644
--- a/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_trait_method;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::implements_trait;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
 use rustc_lint::LateContext;
@@ -116,55 +115,72 @@ fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident
 }
 
 fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) -> Option<LintTrigger> {
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if cx.tcx.type_of(impl_id).instantiate_identity().is_slice();
-        if let ExprKind::Closure(&Closure { body, .. }) = arg.kind;
-        if let closure_body = cx.tcx.hir().body(body);
-        if let &[
-            Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
-            Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. }
-        ] = &closure_body.params;
-        if let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind;
-        if method_path.ident.name == sym::cmp;
-        if is_trait_method(cx, closure_body.value, sym::Ord);
-        then {
-            let (closure_body, closure_arg, reverse) = if mirrored_exprs(
-                left_expr,
-                left_ident,
-                right_expr,
-                right_ident
-            ) {
-                (Sugg::hir(cx, left_expr, "..").to_string(), left_ident.name.to_string(), false)
-            } else if mirrored_exprs(left_expr, right_ident, right_expr, left_ident) {
-                (Sugg::hir(cx, left_expr, "..").to_string(), right_ident.name.to_string(), true)
-            } else {
-                return None;
-            };
-            let vec_name = Sugg::hir(cx, recv, "..").to_string();
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && cx.tcx.type_of(impl_id).instantiate_identity().is_slice()
+        && let ExprKind::Closure(&Closure { body, .. }) = arg.kind
+        && let closure_body = cx.tcx.hir().body(body)
+        && let &[
+            Param {
+                pat:
+                    Pat {
+                        kind: PatKind::Binding(_, _, left_ident, _),
+                        ..
+                    },
+                ..
+            },
+            Param {
+                pat:
+                    Pat {
+                        kind: PatKind::Binding(_, _, right_ident, _),
+                        ..
+                    },
+                ..
+            },
+        ] = &closure_body.params
+        && let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind
+        && method_path.ident.name == sym::cmp
+        && is_trait_method(cx, closure_body.value, sym::Ord)
+    {
+        let (closure_body, closure_arg, reverse) = if mirrored_exprs(left_expr, left_ident, right_expr, right_ident) {
+            (
+                Sugg::hir(cx, left_expr, "..").to_string(),
+                left_ident.name.to_string(),
+                false,
+            )
+        } else if mirrored_exprs(left_expr, right_ident, right_expr, left_ident) {
+            (
+                Sugg::hir(cx, left_expr, "..").to_string(),
+                right_ident.name.to_string(),
+                true,
+            )
+        } else {
+            return None;
+        };
+        let vec_name = Sugg::hir(cx, recv, "..").to_string();
 
-            if_chain! {
-                if let ExprKind::Path(QPath::Resolved(_, Path {
-                    segments: [PathSegment { ident: left_name, .. }], ..
-                })) = &left_expr.kind;
-                if left_name == left_ident;
-                if cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| {
-                    implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])
-                });
-                then {
-                    return Some(LintTrigger::Sort(SortDetection { vec_name }));
-                }
-            }
+        if let ExprKind::Path(QPath::Resolved(
+            _,
+            Path {
+                segments: [PathSegment { ident: left_name, .. }],
+                ..
+            },
+        )) = &left_expr.kind
+            && left_name == left_ident
+            && cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| {
+                implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])
+            })
+        {
+            return Some(LintTrigger::Sort(SortDetection { vec_name }));
+        }
 
-            if !expr_borrows(cx, left_expr) {
-                return Some(LintTrigger::SortByKey(SortByKeyDetection {
-                    vec_name,
-                    closure_arg,
-                    closure_body,
-                    reverse,
-                }));
-            }
+        if !expr_borrows(cx, left_expr) {
+            return Some(LintTrigger::SortByKey(SortByKeyDetection {
+                vec_name,
+                closure_arg,
+                closure_body,
+                reverse,
+            }));
         }
     }
 
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index 772686d93dd..395b22ebc5d 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -32,25 +32,23 @@ pub fn check<'tcx>(
     args: &'tcx [Expr<'_>],
     msrv: &Msrv,
 ) {
-    if_chain! {
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if args.is_empty();
-        then {
-            if is_cloned_or_copied(cx, method_name, method_def_id) {
-                unnecessary_iter_cloned::check(cx, expr, method_name, receiver);
-            } else if is_to_owned_like(cx, expr, method_name, method_def_id) {
-                // At this point, we know the call is of a `to_owned`-like function. The functions
-                // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary
-                // based on its context, that is, whether it is a referent in an `AddrOf` expression, an
-                // argument in a `into_iter` call, or an argument in the call of some other function.
-                if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) {
-                    return;
-                }
-                if check_into_iter_call_arg(cx, expr, method_name, receiver, msrv) {
-                    return;
-                }
-                check_other_call_arg(cx, expr, method_name, receiver);
+    if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && args.is_empty()
+    {
+        if is_cloned_or_copied(cx, method_name, method_def_id) {
+            unnecessary_iter_cloned::check(cx, expr, method_name, receiver);
+        } else if is_to_owned_like(cx, expr, method_name, method_def_id) {
+            // At this point, we know the call is of a `to_owned`-like function. The functions
+            // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary
+            // based on its context, that is, whether it is a referent in an `AddrOf` expression, an
+            // argument in a `into_iter` call, or an argument in the call of some other function.
+            if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) {
+                return;
             }
+            if check_into_iter_call_arg(cx, expr, method_name, receiver, msrv) {
+                return;
+            }
+            check_other_call_arg(cx, expr, method_name, receiver);
         }
     }
 }
@@ -65,11 +63,10 @@ fn check_addr_of_expr(
     method_def_id: DefId,
     receiver: &Expr<'_>,
 ) -> bool {
-    if_chain! {
-        if let Some(parent) = get_parent_expr(cx, expr);
-        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind;
-        let adjustments = cx.typeck_results().expr_adjustments(parent).iter().collect::<Vec<_>>();
-        if let
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind
+        && let adjustments = cx.typeck_results().expr_adjustments(parent).iter().collect::<Vec<_>>()
+        && let
             // For matching uses of `Cow::from`
             [
                 Adjustment {
@@ -110,10 +107,10 @@ fn check_addr_of_expr(
                     kind: Adjust::Borrow(_),
                     target: target_ty,
                 },
-            ] = adjustments[..];
-        let receiver_ty = cx.typeck_results().expr_ty(receiver);
-        let (target_ty, n_target_refs) = peel_mid_ty_refs(*target_ty);
-        let (receiver_ty, n_receiver_refs) = peel_mid_ty_refs(receiver_ty);
+            ] = adjustments[..]
+        && let receiver_ty = cx.typeck_results().expr_ty(receiver)
+        && let (target_ty, n_target_refs) = peel_mid_ty_refs(*target_ty)
+        && let (receiver_ty, n_receiver_refs) = peel_mid_ty_refs(receiver_ty)
         // Only flag cases satisfying at least one of the following three conditions:
         // * the referent and receiver types are distinct
         // * the referent/receiver type is a copyable array
@@ -123,77 +120,72 @@ fn check_addr_of_expr(
         //  https://github.com/rust-lang/rust-clippy/issues/8759
         //   Arrays are a bit of a corner case. Non-copyable arrays are handled by
         // `redundant_clone`, but copyable arrays are not.
-        if *referent_ty != receiver_ty
+        && (*referent_ty != receiver_ty
             || (matches!(referent_ty.kind(), ty::Array(..)) && is_copy(cx, *referent_ty))
-            || is_cow_into_owned(cx, method_name, method_def_id);
-        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
-        then {
-            if receiver_ty == target_ty && n_target_refs >= n_receiver_refs {
+            || is_cow_into_owned(cx, method_name, method_def_id))
+        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+    {
+        if receiver_ty == target_ty && n_target_refs >= n_receiver_refs {
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_TO_OWNED,
+                parent.span,
+                &format!("unnecessary use of `{method_name}`"),
+                "use",
+                format!(
+                    "{:&>width$}{receiver_snippet}",
+                    "",
+                    width = n_target_refs - n_receiver_refs
+                ),
+                Applicability::MachineApplicable,
+            );
+            return true;
+        }
+        if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
+            && implements_trait(cx, receiver_ty, deref_trait_id, &[])
+            && cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty)
+            // Make sure that it's actually calling the right `.to_string()`, (#10033)
+            // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow)
+            // but that's ok for Cow::into_owned specifically)
+            && (cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty
+                || is_cow_into_owned(cx, method_name, method_def_id))
+        {
+            if n_receiver_refs > 0 {
                 span_lint_and_sugg(
                     cx,
                     UNNECESSARY_TO_OWNED,
                     parent.span,
                     &format!("unnecessary use of `{method_name}`"),
                     "use",
-                    format!(
-                        "{:&>width$}{receiver_snippet}",
-                        "",
-                        width = n_target_refs - n_receiver_refs
-                    ),
+                    receiver_snippet,
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                span_lint_and_sugg(
+                    cx,
+                    UNNECESSARY_TO_OWNED,
+                    expr.span.with_lo(receiver.span.hi()),
+                    &format!("unnecessary use of `{method_name}`"),
+                    "remove this",
+                    String::new(),
                     Applicability::MachineApplicable,
                 );
-                return true;
-            }
-            if_chain! {
-                if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
-                if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
-                if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty);
-                // Make sure that it's actually calling the right `.to_string()`, (#10033)
-                // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow)
-                // but that's ok for Cow::into_owned specifically)
-                if cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty
-                    || is_cow_into_owned(cx, method_name, method_def_id);
-                then {
-                    if n_receiver_refs > 0 {
-                        span_lint_and_sugg(
-                            cx,
-                            UNNECESSARY_TO_OWNED,
-                            parent.span,
-                            &format!("unnecessary use of `{method_name}`"),
-                            "use",
-                            receiver_snippet,
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        span_lint_and_sugg(
-                            cx,
-                            UNNECESSARY_TO_OWNED,
-                            expr.span.with_lo(receiver.span.hi()),
-                            &format!("unnecessary use of `{method_name}`"),
-                            "remove this",
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                    return true;
-                }
-            }
-            if_chain! {
-                if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef);
-                if implements_trait(cx, receiver_ty, as_ref_trait_id, &[GenericArg::from(target_ty)]);
-                then {
-                    span_lint_and_sugg(
-                        cx,
-                        UNNECESSARY_TO_OWNED,
-                        parent.span,
-                        &format!("unnecessary use of `{method_name}`"),
-                        "use",
-                        format!("{receiver_snippet}.as_ref()"),
-                        Applicability::MachineApplicable,
-                    );
-                    return true;
-                }
             }
+            return true;
+        }
+        if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
+            && implements_trait(cx, receiver_ty, as_ref_trait_id, &[GenericArg::from(target_ty)])
+        {
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_TO_OWNED,
+                parent.span,
+                &format!("unnecessary use of `{method_name}`"),
+                "use",
+                format!("{receiver_snippet}.as_ref()"),
+                Applicability::MachineApplicable,
+            );
+            return true;
         }
     }
     false
@@ -208,38 +200,36 @@ fn check_into_iter_call_arg(
     receiver: &Expr<'_>,
     msrv: &Msrv,
 ) -> bool {
-    if_chain! {
-        if let Some(parent) = get_parent_expr(cx, expr);
-        if let Some(callee_def_id) = fn_def_id(cx, parent);
-        if is_into_iter(cx, callee_def_id);
-        if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
-        let parent_ty = cx.typeck_results().expr_ty(parent);
-        if implements_trait(cx, parent_ty, iterator_trait_id, &[]);
-        if let Some(item_ty) = get_iterator_item_ty(cx, parent_ty);
-        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
-        then {
-            if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) {
-                return true;
-            }
-            let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) {
-                "copied"
-            } else {
-                "cloned"
-            };
-            // The next suggestion may be incorrect because the removal of the `to_owned`-like
-            // function could cause the iterator to hold a reference to a resource that is used
-            // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148.
-            span_lint_and_sugg(
-                cx,
-                UNNECESSARY_TO_OWNED,
-                parent.span,
-                &format!("unnecessary use of `{method_name}`"),
-                "use",
-                format!("{receiver_snippet}.iter().{cloned_or_copied}()"),
-                Applicability::MaybeIncorrect,
-            );
+    if let Some(parent) = get_parent_expr(cx, expr)
+        && let Some(callee_def_id) = fn_def_id(cx, parent)
+        && is_into_iter(cx, callee_def_id)
+        && let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
+        && let parent_ty = cx.typeck_results().expr_ty(parent)
+        && implements_trait(cx, parent_ty, iterator_trait_id, &[])
+        && let Some(item_ty) = get_iterator_item_ty(cx, parent_ty)
+        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+    {
+        if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) {
             return true;
         }
+        let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) {
+            "copied"
+        } else {
+            "cloned"
+        };
+        // The next suggestion may be incorrect because the removal of the `to_owned`-like
+        // function could cause the iterator to hold a reference to a resource that is used
+        // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148.
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_TO_OWNED,
+            parent.span,
+            &format!("unnecessary use of `{method_name}`"),
+            "use",
+            format!("{receiver_snippet}.iter().{cloned_or_copied}()"),
+            Applicability::MaybeIncorrect,
+        );
+        return true;
     }
     false
 }
@@ -252,26 +242,25 @@ fn check_other_call_arg<'tcx>(
     method_name: Symbol,
     receiver: &'tcx Expr<'tcx>,
 ) -> bool {
-    if_chain! {
-        if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr);
-        if let Some((callee_def_id, _, recv, call_args)) = get_callee_generic_args_and_args(cx, maybe_call);
-        let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder();
-        if let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id);
-        if let Some(input) = fn_sig.inputs().get(i);
-        let (input, n_refs) = peel_mid_ty_refs(*input);
-        if let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input);
-        if let Some(sized_def_id) = cx.tcx.lang_items().sized_trait();
-        if let [trait_predicate] = trait_predicates
+    if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr)
+        && let Some((callee_def_id, _, recv, call_args)) = get_callee_generic_args_and_args(cx, maybe_call)
+        && let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder()
+        && let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id)
+        && let Some(input) = fn_sig.inputs().get(i)
+        && let (input, n_refs) = peel_mid_ty_refs(*input)
+        && let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input)
+        && let Some(sized_def_id) = cx.tcx.lang_items().sized_trait()
+        && let [trait_predicate] = trait_predicates
             .iter()
             .filter(|trait_predicate| trait_predicate.def_id() != sized_def_id)
-            .collect::<Vec<_>>()[..];
-        if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
-        if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef);
-        if trait_predicate.def_id() == deref_trait_id || trait_predicate.def_id() == as_ref_trait_id;
-        let receiver_ty = cx.typeck_results().expr_ty(receiver);
+            .collect::<Vec<_>>()[..]
+        && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
+        && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
+        && (trait_predicate.def_id() == deref_trait_id || trait_predicate.def_id() == as_ref_trait_id)
+        && let receiver_ty = cx.typeck_results().expr_ty(receiver)
         // We can't add an `&` when the trait is `Deref` because `Target = &T` won't match
         // `Target = T`.
-        if let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) {
+        && let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) {
             Some((n_refs, receiver_ty))
         } else if trait_predicate.def_id() != deref_trait_id {
             Some((1, Ty::new_ref(cx.tcx,
@@ -283,21 +272,20 @@ fn check_other_call_arg<'tcx>(
             )))
         } else {
             None
-        };
-        if can_change_type(cx, maybe_arg, receiver_ty);
-        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
-        then {
-            span_lint_and_sugg(
-                cx,
-                UNNECESSARY_TO_OWNED,
-                maybe_arg.span,
-                &format!("unnecessary use of `{method_name}`"),
-                "use",
-                format!("{:&>n_refs$}{receiver_snippet}", ""),
-                Applicability::MachineApplicable,
-            );
-            return true;
         }
+        && can_change_type(cx, maybe_arg, receiver_ty)
+        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+    {
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_TO_OWNED,
+            maybe_arg.span,
+            &format!("unnecessary use of `{method_name}`"),
+            "use",
+            format!("{:&>n_refs$}{receiver_snippet}", ""),
+            Applicability::MachineApplicable,
+        );
+        return true;
     }
     false
 }
@@ -329,22 +317,18 @@ fn get_callee_generic_args_and_args<'tcx>(
     Option<&'tcx Expr<'tcx>>,
     &'tcx [Expr<'tcx>],
 )> {
-    if_chain! {
-        if let ExprKind::Call(callee, args) = expr.kind;
-        let callee_ty = cx.typeck_results().expr_ty(callee);
-        if let ty::FnDef(callee_def_id, _) = callee_ty.kind();
-        then {
-            let generic_args = cx.typeck_results().node_args(callee.hir_id);
-            return Some((*callee_def_id, generic_args, None, args));
-        }
+    if let ExprKind::Call(callee, args) = expr.kind
+        && let callee_ty = cx.typeck_results().expr_ty(callee)
+        && let ty::FnDef(callee_def_id, _) = callee_ty.kind()
+    {
+        let generic_args = cx.typeck_results().node_args(callee.hir_id);
+        return Some((*callee_def_id, generic_args, None, args));
     }
-    if_chain! {
-        if let ExprKind::MethodCall(_, recv, args, _) = expr.kind;
-        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        then {
-            let generic_args = cx.typeck_results().node_args(expr.hir_id);
-            return Some((method_def_id, generic_args, Some(recv), args));
-        }
+    if let ExprKind::MethodCall(_, recv, args, _) = expr.kind
+        && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+    {
+        let generic_args = cx.typeck_results().node_args(expr.hir_id);
+        return Some((method_def_id, generic_args, Some(recv), args));
     }
     None
 }
diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs
index b5f810eddf4..84ee64e88a6 100644
--- a/clippy_lints/src/methods/useless_asref.rs
+++ b/clippy_lints/src/methods/useless_asref.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::walk_ptrs_ty_depth;
 use clippy_utils::{get_parent_expr, is_trait_method};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -22,13 +21,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
         let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty);
         if base_rcv_ty == base_res_ty && rcv_depth >= res_depth {
             // allow the `as_ref` or `as_mut` if it is followed by another method call
-            if_chain! {
-                if let Some(parent) = get_parent_expr(cx, expr);
-                if let hir::ExprKind::MethodCall(segment, ..) = parent.kind;
-                if segment.ident.span != expr.span;
-                then {
-                    return;
-                }
+            if let Some(parent) = get_parent_expr(cx, expr)
+                && let hir::ExprKind::MethodCall(segment, ..) = parent.kind
+                && segment.ident.span != expr.span
+            {
+                return;
             }
 
             let mut applicability = Applicability::MachineApplicable;
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index 9f1f73e6021..9ad4250a141 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -1,7 +1,6 @@
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, path_to_local_id, usage};
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -55,32 +54,33 @@ pub(super) fn get_hint_if_single_char_arg(
     arg: &hir::Expr<'_>,
     applicability: &mut Applicability,
 ) -> Option<String> {
-    if_chain! {
-        if let hir::ExprKind::Lit(lit) = &arg.kind;
-        if let ast::LitKind::Str(r, style) = lit.node;
-        let string = r.as_str();
-        if string.chars().count() == 1;
-        then {
-            let snip = snippet_with_applicability(cx, arg.span, string, applicability);
-            let ch = if let ast::StrStyle::Raw(nhash) = style {
-                let nhash = nhash as usize;
-                // for raw string: r##"a"##
-                &snip[(nhash + 2)..(snip.len() - 1 - nhash)]
-            } else {
-                // for regular string: "a"
-                &snip[1..(snip.len() - 1)]
-            };
+    if let hir::ExprKind::Lit(lit) = &arg.kind
+        && let ast::LitKind::Str(r, style) = lit.node
+        && let string = r.as_str()
+        && string.chars().count() == 1
+    {
+        let snip = snippet_with_applicability(cx, arg.span, string, applicability);
+        let ch = if let ast::StrStyle::Raw(nhash) = style {
+            let nhash = nhash as usize;
+            // for raw string: r##"a"##
+            &snip[(nhash + 2)..(snip.len() - 1 - nhash)]
+        } else {
+            // for regular string: "a"
+            &snip[1..(snip.len() - 1)]
+        };
 
-            let hint = format!("'{}'", match ch {
-                "'" => "\\'" ,
+        let hint = format!(
+            "'{}'",
+            match ch {
+                "'" => "\\'",
                 r"\" => "\\\\",
                 _ => ch,
-            });
+            }
+        );
 
-            Some(hint)
-        } else {
-            None
-        }
+        Some(hint)
+    } else {
+        None
     }
 }
 
@@ -140,15 +140,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
                         return;
                     },
                     ExprKind::MethodCall(.., args, _) => {
-                        if_chain! {
-                            if args.iter().all(|arg| !self.is_binding(arg));
-                            if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
-                            let method_ty = self.cx.tcx.type_of(method_def_id).instantiate_identity();
-                            let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder();
-                            if matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not));
-                            then {
-                                return;
-                            }
+                        if args.iter().all(|arg| !self.is_binding(arg))
+                            && let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id)
+                            && let method_ty = self.cx.tcx.type_of(method_def_id).instantiate_identity()
+                            && let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder()
+                            && matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not))
+                        {
+                            return;
                         }
                     },
                     _ => {},
diff --git a/clippy_lints/src/methods/vec_resize_to_zero.rs b/clippy_lints/src/methods/vec_resize_to_zero.rs
index 73072718678..9e87fb45aa6 100644
--- a/clippy_lints/src/methods/vec_resize_to_zero.rs
+++ b/clippy_lints/src/methods/vec_resize_to_zero.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -17,29 +16,32 @@ pub(super) fn check<'tcx>(
     default_arg: &'tcx Expr<'_>,
     name_span: Span,
 ) {
-    if_chain! {
-        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
-        if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec);
-        if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = count_arg.kind;
-        if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = default_arg.kind;
-        then {
-            let method_call_span = expr.span.with_lo(name_span.lo());
-            span_lint_and_then(
-                cx,
-                VEC_RESIZE_TO_ZERO,
-                expr.span,
-                "emptying a vector with `resize`",
-                |db| {
-                    db.help("the arguments may be inverted...");
-                    db.span_suggestion(
-                        method_call_span,
-                        "...or you can empty the vector with",
-                        "clear()".to_string(),
-                        Applicability::MaybeIncorrect,
-                    );
-                },
-            );
-        }
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+        && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
+        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec)
+        && let ExprKind::Lit(Spanned {
+            node: LitKind::Int(0, _),
+            ..
+        }) = count_arg.kind
+        && let ExprKind::Lit(Spanned {
+            node: LitKind::Int(..), ..
+        }) = default_arg.kind
+    {
+        let method_call_span = expr.span.with_lo(name_span.lo());
+        span_lint_and_then(
+            cx,
+            VEC_RESIZE_TO_ZERO,
+            expr.span,
+            "emptying a vector with `resize`",
+            |db| {
+                db.help("the arguments may be inverted...");
+                db.span_suggestion(
+                    method_call_span,
+                    "...or you can empty the vector with",
+                    "clear()".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            },
+        );
     }
 }
diff --git a/clippy_lints/src/methods/zst_offset.rs b/clippy_lints/src/methods/zst_offset.rs
index e9f268da691..0b829d99aef 100644
--- a/clippy_lints/src/methods/zst_offset.rs
+++ b/clippy_lints/src/methods/zst_offset.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -7,12 +6,10 @@ use rustc_middle::ty;
 use super::ZST_OFFSET;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
-    if_chain! {
-        if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind();
-        if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty));
-        if layout.is_zst();
-        then {
-            span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");
-        }
+    if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind()
+        && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty))
+        && layout.is_zst()
+    {
+        span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");
     }
 }
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 01eace6c48c..a3d5a8a9d83 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -5,7 +5,6 @@ use clippy_utils::{
     any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats,
     last_path_segment, SpanlessEq,
 };
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::FnKind;
@@ -143,73 +142,64 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
     }
 
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if_chain! {
-            if !in_external_macro(cx.tcx.sess, stmt.span);
-            if let StmtKind::Local(local) = stmt.kind;
-            if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
-            if let Some(init) = local.init;
+        if !in_external_macro(cx.tcx.sess, stmt.span)
+            && let StmtKind::Local(local) = stmt.kind
+            && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind
+            && let Some(init) = local.init
             // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
-            if is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id);
-            then {
-                let ctxt = local.span.ctxt();
-                let mut app = Applicability::MachineApplicable;
-                let sugg_init = Sugg::hir_with_context(cx, init, ctxt, "..", &mut app);
-                let (mutopt, initref) = if mutabl == Mutability::Mut {
-                    ("mut ", sugg_init.mut_addr())
-                } else {
-                    ("", sugg_init.addr())
-                };
-                let tyopt = if let Some(ty) = local.ty {
-                    let ty_snip = snippet_with_context(cx, ty.span, ctxt, "_", &mut app).0;
-                    format!(": &{mutopt}{ty_snip}")
-                } else {
-                    String::new()
-                };
-                span_lint_hir_and_then(
-                    cx,
-                    TOPLEVEL_REF_ARG,
-                    init.hir_id,
-                    local.pat.span,
-                    "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
-                    |diag| {
-                        diag.span_suggestion(
-                            stmt.span,
-                            "try",
-                            format!(
-                                "let {name}{tyopt} = {initref};",
-                                name=snippet(cx, name.span, ".."),
-                            ),
-                            app,
-                        );
-                    }
-                );
-            }
+            && is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id)
+        {
+            let ctxt = local.span.ctxt();
+            let mut app = Applicability::MachineApplicable;
+            let sugg_init = Sugg::hir_with_context(cx, init, ctxt, "..", &mut app);
+            let (mutopt, initref) = if mutabl == Mutability::Mut {
+                ("mut ", sugg_init.mut_addr())
+            } else {
+                ("", sugg_init.addr())
+            };
+            let tyopt = if let Some(ty) = local.ty {
+                let ty_snip = snippet_with_context(cx, ty.span, ctxt, "_", &mut app).0;
+                format!(": &{mutopt}{ty_snip}")
+            } else {
+                String::new()
+            };
+            span_lint_hir_and_then(
+                cx,
+                TOPLEVEL_REF_ARG,
+                init.hir_id,
+                local.pat.span,
+                "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
+                |diag| {
+                    diag.span_suggestion(
+                        stmt.span,
+                        "try",
+                        format!("let {name}{tyopt} = {initref};", name = snippet(cx, name.span, ".."),),
+                        app,
+                    );
+                },
+            );
         };
-        if_chain! {
-            if let StmtKind::Semi(expr) = stmt.kind;
-            if let ExprKind::Binary(ref binop, a, b) = expr.kind;
-            if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
-            if let Some(sugg) = Sugg::hir_opt(cx, a);
-            then {
-                span_lint_hir_and_then(
-                    cx,
-                    SHORT_CIRCUIT_STATEMENT,
-                    expr.hir_id,
-                    stmt.span,
-                    "boolean short circuit operator in statement may be clearer using an explicit test",
-                    |diag| {
-                        let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
-                        diag.span_suggestion(
-                            stmt.span,
-                            "replace it with",
-                            format!(
-                                "if {sugg} {{ {}; }}",
-                                &snippet(cx, b.span, ".."),
-                            ),
-                            Applicability::MachineApplicable, // snippet
-                        );
-                    });
-            }
+        if let StmtKind::Semi(expr) = stmt.kind
+            && let ExprKind::Binary(ref binop, a, b) = expr.kind
+            && (binop.node == BinOpKind::And || binop.node == BinOpKind::Or)
+            && let Some(sugg) = Sugg::hir_opt(cx, a)
+        {
+            span_lint_hir_and_then(
+                cx,
+                SHORT_CIRCUIT_STATEMENT,
+                expr.hir_id,
+                stmt.span,
+                "boolean short circuit operator in statement may be clearer using an explicit test",
+                |diag| {
+                    let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
+                    diag.span_suggestion(
+                        stmt.span,
+                        "replace it with",
+                        format!("if {sugg} {{ {}; }}", &snippet(cx, b.span, ".."),),
+                        Applicability::MachineApplicable, // snippet
+                    );
+                },
+            );
         };
     }
 
diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs
index 0d79ece087f..c74d0d623df 100644
--- a/clippy_lints/src/mismatching_type_param_order.rs
+++ b/clippy_lints/src/mismatching_type_param_order.rs
@@ -49,59 +49,59 @@ declare_lint_pass!(TypeParamMismatch => [MISMATCHING_TYPE_PARAM_ORDER]);
 
 impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if_chain! {
-            if !item.span.from_expansion();
-            if let ItemKind::Impl(imp) = &item.kind;
-            if let TyKind::Path(QPath::Resolved(_, path)) = &imp.self_ty.kind;
-            if let Some(segment) = path.segments.iter().next();
-            if let Some(generic_args) = segment.args;
-            if !generic_args.args.is_empty();
-            then {
-                // get the name and span of the generic parameters in the Impl
-                let mut impl_params = Vec::new();
-                for p in generic_args.args {
-                    match p {
-                        GenericArg::Type(Ty {kind: TyKind::Path(QPath::Resolved(_, path)), ..}) =>
-                            impl_params.push((path.segments[0].ident.to_string(), path.span)),
-                        GenericArg::Type(_) => return,
-                        _ => (),
-                    };
-                }
-
-                // find the type that the Impl is for
-                // only lint on struct/enum/union for now
-                let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, defid) = path.res else {
-                    return
+        if !item.span.from_expansion()
+            && let ItemKind::Impl(imp) = &item.kind
+            && let TyKind::Path(QPath::Resolved(_, path)) = &imp.self_ty.kind
+            && let Some(segment) = path.segments.iter().next()
+            && let Some(generic_args) = segment.args
+            && !generic_args.args.is_empty()
+        {
+            // get the name and span of the generic parameters in the Impl
+            let mut impl_params = Vec::new();
+            for p in generic_args.args {
+                match p {
+                    GenericArg::Type(Ty {
+                        kind: TyKind::Path(QPath::Resolved(_, path)),
+                        ..
+                    }) => impl_params.push((path.segments[0].ident.to_string(), path.span)),
+                    GenericArg::Type(_) => return,
+                    _ => (),
                 };
+            }
+
+            // find the type that the Impl is for
+            // only lint on struct/enum/union for now
+            let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, defid) = path.res else {
+                return;
+            };
 
-                // get the names of the generic parameters in the type
-                let type_params = &cx.tcx.generics_of(defid).params;
-                let type_param_names: Vec<_> = type_params.iter()
-                .filter_map(|p|
-                    match p.kind {
-                        GenericParamDefKind::Type {..} => Some(p.name.to_string()),
-                        _ => None,
-                    }
-                ).collect();
-                // hashmap of name -> index for mismatch_param_name
-                let type_param_names_hashmap: FxHashMap<&String, usize> =
-                    type_param_names.iter().enumerate().map(|(i, param)| (param, i)).collect();
+            // get the names of the generic parameters in the type
+            let type_params = &cx.tcx.generics_of(defid).params;
+            let type_param_names: Vec<_> = type_params
+                .iter()
+                .filter_map(|p| match p.kind {
+                    GenericParamDefKind::Type { .. } => Some(p.name.to_string()),
+                    _ => None,
+                })
+                .collect();
+            // hashmap of name -> index for mismatch_param_name
+            let type_param_names_hashmap: FxHashMap<&String, usize> = type_param_names
+                .iter()
+                .enumerate()
+                .map(|(i, param)| (param, i))
+                .collect();
 
-                let type_name = segment.ident;
-                for (i, (impl_param_name, impl_param_span)) in impl_params.iter().enumerate() {
-                    if mismatch_param_name(i, impl_param_name, &type_param_names_hashmap) {
-                        let msg = format!("`{type_name}` has a similarly named generic type parameter `{impl_param_name}` in its declaration, but in a different order");
-                        let help = format!("try `{}`, or a name that does not conflict with `{type_name}`'s generic params",
-                                           type_param_names[i]);
-                        span_lint_and_help(
-                            cx,
-                            MISMATCHING_TYPE_PARAM_ORDER,
-                            *impl_param_span,
-                            &msg,
-                            None,
-                            &help
-                        );
-                    }
+            let type_name = segment.ident;
+            for (i, (impl_param_name, impl_param_span)) in impl_params.iter().enumerate() {
+                if mismatch_param_name(i, impl_param_name, &type_param_names_hashmap) {
+                    let msg = format!(
+                        "`{type_name}` has a similarly named generic type parameter `{impl_param_name}` in its declaration, but in a different order"
+                    );
+                    let help = format!(
+                        "try `{}`, or a name that does not conflict with `{type_name}`'s generic params",
+                        type_param_names[i]
+                    );
+                    span_lint_and_help(cx, MISMATCHING_TYPE_PARAM_ORDER, *impl_param_span, &msg, None, &help);
                 }
             }
         }
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index 0629dee4f72..1dcaa60ac7b 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -8,7 +8,6 @@
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
-use if_chain::if_chain;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -64,16 +63,14 @@ impl MissingDoc {
     }
 
     fn has_include(meta: Option<MetaItem>) -> bool {
-        if_chain! {
-            if let Some(meta) = meta;
-            if let MetaItemKind::List(list) = meta.kind;
-            if let Some(meta) = list.first();
-            if let Some(name) = meta.ident();
-            then {
-                name.name == sym::include
-            } else {
-                false
-            }
+        if let Some(meta) = meta
+            && let MetaItemKind::List(list) = meta.kind
+            && let Some(meta) = list.first()
+            && let Some(name) = meta.ident()
+        {
+            name.name == sym::include
+        } else {
+            false
         }
     }
 
diff --git a/clippy_lints/src/missing_enforced_import_rename.rs b/clippy_lints/src/missing_enforced_import_rename.rs
index 16ff98a5922..f7e42815104 100644
--- a/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/clippy_lints/src/missing_enforced_import_rename.rs
@@ -72,13 +72,12 @@ impl LateLintPass<'_> for ImportRename {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         if let ItemKind::Use(path, UseKind::Single) = &item.kind {
             for &res in &path.res {
-                if_chain! {
-                    if let Res::Def(_, id) = res;
-                    if let Some(name) = self.renames.get(&id);
+                if let Res::Def(_, id) = res
+                    && let Some(name) = self.renames.get(&id)
                     // Remove semicolon since it is not present for nested imports
-                    let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';');
-                    if let Some(snip) = snippet_opt(cx, span_without_semi);
-                    if let Some(import) = match snip.split_once(" as ") {
+                    && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';')
+                    && let Some(snip) = snippet_opt(cx, span_without_semi)
+                    && let Some(import) = match snip.split_once(" as ") {
                         None => Some(snip.as_str()),
                         Some((import, rename)) => {
                             if rename.trim() == name.as_str() {
@@ -87,20 +86,17 @@ impl LateLintPass<'_> for ImportRename {
                                 Some(import.trim())
                             }
                         },
-                    };
-                    then {
-                        span_lint_and_sugg(
-                            cx,
-                            MISSING_ENFORCED_IMPORT_RENAMES,
-                            span_without_semi,
-                            "this import should be renamed",
-                            "try",
-                            format!(
-                                "{import} as {name}",
-                            ),
-                            Applicability::MachineApplicable,
-                        );
                     }
+                {
+                    span_lint_and_sugg(
+                        cx,
+                        MISSING_ENFORCED_IMPORT_RENAMES,
+                        span_without_semi,
+                        "this import should be renamed",
+                        "try",
+                        format!("{import} as {name}",),
+                        Applicability::MachineApplicable,
+                    );
                 }
             }
         }
diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs
index 215161b04c7..b46c006cd57 100644
--- a/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
 use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
-use if_chain::if_chain;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -80,11 +79,13 @@ declare_lint_pass!(EvalOrderDependence => [MIXED_READ_WRITE_IN_EXPRESSION, DIVER
 impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // Find a write to a local variable.
-        let var = if_chain! {
-            if let ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) = expr.kind;
-            if let Some(var) = path_to_local(lhs);
-            if expr.span.desugaring_kind().is_none();
-            then { var } else { return; }
+        let var = if let ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) = expr.kind
+            && let Some(var) = path_to_local(lhs)
+            && expr.span.desugaring_kind().is_none()
+        {
+            var
+        } else {
+            return;
         };
         let mut visitor = ReadVisitor {
             cx,
diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index efdc7560ee4..b49a5614329 100644
--- a/clippy_lints/src/module_style.rs
+++ b/clippy_lints/src/module_style.rs
@@ -153,8 +153,11 @@ fn process_paths_for_mod_files<'a>(
 }
 
 /// Checks every path for the presence of `mod.rs` files and emits the lint if found.
+/// We should not emit a lint for test modules in the presence of `mod.rs`.
+/// Using `mod.rs` in integration tests is a [common pattern](https://doc.rust-lang.org/book/ch11-03-test-organization.html#submodules-in-integration-test)
+/// for code-sharing between tests.
 fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &SourceFile) {
-    if path.ends_with("mod.rs") {
+    if path.ends_with("mod.rs") && !path.starts_with("tests") {
         let mut mod_file = path.to_path_buf();
         mod_file.pop();
         mod_file.set_extension("rs");
diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs
index 97e8f1c030a..1712262ff3e 100644
--- a/clippy_lints/src/needless_arbitrary_self_type.rs
+++ b/clippy_lints/src/needless_arbitrary_self_type.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use if_chain::if_chain;
 use rustc_ast::ast::{BindingAnnotation, ByRef, Lifetime, Mutability, Param, PatKind, Path, TyKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -66,48 +65,46 @@ enum Mode {
 }
 
 fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mode: &Mode, mutbl: Mutability) {
-    if_chain! {
-        if let [segment] = &path.segments[..];
-        if segment.ident.name == kw::SelfUpper;
-        then {
-            // In case we have a named lifetime, we check if the name comes from expansion.
-            // If it does, at this point we know the rest of the parameter was written by the user,
-            // so let them decide what the name of the lifetime should be.
-            // See #6089 for more details.
-            let mut applicability = Applicability::MachineApplicable;
-            let self_param = match (binding_mode, mutbl) {
-                (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(),
-                (Mode::Ref(Some(lifetime)), Mutability::Mut) => {
-                    if lifetime.ident.span.from_expansion() {
-                        applicability = Applicability::HasPlaceholders;
-                        "&'_ mut self".to_string()
-                    } else {
-                        format!("&{} mut self", &lifetime.ident.name)
-                    }
-                },
-                (Mode::Ref(None), Mutability::Not) => "&self".to_string(),
-                (Mode::Ref(Some(lifetime)), Mutability::Not) => {
-                    if lifetime.ident.span.from_expansion() {
-                        applicability = Applicability::HasPlaceholders;
-                        "&'_ self".to_string()
-                    } else {
-                        format!("&{} self", &lifetime.ident.name)
-                    }
-                },
-                (Mode::Value, Mutability::Mut) => "mut self".to_string(),
-                (Mode::Value, Mutability::Not) => "self".to_string(),
-            };
+    if let [segment] = &path.segments[..]
+        && segment.ident.name == kw::SelfUpper
+    {
+        // In case we have a named lifetime, we check if the name comes from expansion.
+        // If it does, at this point we know the rest of the parameter was written by the user,
+        // so let them decide what the name of the lifetime should be.
+        // See #6089 for more details.
+        let mut applicability = Applicability::MachineApplicable;
+        let self_param = match (binding_mode, mutbl) {
+            (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(),
+            (Mode::Ref(Some(lifetime)), Mutability::Mut) => {
+                if lifetime.ident.span.from_expansion() {
+                    applicability = Applicability::HasPlaceholders;
+                    "&'_ mut self".to_string()
+                } else {
+                    format!("&{} mut self", &lifetime.ident.name)
+                }
+            },
+            (Mode::Ref(None), Mutability::Not) => "&self".to_string(),
+            (Mode::Ref(Some(lifetime)), Mutability::Not) => {
+                if lifetime.ident.span.from_expansion() {
+                    applicability = Applicability::HasPlaceholders;
+                    "&'_ self".to_string()
+                } else {
+                    format!("&{} self", &lifetime.ident.name)
+                }
+            },
+            (Mode::Value, Mutability::Mut) => "mut self".to_string(),
+            (Mode::Value, Mutability::Not) => "self".to_string(),
+        };
 
-            span_lint_and_sugg(
-                cx,
-                NEEDLESS_ARBITRARY_SELF_TYPE,
-                span,
-                "the type of the `self` parameter does not need to be arbitrary",
-                "consider to change this parameter to",
-                self_param,
-                applicability,
-            )
-        }
+        span_lint_and_sugg(
+            cx,
+            NEEDLESS_ARBITRARY_SELF_TYPE,
+            span,
+            "the type of the `self` parameter does not need to be arbitrary",
+            "consider to change this parameter to",
+            self_param,
+            applicability,
+        );
     }
 }
 
@@ -125,12 +122,10 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
                 }
             },
             TyKind::Ref(lifetime, mut_ty) => {
-                if_chain! {
-                if let TyKind::Path(None, path) = &mut_ty.ty.kind;
-                if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind;
-                    then {
-                        check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
-                    }
+                if let TyKind::Path(None, path) = &mut_ty.ty.kind
+                    && let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind
+                {
+                    check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
                 }
             },
             _ => {},
diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs
index cb2738947d4..6803034f475 100644
--- a/clippy_lints/src/needless_continue.rs
+++ b/clippy_lints/src/needless_continue.rs
@@ -362,21 +362,19 @@ fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &Lin
 }
 
 fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) {
-    if_chain! {
-        if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind;
-        if let Some(last_stmt) = loop_block.stmts.last();
-        if let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind;
-        if let ast::ExprKind::Continue(_) = inner_expr.kind;
-        then {
-            span_lint_and_help(
-                cx,
-                NEEDLESS_CONTINUE,
-                last_stmt.span,
-                MSG_REDUNDANT_CONTINUE_EXPRESSION,
-                None,
-                DROP_CONTINUE_EXPRESSION_MSG,
-            );
-        }
+    if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind
+        && let Some(last_stmt) = loop_block.stmts.last()
+        && let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind
+        && let ast::ExprKind::Continue(_) = inner_expr.kind
+    {
+        span_lint_and_help(
+            cx,
+            NEEDLESS_CONTINUE,
+            last_stmt.span,
+            MSG_REDUNDANT_CONTINUE_EXPRESSION,
+            None,
+            DROP_CONTINUE_EXPRESSION_MSG,
+        );
     }
     with_loop_block(expr, |loop_block, label| {
         for (i, stmt) in loop_block.stmts.iter().enumerate() {
diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs
index 086c8e6fffe..0203e2ccd63 100644
--- a/clippy_lints/src/needless_for_each.rs
+++ b/clippy_lints/src/needless_for_each.rs
@@ -6,8 +6,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
 
-use if_chain::if_chain;
-
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_trait_method;
 use clippy_utils::source::snippet_with_applicability;
@@ -52,65 +50,63 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
             return;
         };
 
-        if_chain! {
+        if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind
             // Check the method name is `for_each`.
-            if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind;
-            if method_name.ident.name == Symbol::intern("for_each");
+            && method_name.ident.name == Symbol::intern("for_each")
             // Check `for_each` is an associated function of `Iterator`.
-            if is_trait_method(cx, expr, sym::Iterator);
+            && is_trait_method(cx, expr, sym::Iterator)
             // Checks the receiver of `for_each` is also a method call.
-            if let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind;
+            && let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind
             // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or
             // `v.foo().iter().for_each()` must be skipped.
-            if matches!(
+            && matches!(
                 iter_recv.kind,
                 ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..)
-            );
+            )
             // Checks the type of the `iter` method receiver is NOT a user defined type.
-            if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some();
+            && has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some()
             // Skip the lint if the body is not block because this is simpler than `for` loop.
             // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop.
-            if let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind;
-            let body = cx.tcx.hir().body(body);
-            if let ExprKind::Block(..) = body.value.kind;
-            then {
-                let mut ret_collector = RetCollector::default();
-                ret_collector.visit_expr(body.value);
-
-                // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`.
-                if ret_collector.ret_in_loop {
-                    return;
-                }
-
-                let (mut applicability, ret_suggs) = if ret_collector.spans.is_empty() {
-                    (Applicability::MachineApplicable, None)
-                } else {
-                    (
-                        Applicability::MaybeIncorrect,
-                        Some(
-                            ret_collector
-                                .spans
-                                .into_iter()
-                                .map(|span| (span, "continue".to_string()))
-                                .collect(),
-                        ),
-                    )
-                };
+            && let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind
+            && let body = cx.tcx.hir().body(body)
+            && let ExprKind::Block(..) = body.value.kind
+        {
+            let mut ret_collector = RetCollector::default();
+            ret_collector.visit_expr(body.value);
+
+            // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`.
+            if ret_collector.ret_in_loop {
+                return;
+            }
 
-                let sugg = format!(
-                    "for {} in {} {}",
-                    snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability),
-                    snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability),
-                    snippet_with_applicability(cx, body.value.span, "..", &mut applicability),
-                );
+            let (mut applicability, ret_suggs) = if ret_collector.spans.is_empty() {
+                (Applicability::MachineApplicable, None)
+            } else {
+                (
+                    Applicability::MaybeIncorrect,
+                    Some(
+                        ret_collector
+                            .spans
+                            .into_iter()
+                            .map(|span| (span, "continue".to_string()))
+                            .collect(),
+                    ),
+                )
+            };
+
+            let sugg = format!(
+                "for {} in {} {}",
+                snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability),
+                snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability),
+                snippet_with_applicability(cx, body.value.span, "..", &mut applicability),
+            );
 
-                span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| {
-                    diag.span_suggestion(stmt.span, "try", sugg, applicability);
-                    if let Some(ret_suggs) = ret_suggs {
-                        diag.multipart_suggestion("...and replace `return` with `continue`", ret_suggs, applicability);
-                    }
-                })
-            }
+            span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| {
+                diag.span_suggestion(stmt.span, "try", sugg, applicability);
+                if let Some(ret_suggs) = ret_suggs {
+                    diag.multipart_suggestion("...and replace `return` with `continue`", ret_suggs, applicability);
+                }
+            });
         }
     }
 }
diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs
index c8888c744b6..0a95678d31a 100644
--- a/clippy_lints/src/needless_late_init.rs
+++ b/clippy_lints/src/needless_late_init.rs
@@ -128,21 +128,18 @@ impl LocalAssign {
         let assign = match expr.kind {
             ExprKind::Block(Block { expr: Some(expr), .. }, _) => Self::from_expr(expr, expr.span),
             ExprKind::Block(block, _) => {
-                if_chain! {
-                    if let Some((last, other_stmts)) = block.stmts.split_last();
-                    if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = last.kind;
+                if let Some((last, other_stmts)) = block.stmts.split_last()
+                    && let StmtKind::Expr(expr) | StmtKind::Semi(expr) = last.kind
 
-                    let assign = Self::from_expr(expr, last.span)?;
+                    && let assign = Self::from_expr(expr, last.span)?
 
                     // avoid visiting if not needed
-                    if assign.lhs_id == binding_id;
-                    if other_stmts.iter().all(|stmt| !contains_assign_expr(cx, stmt));
-
-                    then {
-                        Some(assign)
-                    } else {
-                        None
-                    }
+                    && assign.lhs_id == binding_id
+                    && other_stmts.iter().all(|stmt| !contains_assign_expr(cx, stmt))
+                {
+                    Some(assign)
+                } else {
+                    None
                 }
             },
             ExprKind::Assign(..) => Self::from_expr(expr, expr.span),
@@ -368,22 +365,20 @@ fn check<'tcx>(
 impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
         let mut parents = cx.tcx.hir().parent_iter(local.hir_id);
-        if_chain! {
-            if let Local {
-                init: None,
-                pat: &Pat {
+        if let Local {
+            init: None,
+            pat:
+                &Pat {
                     kind: PatKind::Binding(BindingAnnotation::NONE, binding_id, _, None),
                     ..
                 },
-                source: LocalSource::Normal,
-                ..
-            } = local;
-            if let Some((_, Node::Stmt(local_stmt))) = parents.next();
-            if let Some((_, Node::Block(block))) = parents.next();
-
-            then {
-                check(cx, local, local_stmt, block, binding_id);
-            }
+            source: LocalSource::Normal,
+            ..
+        } = local
+            && let Some((_, Node::Stmt(local_stmt))) = parents.next()
+            && let Some((_, Node::Block(block))) = parents.next()
+        {
+            check(cx, local, local_stmt, block, binding_id);
         }
     }
 }
diff --git a/clippy_lints/src/needless_parens_on_range_literals.rs b/clippy_lints/src/needless_parens_on_range_literals.rs
index 7bbf1fb4cd9..490c3f9c1ab 100644
--- a/clippy_lints/src/needless_parens_on_range_literals.rs
+++ b/clippy_lints/src/needless_parens_on_range_literals.rs
@@ -53,21 +53,23 @@ fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) {
         // don't check floating point literals on the start expression of a range
         return;
     }
-    if_chain! {
-        if let ExprKind::Lit(literal) = e.kind;
+    if let ExprKind::Lit(literal) = e.kind
         // the indicator that parenthesis surround the literal is that the span of the expression and the literal differ
-        if (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo);
+        && (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo)
         // inspect the source code of the expression for parenthesis
-        if snippet_enclosed_in_parenthesis(&snippet(cx, e.span, ""));
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_then(cx, NEEDLESS_PARENS_ON_RANGE_LITERALS, e.span,
-                "needless parenthesis on range literals can be removed",
-                |diag| {
-                    let suggestion = snippet_with_applicability(cx, literal.span, "_", &mut applicability);
-                    diag.span_suggestion(e.span, "try", suggestion, applicability);
-                });
-        }
+        && snippet_enclosed_in_parenthesis(&snippet(cx, e.span, ""))
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_then(
+            cx,
+            NEEDLESS_PARENS_ON_RANGE_LITERALS,
+            e.span,
+            "needless parenthesis on range literals can be removed",
+            |diag| {
+                let suggestion = snippet_with_applicability(cx, literal.span, "_", &mut applicability);
+                diag.span_suggestion(e.span, "try", suggestion, applicability);
+            },
+        );
     }
 }
 
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 8fa461ac12c..7c48b84e430 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -5,7 +5,6 @@ use clippy_utils::source::{snippet, snippet_opt};
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
 };
-use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir::intravisit::FnKind;
@@ -177,118 +176,119 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 )
             };
 
-            if_chain! {
-                if !is_self(arg);
-                if !ty.is_mutable_ptr();
-                if !is_copy(cx, ty);
-                if ty.is_sized(cx.tcx, cx.param_env);
-                if !allowed_traits.iter().any(|&t| implements_trait_with_env_from_iter(
-                    cx.tcx,
-                    cx.param_env,
-                    ty,
-                    t,
-                    [Option::<ty::GenericArg<'tcx>>::None],
-                ));
-                if !implements_borrow_trait;
-                if !all_borrowable_trait;
-
-                if let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind;
-                if !moved_vars.contains(&canonical_id);
-                then {
-                    // Dereference suggestion
-                    let sugg = |diag: &mut Diagnostic| {
-                        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),
-                                ).is_ok() {
-                                    diag.span_help(span, "consider marking this type as `Copy`");
-                                }
+            if !is_self(arg)
+                && !ty.is_mutable_ptr()
+                && !is_copy(cx, ty)
+                && ty.is_sized(cx.tcx, cx.param_env)
+                && !allowed_traits.iter().any(|&t| {
+                    implements_trait_with_env_from_iter(
+                        cx.tcx,
+                        cx.param_env,
+                        ty,
+                        t,
+                        [Option::<ty::GenericArg<'tcx>>::None],
+                    )
+                })
+                && !implements_borrow_trait
+                && !all_borrowable_trait
+                && let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind
+                && !moved_vars.contains(&canonical_id)
+            {
+                // Dereference suggestion
+                let sugg = |diag: &mut Diagnostic| {
+                    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),
+                            )
+                            .is_ok()
+                            {
+                                diag.span_help(span, "consider marking this type as `Copy`");
                             }
                         }
+                    }
 
-                        if_chain! {
-                            if is_type_diagnostic_item(cx, ty, sym::Vec);
-                            if let Some(clone_spans) =
-                                get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]);
-                            if let TyKind::Path(QPath::Resolved(_, path)) = input.kind;
-                            if let Some(elem_ty) = path.segments.iter()
-                                .find(|seg| seg.ident.name == sym::Vec)
-                                .and_then(|ps| ps.args.as_ref())
-                                .map(|params| params.args.iter().find_map(|arg| match arg {
-                                    GenericArg::Type(ty) => Some(ty),
-                                    _ => None,
-                                }).unwrap());
-                            then {
-                                let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_"));
-                                diag.span_suggestion(
-                                    input.span,
-                                    "consider changing the type to",
-                                    slice_ty,
-                                    Applicability::Unspecified,
-                                );
-
-                                for (span, suggestion) in clone_spans {
-                                    diag.span_suggestion(
-                                        span,
-                                        snippet_opt(cx, span)
-                                            .map_or(
-                                                "change the call to".into(),
-                                                |x| format!("change `{x}` to"),
-                                            ),
-                                        suggestion,
-                                        Applicability::Unspecified,
-                                    );
-                                }
-
-                                // cannot be destructured, no need for `*` suggestion
-                                return;
-                            }
+                    if is_type_diagnostic_item(cx, ty, sym::Vec)
+                        && let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")])
+                        && let TyKind::Path(QPath::Resolved(_, path)) = input.kind
+                        && let Some(elem_ty) = path
+                            .segments
+                            .iter()
+                            .find(|seg| seg.ident.name == sym::Vec)
+                            .and_then(|ps| ps.args.as_ref())
+                            .map(|params| {
+                                params
+                                    .args
+                                    .iter()
+                                    .find_map(|arg| match arg {
+                                        GenericArg::Type(ty) => Some(ty),
+                                        _ => None,
+                                    })
+                                    .unwrap()
+                            })
+                    {
+                        let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_"));
+                        diag.span_suggestion(
+                            input.span,
+                            "consider changing the type to",
+                            slice_ty,
+                            Applicability::Unspecified,
+                        );
+
+                        for (span, suggestion) in clone_spans {
+                            diag.span_suggestion(
+                                span,
+                                snippet_opt(cx, span)
+                                    .map_or("change the call to".into(), |x| format!("change `{x}` to")),
+                                suggestion,
+                                Applicability::Unspecified,
+                            );
                         }
 
-                        if is_type_lang_item(cx, ty, LangItem::String) {
-                            if let Some(clone_spans) =
-                                get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) {
+                        // cannot be destructured, no need for `*` suggestion
+                        return;
+                    }
+
+                    if is_type_lang_item(cx, ty, LangItem::String) {
+                        if 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,
+                                    snippet_opt(cx, span)
+                                        .map_or("change the call to".into(), |x| format!("change `{x}` to")),
+                                    suggestion,
                                     Applicability::Unspecified,
                                 );
-
-                                for (span, suggestion) in clone_spans {
-                                    diag.span_suggestion(
-                                        span,
-                                        snippet_opt(cx, span)
-                                            .map_or(
-                                                "change the call to".into(),
-                                                |x| format!("change `{x}` to")
-                                            ),
-                                        suggestion,
-                                        Applicability::Unspecified,
-                                    );
-                                }
-
-                                return;
                             }
+
+                            return;
                         }
+                    }
 
-                        let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))];
+                    let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))];
 
-                        multispan_sugg(diag, "consider taking a reference instead", spans);
-                    };
+                    multispan_sugg(diag, "consider taking a reference instead", spans);
+                };
 
-                    span_lint_and_then(
-                        cx,
-                        NEEDLESS_PASS_BY_VALUE,
-                        input.span,
-                        "this argument is passed by value, but not consumed in the function body",
-                        sugg,
-                    );
-                }
+                span_lint_and_then(
+                    cx,
+                    NEEDLESS_PASS_BY_VALUE,
+                    input.span,
+                    "this argument is passed by value, but not consumed in the function body",
+                    sugg,
+                );
             }
         }
     }
diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs
index 074c9fef1b2..7ec0879ba38 100644
--- a/clippy_lints/src/needless_question_mark.rs
+++ b/clippy_lints/src/needless_question_mark.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::path_res;
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Block, Body, CoroutineKind, CoroutineSource, Expr, ExprKind, LangItem, MatchSource, QPath};
@@ -111,34 +110,32 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
 }
 
 fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Call(path, [arg]) = expr.kind;
-        if let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path);
-        if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
-        let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) {
+    if let ExprKind::Call(path, [arg]) = expr.kind
+        && let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path)
+        && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
+        && let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) {
             "Some()"
         } else if cx.tcx.lang_items().result_ok_variant() == Some(variant_id) {
             "Ok()"
         } else {
             return;
-        };
-        if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind;
-        if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind;
-        if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind;
-        if expr.span.eq_ctxt(inner_expr.span);
-        let expr_ty = cx.typeck_results().expr_ty(expr);
-        let inner_ty = cx.typeck_results().expr_ty(inner_expr);
-        if expr_ty == inner_ty;
-        then {
-            span_lint_and_sugg(
-                cx,
-                NEEDLESS_QUESTION_MARK,
-                expr.span,
-                "question mark operator is useless here",
-                &format!("try removing question mark and `{sugg_remove}`"),
-                format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
-                Applicability::MachineApplicable,
-            );
         }
+        && let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind
+        && let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind
+        && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind
+        && expr.span.eq_ctxt(inner_expr.span)
+        && let expr_ty = cx.typeck_results().expr_ty(expr)
+        && let inner_ty = cx.typeck_results().expr_ty(inner_expr)
+        && expr_ty == inner_ty
+    {
+        span_lint_and_sugg(
+            cx,
+            NEEDLESS_QUESTION_MARK,
+            expr.span,
+            "question mark operator is useless here",
+            &format!("try removing question mark and `{sugg_remove}`"),
+            format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
+            Applicability::MachineApplicable,
+        );
     }
 }
diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
index 56c67406d6f..30aed8cc04a 100644
--- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
+++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::implements_trait;
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -46,42 +45,39 @@ declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]);
 
 impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if !in_external_macro(cx.sess(), expr.span);
-            if let ExprKind::Unary(UnOp::Not, inner) = expr.kind;
-            if let ExprKind::Binary(ref op, left, _) = inner.kind;
-            if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node;
+        if !in_external_macro(cx.sess(), expr.span)
+            && let ExprKind::Unary(UnOp::Not, inner) = expr.kind
+            && let ExprKind::Binary(ref op, left, _) = inner.kind
+            && let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node
+        {
+            let ty = cx.typeck_results().expr_ty(left);
 
-            then {
-                let ty = cx.typeck_results().expr_ty(left);
-
-                let implements_ord = {
-                    if let Some(id) = cx.tcx.get_diagnostic_item(sym::Ord) {
-                        implements_trait(cx, ty, id, &[])
-                    } else {
-                        return;
-                    }
-                };
-
-                let implements_partial_ord = {
-                    if let Some(id) = cx.tcx.lang_items().partial_ord_trait() {
-                        implements_trait(cx, ty, id, &[ty.into()])
-                    } else {
-                        return;
-                    }
-                };
+            let implements_ord = {
+                if let Some(id) = cx.tcx.get_diagnostic_item(sym::Ord) {
+                    implements_trait(cx, ty, id, &[])
+                } else {
+                    return;
+                }
+            };
 
-                if implements_partial_ord && !implements_ord {
-                    span_lint(
-                        cx,
-                        NEG_CMP_OP_ON_PARTIAL_ORD,
-                        expr.span,
-                        "the use of negated comparison operators on partially ordered \
-                        types produces code that is hard to read and refactor, please \
-                        consider using the `partial_cmp` method instead, to make it \
-                        clear that the two values could be incomparable",
-                    );
+            let implements_partial_ord = {
+                if let Some(id) = cx.tcx.lang_items().partial_ord_trait() {
+                    implements_trait(cx, ty, id, &[ty.into()])
+                } else {
+                    return;
                 }
+            };
+
+            if implements_partial_ord && !implements_ord {
+                span_lint(
+                    cx,
+                    NEG_CMP_OP_ON_PARTIAL_ORD,
+                    expr.span,
+                    "the use of negated comparison operators on partially ordered \
+                    types produces code that is hard to read and refactor, please \
+                    consider using the `partial_cmp` method instead, to make it \
+                    clear that the two values could be incomparable",
+                );
             }
         }
     }
diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs
index db0e22842d1..a6786e913e9 100644
--- a/clippy_lints/src/neg_multiply.rs
+++ b/clippy_lints/src/neg_multiply.rs
@@ -2,7 +2,6 @@ use clippy_utils::consts::{self, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::has_enclosing_paren;
-use if_chain::if_chain;
 use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@@ -53,28 +52,25 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
 }
 
 fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Lit(l) = lit.kind;
-        if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
-        if cx.typeck_results().expr_ty(exp).is_integral();
-
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
-            let suggestion = if !from_macro && exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) {
-                format!("-({snip})")
-            } else {
-                format!("-{snip}")
-            };
-            span_lint_and_sugg(
-                    cx,
-                    NEG_MULTIPLY,
-                    span,
-                    "this multiplication by -1 can be written more succinctly",
-                    "consider using",
-                    suggestion,
-                    applicability,
-                );
-        }
+    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()
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
+        let suggestion = if !from_macro && exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) {
+            format!("-({snip})")
+        } else {
+            format!("-{snip}")
+        };
+        span_lint_and_sugg(
+            cx,
+            NEG_MULTIPLY,
+            span,
+            "this multiplication by -1 can be written more succinctly",
+            "consider using",
+            suggestion,
+            applicability,
+        );
     }
 }
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index f7f9dccfbce..abba622a285 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::return_ty;
 use clippy_utils::source::snippet;
 use clippy_utils::sugg::DiagnosticExt;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::HirIdSet;
@@ -93,73 +92,69 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                             // an impl of `Default`
                             return;
                         }
-                        if_chain! {
-                            if sig.decl.inputs.is_empty();
-                            if name == sym::new;
-                            if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id);
-                            let self_def_id = cx.tcx.hir().get_parent_item(id.into());
-                            let self_ty = cx.tcx.type_of(self_def_id).instantiate_identity();
-                            if self_ty == return_ty(cx, id);
-                            if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
-                            then {
-                                if self.impling_types.is_none() {
-                                    let mut impls = HirIdSet::default();
-                                    cx.tcx.for_each_impl(default_trait_id, |d| {
-                                        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.hir().local_def_id_to_hir_id(local_def_id));
-                                            }
+                        if sig.decl.inputs.is_empty()
+                            && name == sym::new
+                            && cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id)
+                            && let self_def_id = cx.tcx.hir().get_parent_item(id.into())
+                            && let self_ty = cx.tcx.type_of(self_def_id).instantiate_identity()
+                            && self_ty == return_ty(cx, id)
+                            && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
+                        {
+                            if self.impling_types.is_none() {
+                                let mut impls = HirIdSet::default();
+                                cx.tcx.for_each_impl(default_trait_id, |d| {
+                                    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.hir().local_def_id_to_hir_id(local_def_id));
                                         }
-                                    });
-                                    self.impling_types = Some(impls);
-                                }
-
-                                // Check if a Default implementation exists for the Self type, regardless of
-                                // generics
-                                if_chain! {
-                                    if let Some(ref impling_types) = self.impling_types;
-                                    let self_def = cx.tcx.type_of(self_def_id).instantiate_identity();
-                                    if let Some(self_def) = self_def.ty_adt_def();
-                                    if let Some(self_local_did) = self_def.did().as_local();
-                                    let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
-                                    if impling_types.contains(&self_id);
-                                    then {
-                                        return;
                                     }
-                                }
+                                });
+                                self.impling_types = Some(impls);
+                            }
 
-                                let generics_sugg = snippet(cx, generics.span, "");
-                                let where_clause_sugg = if generics.has_where_clause_predicates {
-                                    format!("\n{}\n", snippet(cx, generics.where_clause_span, ""))
-                                } else {
-                                    String::new()
-                                };
-                                let self_ty_fmt = self_ty.to_string();
-                                let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt);
-                                span_lint_hir_and_then(
-                                    cx,
-                                    NEW_WITHOUT_DEFAULT,
-                                    id.into(),
-                                    impl_item.span,
-                                    &format!(
-                                        "you should consider adding a `Default` implementation for `{self_type_snip}`"
-                                    ),
-                                    |diag| {
-                                        diag.suggest_prepend_item(
-                                            cx,
-                                            item.span,
-                                            "try adding this",
-                                            &create_new_without_default_suggest_msg(
-                                                &self_type_snip,
-                                                &generics_sugg,
-                                                &where_clause_sugg
-                                            ),
-                                            Applicability::MachineApplicable,
-                                        );
-                                    },
-                                );
+                            // Check if a Default implementation exists for the Self type, regardless of
+                            // generics
+                            if let Some(ref impling_types) = self.impling_types
+                                && let self_def = cx.tcx.type_of(self_def_id).instantiate_identity()
+                                && let Some(self_def) = self_def.ty_adt_def()
+                                && let Some(self_local_did) = self_def.did().as_local()
+                                && let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did)
+                                && impling_types.contains(&self_id)
+                            {
+                                return;
                             }
+
+                            let generics_sugg = snippet(cx, generics.span, "");
+                            let where_clause_sugg = if generics.has_where_clause_predicates {
+                                format!("\n{}\n", snippet(cx, generics.where_clause_span, ""))
+                            } else {
+                                String::new()
+                            };
+                            let self_ty_fmt = self_ty.to_string();
+                            let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt);
+                            span_lint_hir_and_then(
+                                cx,
+                                NEW_WITHOUT_DEFAULT,
+                                id.into(),
+                                impl_item.span,
+                                &format!(
+                                    "you should consider adding a `Default` implementation for `{self_type_snip}`"
+                                ),
+                                |diag| {
+                                    diag.suggest_prepend_item(
+                                        cx,
+                                        item.span,
+                                        "try adding this",
+                                        &create_new_without_default_suggest_msg(
+                                            &self_type_snip,
+                                            &generics_sugg,
+                                            &where_clause_sugg,
+                                        ),
+                                        Applicability::MachineApplicable,
+                                    );
+                                },
+                            );
                         }
                     }
                 }
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 3a28e511fdd..de8bb123e9b 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -132,24 +132,22 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
             return true;
         }
     } else if let StmtKind::Local(local) = stmt.kind {
-        if_chain! {
-            if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id);
-            if let Some(init) = local.init;
-            if local.els.is_none();
-            if !local.pat.span.from_expansion();
-            if has_no_effect(cx, init);
-            if let PatKind::Binding(_, _, ident, _) = local.pat.kind;
-            if ident.name.to_ident_string().starts_with('_');
-            then {
-                span_lint_hir(
-                    cx,
-                    NO_EFFECT_UNDERSCORE_BINDING,
-                    init.hir_id,
-                    stmt.span,
-                    "binding to `_` prefixed variable with no side-effect"
-                );
-                return true;
-            }
+        if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id)
+            && let Some(init) = local.init
+            && local.els.is_none()
+            && !local.pat.span.from_expansion()
+            && has_no_effect(cx, init)
+            && let PatKind::Binding(_, _, ident, _) = local.pat.kind
+            && ident.name.to_ident_string().starts_with('_')
+        {
+            span_lint_hir(
+                cx,
+                NO_EFFECT_UNDERSCORE_BINDING,
+                init.hir_id,
+                stmt.span,
+                "binding to `_` prefixed variable with no side-effect",
+            );
+            return true;
         }
     }
     false
@@ -199,63 +197,60 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 }
 
 fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
-    if_chain! {
-        if let StmtKind::Semi(expr) = stmt.kind;
-        let ctxt = stmt.span.ctxt();
-        if expr.span.ctxt() == ctxt;
-        if let Some(reduced) = reduce_expression(cx, expr);
-        if !in_external_macro(cx.sess(), stmt.span);
-        if reduced.iter().all(|e| e.span.ctxt() == ctxt);
-        then {
-            if let ExprKind::Index(..) = &expr.kind {
-                let snippet = if let (Some(arr), Some(func)) =
-                    (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span))
-                {
+    if let StmtKind::Semi(expr) = stmt.kind
+        && let ctxt = stmt.span.ctxt()
+        && expr.span.ctxt() == ctxt
+        && let Some(reduced) = reduce_expression(cx, expr)
+        && !in_external_macro(cx.sess(), stmt.span)
+        && reduced.iter().all(|e| e.span.ctxt() == ctxt)
+    {
+        if let ExprKind::Index(..) = &expr.kind {
+            let snippet =
+                if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) {
                     format!("assert!({}.len() > {});", &arr, &func)
                 } else {
                     return;
                 };
-                span_lint_hir_and_then(
-                    cx,
-                    UNNECESSARY_OPERATION,
-                    expr.hir_id,
-                    stmt.span,
-                    "unnecessary operation",
-                    |diag| {
-                        diag.span_suggestion(
-                            stmt.span,
-                            "statement can be written as",
-                            snippet,
-                            Applicability::MaybeIncorrect,
-                        );
-                    },
-                );
-            } else {
-                let mut snippet = String::new();
-                for e in reduced {
-                    if let Some(snip) = snippet_opt(cx, e.span) {
-                        snippet.push_str(&snip);
-                        snippet.push(';');
-                    } else {
-                        return;
-                    }
+            span_lint_hir_and_then(
+                cx,
+                UNNECESSARY_OPERATION,
+                expr.hir_id,
+                stmt.span,
+                "unnecessary operation",
+                |diag| {
+                    diag.span_suggestion(
+                        stmt.span,
+                        "statement can be written as",
+                        snippet,
+                        Applicability::MaybeIncorrect,
+                    );
+                },
+            );
+        } else {
+            let mut snippet = String::new();
+            for e in reduced {
+                if let Some(snip) = snippet_opt(cx, e.span) {
+                    snippet.push_str(&snip);
+                    snippet.push(';');
+                } else {
+                    return;
                 }
-                span_lint_hir_and_then(
-                    cx,
-                    UNNECESSARY_OPERATION,
-                    expr.hir_id,
-                    stmt.span,
-                    "unnecessary operation",
-                    |diag| {
-                        diag.span_suggestion(
-                            stmt.span,
-                            "statement can be reduced to",
-                            snippet,
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                );
             }
+            span_lint_hir_and_then(
+                cx,
+                UNNECESSARY_OPERATION,
+                expr.hir_id,
+                stmt.span,
+                "unnecessary operation",
+                |diag| {
+                    diag.span_suggestion(
+                        stmt.span,
+                        "statement can be reduced to",
+                        snippet,
+                        Applicability::MachineApplicable,
+                    );
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 54cec066ba1..3059eb25d29 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -7,7 +7,6 @@ use std::ptr;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::macro_backtrace;
 use clippy_utils::{def_path_def_ids, in_constant};
-use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -386,15 +385,14 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                     of_trait: Some(of_trait_ref),
                     ..
                 }) => {
-                    if_chain! {
+                    if let Some(of_trait_def_id) = of_trait_ref.trait_def_id()
                         // Lint a trait impl item only when the definition is a generic type,
                         // assuming an assoc const is not meant to be an interior mutable type.
-                        if let Some(of_trait_def_id) = of_trait_ref.trait_def_id();
-                        if let Some(of_assoc_item) = cx
+                        && let Some(of_assoc_item) = cx
                             .tcx
                             .associated_item(impl_item.owner_id)
-                            .trait_item_def_id;
-                        if cx
+                            .trait_item_def_id
+                        && cx
                             .tcx
                             .layout_of(cx.tcx.param_env(of_trait_def_id).and(
                                 // Normalize assoc types because ones originated from generic params
@@ -405,23 +403,17 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                                     cx.tcx.type_of(of_assoc_item).instantiate_identity(),
                                 ),
                             ))
-                            .is_err();
+                            .is_err()
                             // If there were a function like `has_frozen_variant` described above,
                             // we should use here as a frozen variant is a potential to be frozen
                             // similar to unknown layouts.
                             // e.g. `layout_of(...).is_err() || has_frozen_variant(...);`
-                        let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity();
-                        let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-                        if !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized);
-                        if self.is_value_unfrozen_poly(cx, *body_id, normalized);
-                        then {
-                            lint(
-                               cx,
-                               Source::Assoc {
-                                   item: impl_item.span,
-                                },
-                            );
-                        }
+                        && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity()
+                        && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty)
+                        && !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized)
+                        && self.is_value_unfrozen_poly(cx, *body_id, normalized)
+                    {
+                        lint(cx, Source::Assoc { item: impl_item.span });
                     }
                 },
                 ItemKind::Impl(Impl { of_trait: None, .. }) => {
diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs
index e94e4589966..6cfcc81025d 100644
--- a/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
 use clippy_utils::{match_def_path, paths};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -44,38 +43,36 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         match &expr.kind {
             ExprKind::MethodCall(path, func, [param], _) => {
-                if_chain! {
-                    if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def();
-                    if (path.ident.name == sym!(mode)
-                        && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder)))
+                if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def()
+                    && ((path.ident.name == sym!(mode)
+                        && matches!(
+                            cx.tcx.get_diagnostic_name(adt.did()),
+                            Some(sym::FsOpenOptions | sym::DirBuilder)
+                        ))
                         || (path.ident.name == sym!(set_mode)
-                            && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()));
-                    if let ExprKind::Lit(_) = param.kind;
-                    if param.span.eq_ctxt(expr.span);
+                            && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())))
+                    && let ExprKind::Lit(_) = param.kind
+                    && param.span.eq_ctxt(expr.span)
+                {
+                    let Some(snip) = snippet_opt(cx, param.span) else {
+                        return;
+                    };
 
-                    then {
-                        let Some(snip) = snippet_opt(cx, param.span) else {
-                            return
-                        };
-
-                        if !snip.starts_with("0o") {
-                            show_error(cx, param);
-                        }
+                    if !snip.starts_with("0o") {
+                        show_error(cx, param);
                     }
                 }
             },
             ExprKind::Call(func, [param]) => {
-                if_chain! {
-                    if let ExprKind::Path(ref path) = func.kind;
-                    if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
-                    if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
-                    if let ExprKind::Lit(_) = param.kind;
-                    if param.span.eq_ctxt(expr.span);
-                    if let Some(snip) = snippet_opt(cx, param.span);
-                    if !snip.starts_with("0o");
-                    then {
-                        show_error(cx, param);
-                    }
+                if let ExprKind::Path(ref path) = func.kind
+                    && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
+                    && match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE)
+                    && let ExprKind::Lit(_) = param.kind
+                    && param.span.eq_ctxt(expr.span)
+                    && let Some(snip) = snippet_opt(cx, param.span)
+                    && !snip.starts_with("0o")
+                {
+                    show_error(cx, param);
                 }
             },
             _ => {},
diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs
index 62ef48c8a90..df1476e6809 100644
--- a/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -81,73 +81,74 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
         // We start from `Send` impl instead of `check_field_def()` because
         // single `AdtDef` may have multiple `Send` impls due to generic
         // parameters, and the lint is much easier to implement in this way.
-        if_chain! {
-            if !in_external_macro(cx.tcx.sess, item.span);
-            if let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send);
-            if let ItemKind::Impl(hir_impl) = &item.kind;
-            if let Some(trait_ref) = &hir_impl.of_trait;
-            if let Some(trait_id) = trait_ref.trait_def_id();
-            if send_trait == trait_id;
-            if hir_impl.polarity == ImplPolarity::Positive;
-            if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
-            if let self_ty = ty_trait_ref.instantiate_identity().self_ty();
-            if let ty::Adt(adt_def, impl_trait_args) = self_ty.kind();
-            then {
-                let mut non_send_fields = Vec::new();
-
-                let hir_map = cx.tcx.hir();
-                for variant in adt_def.variants() {
-                    for field in &variant.fields {
-                        if_chain! {
-                            if let Some(field_hir_id) = field
-                                .did
-                                .as_local()
-                                .map(|local_def_id| hir_map.local_def_id_to_hir_id(local_def_id));
-                            if !is_lint_allowed(cx, NON_SEND_FIELDS_IN_SEND_TY, field_hir_id);
-                            if let field_ty = field.ty(cx.tcx, impl_trait_args);
-                            if !ty_allowed_in_send(cx, field_ty, send_trait);
-                            if let Node::Field(field_def) = hir_map.get(field_hir_id);
-                            then {
-                                non_send_fields.push(NonSendField {
-                                    def: field_def,
-                                    ty: field_ty,
-                                    generic_params: collect_generic_params(field_ty),
-                                })
-                            }
-                        }
+        if !in_external_macro(cx.tcx.sess, item.span)
+            && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send)
+            && let ItemKind::Impl(hir_impl) = &item.kind
+            && let Some(trait_ref) = &hir_impl.of_trait
+            && let Some(trait_id) = trait_ref.trait_def_id()
+            && send_trait == trait_id
+            && hir_impl.polarity == ImplPolarity::Positive
+            && let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
+            && let self_ty = ty_trait_ref.instantiate_identity().self_ty()
+            && let ty::Adt(adt_def, impl_trait_args) = self_ty.kind()
+        {
+            let mut non_send_fields = Vec::new();
+
+            let hir_map = cx.tcx.hir();
+            for variant in adt_def.variants() {
+                for field in &variant.fields {
+                    if let Some(field_hir_id) = field
+                        .did
+                        .as_local()
+                        .map(|local_def_id| hir_map.local_def_id_to_hir_id(local_def_id))
+                        && !is_lint_allowed(cx, NON_SEND_FIELDS_IN_SEND_TY, field_hir_id)
+                        && let field_ty = field.ty(cx.tcx, impl_trait_args)
+                        && !ty_allowed_in_send(cx, field_ty, send_trait)
+                        && let Node::Field(field_def) = hir_map.get(field_hir_id)
+                    {
+                        non_send_fields.push(NonSendField {
+                            def: field_def,
+                            ty: field_ty,
+                            generic_params: collect_generic_params(field_ty),
+                        });
                     }
                 }
+            }
 
-                if !non_send_fields.is_empty() {
-                    span_lint_and_then(
-                        cx,
-                        NON_SEND_FIELDS_IN_SEND_TY,
-                        item.span,
-                        &format!(
-                            "some fields in `{}` are not safe to be sent to another thread",
-                            snippet(cx, hir_impl.self_ty.span, "Unknown")
-                        ),
-                        |diag| {
-                            for field in non_send_fields {
-                                diag.span_note(
-                                    field.def.span,
-                                    format!("it is not safe to send field `{}` to another thread", field.def.ident.name),
-                                );
-
-                                match field.generic_params.len() {
-                                    0 => diag.help("use a thread-safe type that implements `Send`"),
-                                    1 if is_ty_param(field.ty) => diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty)),
-                                    _ => diag.help(format!(
-                                        "add bounds on type parameter{} `{}` that satisfy `{}: Send`",
-                                        if field.generic_params.len() > 1 { "s" } else { "" },
-                                        field.generic_params_string(),
-                                        snippet(cx, field.def.ty.span, "Unknown"),
-                                    )),
-                                };
-                            }
-                        },
-                    );
-                }
+            if !non_send_fields.is_empty() {
+                span_lint_and_then(
+                    cx,
+                    NON_SEND_FIELDS_IN_SEND_TY,
+                    item.span,
+                    &format!(
+                        "some fields in `{}` are not safe to be sent to another thread",
+                        snippet(cx, hir_impl.self_ty.span, "Unknown")
+                    ),
+                    |diag| {
+                        for field in non_send_fields {
+                            diag.span_note(
+                                field.def.span,
+                                format!(
+                                    "it is not safe to send field `{}` to another thread",
+                                    field.def.ident.name
+                                ),
+                            );
+
+                            match field.generic_params.len() {
+                                0 => diag.help("use a thread-safe type that implements `Send`"),
+                                1 if is_ty_param(field.ty) => {
+                                    diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty))
+                                },
+                                _ => diag.help(format!(
+                                    "add bounds on type parameter{} `{}` that satisfy `{}: Send`",
+                                    if field.generic_params.len() > 1 { "s" } else { "" },
+                                    field.generic_params_string(),
+                                    snippet(cx, field.def.ty.span, "Unknown"),
+                                )),
+                            };
+                        }
+                    },
+                );
             }
         }
     }
diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs
index 11c3a5417b5..1c6a8e16ae2 100644
--- a/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/clippy_lints/src/nonstandard_macro_braces.rs
@@ -1,7 +1,6 @@
 use clippy_config::types::MacroMatcher;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
-use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
@@ -34,17 +33,17 @@ declare_clippy_lint! {
 }
 
 /// The (callsite span, (open brace, close brace), source snippet)
-type MacroInfo<'a> = (Span, &'a (String, String), String);
+type MacroInfo = (Span, (char, char), String);
 
-#[derive(Clone, Debug, Default)]
+#[derive(Debug)]
 pub struct MacroBraces {
-    macro_braces: FxHashMap<String, (String, String)>,
+    macro_braces: FxHashMap<String, (char, char)>,
     done: FxHashSet<Span>,
 }
 
 impl MacroBraces {
-    pub fn new(conf: &FxHashSet<MacroMatcher>) -> Self {
-        let macro_braces = macro_braces(conf.clone());
+    pub fn new(conf: &[MacroMatcher]) -> Self {
+        let macro_braces = macro_braces(conf);
         Self {
             macro_braces,
             done: FxHashSet::default(),
@@ -84,7 +83,7 @@ impl EarlyLintPass for MacroBraces {
     }
 }
 
-fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a MacroBraces) -> Option<MacroInfo<'a>> {
+fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBraces) -> Option<MacroInfo> {
     let unnested_or_local = || {
         !span.ctxt().outer_expn_data().call_site.from_expansion()
             || span
@@ -93,28 +92,26 @@ fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a Mac
                 .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
     };
     let span_call_site = span.ctxt().outer_expn_data().call_site;
-    if_chain! {
-        if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind;
-        let name = mac_name.as_str();
-        if let Some(braces) = mac_braces.macro_braces.get(name);
-        if let Some(snip) = snippet_opt(cx, span_call_site);
+    if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind
+        && let name = mac_name.as_str()
+        && let Some(&braces) = mac_braces.macro_braces.get(name)
+        && let Some(snip) = snippet_opt(cx, span_call_site)
         // we must check only invocation sites
         // https://github.com/rust-lang/rust-clippy/issues/7422
-        if snip.starts_with(&format!("{name}!"));
-        if unnested_or_local();
+        && snip.starts_with(&format!("{name}!"))
+        && unnested_or_local()
         // make formatting consistent
-        let c = snip.replace(' ', "");
-        if !c.starts_with(&format!("{name}!{}", braces.0));
-        if !mac_braces.done.contains(&span_call_site);
-        then {
-            Some((span_call_site, braces, snip))
-        } else {
-            None
-        }
+        && let c = snip.replace(' ', "")
+        && !c.starts_with(&format!("{name}!{}", braces.0))
+        && !mac_braces.done.contains(&span_call_site)
+    {
+        Some((span_call_site, braces, snip))
+    } else {
+        None
     }
 }
 
-fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), span: Span) {
+fn emit_help(cx: &EarlyContext<'_>, snip: &str, (open, close): (char, char), span: Span) {
     if let Some((macro_name, macro_args_str)) = snip.split_once('!') {
         let mut macro_args = macro_args_str.trim().to_string();
         // now remove the wrong braces
@@ -126,67 +123,31 @@ fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), span:
             span,
             &format!("use of irregular braces for `{macro_name}!` macro"),
             "consider writing",
-            format!("{macro_name}!{}{macro_args}{}", braces.0, braces.1),
+            format!("{macro_name}!{open}{macro_args}{close}"),
             Applicability::MachineApplicable,
         );
     }
 }
 
-fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> {
-    let mut braces = vec![
-        macro_matcher!(
-            name: "print",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "println",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "eprint",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "eprintln",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "write",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "writeln",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "format",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "format_args",
-            braces: ("(", ")"),
-        ),
-        macro_matcher!(
-            name: "vec",
-            braces: ("[", "]"),
-        ),
-        macro_matcher!(
-            name: "matches",
-            braces: ("(", ")"),
-        ),
-    ]
-    .into_iter()
-    .collect::<FxHashMap<_, _>>();
+fn macro_braces(conf: &[MacroMatcher]) -> FxHashMap<String, (char, char)> {
+    let mut braces = FxHashMap::from_iter(
+        [
+            ("print", ('(', ')')),
+            ("println", ('(', ')')),
+            ("eprint", ('(', ')')),
+            ("eprintln", ('(', ')')),
+            ("write", ('(', ')')),
+            ("writeln", ('(', ')')),
+            ("format", ('(', ')')),
+            ("format_args", ('(', ')')),
+            ("vec", ('[', ']')),
+            ("matches", ('(', ')')),
+        ]
+        .map(|(k, v)| (k.to_string(), v)),
+    );
     // We want users items to override any existing items
     for it in conf {
-        braces.insert(it.name, it.braces);
+        braces.insert(it.name.clone(), it.braces);
     }
     braces
 }
-
-macro_rules! macro_matcher {
-    (name: $name:expr, braces: ($open:expr, $close:expr) $(,)?) => {
-        ($name.to_owned(), ($open.to_owned(), $close.to_owned()))
-    };
-}
-pub(crate) use macro_matcher;
diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs
index c4572a09db6..2f85130fba1 100644
--- a/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/clippy_lints/src/operators/assign_op_pattern.rs
@@ -4,7 +4,6 @@ use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@@ -25,43 +24,40 @@ pub(super) fn check<'tcx>(
         let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
             let ty = cx.typeck_results().expr_ty(assignee);
             let rty = cx.typeck_results().expr_ty(rhs);
-            if_chain! {
-                if let Some((_, lang_item)) = binop_traits(op.node);
-                if let Some(trait_id) = cx.tcx.lang_items().get(lang_item);
-                let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
-                if trait_ref_of_method(cx, parent_fn)
-                    .map_or(true, |t| t.path.res.def_id() != trait_id);
-                if implements_trait(cx, ty, trait_id, &[rty.into()]);
-                then {
-                    // Primitive types execute assign-ops right-to-left. Every other type is left-to-right.
-                    if !(ty.is_primitive() && rty.is_primitive()) {
-                        // TODO: This will have false negatives as it doesn't check if the borrows are
-                        // actually live at the end of their respective expressions.
-                        let mut_borrows = mut_borrows_in_expr(cx, assignee);
-                        let imm_borrows = imm_borrows_in_expr(cx, rhs);
-                        if mut_borrows.iter().any(|id| imm_borrows.contains(id)) {
-                            return;
-                        }
+            if let Some((_, lang_item)) = binop_traits(op.node)
+                && let Some(trait_id) = cx.tcx.lang_items().get(lang_item)
+                && let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id
+                && trait_ref_of_method(cx, parent_fn).map_or(true, |t| t.path.res.def_id() != trait_id)
+                && implements_trait(cx, ty, trait_id, &[rty.into()])
+            {
+                // Primitive types execute assign-ops right-to-left. Every other type is left-to-right.
+                if !(ty.is_primitive() && rty.is_primitive()) {
+                    // TODO: This will have false negatives as it doesn't check if the borrows are
+                    // actually live at the end of their respective expressions.
+                    let mut_borrows = mut_borrows_in_expr(cx, assignee);
+                    let imm_borrows = imm_borrows_in_expr(cx, rhs);
+                    if mut_borrows.iter().any(|id| imm_borrows.contains(id)) {
+                        return;
                     }
-                    span_lint_and_then(
-                        cx,
-                        ASSIGN_OP_PATTERN,
-                        expr.span,
-                        "manual implementation of an assign operation",
-                        |diag| {
-                            if let (Some(snip_a), Some(snip_r)) =
-                                (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
-                            {
-                                diag.span_suggestion(
-                                    expr.span,
-                                    "replace it with",
-                                    format!("{snip_a} {}= {snip_r}", op.node.as_str()),
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                        },
-                    );
                 }
+                span_lint_and_then(
+                    cx,
+                    ASSIGN_OP_PATTERN,
+                    expr.span,
+                    "manual implementation of an assign operation",
+                    |diag| {
+                        if let (Some(snip_a), Some(snip_r)) =
+                            (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
+                        {
+                            diag.span_suggestion(
+                                expr.span,
+                                "replace it with",
+                                format!("{snip_a} {}= {snip_r}", op.node.as_str()),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    },
+                );
             }
         };
 
diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs
index abe8df19543..52ef9546110 100644
--- a/clippy_lints/src/operators/const_comparisons.rs
+++ b/clippy_lints/src/operators/const_comparisons.rs
@@ -3,7 +3,6 @@
 use std::cmp::Ordering;
 
 use clippy_utils::consts::{constant, Constant};
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::HasTyCtxt;
@@ -23,19 +22,17 @@ fn comparison_to_const<'tcx>(
     typeck: &TypeckResults<'tcx>,
     expr: &'tcx Expr<'tcx>,
 ) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant<'tcx>, Ty<'tcx>)> {
-    if_chain! {
-        if let ExprKind::Binary(operator, left, right) = expr.kind;
-        if let Ok(cmp_op) = CmpOp::try_from(operator.node);
-        then {
-            match (constant(cx, typeck, left), constant(cx, typeck, right)) {
-                (Some(_), Some(_)) => None,
-                (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
-                (Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))),
-                _ => None,
-            }
-        } else {
-            None
+    if let ExprKind::Binary(operator, left, right) = expr.kind
+        && let Ok(cmp_op) = CmpOp::try_from(operator.node)
+    {
+        match (constant(cx, typeck, left), constant(cx, typeck, right)) {
+            (Some(_), Some(_)) => None,
+            (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
+            (Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))),
+            _ => None,
         }
+    } else {
+        None
     }
 }
 
@@ -46,87 +43,89 @@ pub(super) fn check<'tcx>(
     right_cond: &'tcx Expr<'tcx>,
     span: Span,
 ) {
-    if_chain! {
+    if and_op.node == BinOpKind::And
         // Ensure that the binary operator is &&
-        if and_op.node == BinOpKind::And;
 
         // Check that both operands to '&&' are themselves a binary operation
         // The `comparison_to_const` step also checks this, so this step is just an optimization
-        if let ExprKind::Binary(_, _, _) = left_cond.kind;
-        if let ExprKind::Binary(_, _, _) = right_cond.kind;
+        && let ExprKind::Binary(_, _, _) = left_cond.kind
+        && let ExprKind::Binary(_, _, _) = right_cond.kind
 
-        let typeck = cx.typeck_results();
+        && let typeck = cx.typeck_results()
 
         // Check that both operands to '&&' compare a non-literal to a literal
-        if let Some((left_cmp_op, left_expr, left_const_expr, left_const, left_type)) =
-            comparison_to_const(cx, typeck, left_cond);
-        if let Some((right_cmp_op, right_expr, right_const_expr, right_const, right_type)) =
-            comparison_to_const(cx, typeck, right_cond);
+        && let Some((left_cmp_op, left_expr, left_const_expr, left_const, left_type)) =
+            comparison_to_const(cx, typeck, left_cond)
+        && let Some((right_cmp_op, right_expr, right_const_expr, right_const, right_type)) =
+            comparison_to_const(cx, typeck, right_cond)
 
-        if left_type == right_type;
+        && left_type == right_type
 
         // Check that the same expression is compared in both comparisons
-        if SpanlessEq::new(cx).eq_expr(left_expr, right_expr);
+        && SpanlessEq::new(cx).eq_expr(left_expr, right_expr)
 
-        if !left_expr.can_have_side_effects();
+        && !left_expr.can_have_side_effects()
 
         // Compare the two constant expressions
-        if let Some(ordering) = Constant::partial_cmp(cx.tcx(), left_type, &left_const, &right_const);
+        && let Some(ordering) = Constant::partial_cmp(cx.tcx(), left_type, &left_const, &right_const)
 
         // Rule out the `x >= 42 && x <= 42` corner case immediately
         // Mostly to simplify the implementation, but it is also covered by `clippy::double_comparisons`
-        if !matches!(
+        && !matches!(
             (&left_cmp_op, &right_cmp_op, ordering),
             (CmpOp::Le | CmpOp::Ge, CmpOp::Le | CmpOp::Ge, Ordering::Equal)
-        );
-
-        then {
-            if left_cmp_op.direction() == right_cmp_op.direction() {
-                let lhs_str = snippet(cx, left_cond.span, "<lhs>");
-                let rhs_str = snippet(cx, right_cond.span, "<rhs>");
-                // We already know that either side of `&&` has no effect,
-                // but emit a different error message depending on which side it is
-                if left_side_is_useless(left_cmp_op, ordering) {
-                    span_lint_and_note(
-                        cx,
-                        REDUNDANT_COMPARISONS,
-                        span,
-                        "left-hand side of `&&` operator has no effect",
-                        Some(left_cond.span.until(right_cond.span)),
-                        &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"),
-                    );
-                } else {
-                    span_lint_and_note(
-                        cx,
-                        REDUNDANT_COMPARISONS,
-                        span,
-                        "right-hand side of `&&` operator has no effect",
-                        Some(and_op.span.to(right_cond.span)),
-                        &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"),
-                    );
-                }
-                // We could autofix this error but choose not to,
-                // because code triggering this lint probably not behaving correctly in the first place
-            }
-            else if !comparison_is_possible(left_cmp_op.direction(), ordering) {
-                let expr_str = snippet(cx, left_expr.span, "..");
-                let lhs_str = snippet(cx, left_const_expr.span, "<lhs>");
-                let rhs_str = snippet(cx, right_const_expr.span, "<rhs>");
-                let note = match ordering {
-                    Ordering::Less => format!("since `{lhs_str}` < `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"),
-                    Ordering::Equal => format!("`{expr_str}` cannot simultaneously be greater than and less than `{lhs_str}`"),
-                    Ordering::Greater => format!("since `{lhs_str}` > `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"),
-                };
+        )
+    {
+        if left_cmp_op.direction() == right_cmp_op.direction() {
+            let lhs_str = snippet(cx, left_cond.span, "<lhs>");
+            let rhs_str = snippet(cx, right_cond.span, "<rhs>");
+            // We already know that either side of `&&` has no effect,
+            // but emit a different error message depending on which side it is
+            if left_side_is_useless(left_cmp_op, ordering) {
                 span_lint_and_note(
                     cx,
-                    IMPOSSIBLE_COMPARISONS,
+                    REDUNDANT_COMPARISONS,
                     span,
-                    "boolean expression will never evaluate to 'true'",
-                    None,
-                    &note,
+                    "left-hand side of `&&` operator has no effect",
+                    Some(left_cond.span.until(right_cond.span)),
+                    &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"),
                 );
+            } else {
+                span_lint_and_note(
+                    cx,
+                    REDUNDANT_COMPARISONS,
+                    span,
+                    "right-hand side of `&&` operator has no effect",
+                    Some(and_op.span.to(right_cond.span)),
+                    &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"),
+                );
+            }
+            // We could autofix this error but choose not to,
+            // because code triggering this lint probably not behaving correctly in the first place
+        } else if !comparison_is_possible(left_cmp_op.direction(), ordering) {
+            let expr_str = snippet(cx, left_expr.span, "..");
+            let lhs_str = snippet(cx, left_const_expr.span, "<lhs>");
+            let rhs_str = snippet(cx, right_const_expr.span, "<rhs>");
+            let note = match ordering {
+                Ordering::Less => format!(
+                    "since `{lhs_str}` < `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"
+                ),
+                Ordering::Equal => {
+                    format!("`{expr_str}` cannot simultaneously be greater than and less than `{lhs_str}`")
+                },
+                Ordering::Greater => format!(
+                    "since `{lhs_str}` > `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"
+                ),
             };
-        }
+            span_lint_and_note(
+                cx,
+                IMPOSSIBLE_COMPARISONS,
+                span,
+                "boolean expression will never evaluate to 'true'",
+                None,
+                &note,
+            );
+        };
     }
 }
 
diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs
index bce6bdcaf61..0561739d160 100644
--- a/clippy_lints/src/operators/float_cmp.rs
+++ b/clippy_lints/src/operators/float_cmp.rs
@@ -2,7 +2,6 @@ use clippy_utils::consts::{constant_with_source, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_item_name;
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::LateContext;
@@ -105,14 +104,12 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         return is_signum(cx, child_expr);
     }
 
-    if_chain! {
-        if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
-        if sym!(signum) == method_name.ident.name;
-        // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
-        // the method call)
-        then {
-            return is_float(cx, self_arg);
-        }
+    if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind
+        && sym!(signum) == method_name.ident.name
+    // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
+    // the method call)
+    {
+        return is_float(cx, self_arg);
     }
     false
 }
diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs
index a0a8b6aabd9..cace85a2451 100644
--- a/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/clippy_lints/src/operators/float_equality_without_abs.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{match_def_path, paths, sugg};
-use if_chain::if_chain;
 use rustc_ast::util::parser::AssocOp;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -24,48 +23,43 @@ pub(crate) fn check<'tcx>(
         _ => return,
     };
 
-    if_chain! {
+    if let ExprKind::Binary(
         // left hand side is a subtraction
-        if let ExprKind::Binary(
             Spanned {
                 node: BinOpKind::Sub,
                 ..
             },
             val_l,
             val_r,
-        ) = lhs.kind;
+        ) = lhs.kind
 
         // right hand side matches either f32::EPSILON or f64::EPSILON
-        if let ExprKind::Path(ref epsilon_path) = rhs.kind;
-        if let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id);
-        if match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON);
+        && let ExprKind::Path(ref epsilon_path) = rhs.kind
+        && let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id)
+        && (match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON))
 
         // values of the subtractions on the left hand side are of the type float
-        let t_val_l = cx.typeck_results().expr_ty(val_l);
-        let t_val_r = cx.typeck_results().expr_ty(val_r);
-        if let ty::Float(_) = t_val_l.kind();
-        if let ty::Float(_) = t_val_r.kind();
-
-        then {
-            let sug_l = sugg::Sugg::hir(cx, val_l, "..");
-            let sug_r = sugg::Sugg::hir(cx, val_r, "..");
-            // format the suggestion
-            let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par());
-            // spans the lint
-            span_lint_and_then(
-                cx,
-                FLOAT_EQUALITY_WITHOUT_ABS,
-                expr.span,
-                "float equality check without `.abs()`",
-                | diag | {
-                    diag.span_suggestion(
-                        lhs.span,
-                        "add `.abs()`",
-                        suggestion,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            );
-        }
+        && let t_val_l = cx.typeck_results().expr_ty(val_l)
+        && let t_val_r = cx.typeck_results().expr_ty(val_r)
+        && let ty::Float(_) = t_val_l.kind()
+        && let ty::Float(_) = t_val_r.kind()
+    {
+        let sug_l = sugg::Sugg::hir(cx, val_l, "..");
+        let sug_r = sugg::Sugg::hir(cx, val_r, "..");
+        // format the suggestion
+        let suggestion = format!(
+            "{}.abs()",
+            sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()
+        );
+        // spans the lint
+        span_lint_and_then(
+            cx,
+            FLOAT_EQUALITY_WITHOUT_ABS,
+            expr.span,
+            "float equality check without `.abs()`",
+            |diag| {
+                diag.span_suggestion(lhs.span, "add `.abs()`", suggestion, Applicability::MaybeIncorrect);
+            },
+        );
     }
 }
diff --git a/clippy_lints/src/operators/modulo_arithmetic.rs b/clippy_lints/src/operators/modulo_arithmetic.rs
index a2c3a4d8ba7..cb3916484c1 100644
--- a/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -1,7 +1,6 @@
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sext;
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
@@ -19,15 +18,12 @@ pub(super) fn check<'tcx>(
     if op == BinOpKind::Rem {
         let lhs_operand = analyze_operand(lhs, cx, e);
         let rhs_operand = analyze_operand(rhs, cx, e);
-        if_chain! {
-            if let Some(lhs_operand) = lhs_operand;
-            if let Some(rhs_operand) = rhs_operand;
-            then {
-                check_const_operands(cx, e, &lhs_operand, &rhs_operand);
-            }
-            else {
-                check_non_const_operands(cx, e, lhs);
-            }
+        if let Some(lhs_operand) = lhs_operand
+            && let Some(rhs_operand) = rhs_operand
+        {
+            check_const_operands(cx, e, &lhs_operand, &rhs_operand);
+        } else {
+            check_non_const_operands(cx, e, lhs);
         }
     };
 }
diff --git a/clippy_lints/src/operators/op_ref.rs b/clippy_lints/src/operators/op_ref.rs
index 932dd470f9e..7d8aa3f56fe 100644
--- a/clippy_lints/src/operators/op_ref.rs
+++ b/clippy_lints/src/operators/op_ref.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::get_enclosing_block;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{implements_trait, is_copy};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
@@ -180,41 +179,33 @@ fn in_impl<'tcx>(
     e: &'tcx Expr<'_>,
     bin_op: DefId,
 ) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
-    if_chain! {
-        if let Some(block) = get_enclosing_block(cx, e.hir_id);
-        if let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id());
-        let item = cx.tcx.hir().expect_item(impl_def_id.expect_local());
-        if let ItemKind::Impl(item) = &item.kind;
-        if let Some(of_trait) = &item.of_trait;
-        if let Some(seg) = of_trait.path.segments.last();
-        if let Res::Def(_, trait_id) = seg.res;
-        if trait_id == bin_op;
-        if let Some(generic_args) = seg.args;
-        if let Some(GenericArg::Type(other_ty)) = generic_args.args.last();
-
-        then {
-            Some((item.self_ty, other_ty))
-        }
-        else {
-            None
-        }
+    if let Some(block) = get_enclosing_block(cx, e.hir_id)
+        && let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id())
+        && let item = cx.tcx.hir().expect_item(impl_def_id.expect_local())
+        && let ItemKind::Impl(item) = &item.kind
+        && let Some(of_trait) = &item.of_trait
+        && let Some(seg) = of_trait.path.segments.last()
+        && let Res::Def(_, trait_id) = seg.res
+        && trait_id == bin_op
+        && let Some(generic_args) = seg.args
+        && let Some(GenericArg::Type(other_ty)) = generic_args.args.last()
+    {
+        Some((item.self_ty, other_ty))
+    } else {
+        None
     }
 }
 
 fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
-    if_chain! {
-        if let ty::Adt(adt_def, _) = middle_ty.kind();
-        if let Some(local_did) = adt_def.did().as_local();
-        let item = cx.tcx.hir().expect_item(local_did);
-        let middle_ty_id = item.owner_id.to_def_id();
-        if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
-        if let Res::Def(_, hir_ty_id) = path.res;
-
-        then {
-            hir_ty_id == middle_ty_id
-        }
-        else {
-            false
-        }
+    if let ty::Adt(adt_def, _) = middle_ty.kind()
+        && let Some(local_did) = adt_def.did().as_local()
+        && let item = cx.tcx.hir().expect_item(local_did)
+        && let middle_ty_id = item.owner_id.to_def_id()
+        && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
+        && let Res::Def(_, hir_ty_id) = path.res
+    {
+        hir_ty_id == middle_ty_id
+    } else {
+        false
     }
 }
diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs
index 1229c202f5a..9db2e24630a 100644
--- a/clippy_lints/src/operators/ptr_eq.rs
+++ b/clippy_lints/src/operators/ptr_eq.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -22,22 +21,20 @@ pub(super) fn check<'tcx>(
             _ => (left, right),
         };
 
-        if_chain! {
-            if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left);
-            if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right);
-            if let Some(left_snip) = snippet_opt(cx, left_var.span);
-            if let Some(right_snip) = snippet_opt(cx, right_var.span);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    PTR_EQ,
-                    expr.span,
-                    LINT_MSG,
-                    "try",
-                    format!("std::ptr::eq({left_snip}, {right_snip})"),
-                    Applicability::MachineApplicable,
-                    );
-            }
+        if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left)
+            && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right)
+            && let Some(left_snip) = snippet_opt(cx, left_var.span)
+            && let Some(right_snip) = snippet_opt(cx, right_var.span)
+        {
+            span_lint_and_sugg(
+                cx,
+                PTR_EQ,
+                expr.span,
+                LINT_MSG,
+                "try",
+                format!("std::ptr::eq({left_snip}, {right_snip})"),
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index d7cbbe13a26..6e4e0c98d29 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -4,7 +4,6 @@ use clippy_utils::{
     can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_res_lang_ctor, peel_blocks,
     peel_hir_expr_while, CaptureKind,
 };
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
@@ -122,73 +121,97 @@ fn try_get_option_occurrence<'tcx>(
         _ => expr,
     };
     let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?;
-    if_chain! {
-        if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind;
-        if let Some(some_captures) = can_move_expr_to_closure(cx, if_then);
-        if let Some(none_captures) = can_move_expr_to_closure(cx, if_else);
-        if some_captures
+    if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind
+        && let Some(some_captures) = can_move_expr_to_closure(cx, if_then)
+        && let Some(none_captures) = can_move_expr_to_closure(cx, if_else)
+        && some_captures
             .iter()
             .filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2)))
-            .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref());
-        then {
-            let capture_mut = if bind_annotation == BindingAnnotation::MUT { "mut " } else { "" };
-            let some_body = peel_blocks(if_then);
-            let none_body = peel_blocks(if_else);
-            let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { "map_or" } else { "map_or_else" };
-            let capture_name = id.name.to_ident_string();
-            let (as_ref, as_mut) = match &expr.kind {
-                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
-                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
-                _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => {
-                    (mutb == Mutability::Not, mutb == Mutability::Mut)
-                }
-                _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT),
-            };
+            .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref())
+    {
+        let capture_mut = if bind_annotation == BindingAnnotation::MUT {
+            "mut "
+        } else {
+            ""
+        };
+        let some_body = peel_blocks(if_then);
+        let none_body = peel_blocks(if_else);
+        let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) {
+            "map_or"
+        } else {
+            "map_or_else"
+        };
+        let capture_name = id.name.to_ident_string();
+        let (as_ref, as_mut) = match &expr.kind {
+            ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
+            ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
+            _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => {
+                (mutb == Mutability::Not, mutb == Mutability::Mut)
+            },
+            _ => (
+                bind_annotation == BindingAnnotation::REF,
+                bind_annotation == BindingAnnotation::REF_MUT,
+            ),
+        };
 
-            // Check if captures the closure will need conflict with borrows made in the scrutinee.
-            // TODO: check all the references made in the scrutinee expression. This will require interacting
-            // with the borrow checker. Currently only `<local>[.<field>]*` is checked for.
-            if as_ref || as_mut {
-                let e = peel_hir_expr_while(cond_expr, |e| match e.kind {
-                    ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e),
-                    _ => None,
-                });
-                if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
-                    match some_captures.get(local_id)
-                        .or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|()| none_captures.get(local_id)))
-                    {
-                        Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
-                        Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
-                        Some(CaptureKind::Ref(Mutability::Not)) | None => (),
-                    }
+        // Check if captures the closure will need conflict with borrows made in the scrutinee.
+        // TODO: check all the references made in the scrutinee expression. This will require interacting
+        // with the borrow checker. Currently only `<local>[.<field>]*` is checked for.
+        if as_ref || as_mut {
+            let e = peel_hir_expr_while(cond_expr, |e| match e.kind {
+                ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e),
+                _ => None,
+            });
+            if let ExprKind::Path(QPath::Resolved(
+                None,
+                Path {
+                    res: Res::Local(local_id),
+                    ..
+                },
+            )) = e.kind
+            {
+                match some_captures.get(local_id).or_else(|| {
+                    (method_sugg == "map_or_else")
+                        .then_some(())
+                        .and_then(|()| none_captures.get(local_id))
+                }) {
+                    Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
+                    Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
+                    Some(CaptureKind::Ref(Mutability::Not)) | None => (),
                 }
             }
+        }
 
-            let mut app = Applicability::Unspecified;
+        let mut app = Applicability::Unspecified;
 
-            let (none_body, is_argless_call) = match none_body.kind {
-                ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() => (call_expr, true),
-                _ => (none_body, false),
-            };
+        let (none_body, is_argless_call) = match none_body.kind {
+            ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() => (call_expr, true),
+            _ => (none_body, false),
+        };
 
-            return Some(OptionOccurrence {
-                option: format_option_in_sugg(
-                    Sugg::hir_with_context(cx, cond_expr, ctxt, "..", &mut app),
-                    as_ref,
-                    as_mut,
-                ),
-                method_sugg: method_sugg.to_string(),
-                some_expr: format!(
-                    "|{capture_mut}{capture_name}| {}",
-                    Sugg::hir_with_context(cx, some_body, ctxt, "..", &mut app),
-                ),
-                none_expr: format!(
-                    "{}{}",
-                    if method_sugg == "map_or" || is_argless_call { "" } else if is_result { "|_| " } else { "|| "},
-                    Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
-                ),
-            });
-        }
+        return Some(OptionOccurrence {
+            option: format_option_in_sugg(
+                Sugg::hir_with_context(cx, cond_expr, ctxt, "..", &mut app),
+                as_ref,
+                as_mut,
+            ),
+            method_sugg: method_sugg.to_string(),
+            some_expr: format!(
+                "|{capture_mut}{capture_name}| {}",
+                Sugg::hir_with_context(cx, some_body, ctxt, "..", &mut app),
+            ),
+            none_expr: format!(
+                "{}{}",
+                if method_sugg == "map_or" || is_argless_call {
+                    ""
+                } else if is_result {
+                    "|_| "
+                } else {
+                    "|| "
+                },
+                Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
+            ),
+        });
     }
 
     None
diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs
index 38cd5043adc..e661bfbb96c 100644
--- a/clippy_lints/src/overflow_check_conditional.rs
+++ b/clippy_lints/src/overflow_check_conditional.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::SpanlessEq;
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -34,41 +33,37 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
     // a + b < a, a > a + b, a < a - b, a - b > a
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r);
-        if_chain! {
-            if let ExprKind::Binary(ref op, first, second) = expr.kind;
-            if let ExprKind::Binary(ref op2, ident1, ident2) = first.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path3)) = second.kind;
-            if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
-            if cx.typeck_results().expr_ty(ident1).is_integral();
-            if cx.typeck_results().expr_ty(ident2).is_integral();
-            then {
-                if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add {
-                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
-                }
-                if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub {
-                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
-                }
+        if let ExprKind::Binary(ref op, first, second) = expr.kind
+            && let ExprKind::Binary(ref op2, ident1, ident2) = first.kind
+            && let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind
+            && let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind
+            && let ExprKind::Path(QPath::Resolved(_, path3)) = second.kind
+            && (eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]))
+            && cx.typeck_results().expr_ty(ident1).is_integral()
+            && cx.typeck_results().expr_ty(ident2).is_integral()
+        {
+            if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add {
+                span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
+            }
+            if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub {
+                span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
             }
         }
 
-        if_chain! {
-            if let ExprKind::Binary(ref op, first, second) = expr.kind;
-            if let ExprKind::Binary(ref op2, ident1, ident2) = second.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind;
-            if let ExprKind::Path(QPath::Resolved(_, path3)) = first.kind;
-            if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
-            if cx.typeck_results().expr_ty(ident1).is_integral();
-            if cx.typeck_results().expr_ty(ident2).is_integral();
-            then {
-                if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add {
-                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
-                }
-                if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub {
-                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
-                }
+        if let ExprKind::Binary(ref op, first, second) = expr.kind
+            && let ExprKind::Binary(ref op2, ident1, ident2) = second.kind
+            && let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind
+            && let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind
+            && let ExprKind::Path(QPath::Resolved(_, path3)) = first.kind
+            && (eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]))
+            && cx.typeck_results().expr_ty(ident1).is_integral()
+            && cx.typeck_results().expr_ty(ident2).is_integral()
+        {
+            if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add {
+                span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
+            }
+            if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub {
+                span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
             }
         }
     }
diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs
index 68d3d00ac16..1b06762415d 100644
--- a/clippy_lints/src/partialeq_ne_impl.rs
+++ b/clippy_lints/src/partialeq_ne_impl.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_hir;
-use if_chain::if_chain;
 use rustc_hir::{Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -34,22 +33,24 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]);
 
 impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if_chain! {
-            if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
-            if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
-            if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
-            if trait_ref.path.res.def_id() == eq_trait;
-            then {
-                for impl_item in *impl_items {
-                    if impl_item.ident.name == sym::ne {
-                        span_lint_hir(
-                            cx,
-                            PARTIALEQ_NE_IMPL,
-                            impl_item.id.hir_id(),
-                            impl_item.span,
-                            "re-implementing `PartialEq::ne` is unnecessary",
-                        );
-                    }
+        if let ItemKind::Impl(Impl {
+            of_trait: Some(ref trait_ref),
+            items: impl_items,
+            ..
+        }) = item.kind
+            && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
+            && let Some(eq_trait) = cx.tcx.lang_items().eq_trait()
+            && trait_ref.path.res.def_id() == eq_trait
+        {
+            for impl_item in *impl_items {
+                if impl_item.ident.name == sym::ne {
+                    span_lint_hir(
+                        cx,
+                        PARTIALEQ_NE_IMPL,
+                        impl_item.id.hir_id(),
+                        impl_item.span,
+                        "re-implementing `PartialEq::ne` is unnecessary",
+                    );
                 }
             }
         };
diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index 4d7a055dae1..85cea8db490 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/clippy_lints/src/pass_by_ref_or_value.rs
@@ -5,7 +5,6 @@ use clippy_utils::source::snippet;
 use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy};
 use clippy_utils::{is_self, is_self_ty};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -20,7 +19,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
 use rustc_target::spec::abi::Abi;
-use rustc_target::spec::Target;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -117,10 +115,10 @@ impl<'tcx> PassByRefOrValue {
         ref_min_size: Option<u64>,
         value_max_size: u64,
         avoid_breaking_exported_api: bool,
-        target: &Target,
+        pointer_width: u32,
     ) -> Self {
         let ref_min_size = ref_min_size.unwrap_or_else(|| {
-            let bit_width = u64::from(target.pointer_width);
+            let bit_width = u64::from(pointer_width);
             // Cap the calculated bit width at 32-bits to reduce
             // portability problems between 32 and 64-bit targets
             let bit_width = cmp::min(bit_width, 32);
@@ -229,22 +227,23 @@ impl<'tcx> PassByRefOrValue {
                     }
                     let ty = cx.tcx.erase_late_bound_regions(ty);
 
-                    if_chain! {
-                        if is_copy(cx, ty);
-                        if !is_self_ty(input);
-                        if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
-                        if size > self.value_max_size;
-                        then {
-                            span_lint_and_sugg(
-                                cx,
-                                LARGE_TYPES_PASSED_BY_VALUE,
-                                input.span,
-                                &format!("this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", self.value_max_size),
-                                "consider passing by reference instead",
-                                format!("&{}", snippet(cx, input.span, "_")),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
+                    if is_copy(cx, ty)
+                        && !is_self_ty(input)
+                        && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes())
+                        && size > self.value_max_size
+                    {
+                        span_lint_and_sugg(
+                            cx,
+                            LARGE_TYPES_PASSED_BY_VALUE,
+                            input.span,
+                            &format!(
+                                "this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)",
+                                self.value_max_size
+                            ),
+                            "consider passing by reference instead",
+                            format!("&{}", snippet(cx, input.span, "_")),
+                            Applicability::MaybeIncorrect,
+                        );
                     }
                 },
 
diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs
index 057b7e30642..b638e83997a 100644
--- a/clippy_lints/src/precedence.rs
+++ b/clippy_lints/src/precedence.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp};
 use rustc_ast::token;
 use rustc_errors::Applicability;
@@ -118,25 +117,23 @@ impl EarlyLintPass for Precedence {
                 arg = receiver;
             }
 
-            if_chain! {
-                if !all_odd;
-                if let ExprKind::Lit(lit) = &arg.kind;
-                if let token::LitKind::Integer | token::LitKind::Float = &lit.kind;
-                then {
-                    let mut applicability = Applicability::MachineApplicable;
-                    span_lint_and_sugg(
-                        cx,
-                        PRECEDENCE,
-                        expr.span,
-                        "unary minus has lower precedence than method call",
-                        "consider adding parentheses to clarify your intent",
-                        format!(
-                            "-({})",
-                            snippet_with_applicability(cx, operand.span, "..", &mut applicability)
-                        ),
-                        applicability,
-                    );
-                }
+            if !all_odd
+                && let ExprKind::Lit(lit) = &arg.kind
+                && let token::LitKind::Integer | token::LitKind::Float = &lit.kind
+            {
+                let mut applicability = Applicability::MachineApplicable;
+                span_lint_and_sugg(
+                    cx,
+                    PRECEDENCE,
+                    expr.span,
+                    "unary minus has lower precedence than method call",
+                    "consider adding parentheses to clarify your intent",
+                    format!(
+                        "-({})",
+                        snippet_with_applicability(cx, operand.span, "..", &mut applicability)
+                    ),
+                    applicability,
+                );
             }
         }
     }
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index b133635e883..5c395143b9a 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -10,7 +10,6 @@ use clippy_utils::{
     is_res_lang_ctor, pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks,
     peel_blocks_with_stmt,
 };
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
@@ -179,17 +178,15 @@ fn expr_return_none_or_err(
             _ => false,
         },
         ExprKind::Call(call_expr, args_expr) => {
-            if_chain! {
-                if smbl == sym::Result;
-                if let ExprKind::Path(QPath::Resolved(_, path)) = &call_expr.kind;
-                if let Some(segment) = path.segments.first();
-                if let Some(err_sym) = err_sym;
-                if let Some(arg) = args_expr.first();
-                if let ExprKind::Path(QPath::Resolved(_, arg_path)) = &arg.kind;
-                if let Some(PathSegment { ident, .. }) = arg_path.segments.first();
-                then {
-                    return segment.ident.name == sym::Err && err_sym == ident.name;
-                }
+            if smbl == sym::Result
+                && let ExprKind::Path(QPath::Resolved(_, path)) = &call_expr.kind
+                && let Some(segment) = path.segments.first()
+                && let Some(err_sym) = err_sym
+                && let Some(arg) = args_expr.first()
+                && let ExprKind::Path(QPath::Resolved(_, arg_path)) = &arg.kind
+                && let Some(PathSegment { ident, .. }) = arg_path.segments.first()
+            {
+                return segment.ident.name == sym::Err && err_sym == ident.name;
             }
             false
         },
@@ -218,81 +215,85 @@ impl QuestionMark {
     ///
     /// If it matches, it will suggest to use the question mark operator instead
     fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-        if_chain! {
-            if !self.inside_try_block();
-            if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
-            if !is_else_clause(cx.tcx, expr);
-            if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind;
-            let caller_ty = cx.typeck_results().expr_ty(caller);
-            let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else);
-            if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block);
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
-                let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) &&
-                    !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
-                let sugg = if let Some(else_inner) = r#else {
-                    if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
-                        format!("Some({receiver_str}?)")
-                    } else {
-                        return;
-                    }
+        if !self.inside_try_block()
+            && let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
+            && !is_else_clause(cx.tcx, expr)
+            && let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
+            && let caller_ty = cx.typeck_results().expr_ty(caller)
+            && let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else)
+            && (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
+            let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
+                && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
+            let sugg = if let Some(else_inner) = r#else {
+                if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
+                    format!("Some({receiver_str}?)")
                 } else {
-                    format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
-                };
+                    return;
+                }
+            } else {
+                format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
+            };
 
-                span_lint_and_sugg(
-                    cx,
-                    QUESTION_MARK,
-                    expr.span,
-                    "this block may be rewritten with the `?` operator",
-                    "replace it with",
-                    sugg,
-                    applicability,
-                );
-            }
+            span_lint_and_sugg(
+                cx,
+                QUESTION_MARK,
+                expr.span,
+                "this block may be rewritten with the `?` operator",
+                "replace it with",
+                sugg,
+                applicability,
+            );
         }
     }
 
     fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-        if_chain! {
-            if !self.inside_try_block();
-            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
-            if !is_else_clause(cx.tcx, expr);
-            if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind;
-            if ddpos.as_opt_usize().is_none();
-            if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
-            let caller_ty = cx.typeck_results().expr_ty(let_expr);
-            let if_block = IfBlockType::IfLet(
+        if !self.inside_try_block()
+            && let Some(higher::IfLet {
+                let_pat,
+                let_expr,
+                if_then,
+                if_else,
+            }) = higher::IfLet::hir(cx, expr)
+            && !is_else_clause(cx.tcx, expr)
+            && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
+            && ddpos.as_opt_usize().is_none()
+            && let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
+            && let caller_ty = cx.typeck_results().expr_ty(let_expr)
+            && let if_block = IfBlockType::IfLet(
                 cx.qpath_res(path1, let_pat.hir_id),
                 caller_ty,
                 ident.name,
                 let_expr,
                 if_then,
-                if_else
+                if_else,
+            )
+            && ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
+                || is_early_return(sym::Result, cx, &if_block))
+            && if_else
+                .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
+                .filter(|e| *e)
+                .is_none()
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
+            let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
+            let sugg = format!(
+                "{receiver_str}{}?{}",
+                if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
+                if requires_semi { ";" } else { "" }
+            );
+            span_lint_and_sugg(
+                cx,
+                QUESTION_MARK,
+                expr.span,
+                "this block may be rewritten with the `?` operator",
+                "replace it with",
+                sugg,
+                applicability,
             );
-            if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
-                || is_early_return(sym::Result, cx, &if_block);
-            if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
-                let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
-                let sugg = format!(
-                    "{receiver_str}{}?{}",
-                    if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
-                    if requires_semi { ";" } else { "" }
-                );
-                span_lint_and_sugg(
-                    cx,
-                    QUESTION_MARK,
-                    expr.span,
-                    "this block may be rewritten with the `?` operator",
-                    "replace it with",
-                    sugg,
-                    applicability,
-                );
-            }
         }
     }
 }
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index ffd49de3820..9bdba994020 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -4,7 +4,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
 use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{get_parent_expr, higher, in_constant, is_integer_const, path_to_local};
-use if_chain::if_chain;
 use rustc_ast::ast::RangeLimits;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, HirId};
@@ -282,16 +281,14 @@ fn check_possible_range_contains(
 
     // If the LHS is the same operator, we have to recurse to get the "real" RHS, since they have
     // the same operator precedence
-    if_chain! {
-        if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind;
-        if op == lhs_op.node;
-        let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent());
-        if let Some(snip) = &snippet_opt(cx, new_span);
+    if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind
+        && op == lhs_op.node
+        && let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent())
+        && let Some(snip) = &snippet_opt(cx, new_span)
         // Do not continue if we have mismatched number of parens, otherwise the suggestion is wrong
-        if snip.matches('(').count() == snip.matches(')').count();
-        then {
-            check_possible_range_contains(cx, op, new_lhs, right, expr, new_span);
-        }
+        && snip.matches('(').count() == snip.matches(')').count()
+    {
+        check_possible_range_contains(cx, op, new_lhs, right, expr, new_span);
     }
 }
 
@@ -348,71 +345,66 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) ->
 
 // exclusive range plus one: `x..(y+1)`
 fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if expr.span.can_be_used_for_suggestions();
-        if let Some(higher::Range {
+    if expr.span.can_be_used_for_suggestions()
+        && let Some(higher::Range {
             start,
             end: Some(end),
-            limits: RangeLimits::HalfOpen
-        }) = higher::Range::hir(expr);
-        if let Some(y) = y_plus_one(cx, end);
-        then {
-            let span = expr.span;
-            span_lint_and_then(
-                cx,
-                RANGE_PLUS_ONE,
-                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();
-                    if let Some(is_wrapped) = &snippet_opt(cx, span) {
-                        if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
-                            diag.span_suggestion(
-                                span,
-                                "use",
-                                format!("({start}..={end})"),
-                                Applicability::MaybeIncorrect,
-                            );
-                        } else {
-                            diag.span_suggestion(
-                                span,
-                                "use",
-                                format!("{start}..={end}"),
-                                Applicability::MachineApplicable, // snippet
-                            );
-                        }
+            limits: RangeLimits::HalfOpen,
+        }) = higher::Range::hir(expr)
+        && let Some(y) = y_plus_one(cx, end)
+    {
+        let span = expr.span;
+        span_lint_and_then(
+            cx,
+            RANGE_PLUS_ONE,
+            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();
+                if let Some(is_wrapped) = &snippet_opt(cx, span) {
+                    if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
+                        diag.span_suggestion(span, "use", format!("({start}..={end})"), Applicability::MaybeIncorrect);
+                    } else {
+                        diag.span_suggestion(
+                            span,
+                            "use",
+                            format!("{start}..={end}"),
+                            Applicability::MachineApplicable, // snippet
+                        );
                     }
-                },
-            );
-        }
+                }
+            },
+        );
     }
 }
 
 // inclusive range minus one: `x..=(y-1)`
 fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if expr.span.can_be_used_for_suggestions();
-        if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::Range::hir(expr);
-        if let Some(y) = y_minus_one(cx, end);
-        then {
-            span_lint_and_then(
-                cx,
-                RANGE_MINUS_ONE,
-                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();
-                    diag.span_suggestion(
-                        expr.span,
-                        "use",
-                        format!("{start}..{end}"),
-                        Applicability::MachineApplicable, // snippet
-                    );
-                },
-            );
-        }
+    if expr.span.can_be_used_for_suggestions()
+        && let Some(higher::Range {
+            start,
+            end: Some(end),
+            limits: RangeLimits::Closed,
+        }) = higher::Range::hir(expr)
+        && let Some(y) = y_minus_one(cx, end)
+    {
+        span_lint_and_then(
+            cx,
+            RANGE_MINUS_ONE,
+            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();
+                diag.span_suggestion(
+                    expr.span,
+                    "use",
+                    format!("{start}..{end}"),
+                    Applicability::MachineApplicable, // snippet
+                );
+            },
+        );
     }
 }
 
@@ -446,52 +438,54 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
         }
     }
 
-    if_chain! {
-        if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr);
-        let ty = cx.typeck_results().expr_ty(start);
-        if let ty::Int(_) | ty::Uint(_) = ty.kind();
-        if let Some(start_idx) = constant(cx, cx.typeck_results(), start);
-        if let Some(end_idx) = constant(cx, cx.typeck_results(), end);
-        if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
-        if is_empty_range(limits, ordering);
-        then {
-            if inside_indexing_expr(cx, expr) {
-                // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ...
-                if ordering != Ordering::Equal {
-                    span_lint(
-                        cx,
-                        REVERSED_EMPTY_RANGES,
-                        expr.span,
-                        "this range is reversed and using it to index a slice will panic at run-time",
-                    );
-                }
-            // ... except in for loop arguments for backwards compatibility with `reverse_range_loop`
-            } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) {
-                span_lint_and_then(
+    if let Some(higher::Range {
+        start: Some(start),
+        end: Some(end),
+        limits,
+    }) = higher::Range::hir(expr)
+        && let ty = cx.typeck_results().expr_ty(start)
+        && let ty::Int(_) | ty::Uint(_) = ty.kind()
+        && let Some(start_idx) = constant(cx, cx.typeck_results(), start)
+        && let Some(end_idx) = constant(cx, cx.typeck_results(), end)
+        && let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx)
+        && is_empty_range(limits, ordering)
+    {
+        if inside_indexing_expr(cx, expr) {
+            // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ...
+            if ordering != Ordering::Equal {
+                span_lint(
                     cx,
                     REVERSED_EMPTY_RANGES,
                     expr.span,
-                    "this range is empty so it will yield no values",
-                    |diag| {
-                        if ordering != Ordering::Equal {
-                            let start_snippet = snippet(cx, start.span, "_");
-                            let end_snippet = snippet(cx, end.span, "_");
-                            let dots = match limits {
-                                RangeLimits::HalfOpen => "..",
-                                RangeLimits::Closed => "..="
-                            };
-
-                            diag.span_suggestion(
-                                expr.span,
-                                "consider using the following if you are attempting to iterate over this \
-                                 range in reverse",
-                                format!("({end_snippet}{dots}{start_snippet}).rev()"),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                    },
+                    "this range is reversed and using it to index a slice will panic at run-time",
                 );
             }
+        // ... except in for loop arguments for backwards compatibility with `reverse_range_loop`
+        } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) {
+            span_lint_and_then(
+                cx,
+                REVERSED_EMPTY_RANGES,
+                expr.span,
+                "this range is empty so it will yield no values",
+                |diag| {
+                    if ordering != Ordering::Equal {
+                        let start_snippet = snippet(cx, start.span, "_");
+                        let end_snippet = snippet(cx, end.span, "_");
+                        let dots = match limits {
+                            RangeLimits::HalfOpen => "..",
+                            RangeLimits::Closed => "..=",
+                        };
+
+                        diag.span_suggestion(
+                            expr.span,
+                            "consider using the following if you are attempting to iterate over this \
+                             range in reverse",
+                            format!("({end_snippet}{dots}{start_snippet}).rev()"),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs
index 391c77dbf90..98f5a07da0d 100644
--- a/clippy_lints/src/raw_strings.rs
+++ b/clippy_lints/src/raw_strings.rs
@@ -56,7 +56,7 @@ declare_clippy_lint! {
 impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]);
 
 pub struct RawStrings {
-    pub needless_raw_string_hashes_allow_one: bool,
+    pub allow_one_hash_in_raw_strings: bool,
 }
 
 impl EarlyLintPass for RawStrings {
diff --git a/clippy_lints/src/rc_clone_in_vec_init.rs b/clippy_lints/src/rc_clone_in_vec_init.rs
index 59ce289e7d2..b99af44655d 100644
--- a/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/clippy_lints/src/rc_clone_in_vec_init.rs
@@ -118,26 +118,24 @@ fn emit_lint(cx: &LateContext<'_>, symbol: Symbol, lint_span: Span, elem: &Expr<
 
 /// Checks whether the given `expr` is a call to `Arc::new`, `Rc::new`, or evaluates to a `Weak`
 fn ref_init(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(Symbol, Span)> {
-    if_chain! {
-        if let ExprKind::Call(func, _args) = expr.kind;
-        if let ExprKind::Path(ref func_path @ QPath::TypeRelative(ty, _)) = func.kind;
-        if let TyKind::Path(ref ty_path) = ty.kind;
-        if let Some(def_id) = cx.qpath_res(ty_path, ty.hir_id).opt_def_id();
-
-        then {
-            if last_path_segment(func_path).ident.name == sym::new
-                && let Some(symbol) = cx
-                    .tcx
-                    .get_diagnostic_name(def_id)
-                    .filter(|symbol| symbol == &sym::Arc || symbol == &sym::Rc) {
-                return Some((symbol, func.span));
-            }
+    if let ExprKind::Call(func, _args) = expr.kind
+        && let ExprKind::Path(ref func_path @ QPath::TypeRelative(ty, _)) = func.kind
+        && let TyKind::Path(ref ty_path) = ty.kind
+        && let Some(def_id) = cx.qpath_res(ty_path, ty.hir_id).opt_def_id()
+    {
+        if last_path_segment(func_path).ident.name == sym::new
+            && let Some(symbol) = cx
+                .tcx
+                .get_diagnostic_name(def_id)
+                .filter(|symbol| symbol == &sym::Arc || symbol == &sym::Rc)
+        {
+            return Some((symbol, func.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));
-            }
+        if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind()
+            && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak))
+        {
+            return Some((Symbol::intern("Weak"), func.span));
         }
     }
 
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index ef14e68967e..88dbf9ef549 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -3,7 +3,6 @@ use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
 use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{def_id, Body, FnDecl, LangItem};
@@ -146,18 +145,16 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 let pred_terminator = mir[ps[0]].terminator();
 
                 // receiver of the `deref()` call
-                let (pred_arg, deref_clone_ret) = if_chain! {
-                    if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) =
-                        is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
-                    if res == cloned;
-                    if cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id);
-                    if is_type_diagnostic_item(cx, pred_arg_ty, sym::PathBuf)
-                        || is_type_diagnostic_item(cx, pred_arg_ty, sym::OsString);
-                    then {
-                        (pred_arg, res)
-                    } else {
-                        continue;
-                    }
+                let (pred_arg, deref_clone_ret) = if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) =
+                    is_call_with_ref_arg(cx, mir, &pred_terminator.kind)
+                    && res == cloned
+                    && cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id)
+                    && (is_type_diagnostic_item(cx, pred_arg_ty, sym::PathBuf)
+                        || is_type_diagnostic_item(cx, pred_arg_ty, sym::OsString))
+                {
+                    (pred_arg, res)
+                } else {
+                    continue;
                 };
 
                 let (local, cannot_move_out) =
@@ -212,45 +209,37 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 .assert_crate_local()
                 .lint_root;
 
-            if_chain! {
-                if let Some(snip) = snippet_opt(cx, span);
-                if let Some(dot) = snip.rfind('.');
-                then {
-                    let sugg_span = span.with_lo(
-                        span.lo() + BytePos(u32::try_from(dot).unwrap())
-                    );
-                    let mut app = Applicability::MaybeIncorrect;
-
-                    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.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') {
-                            app = Applicability::MachineApplicable;
-                        }
+            if let Some(snip) = snippet_opt(cx, span)
+                && let Some(dot) = snip.rfind('.')
+            {
+                let sugg_span = span.with_lo(span.lo() + BytePos(u32::try_from(dot).unwrap()));
+                let mut app = Applicability::MaybeIncorrect;
+
+                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
+                        .as_bytes()
+                        .iter()
+                        .all(|b| b.is_ascii_alphabetic() || *b == b'_')
+                    {
+                        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,
+                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 {
+                        diag.span_note(span, "cloned value is neither consumed nor mutated");
+                    } else {
+                        diag.span_note(
+                            span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
+                            "this value is dropped without further use",
                         );
-                        if clone_usage.cloned_used {
-                            diag.span_note(
-                                span,
-                                "cloned value is neither consumed nor mutated",
-                            );
-                        } else {
-                            diag.span_note(
-                                span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
-                                "this value is dropped without further use",
-                            );
-                        }
-                    });
-                } else {
-                    span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
-                }
+                    }
+                });
+            } else {
+                span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
             }
         }
     }
@@ -262,18 +251,21 @@ fn is_call_with_ref_arg<'tcx>(
     mir: &'tcx mir::Body<'tcx>,
     kind: &'tcx mir::TerminatorKind<'tcx>,
 ) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, mir::Local)> {
-    if_chain! {
-        if let mir::TerminatorKind::Call { func, args, destination, .. } = kind;
-        if args.len() == 1;
-        if let mir::Operand::Move(mir::Place { local, .. }) = &args[0];
-        if let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind();
-        if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx));
-        if !is_copy(cx, inner_ty);
-        then {
-            Some((def_id, *local, inner_ty, destination.as_local()?))
-        } else {
-            None
-        }
+    if let mir::TerminatorKind::Call {
+        func,
+        args,
+        destination,
+        ..
+    } = kind
+        && args.len() == 1
+        && let mir::Operand::Move(mir::Place { local, .. }) = &args[0]
+        && let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind()
+        && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx))
+        && !is_copy(cx, inner_ty)
+    {
+        Some((def_id, *local, inner_ty, destination.as_local()?))
+    } else {
+        None
     }
 }
 
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index e679fab5323..f2a006ebdfc 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/clippy_lints/src/redundant_closure_call.rs
@@ -2,7 +2,6 @@ use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::get_parent_expr;
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit as hir_visit;
@@ -141,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
         }
 
         if let hir::ExprKind::Call(recv, _) = expr.kind
-            // don't lint if the receiver is a call, too. 
+            // don't lint if the receiver is a call, too.
             // we do this in order to prevent linting multiple times; consider:
             // `(|| || 1)()()`
             //           ^^  we only want to lint for this call (but we walk up the calls to consider both calls).
@@ -201,14 +200,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                 type NestedFilter = nested_filter::OnlyBodies;
 
                 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-                    if_chain! {
-                        if let hir::ExprKind::Call(closure, _) = expr.kind;
-                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind;
-                        if self.path.segments[0].ident == path.segments[0].ident;
-                        if self.path.res == path.res;
-                        then {
-                            self.count += 1;
-                        }
+                    if let hir::ExprKind::Call(closure, _) = expr.kind
+                        && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind
+                        && self.path.segments[0].ident == path.segments[0].ident
+                        && self.path.res == path.res
+                    {
+                        self.count += 1;
                     }
                     hir_visit::walk_expr(self, expr);
                 }
@@ -223,25 +220,23 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
         }
 
         for w in block.stmts.windows(2) {
-            if_chain! {
-                if let hir::StmtKind::Local(local) = w[0].kind;
-                if let Option::Some(t) = local.init;
-                if let hir::ExprKind::Closure { .. } = t.kind;
-                if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
-                if let hir::StmtKind::Semi(second) = w[1].kind;
-                if let hir::ExprKind::Assign(_, call, _) = second.kind;
-                if let hir::ExprKind::Call(closure, _) = call.kind;
-                if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind;
-                if ident == path.segments[0].ident;
-                if count_closure_usage(cx, block, path) == 1;
-                then {
-                    span_lint(
-                        cx,
-                        REDUNDANT_CLOSURE_CALL,
-                        second.span,
-                        "closure called just once immediately after it was declared",
-                    );
-                }
+            if let hir::StmtKind::Local(local) = w[0].kind
+                && let Option::Some(t) = local.init
+                && let hir::ExprKind::Closure { .. } = t.kind
+                && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind
+                && let hir::StmtKind::Semi(second) = w[1].kind
+                && let hir::ExprKind::Assign(_, call, _) = second.kind
+                && let hir::ExprKind::Call(closure, _) = call.kind
+                && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind
+                && ident == path.segments[0].ident
+                && count_closure_usage(cx, block, path) == 1
+            {
+                span_lint(
+                    cx,
+                    REDUNDANT_CLOSURE_CALL,
+                    second.span,
+                    "closure called just once immediately after it was declared",
+                );
             }
         }
     }
diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs
index 6bc0d06183f..15b784039b6 100644
--- a/clippy_lints/src/redundant_locals.rs
+++ b/clippy_lints/src/redundant_locals.rs
@@ -46,40 +46,38 @@ declare_lint_pass!(RedundantLocals => [REDUNDANT_LOCALS]);
 
 impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
-        if_chain! {
-            if !local.span.is_desugaring(DesugaringKind::Async);
+        if !local.span.is_desugaring(DesugaringKind::Async)
             // the pattern is a single by-value binding
-            if let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind;
+            && let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind
             // the binding is not type-ascribed
-            if local.ty.is_none();
+            && local.ty.is_none()
             // the expression is a resolved path
-            if let Some(expr) = local.init;
-            if let ExprKind::Path(qpath @ QPath::Resolved(None, path)) = expr.kind;
+            && let Some(expr) = local.init
+            && let ExprKind::Path(qpath @ QPath::Resolved(None, path)) = expr.kind
             // the path is a single segment equal to the local's name
-            if let [last_segment] = path.segments;
-            if last_segment.ident == ident;
+            && let [last_segment] = path.segments
+            && last_segment.ident == ident
             // resolve the path to its defining binding pattern
-            if let Res::Local(binding_id) = cx.qpath_res(&qpath, expr.hir_id);
-            if let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id);
+            && let Res::Local(binding_id) = cx.qpath_res(&qpath, expr.hir_id)
+            && let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id)
             // the previous binding has the same mutability
-            if find_binding(binding_pat, ident).is_some_and(|bind| bind.1 == mutability);
+            && find_binding(binding_pat, ident).is_some_and(|bind| bind.1 == mutability)
             // the local does not change the effect of assignments to the binding. see #11290
-            if !affects_assignments(cx, mutability, binding_id, local.hir_id);
+            && !affects_assignments(cx, mutability, binding_id, local.hir_id)
             // the local does not affect the code's drop behavior
-            if !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr));
+            && !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr))
             // the local is user-controlled
-            if !in_external_macro(cx.sess(), local.span);
-            if !is_from_proc_macro(cx, expr);
-            then {
-                span_lint_and_help(
-                    cx,
-                    REDUNDANT_LOCALS,
-                    local.span,
-                    &format!("redundant redefinition of a binding `{ident}`"),
-                    Some(binding_pat.span),
-                    &format!("`{ident}` is initially defined here"),
-                );
-            }
+            && !in_external_macro(cx.sess(), local.span)
+            && !is_from_proc_macro(cx, expr)
+        {
+            span_lint_and_help(
+                cx,
+                REDUNDANT_LOCALS,
+                local.span,
+                &format!("redundant redefinition of a binding `{ident}`"),
+                Some(binding_pat.span),
+                &format!("`{ident}` is initially defined here"),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs
index 03673eb27f8..32e0c3749ab 100644
--- a/clippy_lints/src/redundant_pub_crate.rs
+++ b/clippy_lints/src/redundant_pub_crate.rs
@@ -45,28 +45,27 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);
 
 impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if_chain! {
-            if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id());
-            if !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false);
-            if is_not_macro_export(item);
-            then {
-                let span = item.span.with_hi(item.ident.span.hi());
-                let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
-                span_lint_and_then(
-                    cx,
-                    REDUNDANT_PUB_CRATE,
-                    span,
-                    &format!("pub(crate) {descr} inside private module"),
-                    |diag| {
-                        diag.span_suggestion(
-                            item.vis_span,
-                            "consider using",
-                            "pub".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                );
-            }
+        if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
+            && !cx.effective_visibilities.is_exported(item.owner_id.def_id)
+            && self.is_exported.last() == Some(&false)
+            && is_not_macro_export(item)
+        {
+            let span = item.span.with_hi(item.ident.span.hi());
+            let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
+            span_lint_and_then(
+                cx,
+                REDUNDANT_PUB_CRATE,
+                span,
+                &format!("pub(crate) {descr} inside private module"),
+                |diag| {
+                    diag.span_suggestion(
+                        item.vis_span,
+                        "consider using",
+                        "pub".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                },
+            );
         }
 
         if let ItemKind::Mod { .. } = item.kind {
diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs
index 7adbd67912c..c9fc65653c2 100644
--- a/clippy_lints/src/redundant_slicing.rs
+++ b/clippy_lints/src/redundant_slicing.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{is_type_lang_item, peel_mid_ty_refs};
-use if_chain::if_chain;
 use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
@@ -78,92 +77,83 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
         }
 
         let ctxt = expr.span.ctxt();
-        if_chain! {
-            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
-            if addressee.span.ctxt() == ctxt;
-            if let ExprKind::Index(indexed, range, _) = addressee.kind;
-            if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull);
-            then {
-                let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr));
-                let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed));
-                let parent_expr = get_parent_expr(cx, expr);
-                let needs_parens_for_prefix = parent_expr.map_or(false, |parent| {
-                    parent.precedence().order() > PREC_PREFIX
-                });
-                let mut app = Applicability::MachineApplicable;
+        if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind
+            && addressee.span.ctxt() == ctxt
+            && let ExprKind::Index(indexed, range, _) = addressee.kind
+            && is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull)
+        {
+            let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr));
+            let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed));
+            let parent_expr = get_parent_expr(cx, expr);
+            let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX);
+            let mut app = Applicability::MachineApplicable;
 
-                let ((lint, msg), help, sugg) = if expr_ty == indexed_ty {
-                    if expr_ref_count > indexed_ref_count {
-                        // Indexing takes self by reference and can't return a reference to that
-                        // reference as it's a local variable. The only way this could happen is if
-                        // `self` contains a reference to the `Self` type. If this occurs then the
-                        // lint no longer applies as it's essentially a field access, which is not
-                        // redundant.
-                        return;
-                    }
-                    let deref_count = indexed_ref_count - expr_ref_count;
+            let ((lint, msg), help, sugg) = if expr_ty == indexed_ty {
+                if expr_ref_count > indexed_ref_count {
+                    // Indexing takes self by reference and can't return a reference to that
+                    // reference as it's a local variable. The only way this could happen is if
+                    // `self` contains a reference to the `Self` type. If this occurs then the
+                    // lint no longer applies as it's essentially a field access, which is not
+                    // redundant.
+                    return;
+                }
+                let deref_count = indexed_ref_count - expr_ref_count;
 
-                    let (lint, reborrow_str, help_str) = if mutability == Mutability::Mut {
-                        // The slice was used to reborrow the mutable reference.
-                        (DEREF_BY_SLICING_LINT, "&mut *", "reborrow the original value instead")
-                    } else if matches!(
-                        parent_expr,
-                        Some(Expr {
-                            kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _),
-                            ..
-                        })
-                    ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| {
-                        matches!(a.kind, Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })))
-                    }) {
-                        // The slice was used to make a temporary reference.
-                        (DEREF_BY_SLICING_LINT, "&*", "reborrow the original value instead")
-                    } else if deref_count != 0 {
-                        (DEREF_BY_SLICING_LINT, "", "dereference the original value instead")
-                    } else {
-                        (REDUNDANT_SLICING_LINT, "", "use the original value instead")
-                    };
+                let (lint, reborrow_str, help_str) = if mutability == Mutability::Mut {
+                    // The slice was used to reborrow the mutable reference.
+                    (DEREF_BY_SLICING_LINT, "&mut *", "reborrow the original value instead")
+                } else if matches!(
+                    parent_expr,
+                    Some(Expr {
+                        kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _),
+                        ..
+                    })
+                ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| {
+                    matches!(
+                        a.kind,
+                        Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. }))
+                    )
+                }) {
+                    // The slice was used to make a temporary reference.
+                    (DEREF_BY_SLICING_LINT, "&*", "reborrow the original value instead")
+                } else if deref_count != 0 {
+                    (DEREF_BY_SLICING_LINT, "", "dereference the original value instead")
+                } else {
+                    (REDUNDANT_SLICING_LINT, "", "use the original value instead")
+                };
 
-                    let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
-                    let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
-                        format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
-                    } else {
-                        format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
-                    };
+                let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
+                let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
+                    format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
+                } else {
+                    format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
+                };
 
-                    (lint, help_str, sugg)
-                } else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
-                    if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
-                        cx.param_env,
-                        Ty::new_projection(cx.tcx,target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
-                    ) {
-                        if deref_ty == expr_ty {
-                            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))
-                            };
-                            (DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg)
+                (lint, help_str, sugg)
+            } else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
+                if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
+                    cx.param_env,
+                    Ty::new_projection(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
+                ) {
+                    if deref_ty == expr_ty {
+                        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 {
-                            return;
-                        }
+                            format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
+                        };
+                        (DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg)
                     } else {
                         return;
                     }
                 } else {
                     return;
-                };
+                }
+            } else {
+                return;
+            };
 
-                span_lint_and_sugg(
-                    cx,
-                    lint,
-                    expr.span,
-                    msg,
-                    help,
-                    sugg,
-                    app,
-                );
-            }
+            span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg, app);
         }
     }
 }
diff --git a/clippy_lints/src/ref_option_ref.rs b/clippy_lints/src/ref_option_ref.rs
index c984a8286eb..0ba898e75a1 100644
--- a/clippy_lints/src/ref_option_ref.rs
+++ b/clippy_lints/src/ref_option_ref.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::last_path_segment;
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -38,34 +37,30 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]);
 
 impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
     fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
-        if_chain! {
-            if let TyKind::Ref(_, ref mut_ty) = ty.kind;
-            if mut_ty.mutbl == Mutability::Not;
-            if let TyKind::Path(ref qpath) = &mut_ty.ty.kind;
-            let last = last_path_segment(qpath);
-            if let Some(def_id) = last.res.opt_def_id();
-
-            if cx.tcx.is_diagnostic_item(sym::Option, def_id);
-            if let Some(params) = last_path_segment(qpath).args ;
-            if params.parenthesized == GenericArgsParentheses::No;
-            if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg {
+        if let TyKind::Ref(_, ref mut_ty) = ty.kind
+            && mut_ty.mutbl == Mutability::Not
+            && let TyKind::Path(ref qpath) = &mut_ty.ty.kind
+            && let last = last_path_segment(qpath)
+            && let Some(def_id) = last.res.opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::Option, def_id)
+            && let Some(params) = last_path_segment(qpath).args
+            && params.parenthesized == GenericArgsParentheses::No
+            && let Some(inner_ty) = params.args.iter().find_map(|arg| match arg {
                 GenericArg::Type(inner_ty) => Some(inner_ty),
                 _ => None,
-            });
-            if let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind;
-            if inner_mut_ty.mutbl == Mutability::Not;
-
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    REF_OPTION_REF,
-                    ty.span,
-                    "since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`",
-                    "try",
-                    format!("Option<{}>", &snippet(cx, inner_ty.span, "..")),
-                    Applicability::MaybeIncorrect,
-                );
-            }
+            })
+            && let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind
+            && inner_mut_ty.mutbl == Mutability::Not
+        {
+            span_lint_and_sugg(
+                cx,
+                REF_OPTION_REF,
+                ty.span,
+                "since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`",
+                "try",
+                format!("Option<{}>", &snippet(cx, inner_ty.span, "..")),
+                Applicability::MaybeIncorrect,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs
index 12da29f1108..69818db7c82 100644
--- a/clippy_lints/src/reference.rs
+++ b/clippy_lints/src/reference.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -47,58 +46,62 @@ fn without_parens(mut e: &Expr) -> &Expr {
 
 impl EarlyLintPass for DerefAddrOf {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
-        if_chain! {
-            if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind;
-            if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind;
-            if deref_target.span.eq_ctxt(e.span);
-            if !addrof_target.span.from_expansion();
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let sugg = if e.span.from_expansion() {
-                    if let Some(macro_source) = snippet_opt(cx, e.span) {
-                        // Remove leading whitespace from the given span
-                        // e.g: ` $visitor` turns into `$visitor`
-                        let trim_leading_whitespaces = |span| {
-                            snippet_opt(cx, span).and_then(|snip| {
+        if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind
+            && let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind
+            && deref_target.span.eq_ctxt(e.span)
+            && !addrof_target.span.from_expansion()
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let sugg = if e.span.from_expansion() {
+                if let Some(macro_source) = snippet_opt(cx, e.span) {
+                    // Remove leading whitespace from the given span
+                    // e.g: ` $visitor` turns into `$visitor`
+                    let trim_leading_whitespaces = |span| {
+                        snippet_opt(cx, span)
+                            .and_then(|snip| {
                                 #[expect(clippy::cast_possible_truncation)]
-                                snip.find(|c: char| !c.is_whitespace()).map(|pos| {
-                                    span.lo() + BytePos(pos as u32)
-                                })
-                            }).map_or(span, |start_no_whitespace| e.span.with_lo(start_no_whitespace))
-                        };
-
-                        let mut generate_snippet = |pattern: &str| {
-                            #[expect(clippy::cast_possible_truncation)]
-                            macro_source.rfind(pattern).map(|pattern_pos| {
-                                let rpos = pattern_pos + pattern.len();
-                                let span_after_ref = e.span.with_lo(BytePos(e.span.lo().0 + rpos as u32));
-                                let span = trim_leading_whitespaces(span_after_ref);
-                                snippet_with_applicability(cx, span, "_", &mut applicability)
+                                snip.find(|c: char| !c.is_whitespace())
+                                    .map(|pos| span.lo() + BytePos(pos as u32))
                             })
-                        };
+                            .map_or(span, |start_no_whitespace| e.span.with_lo(start_no_whitespace))
+                    };
+
+                    let mut generate_snippet = |pattern: &str| {
+                        #[expect(clippy::cast_possible_truncation)]
+                        macro_source.rfind(pattern).map(|pattern_pos| {
+                            let rpos = pattern_pos + pattern.len();
+                            let span_after_ref = e.span.with_lo(BytePos(e.span.lo().0 + rpos as u32));
+                            let span = trim_leading_whitespaces(span_after_ref);
+                            snippet_with_applicability(cx, span, "_", &mut applicability)
+                        })
+                    };
 
-                        if *mutability == Mutability::Mut {
-                            generate_snippet("mut")
-                        } else {
-                            generate_snippet("&")
-                        }
+                    if *mutability == Mutability::Mut {
+                        generate_snippet("mut")
                     } else {
-                        Some(snippet_with_applicability(cx, e.span, "_", &mut applicability))
+                        generate_snippet("&")
                     }
                 } else {
-                    Some(snippet_with_applicability(cx, addrof_target.span, "_", &mut applicability))
-                };
-                if let Some(sugg) = sugg {
-                    span_lint_and_sugg(
-                        cx,
-                        DEREF_ADDROF,
-                        e.span,
-                        "immediately dereferencing a reference",
-                        "try",
-                        sugg.to_string(),
-                        applicability,
-                    );
+                    Some(snippet_with_applicability(cx, e.span, "_", &mut applicability))
                 }
+            } else {
+                Some(snippet_with_applicability(
+                    cx,
+                    addrof_target.span,
+                    "_",
+                    &mut applicability,
+                ))
+            };
+            if let Some(sugg) = sugg {
+                span_lint_and_sugg(
+                    cx,
+                    DEREF_ADDROF,
+                    e.span,
+                    "immediately dereferencing a reference",
+                    "try",
+                    sugg.to_string(),
+                    applicability,
+                );
             }
         }
     }
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index b795e4b15ba..3571b9bfb8d 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -191,13 +191,11 @@ fn is_trivial_regex(s: &regex_syntax::hir::Hir) -> Option<&'static str> {
 }
 
 fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
-    if_chain! {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind;
-        if let ExprKind::Array(exprs) = expr.kind;
-        then {
-            for expr in exprs {
-                check_regex(cx, expr, utf8);
-            }
+    if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind
+        && let ExprKind::Array(exprs) = expr.kind
+    {
+        for expr in exprs {
+            check_regex(cx, expr, utf8);
         }
     }
 }
diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs
index 245029a066d..ad22b751bef 100644
--- a/clippy_lints/src/return_self_not_must_use.rs
+++ b/clippy_lints/src/return_self_not_must_use.rs
@@ -69,35 +69,32 @@ declare_clippy_lint! {
 declare_lint_pass!(ReturnSelfNotMustUse => [RETURN_SELF_NOT_MUST_USE]);
 
 fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, owner_id: OwnerId) {
-    if_chain! {
+    if !in_external_macro(cx.sess(), span)
         // If it comes from an external macro, better ignore it.
-        if !in_external_macro(cx.sess(), span);
-        if decl.implicit_self.has_implicit_self();
+        && decl.implicit_self.has_implicit_self()
         // We only show this warning for public exported methods.
-        if cx.effective_visibilities.is_exported(fn_def);
+        && cx.effective_visibilities.is_exported(fn_def)
         // We don't want to emit this lint if the `#[must_use]` attribute is already there.
-        if !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use));
-        if cx.tcx.visibility(fn_def.to_def_id()).is_public();
-        let ret_ty = return_ty(cx, owner_id);
-        let self_arg = nth_arg(cx, owner_id, 0);
+        && !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
+        && cx.tcx.visibility(fn_def.to_def_id()).is_public()
+        && let ret_ty = return_ty(cx, owner_id)
+        && let self_arg = nth_arg(cx, owner_id, 0)
         // If `Self` has the same type as the returned type, then we want to warn.
         //
         // For this check, we don't want to remove the reference on the returned type because if
         // there is one, we shouldn't emit a warning!
-        if self_arg.peel_refs() == ret_ty;
+        && self_arg.peel_refs() == ret_ty
         // If `Self` is already marked as `#[must_use]`, no need for the attribute here.
-        if !is_must_use_ty(cx, ret_ty);
-
-        then {
-            span_lint_and_help(
-                cx,
-                RETURN_SELF_NOT_MUST_USE,
-                span,
-                "missing `#[must_use]` attribute on a method returning `Self`",
-                None,
-                "consider adding the `#[must_use]` attribute to the method or directly to the `Self` type"
-            );
-        }
+        && !is_must_use_ty(cx, ret_ty)
+    {
+        span_lint_and_help(
+            cx,
+            RETURN_SELF_NOT_MUST_USE,
+            span,
+            "missing `#[must_use]` attribute on a method returning `Self`",
+            None,
+            "consider adding the `#[must_use]` attribute to the method or directly to the `Self` type",
+        );
     }
 }
 
@@ -111,18 +108,15 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse {
         span: Span,
         fn_def: LocalDefId,
     ) {
-        if_chain! {
+        if matches!(kind, FnKind::Method(_, _))
             // We are only interested in methods, not in functions or associated functions.
-            if matches!(kind, FnKind::Method(_, _));
-            if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id());
+            && let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id())
             // We don't want this method to be te implementation of a trait because the
             // `#[must_use]` should be put on the trait definition directly.
-            if cx.tcx.trait_id_of_impl(impl_def).is_none();
-
-            then {
-                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def);
-                check_method(cx, decl, fn_def, span, hir_id.expect_owner());
-            }
+            && cx.tcx.trait_id_of_impl(impl_def).is_none()
+        {
+            let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def);
+            check_method(cx, decl, fn_def, span, hir_id.expect_owner());
         }
     }
 
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 72235a954ba..7468bda02e8 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -4,7 +4,6 @@ use clippy_utils::sugg::has_enclosing_paren;
 use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
 use clippy_utils::{fn_def_id, is_from_proc_macro, path_to_local_id, span_find_starting_semi};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
@@ -189,50 +188,45 @@ impl<'tcx> LateLintPass<'tcx> for Return {
 
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
         // we need both a let-binding stmt and an expr
-        if_chain! {
-            if let Some(retexpr) = block.expr;
-            if let Some(stmt) = block.stmts.iter().last();
-            if let StmtKind::Local(local) = &stmt.kind;
-            if local.ty.is_none();
-            if cx.tcx.hir().attrs(local.hir_id).is_empty();
-            if let Some(initexpr) = &local.init;
-            if let PatKind::Binding(_, local_id, _, _) = local.pat.kind;
-            if path_to_local_id(retexpr, local_id);
-            if !last_statement_borrows(cx, initexpr);
-            if !in_external_macro(cx.sess(), initexpr.span);
-            if !in_external_macro(cx.sess(), retexpr.span);
-            if !local.span.from_expansion();
-            then {
-                span_lint_hir_and_then(
-                    cx,
-                    LET_AND_RETURN,
-                    retexpr.hir_id,
-                    retexpr.span,
-                    "returning the result of a `let` binding from a block",
-                    |err| {
-                        err.span_label(local.span, "unnecessary `let` binding");
+        if let Some(retexpr) = block.expr
+            && let Some(stmt) = block.stmts.iter().last()
+            && let StmtKind::Local(local) = &stmt.kind
+            && local.ty.is_none()
+            && cx.tcx.hir().attrs(local.hir_id).is_empty()
+            && let Some(initexpr) = &local.init
+            && let PatKind::Binding(_, local_id, _, _) = local.pat.kind
+            && path_to_local_id(retexpr, local_id)
+            && !last_statement_borrows(cx, initexpr)
+            && !in_external_macro(cx.sess(), initexpr.span)
+            && !in_external_macro(cx.sess(), retexpr.span)
+            && !local.span.from_expansion()
+        {
+            span_lint_hir_and_then(
+                cx,
+                LET_AND_RETURN,
+                retexpr.hir_id,
+                retexpr.span,
+                "returning the result of a `let` binding from a block",
+                |err| {
+                    err.span_label(local.span, "unnecessary `let` binding");
 
-                        if let Some(mut snippet) = snippet_opt(cx, initexpr.span) {
-                            if !cx.typeck_results().expr_adjustments(retexpr).is_empty() {
-                                if !has_enclosing_paren(&snippet) {
-                                    snippet = format!("({snippet})");
-                                }
-                                snippet.push_str(" as _");
+                    if let Some(mut snippet) = snippet_opt(cx, initexpr.span) {
+                        if !cx.typeck_results().expr_adjustments(retexpr).is_empty() {
+                            if !has_enclosing_paren(&snippet) {
+                                snippet = format!("({snippet})");
                             }
-                            err.multipart_suggestion(
-                                "return the expression directly",
-                                vec![
-                                    (local.span, String::new()),
-                                    (retexpr.span, snippet),
-                                ],
-                                Applicability::MachineApplicable,
-                            );
-                        } else {
-                            err.span_help(initexpr.span, "this expression can be directly returned");
+                            snippet.push_str(" as _");
                         }
-                    },
-                );
-            }
+                        err.multipart_suggestion(
+                            "return the expression directly",
+                            vec![(local.span, String::new()), (retexpr.span, snippet)],
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.span_help(initexpr.span, "this expression can be directly returned");
+                    }
+                },
+            );
         }
     }
 
diff --git a/clippy_lints/src/same_name_method.rs b/clippy_lints/src/same_name_method.rs
index 9587326ca00..52475ff9ef7 100644
--- a/clippy_lints/src/same_name_method.rs
+++ b/clippy_lints/src/same_name_method.rs
@@ -75,26 +75,23 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
 
                 match of_trait {
                     Some(trait_ref) => {
-                        let mut methods_in_trait: BTreeSet<Symbol> = if_chain! {
-                            if let Some(Node::TraitRef(TraitRef { path, .. })) =
-                                cx.tcx.hir().find(trait_ref.hir_ref_id);
-                            if let Res::Def(DefKind::Trait, did) = path.res;
-                            then{
-                                // FIXME: if
-                                // `rustc_middle::ty::assoc::AssocItems::items` is public,
-                                // we can iterate its keys instead of `in_definition_order`,
-                                // which's more efficient
-                                cx.tcx
-                                    .associated_items(did)
-                                    .in_definition_order()
-                                    .filter(|assoc_item| {
-                                        matches!(assoc_item.kind, AssocKind::Fn)
-                                    })
-                                    .map(|assoc_item| assoc_item.name)
-                                    .collect()
-                            }else{
-                                BTreeSet::new()
-                            }
+                        let mut methods_in_trait: BTreeSet<Symbol> = if let Some(Node::TraitRef(TraitRef {
+                            path, ..
+                        })) = cx.tcx.hir().find(trait_ref.hir_ref_id)
+                            && let Res::Def(DefKind::Trait, did) = path.res
+                        {
+                            // FIXME: if
+                            // `rustc_middle::ty::assoc::AssocItems::items` is public,
+                            // we can iterate its keys instead of `in_definition_order`,
+                            // which's more efficient
+                            cx.tcx
+                                .associated_items(did)
+                                .in_definition_order()
+                                .filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn))
+                                .map(|assoc_item| assoc_item.name)
+                                .collect()
+                        } else {
+                            BTreeSet::new()
                         };
 
                         let mut check_trait_method = |method_name: Symbol, trait_method_span: Span| {
diff --git a/clippy_lints/src/self_named_constructors.rs b/clippy_lints/src/self_named_constructors.rs
index b92014f68b3..c1edcf509ef 100644
--- a/clippy_lints/src/self_named_constructors.rs
+++ b/clippy_lints/src/self_named_constructors.rs
@@ -70,22 +70,20 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
             return;
         }
 
-        if_chain! {
-            if let Some(self_def) = self_ty.ty_adt_def();
-            if let Some(self_local_did) = self_def.did().as_local();
-            let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
-            if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id);
-            let type_name = x.ident.name.as_str().to_lowercase();
-            if impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name;
-
-            then {
-                span_lint(
-                    cx,
-                    SELF_NAMED_CONSTRUCTORS,
-                    impl_item.span,
-                    &format!("constructor `{}` has the same name as the type", impl_item.ident.name),
-                );
-            }
+        if let Some(self_def) = self_ty.ty_adt_def()
+            && let Some(self_local_did) = self_def.did().as_local()
+            && let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did)
+            && let Some(Node::Item(x)) = cx.tcx.hir().find(self_id)
+            && let type_name = x.ident.name.as_str().to_lowercase()
+            && (impl_item.ident.name.as_str() == type_name
+                || impl_item.ident.name.as_str().replace('_', "") == type_name)
+        {
+            span_lint(
+                cx,
+                SELF_NAMED_CONSTRUCTORS,
+                impl_item.span,
+                &format!("constructor `{}` has the same name as the type", impl_item.ident.name),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/semicolon_if_nothing_returned.rs b/clippy_lints/src/semicolon_if_nothing_returned.rs
index ccf8b997705..3aabcadaa1f 100644
--- a/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -1,7 +1,6 @@
 use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -38,30 +37,29 @@ declare_lint_pass!(SemicolonIfNothingReturned => [SEMICOLON_IF_NOTHING_RETURNED]
 
 impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
-        if_chain! {
-            if !block.span.from_expansion();
-            if let Some(expr) = block.expr;
-            let t_expr = cx.typeck_results().expr_ty(expr);
-            if t_expr.is_unit();
-            let mut app = Applicability::MachineApplicable;
-            if let snippet = snippet_with_context(cx, expr.span, block.span.ctxt(), "}", &mut app).0;
-            if !snippet.ends_with('}') && !snippet.ends_with(';');
-            if cx.sess().source_map().is_multiline(block.span);
-            then {
-                // filter out the desugared `for` loop
-                if let ExprKind::DropTemps(..) = &expr.kind {
-                    return;
-                }
-                span_lint_and_sugg(
-                    cx,
-                    SEMICOLON_IF_NOTHING_RETURNED,
-                    expr.span.source_callsite(),
-                    "consider adding a `;` to the last statement for consistent formatting",
-                    "add a `;` here",
-                    format!("{snippet};"),
-                    app,
-                );
+        if !block.span.from_expansion()
+            && let Some(expr) = block.expr
+            && let t_expr = cx.typeck_results().expr_ty(expr)
+            && t_expr.is_unit()
+            && let mut app = Applicability::MachineApplicable
+            && let snippet = snippet_with_context(cx, expr.span, block.span.ctxt(), "}", &mut app).0
+            && !snippet.ends_with('}')
+            && !snippet.ends_with(';')
+            && cx.sess().source_map().is_multiline(block.span)
+        {
+            // filter out the desugared `for` loop
+            if let ExprKind::DropTemps(..) = &expr.kind {
+                return;
             }
+            span_lint_and_sugg(
+                cx,
+                SEMICOLON_IF_NOTHING_RETURNED,
+                expr.span.source_callsite(),
+                "consider adding a `;` to the last statement for consistent formatting",
+                "add a `;` here",
+                format!("{snippet};"),
+                app,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs
index b940cac6047..0385f1a98e5 100644
--- a/clippy_lints/src/size_of_in_element_count.rs
+++ b/clippy_lints/src/size_of_in_element_count.rs
@@ -2,7 +2,6 @@
 //! expecting a count of T
 
 use clippy_utils::diagnostics::span_lint_and_help;
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty, TypeAndMut};
@@ -39,16 +38,17 @@ declare_lint_pass!(SizeOfInElementCount => [SIZE_OF_IN_ELEMENT_COUNT]);
 fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) -> Option<Ty<'tcx>> {
     match expr.kind {
         ExprKind::Call(count_func, _func_args) => {
-            if_chain! {
-                if !inverted;
-                if let ExprKind::Path(ref count_func_qpath) = count_func.kind;
-                if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
-                if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::mem_size_of | sym::mem_size_of_val));
-                then {
-                    cx.typeck_results().node_args(count_func.hir_id).types().next()
-                } else {
-                    None
-                }
+            if !inverted
+                && let ExprKind::Path(ref count_func_qpath) = count_func.kind
+                && let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id()
+                && matches!(
+                    cx.tcx.get_diagnostic_name(def_id),
+                    Some(sym::mem_size_of | sym::mem_size_of_val)
+                )
+            {
+                cx.typeck_results().node_args(count_func.hir_id).types().next()
+            } else {
+                None
             }
         },
         ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node => {
@@ -80,13 +80,12 @@ fn get_pointee_ty_and_count_expr<'tcx>(
         "wrapping_offset",
     ];
 
-    if_chain! {
+    if let ExprKind::Call(func, [.., count]) = expr.kind
         // Find calls to ptr::{copy, copy_nonoverlapping}
         // and ptr::{swap_nonoverlapping, write_bytes},
-        if let ExprKind::Call(func, [.., count]) = expr.kind;
-        if let ExprKind::Path(ref func_qpath) = func.kind;
-        if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
-        if matches!(cx.tcx.get_diagnostic_name(def_id), Some(
+        && let ExprKind::Path(ref func_qpath) = func.kind
+        && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
+        && matches!(cx.tcx.get_diagnostic_name(def_id), Some(
             sym::ptr_copy
             | sym::ptr_copy_nonoverlapping
             | sym::ptr_slice_from_raw_parts
@@ -95,26 +94,23 @@ fn get_pointee_ty_and_count_expr<'tcx>(
             | sym::ptr_write_bytes
             | sym::slice_from_raw_parts
             | sym::slice_from_raw_parts_mut
-        ));
+        ))
 
         // Get the pointee type
-        if let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next();
-        then {
-            return Some((pointee_ty, count));
-        }
+        && let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next()
+    {
+        return Some((pointee_ty, count));
     };
-    if_chain! {
+    if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind
         // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
-        if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind;
-        let method_ident = method_path.ident.as_str();
-        if METHODS.iter().any(|m| *m == method_ident);
+        && let method_ident = method_path.ident.as_str()
+        && METHODS.iter().any(|m| *m == method_ident)
 
         // Get the pointee type
-        if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =
-            cx.typeck_results().expr_ty(ptr_self).kind();
-        then {
-            return Some((*pointee_ty, count));
-        }
+        && let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =
+            cx.typeck_results().expr_ty(ptr_self).kind()
+    {
+        return Some((*pointee_ty, count));
     };
     None
 }
@@ -127,25 +123,16 @@ impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
         const LINT_MSG: &str = "found a count of bytes \
              instead of a count of elements of `T`";
 
-        if_chain! {
+        if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr)
             // Find calls to functions with an element count parameter and get
             // the pointee type and count parameter expression
-            if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr);
 
             // Find a size_of call in the count parameter expression and
             // check that it's the same type
-            if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr, false);
-            if pointee_ty == ty_used_for_size_of;
-            then {
-                span_lint_and_help(
-                    cx,
-                    SIZE_OF_IN_ELEMENT_COUNT,
-                    count_expr.span,
-                    LINT_MSG,
-                    None,
-                    HELP_MSG
-                );
-            }
+            && let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr, false)
+            && pointee_ty == ty_used_for_size_of
+        {
+            span_lint_and_help(cx, SIZE_OF_IN_ELEMENT_COUNT, count_expr.span, LINT_MSG, None, HELP_MSG);
         };
     }
 }
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index 2244eab96ca..733da790441 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -5,7 +5,6 @@ use clippy_utils::{
     get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local,
     path_to_local_id, paths, SpanlessEq,
 };
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
 use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, Stmt, StmtKind};
@@ -103,41 +102,35 @@ enum InitializationType<'tcx> {
 impl<'tcx> LateLintPass<'tcx> for SlowVectorInit {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // Matches initialization on reassignments. For example: `vec = Vec::with_capacity(100)`
-        if_chain! {
-            if let ExprKind::Assign(left, right, _) = expr.kind;
-            if let Some(local_id) = path_to_local(left);
-            if let Some(size_expr) = Self::as_vec_initializer(cx, right);
-
-            then {
-                let vi = VecAllocation {
-                    local_id,
-                    allocation_expr: right,
-                    size_expr,
-                };
-
-                Self::search_initialization(cx, vi, expr.hir_id);
-            }
+        if let ExprKind::Assign(left, right, _) = expr.kind
+            && let Some(local_id) = path_to_local(left)
+            && let Some(size_expr) = Self::as_vec_initializer(cx, right)
+        {
+            let vi = VecAllocation {
+                local_id,
+                allocation_expr: right,
+                size_expr,
+            };
+
+            Self::search_initialization(cx, vi, expr.hir_id);
         }
     }
 
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
         // or `Vec::new()`
-        if_chain! {
-            if let StmtKind::Local(local) = stmt.kind;
-            if let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind;
-            if let Some(init) = local.init;
-            if let Some(size_expr) = Self::as_vec_initializer(cx, init);
-
-            then {
-                let vi = VecAllocation {
-                    local_id,
-                    allocation_expr: init,
-                    size_expr,
-                };
-
-                Self::search_initialization(cx, vi, stmt.hir_id);
-            }
+        if let StmtKind::Local(local) = stmt.kind
+            && let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind
+            && let Some(init) = local.init
+            && let Some(size_expr) = Self::as_vec_initializer(cx, init)
+        {
+            let vi = VecAllocation {
+                local_id,
+                allocation_expr: init,
+                size_expr,
+            };
+
+            Self::search_initialization(cx, vi, stmt.hir_id);
         }
     }
 }
@@ -242,16 +235,13 @@ struct VectorInitializationVisitor<'a, 'tcx> {
 impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     /// Checks if the given expression is extending a vector with `repeat(0).take(..)`
     fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if self.initialization_found;
-            if let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind;
-            if path_to_local_id(self_arg, self.vec_alloc.local_id);
-            if path.ident.name == sym!(extend);
-            if self.is_repeat_take(extend_arg);
-
-            then {
-                self.slow_expression = Some(InitializationType::Extend(expr));
-            }
+        if self.initialization_found
+            && let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind
+            && path_to_local_id(self_arg, self.vec_alloc.local_id)
+            && path.ident.name == sym!(extend)
+            && self.is_repeat_take(extend_arg)
+        {
+            self.slow_expression = Some(InitializationType::Extend(expr));
         }
     }
 
@@ -281,21 +271,19 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
 
     /// Returns `true` if give expression is `repeat(0).take(...)`
     fn is_repeat_take(&mut self, expr: &'tcx Expr<'tcx>) -> bool {
-        if_chain! {
-            if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind;
-            if take_path.ident.name == sym!(take);
+        if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind
+            && take_path.ident.name == sym!(take)
             // Check that take is applied to `repeat(0)`
-            if self.is_repeat_zero(recv);
-            then {
-                if let InitializedSize::Initialized(size_expr) = self.vec_alloc.size_expr {
-                    // Check that len expression is equals to `with_capacity` expression
-                    return SpanlessEq::new(self.cx).eq_expr(len_arg, size_expr)
-                        || matches!(len_arg.kind, ExprKind::MethodCall(path, ..) if path.ident.as_str() == "capacity")
-                }
-
-                self.vec_alloc.size_expr = InitializedSize::Initialized(len_arg);
-                return true;
+            && self.is_repeat_zero(recv)
+        {
+            if let InitializedSize::Initialized(size_expr) = self.vec_alloc.size_expr {
+                // Check that len expression is equals to `with_capacity` expression
+                return SpanlessEq::new(self.cx).eq_expr(len_arg, size_expr)
+                    || matches!(len_arg.kind, ExprKind::MethodCall(path, ..) if path.ident.as_str() == "capacity");
             }
+
+            self.vec_alloc.size_expr = InitializedSize::Initialized(len_arg);
+            return true;
         }
 
         false
@@ -303,15 +291,13 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
 
     /// Returns `true` if given expression is `repeat(0)`
     fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool {
-        if_chain! {
-            if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind;
-            if is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat);
-            if is_integer_literal(repeat_arg, 0);
-            then {
-                true
-            } else {
-                false
-            }
+        if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind
+            && is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat)
+            && is_integer_literal(repeat_arg, 0)
+        {
+            true
+        } else {
+            false
         }
     }
 }
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index a44adc93855..baa9750cc01 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -5,7 +5,6 @@ use clippy_utils::{
     get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls,
     peel_blocks, SpanlessEq,
 };
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath};
@@ -251,128 +250,115 @@ const MAX_LENGTH_BYTE_STRING_LIT: usize = 32;
 declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]);
 
 impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
-    #[expect(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use rustc_ast::LitKind;
 
-        if_chain! {
+        if let ExprKind::Call(fun, args) = e.kind
             // Find std::str::converts::from_utf8
-            if let ExprKind::Call(fun, args) = e.kind;
-            if is_path_diagnostic_item(cx, fun, sym::str_from_utf8);
+            && is_path_diagnostic_item(cx, fun, sym::str_from_utf8)
 
             // Find string::as_bytes
-            if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind;
-            if let ExprKind::Index(left, right, _) = args.kind;
-            let (method_names, expressions, _) = method_calls(left, 1);
-            if method_names.len() == 1;
-            if expressions.len() == 1;
-            if expressions[0].1.is_empty();
-            if method_names[0] == sym!(as_bytes);
+            && let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind
+            && let ExprKind::Index(left, right, _) = args.kind
+            && let (method_names, expressions, _) = method_calls(left, 1)
+            && method_names.len() == 1
+            && expressions.len() == 1
+            && expressions[0].1.is_empty()
+            && method_names[0] == sym!(as_bytes)
 
             // Check for slicer
-            if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind;
+            && let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let string_expression = &expressions[0].0;
 
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let string_expression = &expressions[0].0;
+            let snippet_app = snippet_with_applicability(cx, string_expression.span, "..", &mut applicability);
 
-                let snippet_app = snippet_with_applicability(
-                    cx,
-                    string_expression.span, "..",
-                    &mut applicability,
-                );
+            span_lint_and_sugg(
+                cx,
+                STRING_FROM_UTF8_AS_BYTES,
+                e.span,
+                "calling a slice of `as_bytes()` with `from_utf8` should be not necessary",
+                "try",
+                format!("Some(&{snippet_app}[{}])", snippet(cx, right.span, "..")),
+                applicability,
+            );
+        }
 
+        if !in_external_macro(cx.sess(), e.span)
+            && let ExprKind::MethodCall(path, receiver, ..) = &e.kind
+            && path.ident.name == sym!(as_bytes)
+            && let ExprKind::Lit(lit) = &receiver.kind
+            && let LitKind::Str(lit_content, _) = &lit.node
+        {
+            let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#);
+            let mut applicability = Applicability::MachineApplicable;
+            if callsite.starts_with("include_str!") {
                 span_lint_and_sugg(
                     cx,
-                    STRING_FROM_UTF8_AS_BYTES,
+                    STRING_LIT_AS_BYTES,
                     e.span,
-                    "calling a slice of `as_bytes()` with `from_utf8` should be not necessary",
-                    "try",
-                    format!("Some(&{snippet_app}[{}])", snippet(cx, right.span, "..")),
-                    applicability
-                )
-            }
-        }
-
-        if_chain! {
-            if !in_external_macro(cx.sess(), e.span);
-            if let ExprKind::MethodCall(path, receiver, ..) = &e.kind;
-            if path.ident.name == sym!(as_bytes);
-            if let ExprKind::Lit(lit) = &receiver.kind;
-            if let LitKind::Str(lit_content, _) = &lit.node;
-            then {
-                let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#);
-                let mut applicability = Applicability::MachineApplicable;
-                if callsite.starts_with("include_str!") {
+                    "calling `as_bytes()` on `include_str!(..)`",
+                    "consider using `include_bytes!(..)` instead",
+                    snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen(
+                        "include_str",
+                        "include_bytes",
+                        1,
+                    ),
+                    applicability,
+                );
+            } else if lit_content.as_str().is_ascii()
+                && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
+                && !receiver.span.from_expansion()
+            {
+                if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e)
+                    && let Node::Expr(parent) = parent
+                    && let ExprKind::Match(scrutinee, ..) = parent.kind
+                    && scrutinee.hir_id == id
+                {
+                    // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces
+                    // `&[u8]`. This change would prevent matching with different sized slices.
+                } else if !callsite.starts_with("env!") {
                     span_lint_and_sugg(
                         cx,
                         STRING_LIT_AS_BYTES,
                         e.span,
-                        "calling `as_bytes()` on `include_str!(..)`",
-                        "consider using `include_bytes!(..)` instead",
-                        snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen(
-                            "include_str",
-                            "include_bytes",
-                            1,
+                        "calling `as_bytes()` on a string literal",
+                        "consider using a byte string literal instead",
+                        format!(
+                            "b{}",
+                            snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
                         ),
                         applicability,
                     );
-                } else if lit_content.as_str().is_ascii()
-                    && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
-                    && !receiver.span.from_expansion()
-                {
-                    if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e)
-                        && let Node::Expr(parent) = parent
-                        && let ExprKind::Match(scrutinee, ..) = parent.kind
-                        && scrutinee.hir_id == id
-                    {
-                        // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces
-                        // `&[u8]`. This change would prevent matching with different sized slices.
-                    } else if !callsite.starts_with("env!") {
-                        span_lint_and_sugg(
-                            cx,
-                            STRING_LIT_AS_BYTES,
-                            e.span,
-                            "calling `as_bytes()` on a string literal",
-                            "consider using a byte string literal instead",
-                            format!(
-                                "b{}",
-                                snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
-                            ),
-                            applicability,
-                        );
-                    }
                 }
             }
         }
 
-        if_chain! {
-            if let ExprKind::MethodCall(path, recv, [], _) = &e.kind;
-            if path.ident.name == sym!(into_bytes);
-            if let ExprKind::MethodCall(path, recv, [], _) = &recv.kind;
-            if matches!(path.ident.name.as_str(), "to_owned" | "to_string");
-            if let ExprKind::Lit(lit) = &recv.kind;
-            if let LitKind::Str(lit_content, _) = &lit.node;
-
-            if lit_content.as_str().is_ascii();
-            if lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT;
-            if !recv.span.from_expansion();
-            then {
-                let mut applicability = Applicability::MachineApplicable;
+        if let ExprKind::MethodCall(path, recv, [], _) = &e.kind
+            && path.ident.name == sym!(into_bytes)
+            && let ExprKind::MethodCall(path, recv, [], _) = &recv.kind
+            && matches!(path.ident.name.as_str(), "to_owned" | "to_string")
+            && let ExprKind::Lit(lit) = &recv.kind
+            && let LitKind::Str(lit_content, _) = &lit.node
+            && lit_content.as_str().is_ascii()
+            && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
+            && !recv.span.from_expansion()
+        {
+            let mut applicability = Applicability::MachineApplicable;
 
-                span_lint_and_sugg(
-                    cx,
-                    STRING_LIT_AS_BYTES,
-                    e.span,
-                    "calling `into_bytes()` on a string literal",
-                    "consider using a byte string literal instead",
-                    format!(
-                        "b{}.to_vec()",
-                        snippet_with_applicability(cx, recv.span, r#""..""#, &mut applicability)
-                    ),
-                    applicability,
-                );
-            }
+            span_lint_and_sugg(
+                cx,
+                STRING_LIT_AS_BYTES,
+                e.span,
+                "calling `into_bytes()` on a string literal",
+                "consider using a byte string literal instead",
+                format!(
+                    "b{}.to_vec()",
+                    snippet_with_applicability(cx, recv.span, r#""..""#, &mut applicability)
+                ),
+                applicability,
+            );
         }
     }
 }
@@ -406,22 +392,20 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]);
 
 impl<'tcx> LateLintPass<'tcx> for StrToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
-        if_chain! {
-            if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
-            if path.ident.name == sym::to_string;
-            let ty = cx.typeck_results().expr_ty(self_arg);
-            if let ty::Ref(_, ty, ..) = ty.kind();
-            if ty.is_str();
-            then {
-                span_lint_and_help(
-                    cx,
-                    STR_TO_STRING,
-                    expr.span,
-                    "`to_string()` called on a `&str`",
-                    None,
-                    "consider using `.to_owned()`",
-                );
-            }
+        if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
+            && path.ident.name == sym::to_string
+            && let ty = cx.typeck_results().expr_ty(self_arg)
+            && let ty::Ref(_, ty, ..) = ty.kind()
+            && ty.is_str()
+        {
+            span_lint_and_help(
+                cx,
+                STR_TO_STRING,
+                expr.span,
+                "`to_string()` called on a `&str`",
+                None,
+                "consider using `.to_owned()`",
+            );
         }
     }
 }
@@ -456,21 +440,19 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]);
 
 impl<'tcx> LateLintPass<'tcx> for StringToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
-        if_chain! {
-            if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind;
-            if path.ident.name == sym::to_string;
-            let ty = cx.typeck_results().expr_ty(self_arg);
-            if is_type_lang_item(cx, ty, LangItem::String);
-            then {
-                span_lint_and_help(
-                    cx,
-                    STRING_TO_STRING,
-                    expr.span,
-                    "`to_string()` called on a `String`",
-                    None,
-                    "consider using `.clone()`",
-                );
-            }
+        if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
+            && path.ident.name == sym::to_string
+            && let ty = cx.typeck_results().expr_ty(self_arg)
+            && is_type_lang_item(cx, ty, LangItem::String)
+        {
+            span_lint_and_help(
+                cx,
+                STRING_TO_STRING,
+                expr.span,
+                "`to_string()` called on a `String`",
+                None,
+                "consider using `.clone()`",
+            );
         }
     }
 }
@@ -500,26 +482,24 @@ declare_lint_pass!(TrimSplitWhitespace => [TRIM_SPLIT_WHITESPACE]);
 impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         let tyckres = cx.typeck_results();
-        if_chain! {
-            if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind;
-            if path.ident.name == sym!(split_whitespace);
-            if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id);
-            if cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id);
-            if let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind;
-            if let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str();
-            if let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id);
-            if is_one_of_trim_diagnostic_items(cx, trim_def_id);
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    TRIM_SPLIT_WHITESPACE,
-                    trim_span.with_hi(split_ws_span.lo()),
-                    &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"),
-                    &format!("remove `{trim_fn_name}()`"),
-                    String::new(),
-                    Applicability::MachineApplicable,
-                );
-            }
+        if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind
+            && path.ident.name == sym!(split_whitespace)
+            && let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id)
+            && cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id)
+            && let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind
+            && let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str()
+            && let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id)
+            && is_one_of_trim_diagnostic_items(cx, trim_def_id)
+        {
+            span_lint_and_sugg(
+                cx,
+                TRIM_SPLIT_WHITESPACE,
+                trim_span.with_hi(split_ws_span.lo()),
+                &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"),
+                &format!("remove `{trim_fn_name}()`"),
+                String::new(),
+                Applicability::MachineApplicable,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs
index b3db5e9a422..644664b104d 100644
--- a/clippy_lints/src/strlen_on_c_strings.rs
+++ b/clippy_lints/src/strlen_on_c_strings.rs
@@ -3,7 +3,6 @@ use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::is_expr_unsafe;
 use clippy_utils::{get_parent_node, match_libc_symbol};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, LangItem, Node, UnsafeSource};
 use rustc_lint::{LateContext, LateLintPass};
@@ -41,48 +40,45 @@ declare_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]);
 
 impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if !expr.span.from_expansion();
-            if let ExprKind::Call(func, [recv]) = expr.kind;
-            if let ExprKind::Path(path) = &func.kind;
-            if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id();
-            if match_libc_symbol(cx, did, "strlen");
-            if let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind;
-            if !recv.span.from_expansion();
-            if path.ident.name == sym::as_ptr;
-            then {
-                let ctxt = expr.span.ctxt();
-                let span = match get_parent_node(cx.tcx, expr.hir_id) {
-                    Some(Node::Block(&Block {
-                        rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), span, ..
-                    }))
-                    if span.ctxt() == ctxt && !is_expr_unsafe(cx, self_arg) => {
-                        span
-                    }
-                    _ => expr.span,
-                };
+        if !expr.span.from_expansion()
+            && let ExprKind::Call(func, [recv]) = expr.kind
+            && let ExprKind::Path(path) = &func.kind
+            && let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id()
+            && match_libc_symbol(cx, did, "strlen")
+            && let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind
+            && !recv.span.from_expansion()
+            && path.ident.name == sym::as_ptr
+        {
+            let ctxt = expr.span.ctxt();
+            let span = match get_parent_node(cx.tcx, expr.hir_id) {
+                Some(Node::Block(&Block {
+                    rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
+                    span,
+                    ..
+                })) if span.ctxt() == ctxt && !is_expr_unsafe(cx, self_arg) => span,
+                _ => expr.span,
+            };
 
-                let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
-                let mut app = Applicability::MachineApplicable;
-                let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0;
-                let method_name = if is_type_diagnostic_item(cx, ty, sym::cstring_type) {
-                    "as_bytes"
-                } else if is_type_lang_item(cx, ty, LangItem::CStr) {
-                    "to_bytes"
-                } else {
-                    return;
-                };
+            let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
+            let mut app = Applicability::MachineApplicable;
+            let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0;
+            let method_name = if is_type_diagnostic_item(cx, ty, sym::cstring_type) {
+                "as_bytes"
+            } else if is_type_lang_item(cx, ty, LangItem::CStr) {
+                "to_bytes"
+            } else {
+                return;
+            };
 
-                span_lint_and_sugg(
-                    cx,
-                    STRLEN_ON_C_STRINGS,
-                    span,
-                    "using `libc::strlen` on a `CString` or `CStr` value",
-                    "try",
-                    format!("{val_name}.{method_name}().len()"),
-                    app,
-                );
-            }
+            span_lint_and_sugg(
+                cx,
+                STRLEN_ON_C_STRINGS,
+                span,
+                "using `libc::strlen` on a `CString` or `CStr` value",
+                "try",
+                format!("{val_name}.{method_name}().len()"),
+                app,
+            );
         }
     }
 }
diff --git a/clippy_lints/src/suspicious_doc_comments.rs b/clippy_lints/src/suspicious_doc_comments.rs
index 0abc199da16..cbd6e745841 100644
--- a/clippy_lints/src/suspicious_doc_comments.rs
+++ b/clippy_lints/src/suspicious_doc_comments.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
-use if_chain::if_chain;
 use rustc_ast::token::CommentKind;
 use rustc_ast::{AttrKind, AttrStyle, Attribute, Item};
 use rustc_errors::Applicability;
@@ -76,19 +75,17 @@ fn collect_doc_comment_replacements(attrs: &[Attribute]) -> Vec<(Span, String)>
     attrs
         .iter()
         .filter_map(|attr| {
-            if_chain! {
-                if let AttrKind::DocComment(com_kind, sym) = attr.kind;
-                if let AttrStyle::Outer = attr.style;
-                if let Some(com) = sym.as_str().strip_prefix('!');
-                then {
-                    let sugg = match com_kind {
-                        CommentKind::Line => format!("//!{com}"),
-                        CommentKind::Block => format!("/*!{com}*/")
-                    };
-                    Some((attr.span, sugg))
-                } else {
-                    None
-                }
+            if let AttrKind::DocComment(com_kind, sym) = attr.kind
+                && let AttrStyle::Outer = attr.style
+                && let Some(com) = sym.as_str().strip_prefix('!')
+            {
+                let sugg = match com_kind {
+                    CommentKind::Line => format!("//!{com}"),
+                    CommentKind::Block => format!("/*!{com}*/"),
+                };
+                Some((attr.span, sugg))
+            } else {
+                None
             }
         })
         .collect()
diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs
index bb8cde5b94d..92de7917871 100644
--- a/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/clippy_lints/src/suspicious_operation_groupings.rs
@@ -2,7 +2,6 @@ use clippy_utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use core::ops::{Add, AddAssign};
-use if_chain::if_chain;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, StmtKind};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -155,34 +154,22 @@ fn check_binops(cx: &EarlyContext<'_>, binops: &[&BinaryOp<'_>]) {
         match (no_difference_info, double_difference_info) {
             (Some(i), None) => attempt_to_emit_no_difference_lint(cx, binops, i, expected_loc),
             (None, Some((double_difference_index, ident_loc1, ident_loc2))) => {
-                if_chain! {
-                    if one_ident_difference_count == binop_count - 1;
-                    if let Some(binop) = binops.get(double_difference_index);
-                    then {
-                        let changed_loc = if ident_loc1 == expected_loc {
-                            ident_loc2
-                        } else if ident_loc2 == expected_loc {
-                            ident_loc1
-                        } else {
-                            // This expression doesn't match the form we're
-                            // looking for.
-                            return;
-                        };
-
-                        if let Some(sugg) = ident_swap_sugg(
-                            cx,
-                            &paired_identifiers,
-                            binop,
-                            changed_loc,
-                            &mut applicability,
-                        ) {
-                            emit_suggestion(
-                                cx,
-                                binop.span,
-                                sugg,
-                                applicability,
-                            );
-                        }
+                if one_ident_difference_count == binop_count - 1
+                    && let Some(binop) = binops.get(double_difference_index)
+                {
+                    let changed_loc = if ident_loc1 == expected_loc {
+                        ident_loc2
+                    } else if ident_loc2 == expected_loc {
+                        ident_loc1
+                    } else {
+                        // This expression doesn't match the form we're
+                        // looking for.
+                        return;
+                    };
+
+                    if let Some(sugg) = ident_swap_sugg(cx, &paired_identifiers, binop, changed_loc, &mut applicability)
+                    {
+                        emit_suggestion(cx, binop.span, sugg, applicability);
                     }
                 }
             },
@@ -212,48 +199,32 @@ fn attempt_to_emit_no_difference_lint(
         let old_right_ident = get_ident(binop.right, expected_loc);
 
         for b in skip_index(binops.iter(), i) {
-            if_chain! {
-                if let (Some(old_ident), Some(new_ident)) =
-                (old_left_ident, get_ident(b.left, expected_loc));
-                if old_ident != new_ident;
-                if let Some(sugg) = suggestion_with_swapped_ident(
+            if let (Some(old_ident), Some(new_ident)) = (old_left_ident, get_ident(b.left, expected_loc))
+                && old_ident != new_ident
+                && let Some(sugg) =
+                    suggestion_with_swapped_ident(cx, binop.left, expected_loc, new_ident, &mut applicability)
+            {
+                emit_suggestion(
                     cx,
-                    binop.left,
-                    expected_loc,
-                    new_ident,
-                    &mut applicability,
+                    binop.span,
+                    replace_left_sugg(cx, binop, &sugg, &mut applicability),
+                    applicability,
                 );
-                then {
-                    emit_suggestion(
-                        cx,
-                        binop.span,
-                        replace_left_sugg(cx, binop, &sugg, &mut applicability),
-                        applicability,
-                    );
-                    return;
-                }
+                return;
             }
 
-            if_chain! {
-                if let (Some(old_ident), Some(new_ident)) =
-                    (old_right_ident, get_ident(b.right, expected_loc));
-                if old_ident != new_ident;
-                if let Some(sugg) = suggestion_with_swapped_ident(
+            if let (Some(old_ident), Some(new_ident)) = (old_right_ident, get_ident(b.right, expected_loc))
+                && old_ident != new_ident
+                && let Some(sugg) =
+                    suggestion_with_swapped_ident(cx, binop.right, expected_loc, new_ident, &mut applicability)
+            {
+                emit_suggestion(
                     cx,
-                    binop.right,
-                    expected_loc,
-                    new_ident,
-                    &mut applicability,
+                    binop.span,
+                    replace_right_sugg(cx, binop, &sugg, &mut applicability),
+                    applicability,
                 );
-                then {
-                    emit_suggestion(
-                        cx,
-                        binop.span,
-                        replace_right_sugg(cx, binop, &sugg, &mut applicability),
-                        applicability,
-                    );
-                    return;
-                }
+                return;
             }
         }
     }
diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs
index 6271ea02731..3244933a124 100644
--- a/clippy_lints/src/suspicious_trait_impl.rs
+++ b/clippy_lints/src/suspicious_trait_impl.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -57,37 +56,39 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_
 
 impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if_chain! {
-            if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
-            if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
-            if let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang);
-            if let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang);
+        if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind
+            && let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node)
+            && 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)
 
             // Check for more than one binary operation in the implemented function
             // Linting when multiple operations are involved can result in false positives
-            let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
-            if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn);
-            if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
-            let body = cx.tcx.hir().body(body_id);
-            let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
-            if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
-            let trait_id = trait_ref.path.res.def_id();
-            if ![binop_trait_id, op_assign_trait_id].contains(&trait_id);
-            if let Some(&(_, lint)) = [
+            && let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id
+            && let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn)
+            && let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind
+            && let body = cx.tcx.hir().body(body_id)
+            && let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id
+            && let Some(trait_ref) = trait_ref_of_method(cx, parent_fn)
+            && let trait_id = trait_ref.path.res.def_id()
+            && ![binop_trait_id, op_assign_trait_id].contains(&trait_id)
+            && let Some(&(_, lint)) = [
                 (&BINOP_TRAITS, SUSPICIOUS_ARITHMETIC_IMPL),
                 (&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
             ]
                 .iter()
-                .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t)));
-            if count_binops(body.value) == 1;
-            then {
-                span_lint(
-                    cx,
-                    lint,
-                    binop.span,
-                    &format!("suspicious use of `{}` in `{}` impl", binop.node.as_str(), cx.tcx.item_name(trait_id)),
-                );
-            }
+                .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t)))
+            && count_binops(body.value) == 1
+        {
+            span_lint(
+                cx,
+                lint,
+                binop.span,
+                &format!(
+                    "suspicious use of `{}` in `{}` impl",
+                    binop.node.as_str(),
+                    cx.tcx.item_name(trait_id)
+                ),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs
index 660e6835e46..285f2f4f6f9 100644
--- a/clippy_lints/src/swap.rs
+++ b/clippy_lints/src/swap.rs
@@ -3,7 +3,6 @@ use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{can_mut_borrow_both, eq_expr_value, in_constant, std_or_core};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -149,36 +148,33 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
     }
 
     for [s1, s2, s3] in block.stmts.array_windows::<3>() {
-        if_chain! {
+        if let StmtKind::Local(tmp) = s1.kind
             // let t = foo();
-            if let StmtKind::Local(tmp) = s1.kind;
-            if let Some(tmp_init) = tmp.init;
-            if let PatKind::Binding(.., ident, None) = tmp.pat.kind;
+            && let Some(tmp_init) = tmp.init
+            && let PatKind::Binding(.., ident, None) = tmp.pat.kind
 
             // foo() = bar();
-            if let StmtKind::Semi(first) = s2.kind;
-            if let ExprKind::Assign(lhs1, rhs1, _) = first.kind;
+            && let StmtKind::Semi(first) = s2.kind
+            && let ExprKind::Assign(lhs1, rhs1, _) = first.kind
 
             // bar() = t;
-            if let StmtKind::Semi(second) = s3.kind;
-            if let ExprKind::Assign(lhs2, rhs2, _) = second.kind;
-            if let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind;
-            if rhs2.segments.len() == 1;
+            && let StmtKind::Semi(second) = s3.kind
+            && let ExprKind::Assign(lhs2, rhs2, _) = second.kind
+            && let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind
+            && rhs2.segments.len() == 1
 
-            if ident.name == rhs2.segments[0].ident.name;
-            if eq_expr_value(cx, tmp_init, lhs1);
-            if eq_expr_value(cx, rhs1, lhs2);
+            && ident.name == rhs2.segments[0].ident.name
+            && eq_expr_value(cx, tmp_init, lhs1)
+            && eq_expr_value(cx, rhs1, lhs2)
 
-            let ctxt = s1.span.ctxt();
-            if s2.span.ctxt() == ctxt;
-            if s3.span.ctxt() == ctxt;
-            if first.span.ctxt() == ctxt;
-            if second.span.ctxt() == ctxt;
-
-            then {
-                let span = s1.span.to(s3.span);
-                generate_swap_warning(cx, lhs1, lhs2, span, false);
-            }
+            && let ctxt = s1.span.ctxt()
+            && s2.span.ctxt() == ctxt
+            && s3.span.ctxt() == ctxt
+            && first.span.ctxt() == ctxt
+            && second.span.ctxt() == ctxt
+        {
+            let span = s1.span.to(s3.span);
+            generate_swap_warning(cx, lhs1, lhs2, span, false);
         }
     }
 }
@@ -261,20 +257,18 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr<
 fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) {
     for [s1, s2, s3] in block.stmts.array_windows::<3>() {
         let ctxt = s1.span.ctxt();
-        if_chain! {
-            if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(s1, ctxt);
-            if let Some((lhs1, rhs1)) = extract_sides_of_xor_assign(s2, ctxt);
-            if let Some((lhs2, rhs2)) = extract_sides_of_xor_assign(s3, ctxt);
-            if eq_expr_value(cx, lhs0, rhs1);
-            if eq_expr_value(cx, lhs2, rhs1);
-            if eq_expr_value(cx, lhs1, rhs0);
-            if eq_expr_value(cx, lhs1, rhs2);
-            if s2.span.ctxt() == ctxt;
-            if s3.span.ctxt() == ctxt;
-            then {
-                let span = s1.span.to(s3.span);
-                generate_swap_warning(cx, lhs0, rhs0, span, true);
-            }
+        if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(s1, ctxt)
+            && let Some((lhs1, rhs1)) = extract_sides_of_xor_assign(s2, ctxt)
+            && let Some((lhs2, rhs2)) = extract_sides_of_xor_assign(s3, ctxt)
+            && eq_expr_value(cx, lhs0, rhs1)
+            && eq_expr_value(cx, lhs2, rhs1)
+            && eq_expr_value(cx, lhs1, rhs0)
+            && eq_expr_value(cx, lhs1, rhs2)
+            && s2.span.ctxt() == ctxt
+            && s3.span.ctxt() == ctxt
+        {
+            let span = s1.span.to(s3.span);
+            generate_swap_warning(cx, lhs0, rhs0, span, true);
         };
     }
 }
diff --git a/clippy_lints/src/tests_outside_test_module.rs b/clippy_lints/src/tests_outside_test_module.rs
index 0cfb1c1253c..9481c78a505 100644
--- a/clippy_lints/src/tests_outside_test_module.rs
+++ b/clippy_lints/src/tests_outside_test_module.rs
@@ -55,20 +55,18 @@ impl LateLintPass<'_> for TestsOutsideTestModule {
         sp: Span,
         _: LocalDefId,
     ) {
-        if_chain! {
-            if !matches!(kind, FnKind::Closure);
-            if is_in_test_function(cx.tcx, body.id().hir_id);
-            if !is_in_cfg_test(cx.tcx, body.id().hir_id);
-            then {
-                span_lint_and_note(
-                    cx,
-                    TESTS_OUTSIDE_TEST_MODULE,
-                    sp,
-                    "this function marked with #[test] is outside a #[cfg(test)] module",
-                    None,
-                    "move it to a testing module marked with #[cfg(test)]",
-                );
-            }
+        if !matches!(kind, FnKind::Closure)
+            && is_in_test_function(cx.tcx, body.id().hir_id)
+            && !is_in_cfg_test(cx.tcx, body.id().hir_id)
+        {
+            span_lint_and_note(
+                cx,
+                TESTS_OUTSIDE_TEST_MODULE,
+                sp,
+                "this function marked with #[test] is outside a #[cfg(test)] module",
+                None,
+                "move it to a testing module marked with #[cfg(test)]",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs
index a171d225f1e..1dca523a966 100644
--- a/clippy_lints/src/to_digit_is_some.rs
+++ b/clippy_lints/src/to_digit_is_some.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::match_def_path;
 use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
@@ -38,59 +37,57 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]);
 
 impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if_chain! {
-            if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind;
-            if is_some_path.ident.name.as_str() == "is_some";
-            then {
-                let match_result = match &to_digit_expr.kind {
-                    hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => {
-                        if_chain! {
-                            if to_digits_path.ident.name.as_str() == "to_digit";
-                            let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg);
-                            if *char_arg_ty.kind() == ty::Char;
-                            then {
-                                Some((true, *char_arg, radix_arg))
-                            } else {
-                                None
-                            }
-                        }
+        if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind
+            && is_some_path.ident.name.as_str() == "is_some"
+        {
+            let match_result = match &to_digit_expr.kind {
+                hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => {
+                    if to_digits_path.ident.name.as_str() == "to_digit"
+                        && let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg)
+                        && *char_arg_ty.kind() == ty::Char
+                    {
+                        Some((true, *char_arg, radix_arg))
+                    } else {
+                        None
                     }
-                    hir::ExprKind::Call(to_digits_call, to_digit_args) => {
-                        if_chain! {
-                            if let [char_arg, radix_arg] = *to_digit_args;
-                            if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind;
-                            if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id);
-                            if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id();
-                            if match_def_path(cx, to_digits_def_id, &["core", "char", "methods", "<impl char>", "to_digit"]);
-                            then {
-                                Some((false, char_arg, radix_arg))
-                            } else {
-                                None
-                            }
-                        }
+                },
+                hir::ExprKind::Call(to_digits_call, to_digit_args) => {
+                    if let [char_arg, radix_arg] = *to_digit_args
+                        && let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind
+                        && let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id)
+                        && let Some(to_digits_def_id) = to_digits_call_res.opt_def_id()
+                        && match_def_path(
+                            cx,
+                            to_digits_def_id,
+                            &["core", "char", "methods", "<impl char>", "to_digit"],
+                        )
+                    {
+                        Some((false, char_arg, radix_arg))
+                    } else {
+                        None
                     }
-                    _ => None
-                };
+                },
+                _ => None,
+            };
 
-                if let Some((is_method_call, char_arg, radix_arg)) = match_result {
-                    let mut applicability = Applicability::MachineApplicable;
-                    let char_arg_snip = snippet_with_applicability(cx, char_arg.span, "_", &mut applicability);
-                    let radix_snip = snippet_with_applicability(cx, radix_arg.span, "_", &mut applicability);
+            if let Some((is_method_call, char_arg, radix_arg)) = match_result {
+                let mut applicability = Applicability::MachineApplicable;
+                let char_arg_snip = snippet_with_applicability(cx, char_arg.span, "_", &mut applicability);
+                let radix_snip = snippet_with_applicability(cx, radix_arg.span, "_", &mut applicability);
 
-                    span_lint_and_sugg(
-                        cx,
-                        TO_DIGIT_IS_SOME,
-                        expr.span,
-                        "use of `.to_digit(..).is_some()`",
-                        "try",
-                        if is_method_call {
-                            format!("{char_arg_snip}.is_digit({radix_snip})")
-                        } else {
-                            format!("char::is_digit({char_arg_snip}, {radix_snip})")
-                        },
-                        applicability,
-                    );
-                }
+                span_lint_and_sugg(
+                    cx,
+                    TO_DIGIT_IS_SOME,
+                    expr.span,
+                    "use of `.to_digit(..).is_some()`",
+                    "try",
+                    if is_method_call {
+                        format!("{char_arg_snip}.is_digit({radix_snip})")
+                    } else {
+                        format!("char::is_digit({char_arg_snip}, {radix_snip})")
+                    },
+                    applicability,
+                );
             }
         }
     }
diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs
index 87181adc24b..7eef02b3c65 100644
--- a/clippy_lints/src/trailing_empty_array.rs
+++ b/clippy_lints/src/trailing_empty_array.rs
@@ -54,20 +54,18 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
 }
 
 fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
-    if_chain! {
+    if let ItemKind::Struct(data, _) = &item.kind
         // First check if last field is an array
-        if let ItemKind::Struct(data, _) = &item.kind;
-        if let Some(last_field) = data.fields().last();
-        if let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind;
+        && let Some(last_field) = data.fields().last()
+        && let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
 
         // Then check if that array is zero-sized
-        let length = Const::from_anon_const(cx.tcx, length.def_id);
-        let length = length.try_eval_target_usize(cx.tcx, cx.param_env);
-        if let Some(length) = length;
-        then {
-            length == 0
-        } else {
-            false
-        }
+        && let length = Const::from_anon_const(cx.tcx, length.def_id)
+        && let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
+        && let Some(length) = length
+    {
+        length == 0
+    } else {
+        false
     }
 }
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index f065d215e48..e624bbe5ff1 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
 use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
 use core::hash::{Hash, Hasher};
-use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::unhash::UnhashMap;
@@ -124,103 +123,100 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
         let mut self_bounds_map = FxHashMap::default();
 
         for predicate in item.generics.predicates {
-            if_chain! {
-                if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
-                if bound_predicate.origin != PredicateOrigin::ImplTrait;
-                if !bound_predicate.span.from_expansion();
-                if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
-                if let Some(PathSegment {
-                    res: Res::SelfTyParam { trait_: def_id }, ..
-                }) = segments.first();
-                if let Some(
-                    Node::Item(
-                        Item {
-                            kind: ItemKind::Trait(_, _, _, self_bounds, _),
-                            .. }
-                        )
-                    ) = cx.tcx.hir().get_if_local(*def_id);
-                then {
-                    if self_bounds_map.is_empty() {
-                        for bound in *self_bounds {
-                            let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { continue };
-                            self_bounds_map.insert(self_res, self_segments);
-                        }
+            if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate
+                && bound_predicate.origin != PredicateOrigin::ImplTrait
+                && !bound_predicate.span.from_expansion()
+                && let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind
+                && let Some(PathSegment {
+                    res: Res::SelfTyParam { trait_: def_id },
+                    ..
+                }) = segments.first()
+                && let Some(Node::Item(Item {
+                    kind: ItemKind::Trait(_, _, _, self_bounds, _),
+                    ..
+                })) = cx.tcx.hir().get_if_local(*def_id)
+            {
+                if self_bounds_map.is_empty() {
+                    for bound in *self_bounds {
+                        let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else {
+                            continue;
+                        };
+                        self_bounds_map.insert(self_res, self_segments);
                     }
+                }
 
-                    bound_predicate
-                        .bounds
-                        .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).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",
-                                    );
-                                }
+                bound_predicate
+                    .bounds
+                    .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).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",
+                                );
                             }
-                        });
-                }
+                        }
+                    });
             }
         }
     }
 
     fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
-        if_chain! {
-            if let TyKind::Ref(.., mut_ty) = &ty.kind;
-            if let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind;
-            if bounds.len() > 2;
-            then {
-
-                // Build up a hash of every trait we've seen
-                // When we see a trait for the first time, add it to unique_traits
-                // so we can later use it to build a string of all traits exactly once, without duplicates
+        if let TyKind::Ref(.., mut_ty) = &ty.kind
+            && let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind
+            && bounds.len() > 2
+        {
+            // Build up a hash of every trait we've seen
+            // When we see a trait for the first time, add it to unique_traits
+            // so we can later use it to build a string of all traits exactly once, without duplicates
 
-                let mut seen_def_ids = FxHashSet::default();
-                let mut unique_traits = Vec::new();
+            let mut seen_def_ids = FxHashSet::default();
+            let mut unique_traits = Vec::new();
 
-                // Iterate the bounds and add them to our seen hash
-                // If we haven't yet seen it, add it to the fixed traits
-                for bound in bounds {
-                    let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
+            // Iterate the bounds and add them to our seen hash
+            // If we haven't yet seen it, add it to the fixed traits
+            for bound in bounds {
+                let Some(def_id) = bound.trait_ref.trait_def_id() else {
+                    continue;
+                };
 
-                    let new_trait = seen_def_ids.insert(def_id);
+                let new_trait = seen_def_ids.insert(def_id);
 
-                    if new_trait {
-                        unique_traits.push(bound);
-                    }
+                if new_trait {
+                    unique_traits.push(bound);
                 }
+            }
 
-                // If the number of unique traits isn't the same as the number of traits in the bounds,
-                // there must be 1 or more duplicates
-                if bounds.len() != unique_traits.len() {
-                    let mut bounds_span = bounds[0].span;
-
-                    for bound in bounds.iter().skip(1) {
-                        bounds_span = bounds_span.to(bound.span);
-                    }
-
-                    let fixed_trait_snippet = unique_traits
-                        .iter()
-                        .filter_map(|b| snippet_opt(cx, b.span))
-                        .collect::<Vec<_>>()
-                        .join(" + ");
+            // If the number of unique traits isn't the same as the number of traits in the bounds,
+            // there must be 1 or more duplicates
+            if bounds.len() != unique_traits.len() {
+                let mut bounds_span = bounds[0].span;
 
-                    span_lint_and_sugg(
-                        cx,
-                        TRAIT_DUPLICATION_IN_BOUNDS,
-                        bounds_span,
-                        "this trait bound is already specified in trait declaration",
-                        "try",
-                        fixed_trait_snippet,
-                        Applicability::MaybeIncorrect,
-                    );
+                for bound in bounds.iter().skip(1) {
+                    bounds_span = bounds_span.to(bound.span);
                 }
+
+                let fixed_trait_snippet = unique_traits
+                    .iter()
+                    .filter_map(|b| snippet_opt(cx, b.span))
+                    .collect::<Vec<_>>()
+                    .join(" + ");
+
+                span_lint_and_sugg(
+                    cx,
+                    TRAIT_DUPLICATION_IN_BOUNDS,
+                    bounds_span,
+                    "this trait bound is already specified in trait declaration",
+                    "try",
+                    fixed_trait_snippet,
+                    Applicability::MaybeIncorrect,
+                );
             }
         }
     }
@@ -267,36 +263,38 @@ impl TraitBounds {
         let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default();
         let mut applicability = Applicability::MaybeIncorrect;
         for bound in gen.predicates {
-            if_chain! {
-                if let WherePredicate::BoundPredicate(ref p) = bound;
-                if p.origin != PredicateOrigin::ImplTrait;
-                if p.bounds.len() as u64 <= self.max_trait_bounds;
-                if !p.span.from_expansion();
-                let bounds = p.bounds.iter().filter(|b| !self.cannot_combine_maybe_bound(cx, b)).collect::<Vec<_>>();
-                if !bounds.is_empty();
-                if let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds);
-                if !is_from_proc_macro(cx, p.bounded_ty);
-                then {
-                    let trait_bounds = v
-                        .iter()
-                        .copied()
-                        .chain(p.bounds.iter())
-                        .filter_map(get_trait_info_from_bound)
-                        .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability))
-                        .join(" + ");
-                    let hint_string = format!(
-                        "consider combining the bounds: `{}: {trait_bounds}`",
-                        snippet(cx, p.bounded_ty.span, "_"),
-                    );
-                    span_lint_and_help(
-                        cx,
-                        TYPE_REPETITION_IN_BOUNDS,
-                        p.span,
-                        "this type has already been used as a bound predicate",
-                        None,
-                        &hint_string,
-                    );
-                }
+            if let WherePredicate::BoundPredicate(ref p) = bound
+                && p.origin != PredicateOrigin::ImplTrait
+                && p.bounds.len() as u64 <= self.max_trait_bounds
+                && !p.span.from_expansion()
+                && let bounds = p
+                    .bounds
+                    .iter()
+                    .filter(|b| !self.cannot_combine_maybe_bound(cx, b))
+                    .collect::<Vec<_>>()
+                && !bounds.is_empty()
+                && let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds)
+                && !is_from_proc_macro(cx, p.bounded_ty)
+            {
+                let trait_bounds = v
+                    .iter()
+                    .copied()
+                    .chain(p.bounds.iter())
+                    .filter_map(get_trait_info_from_bound)
+                    .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability))
+                    .join(" + ");
+                let hint_string = format!(
+                    "consider combining the bounds: `{}: {trait_bounds}`",
+                    snippet(cx, p.bounded_ty.span, "_"),
+                );
+                span_lint_and_help(
+                    cx,
+                    TYPE_REPETITION_IN_BOUNDS,
+                    p.span,
+                    "this type has already been used as a bound predicate",
+                    None,
+                    &hint_string,
+                );
             }
         }
     }
@@ -318,15 +316,19 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
         .predicates
         .iter()
         .filter_map(|pred| {
-            if_chain! {
-                if pred.in_where_clause();
-                if let WherePredicate::BoundPredicate(bound_predicate) = pred;
-                if let TyKind::Path(QPath::Resolved(_, path)) =  bound_predicate.bounded_ty.kind;
-                then {
-                    return Some(
-                        rollup_traits(cx, bound_predicate.bounds, "these where clauses contain repeated elements")
-                        .into_iter().map(|(trait_ref, _)| (path.res, trait_ref)))
-                }
+            if pred.in_where_clause()
+                && let WherePredicate::BoundPredicate(bound_predicate) = pred
+                && let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind
+            {
+                return Some(
+                    rollup_traits(
+                        cx,
+                        bound_predicate.bounds,
+                        "these where clauses contain repeated elements",
+                    )
+                    .into_iter()
+                    .map(|(trait_ref, _)| (path.res, trait_ref)),
+                );
             }
             None
         })
@@ -340,25 +342,23 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
     // compare trait bounds keyed by generic name and comparable trait to collected where
     // predicates eg. (T, Clone)
     for predicate in gen.predicates.iter().filter(|pred| !pred.in_where_clause()) {
-        if_chain! {
-            if let WherePredicate::BoundPredicate(bound_predicate) = predicate;
-            if bound_predicate.origin != PredicateOrigin::ImplTrait;
-            if !bound_predicate.span.from_expansion();
-            if let TyKind::Path(QPath::Resolved(_, path)) =  bound_predicate.bounded_ty.kind;
-            then {
-                let traits = rollup_traits(cx, bound_predicate.bounds, "these bounds contain repeated elements");
-                for (trait_ref, span) in traits {
-                    let key = (path.res, trait_ref);
-                    if where_predicates.contains(&key) {
-                        span_lint_and_help(
-                            cx,
-                            TRAIT_DUPLICATION_IN_BOUNDS,
-                            span,
-                            "this trait bound is already specified in the where clause",
-                            None,
-                            "consider removing this trait bound",
-                        );
-                    }
+        if let WherePredicate::BoundPredicate(bound_predicate) = predicate
+            && bound_predicate.origin != PredicateOrigin::ImplTrait
+            && !bound_predicate.span.from_expansion()
+            && let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind
+        {
+            let traits = rollup_traits(cx, bound_predicate.bounds, "these bounds contain repeated elements");
+            for (trait_ref, span) in traits {
+                let key = (path.res, trait_ref);
+                if where_predicates.contains(&key) {
+                    span_lint_and_help(
+                        cx,
+                        TRAIT_DUPLICATION_IN_BOUNDS,
+                        span,
+                        "this trait bound is already specified in the where clause",
+                        None,
+                        "consider removing this trait bound",
+                    );
                 }
             }
         }
@@ -401,10 +401,10 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef {
             .filter_map(|segment| {
                 // get trait bound type arguments
                 Some(segment.args?.args.iter().filter_map(|arg| {
-                    if_chain! {
-                        if let GenericArg::Type(ty) = arg;
-                        if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
-                        then { return Some(path.res) }
+                    if let GenericArg::Type(ty) = arg
+                        && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
+                    {
+                        return Some(path.res);
                     }
                     None
                 }))
@@ -444,27 +444,24 @@ fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -
         comparable_bounds[i] = (k, v);
     }
 
-    if_chain! {
-        if repeated_res;
-        if let [first_trait, .., last_trait] = bounds;
-        then {
-            let all_trait_span = first_trait.span().to(last_trait.span());
-
-            let traits = comparable_bounds.iter()
-                .filter_map(|&(_, span)| snippet_opt(cx, span))
-                .collect::<Vec<_>>();
-            let traits = traits.join(" + ");
-
-            span_lint_and_sugg(
-                cx,
-                TRAIT_DUPLICATION_IN_BOUNDS,
-                all_trait_span,
-                msg,
-                "try",
-                traits,
-                Applicability::MachineApplicable
-            );
-        }
+    if repeated_res && let [first_trait, .., last_trait] = bounds {
+        let all_trait_span = first_trait.span().to(last_trait.span());
+
+        let traits = comparable_bounds
+            .iter()
+            .filter_map(|&(_, span)| snippet_opt(cx, span))
+            .collect::<Vec<_>>();
+        let traits = traits.join(" + ");
+
+        span_lint_and_sugg(
+            cx,
+            TRAIT_DUPLICATION_IN_BOUNDS,
+            all_trait_span,
+            msg,
+            "try",
+            traits,
+            Applicability::MachineApplicable,
+        );
     }
 
     comparable_bounds
diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index 6eec40cb529..a3a50acb609 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -19,7 +19,6 @@ mod wrong_transmute;
 
 use clippy_config::msrvs::Msrv;
 use clippy_utils::in_constant;
-use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -494,51 +493,47 @@ impl Transmute {
 }
 impl<'tcx> LateLintPass<'tcx> for Transmute {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Call(path_expr, [arg]) = e.kind;
-            if let ExprKind::Path(QPath::Resolved(None, path)) = path_expr.kind;
-            if let Some(def_id) = path.res.opt_def_id();
-            if cx.tcx.is_diagnostic_item(sym::transmute, def_id);
-            then {
-                // Avoid suggesting non-const operations in const contexts:
-                // - from/to bits (https://github.com/rust-lang/rust/issues/73736)
-                // - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911)
-                // - char conversions (https://github.com/rust-lang/rust/issues/89259)
-                let const_context = in_constant(cx, e.hir_id);
+        if let ExprKind::Call(path_expr, [arg]) = e.kind
+            && let ExprKind::Path(QPath::Resolved(None, path)) = path_expr.kind
+            && let Some(def_id) = path.res.opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::transmute, def_id)
+        {
+            // Avoid suggesting non-const operations in const contexts:
+            // - from/to bits (https://github.com/rust-lang/rust/issues/73736)
+            // - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911)
+            // - char conversions (https://github.com/rust-lang/rust/issues/89259)
+            let const_context = in_constant(cx, e.hir_id);
 
-                let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) {
-                    [] => (cx.typeck_results().expr_ty(arg), false),
-                    [.., a] => (a.target, true),
-                };
-                // Adjustments for `to_ty` happen after the call to `transmute`, so don't use them.
-                let to_ty = cx.typeck_results().expr_ty(e);
+            let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) {
+                [] => (cx.typeck_results().expr_ty(arg), false),
+                [.., a] => (a.target, true),
+            };
+            // Adjustments for `to_ty` happen after the call to `transmute`, so don't use them.
+            let to_ty = cx.typeck_results().expr_ty(e);
 
-                // If useless_transmute is triggered, the other lints can be skipped.
-                if useless_transmute::check(cx, e, from_ty, to_ty, arg) {
-                    return;
-                }
+            // If useless_transmute is triggered, the other lints can be skipped.
+            if useless_transmute::check(cx, e, from_ty, to_ty, arg) {
+                return;
+            }
 
-                let linted = wrong_transmute::check(cx, e, from_ty, to_ty)
-                    | crosspointer_transmute::check(cx, e, from_ty, to_ty)
-                    | transmuting_null::check(cx, e, arg, to_ty)
-                    | transmute_null_to_fn::check(cx, e, arg, to_ty)
-                    | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv)
-                    | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
-                    | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
-                    | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
-                    | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
-                    | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
-                    | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
-                    | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
-                    | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
-                    | (
-                        unsound_collection_transmute::check(cx, e, from_ty, to_ty)
-                        || transmute_undefined_repr::check(cx, e, from_ty, to_ty)
-                    );
+            let linted = wrong_transmute::check(cx, e, from_ty, to_ty)
+                | crosspointer_transmute::check(cx, e, from_ty, to_ty)
+                | transmuting_null::check(cx, e, arg, to_ty)
+                | transmute_null_to_fn::check(cx, e, arg, to_ty)
+                | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv)
+                | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
+                | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
+                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
+                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
+                | (unsound_collection_transmute::check(cx, e, from_ty, to_ty)
+                    || transmute_undefined_repr::check(cx, e, from_ty, to_ty));
 
-                if !linted {
-                    transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg);
-                }
+            if !linted {
+                transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg);
             }
         }
     }
diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index 5ecba512b0f..aef520923e4 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -1,7 +1,6 @@
 use super::TRANSMUTE_FLOAT_TO_INT;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg;
-use if_chain::if_chain;
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, UnOp};
@@ -32,17 +31,15 @@ pub(super) fn check<'tcx>(
                         arg = inner_expr;
                     }
 
-                    if_chain! {
+                    if let ExprKind::Lit(lit) = &arg.kind
                         // if the expression is a float literal and it is unsuffixed then
                         // add a suffix so the suggestion is valid and unambiguous
-                        if let ExprKind::Lit(lit) = &arg.kind;
-                        if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node;
-                        then {
-                            let op = format!("{sugg}{}", float_ty.name_str()).into();
-                            match sugg {
-                                sugg::Sugg::MaybeParen(_) => sugg = sugg::Sugg::MaybeParen(op),
-                                _ => sugg = sugg::Sugg::NonParen(op)
-                            }
+                        && let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node
+                    {
+                        let op = format!("{sugg}{}", float_ty.name_str()).into();
+                        match sugg {
+                            sugg::Sugg::MaybeParen(_) => sugg = sugg::Sugg::MaybeParen(op),
+                            _ => sugg = sugg::Sugg::NonParen(op),
                         }
                     }
 
diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index ea9ad99618a..98e9ea2d775 100644
--- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -2,7 +2,6 @@ use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
@@ -21,68 +20,59 @@ pub(super) fn check<'tcx>(
     let mut triggered = false;
 
     if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (&from_ty.kind(), &to_ty.kind()) {
-        if_chain! {
-            if let ty::Slice(slice_ty) = *ty_from.kind();
-            if ty_to.is_str();
-            if let ty::Uint(ty::UintTy::U8) = slice_ty.kind();
-            if from_mutbl == to_mutbl;
-            then {
-                let postfix = if *from_mutbl == Mutability::Mut {
-                    "_mut"
-                } else {
-                    ""
-                };
+        if let ty::Slice(slice_ty) = *ty_from.kind()
+            && ty_to.is_str()
+            && let ty::Uint(ty::UintTy::U8) = slice_ty.kind()
+            && from_mutbl == to_mutbl
+        {
+            let postfix = if *from_mutbl == Mutability::Mut { "_mut" } else { "" };
 
-                let snippet = snippet(cx, arg.span, "..");
+            let snippet = snippet(cx, arg.span, "..");
 
-                span_lint_and_sugg(
-                    cx,
-                    TRANSMUTE_BYTES_TO_STR,
-                    e.span,
-                    &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
-                    "consider using",
-                    if const_context {
-                        format!("std::str::from_utf8_unchecked{postfix}({snippet})")
-                    } else {
-                        format!("std::str::from_utf8{postfix}({snippet}).unwrap()")
-                    },
-                    Applicability::MaybeIncorrect,
-                );
-                triggered = true;
-            } else {
-                if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty))
-                    && !const_context {
-                    span_lint_and_then(
-                        cx,
-                        TRANSMUTE_PTR_TO_PTR,
-                        e.span,
-                        "transmute from a reference to a reference",
-                        |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
-                            let ty_from_and_mut = ty::TypeAndMut {
-                                ty: *ty_from,
-                                mutbl: *from_mutbl
-                            };
-                            let ty_to_and_mut = ty::TypeAndMut { ty: *ty_to, mutbl: *to_mutbl };
-                            let sugg_paren = arg
-                                .as_ty(Ty::new_ptr(cx.tcx,ty_from_and_mut))
-                                .as_ty(Ty::new_ptr(cx.tcx,ty_to_and_mut));
-                            let sugg = if *to_mutbl == Mutability::Mut {
-                                sugg_paren.mut_addr_deref()
-                            } else {
-                                sugg_paren.addr_deref()
-                            };
-                            diag.span_suggestion(
-                                e.span,
-                                "try",
-                                sugg,
-                                Applicability::Unspecified,
-                            );
-                        },
-                    );
+            span_lint_and_sugg(
+                cx,
+                TRANSMUTE_BYTES_TO_STR,
+                e.span,
+                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
+                "consider using",
+                if const_context {
+                    format!("std::str::from_utf8_unchecked{postfix}({snippet})")
+                } else {
+                    format!("std::str::from_utf8{postfix}({snippet}).unwrap()")
+                },
+                Applicability::MaybeIncorrect,
+            );
+            triggered = true;
+        } else if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) && !const_context {
+            span_lint_and_then(
+                cx,
+                TRANSMUTE_PTR_TO_PTR,
+                e.span,
+                "transmute from a reference to a reference",
+                |diag| {
+                    if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
+                        let ty_from_and_mut = ty::TypeAndMut {
+                            ty: *ty_from,
+                            mutbl: *from_mutbl,
+                        };
+                        let ty_to_and_mut = ty::TypeAndMut {
+                            ty: *ty_to,
+                            mutbl: *to_mutbl,
+                        };
+                        let sugg_paren = arg
+                            .as_ty(Ty::new_ptr(cx.tcx, ty_from_and_mut))
+                            .as_ty(Ty::new_ptr(cx.tcx, ty_to_and_mut));
+                        let sugg = if *to_mutbl == Mutability::Mut {
+                            sugg_paren.mut_addr_deref()
+                        } else {
+                            sugg_paren.addr_deref()
+                        };
+                        diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
+                    }
+                },
+            );
 
-                    triggered = true;
-                }
-            }
+            triggered = true;
         }
     }
 
diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 7c2223ca3ab..a65bc0ce458 100644
--- a/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -299,14 +299,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
 }
 
 fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    if_chain! {
-        if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty);
-        if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
-        then {
-            layout.layout.size().bytes() == 0
-        } else {
-            false
-        }
+    if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty)
+        && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
+    {
+        layout.layout.size().bytes() == 0
+    } else {
+        false
     }
 }
 
diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs
index 306ca5724da..801e8862619 100644
--- a/clippy_lints/src/types/borrowed_box.rs
+++ b/clippy_lints/src/types/borrowed_box.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{
     self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind,
@@ -15,66 +14,64 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
         TyKind::Path(ref qpath) => {
             let hir_id = mut_ty.ty.hir_id;
             let def = cx.qpath_res(qpath, hir_id);
-            if_chain! {
-                if let Some(def_id) = def.opt_def_id();
-                if Some(def_id) == cx.tcx.lang_items().owned_box();
-                if let QPath::Resolved(None, path) = *qpath;
-                if let [ref bx] = *path.segments;
-                if let Some(params) = bx.args;
-                if params.parenthesized == hir::GenericArgsParentheses::No;
-                if let Some(inner) = params.args.iter().find_map(|arg| match arg {
+            if let Some(def_id) = def.opt_def_id()
+                && Some(def_id) == cx.tcx.lang_items().owned_box()
+                && let QPath::Resolved(None, path) = *qpath
+                && let [ref bx] = *path.segments
+                && let Some(params) = bx.args
+                && params.parenthesized == hir::GenericArgsParentheses::No
+                && let Some(inner) = params.args.iter().find_map(|arg| match arg {
                     GenericArg::Type(ty) => Some(ty),
                     _ => None,
-                });
-                then {
-                    if is_any_trait(cx, inner) {
-                        // Ignore `Box<Any>` types; see issue #1884 for details.
-                        return false;
-                    }
-
-                    let ltopt = if lt.is_anonymous() {
-                        String::new()
-                    } else {
-                        format!("{} ", lt.ident.as_str())
-                    };
+                })
+            {
+                if is_any_trait(cx, inner) {
+                    // Ignore `Box<Any>` types; see issue #1884 for details.
+                    return false;
+                }
 
-                    if mut_ty.mutbl == Mutability::Mut {
-                        // Ignore `&mut Box<T>` types; see issue #2907 for
-                        // details.
-                        return false;
-                    }
+                let ltopt = if lt.is_anonymous() {
+                    String::new()
+                } else {
+                    format!("{} ", lt.ident.as_str())
+                };
 
-                    // When trait objects or opaque types have lifetime or auto-trait bounds,
-                    // we need to add parentheses to avoid a syntax error due to its ambiguity.
-                    // Originally reported as the issue #3128.
-                    let inner_snippet = snippet(cx, inner.span, "..");
-                    let suggestion = match &inner.kind {
-                        TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
-                            format!("&{ltopt}({})", &inner_snippet)
-                        },
-                        TyKind::Path(qpath)
-                            if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
-                                .map_or(false, |bounds| bounds.len() > 1) =>
-                        {
-                            format!("&{ltopt}({})", &inner_snippet)
-                        },
-                        _ => format!("&{ltopt}{}", &inner_snippet),
-                    };
-                    span_lint_and_sugg(
-                        cx,
-                        BORROWED_BOX,
-                        hir_ty.span,
-                        "you seem to be trying to use `&Box<T>`. Consider using just `&T`",
-                        "try",
-                        suggestion,
-                        // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
-                        // because the trait impls of it will break otherwise;
-                        // and there may be other cases that result in invalid code.
-                        // For example, type coercion doesn't work nicely.
-                        Applicability::Unspecified,
-                    );
-                    return true;
+                if mut_ty.mutbl == Mutability::Mut {
+                    // Ignore `&mut Box<T>` types; see issue #2907 for
+                    // details.
+                    return false;
                 }
+
+                // When trait objects or opaque types have lifetime or auto-trait bounds,
+                // we need to add parentheses to avoid a syntax error due to its ambiguity.
+                // Originally reported as the issue #3128.
+                let inner_snippet = snippet(cx, inner.span, "..");
+                let suggestion = match &inner.kind {
+                    TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
+                        format!("&{ltopt}({})", &inner_snippet)
+                    },
+                    TyKind::Path(qpath)
+                        if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
+                            .map_or(false, |bounds| bounds.len() > 1) =>
+                    {
+                        format!("&{ltopt}({})", &inner_snippet)
+                    },
+                    _ => format!("&{ltopt}{}", &inner_snippet),
+                };
+                span_lint_and_sugg(
+                    cx,
+                    BORROWED_BOX,
+                    hir_ty.span,
+                    "you seem to be trying to use `&Box<T>`. Consider using just `&T`",
+                    "try",
+                    suggestion,
+                    // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
+                    // because the trait impls of it will break otherwise;
+                    // and there may be other cases that result in invalid code.
+                    // For example, type coercion doesn't work nicely.
+                    Applicability::Unspecified,
+                );
+                return true;
             };
             false
         },
@@ -84,33 +81,29 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
 
 // Returns true if given type is `Any` trait.
 fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
-    if_chain! {
-        if let TyKind::TraitObject(traits, ..) = t.kind;
-        if !traits.is_empty();
-        if let Some(trait_did) = traits[0].trait_ref.trait_def_id();
+    if let TyKind::TraitObject(traits, ..) = t.kind
+        && !traits.is_empty()
+        && let Some(trait_did) = traits[0].trait_ref.trait_def_id()
         // Only Send/Sync can be used as additional traits, so it is enough to
         // check only the first trait.
-        if cx.tcx.is_diagnostic_item(sym::Any, trait_did);
-        then {
-            return true;
-        }
+        && cx.tcx.is_diagnostic_item(sym::Any, trait_did)
+    {
+        return true;
     }
 
     false
 }
 
 fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option<GenericBounds<'tcx>> {
-    if_chain! {
-        if let Some(did) = cx.qpath_res(qpath, id).opt_def_id();
-        if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
-        if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
-        if synthetic;
-        if let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id);
-        if let Some(pred) = generics.bounds_for_param(did.expect_local()).next();
-        then {
-            Some(pred.bounds)
-        } else {
-            None
-        }
+    if let Some(did) = cx.qpath_res(qpath, id).opt_def_id()
+        && let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did)
+        && let GenericParamKind::Type { synthetic, .. } = generic_param.kind
+        && synthetic
+        && let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id)
+        && let Some(pred) = generics.bounds_for_param(did.expect_local()).next()
+    {
+        Some(pred.bounds)
+    } else {
+        None
     }
 }
diff --git a/clippy_lints/src/types/box_collection.rs b/clippy_lints/src/types/box_collection.rs
index 4a5a94f2630..fc3420af020 100644
--- a/clippy_lints/src/types/box_collection.rs
+++ b/clippy_lints/src/types/box_collection.rs
@@ -8,30 +8,26 @@ use rustc_span::{sym, Symbol};
 use super::BOX_COLLECTION;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
-    if_chain! {
-        if Some(def_id) == cx.tcx.lang_items().owned_box();
-        if let Some(item_type) = get_std_collection(cx, qpath);
-        then {
-            let generic = match item_type {
-                sym::String => "",
-                _ => "<..>",
-            };
+    if Some(def_id) == cx.tcx.lang_items().owned_box()
+        && let Some(item_type) = get_std_collection(cx, qpath)
+    {
+        let generic = match item_type {
+            sym::String => "",
+            _ => "<..>",
+        };
 
-            let box_content = format!("{item_type}{generic}");
-            span_lint_and_help(
-                cx,
-                BOX_COLLECTION,
-                hir_ty.span,
-                &format!(
-                    "you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"),
-                None,
-                &format!(
-                    "`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation")
-            );
-            true
-        } else {
-            false
-        }
+        let box_content = format!("{item_type}{generic}");
+        span_lint_and_help(
+            cx,
+            BOX_COLLECTION,
+            hir_ty.span,
+            &format!("you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"),
+            None,
+            &format!("`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation"),
+        );
+        true
+    } else {
+        false
     }
 }
 
diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs
index 781e0aa22ed..3870936ef00 100644
--- a/clippy_lints/src/types/mod.rs
+++ b/clippy_lints/src/types/mod.rs
@@ -490,7 +490,7 @@ impl Types {
                         // 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_lints::utils::conf.rs`
+                        // in `clippy_config::conf`
 
                         let mut triggered = false;
                         triggered |= box_collection::check(cx, hir_ty, qpath, def_id);
diff --git a/clippy_lints/src/types/option_option.rs b/clippy_lints/src/types/option_option.rs
index 60622903af1..d12d14f2b14 100644
--- a/clippy_lints/src/types/option_option.rs
+++ b/clippy_lints/src/types/option_option.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{path_def_id, qpath_generic_tys};
-use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, QPath};
 use rustc_lint::LateContext;
@@ -9,21 +8,19 @@ use rustc_span::symbol::sym;
 use super::OPTION_OPTION;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
-    if_chain! {
-        if cx.tcx.is_diagnostic_item(sym::Option, def_id);
-        if let Some(arg) = qpath_generic_tys(qpath).next();
-        if path_def_id(cx, arg) == Some(def_id);
-        then {
-            span_lint(
-                cx,
-                OPTION_OPTION,
-                hir_ty.span,
-                "consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
-                                     enum if you need to distinguish all 3 cases",
-            );
-            true
-        } else {
-            false
-        }
+    if cx.tcx.is_diagnostic_item(sym::Option, def_id)
+        && let Some(arg) = qpath_generic_tys(qpath).next()
+        && path_def_id(cx, arg) == Some(def_id)
+    {
+        span_lint(
+            cx,
+            OPTION_OPTION,
+            hir_ty.span,
+            "consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
+                                 enum if you need to distinguish all 3 cases",
+        );
+        true
+    } else {
+        false
     }
 }
diff --git a/clippy_lints/src/types/rc_mutex.rs b/clippy_lints/src/types/rc_mutex.rs
index a616c3e4ea8..afc31921704 100644
--- a/clippy_lints/src/types/rc_mutex.rs
+++ b/clippy_lints/src/types/rc_mutex.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::{path_def_id, qpath_generic_tys};
-use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, QPath};
 use rustc_lint::LateContext;
@@ -9,22 +8,20 @@ use rustc_span::symbol::sym;
 use super::RC_MUTEX;
 
 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
-    if_chain! {
-        if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ;
-        if let Some(arg) = qpath_generic_tys(qpath).next();
-        if let Some(id) = path_def_id(cx, arg);
-        if cx.tcx.is_diagnostic_item(sym::Mutex, id);
-        then {
-            span_lint_and_help(
-                cx,
-                RC_MUTEX,
-                hir_ty.span,
-                "usage of `Rc<Mutex<_>>`",
-                None,
-                "consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
-            );
-            return true;
-        }
+    if cx.tcx.is_diagnostic_item(sym::Rc, def_id)
+        && let Some(arg) = qpath_generic_tys(qpath).next()
+        && let Some(id) = path_def_id(cx, arg)
+        && cx.tcx.is_diagnostic_item(sym::Mutex, id)
+    {
+        span_lint_and_help(
+            cx,
+            RC_MUTEX,
+            hir_ty.span,
+            "usage of `Rc<Mutex<_>>`",
+            None,
+            "consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
+        );
+        return true;
     }
 
     false
diff --git a/clippy_lints/src/types/utils.rs b/clippy_lints/src/types/utils.rs
index a30748db88f..b1aa1ab4566 100644
--- a/clippy_lints/src/types/utils.rs
+++ b/clippy_lints/src/types/utils.rs
@@ -1,22 +1,19 @@
 use clippy_utils::last_path_segment;
-use if_chain::if_chain;
 use rustc_hir::{GenericArg, GenericArgsParentheses, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
 
 pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<Span> {
     let last = last_path_segment(qpath);
-    if_chain! {
-        if let Some(params) = last.args;
-        if params.parenthesized == GenericArgsParentheses::No;
-        if let Some(ty) = params.args.iter().find_map(|arg| match arg {
+    if let Some(params) = last.args
+        && params.parenthesized == GenericArgsParentheses::No
+        && let Some(ty) = params.args.iter().find_map(|arg| match arg {
             GenericArg::Type(ty) => Some(ty),
             _ => None,
-        });
-        if let TyKind::Ref(..) = ty.kind;
-        then {
-            return Some(ty.span);
-        }
+        })
+        && let TyKind::Ref(..) = ty.kind
+    {
+        return Some(ty.span);
     }
     None
 }
diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs
index decc183ad96..9d5066199bd 100644
--- a/clippy_lints/src/types/vec_box.rs
+++ b/clippy_lints/src/types/vec_box.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::last_path_segment;
+use clippy_utils::paths::ALLOCATOR_GLOBAL;
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
+use clippy_utils::{last_path_segment, match_def_path};
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, GenericArg, QPath, TyKind};
@@ -21,43 +21,57 @@ pub(super) fn check(
     box_size_threshold: u64,
 ) -> bool {
     if cx.tcx.is_diagnostic_item(sym::Vec, def_id) {
-        if_chain! {
+        if let Some(last) = last_path_segment(qpath).args
             // Get the _ part of Vec<_>
-            if let Some(last) = last_path_segment(qpath).args;
-            if let Some(ty) = last.args.iter().find_map(|arg| match arg {
-                GenericArg::Type(ty) => Some(ty),
-                _ => None,
-            });
+            && let Some(GenericArg::Type(ty)) = last.args.first()
+            // extract allocator from the Vec for later
+            && let vec_alloc_ty = last.args.get(1)
             // ty is now _ at this point
-            if let TyKind::Path(ref ty_qpath) = ty.kind;
-            let res = cx.qpath_res(ty_qpath, ty.hir_id);
-            if let Some(def_id) = res.opt_def_id();
-            if Some(def_id) == cx.tcx.lang_items().owned_box();
+            && let TyKind::Path(ref ty_qpath) = ty.kind
+            && let res = cx.qpath_res(ty_qpath, ty.hir_id)
+            && let Some(def_id) = res.opt_def_id()
+            && Some(def_id) == cx.tcx.lang_items().owned_box()
             // At this point, we know ty is Box<T>, now get T
-            if let Some(last) = last_path_segment(ty_qpath).args;
-            if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg {
-                GenericArg::Type(ty) => Some(ty),
-                _ => None,
-            });
-            let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
-            if !ty_ty.has_escaping_bound_vars();
-            if ty_ty.is_sized(cx.tcx, cx.param_env);
-            if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
-            if ty_ty_size < box_size_threshold;
-            then {
-                span_lint_and_sugg(
-                    cx,
-                    VEC_BOX,
-                    hir_ty.span,
-                    "`Vec<T>` is already on the heap, the boxing is unnecessary",
-                    "try",
-                    format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
-                    Applicability::MachineApplicable,
-                );
-                true
-            } else {
-                false
+            && let Some(last) = last_path_segment(ty_qpath).args
+            && let Some(GenericArg::Type(boxed_ty)) = last.args.first()
+            // extract allocator from the Box for later
+            && let boxed_alloc_ty = last.args.get(1)
+            && let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty)
+            && !ty_ty.has_escaping_bound_vars()
+            && ty_ty.is_sized(cx.tcx, cx.param_env)
+            && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes())
+            && ty_ty_size < box_size_threshold
+            // https://github.com/rust-lang/rust-clippy/issues/7114
+            && match (vec_alloc_ty, boxed_alloc_ty) {
+                (None, None) => true,
+                // this is in the event that we have something like
+                // Vec<_, Global>, in which case is equivalent to
+                // Vec<_>
+                (None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => {
+                    if let TyKind::Path(path) = inner.kind
+                        && let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() {
+                        match_def_path(cx, did, &ALLOCATOR_GLOBAL)
+                    } else {
+                        false
+                    }
+                },
+                (Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) =>
+                    hir_ty_to_ty(cx.tcx, l) == hir_ty_to_ty(cx.tcx, r),
+                _ => false
             }
+        {
+            span_lint_and_sugg(
+                cx,
+                VEC_BOX,
+                hir_ty.span,
+                "`Vec<T>` is already on the heap, the boxing is unnecessary",
+                "try",
+                format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
+                Applicability::Unspecified,
+            );
+            true
+        } else {
+            false
         }
     } else {
         false
diff --git a/clippy_lints/src/uninit_vec.rs b/clippy_lints/src/uninit_vec.rs
index 72569e10f05..a7119434517 100644
--- a/clippy_lints/src/uninit_vec.rs
+++ b/clippy_lints/src/uninit_vec.rs
@@ -83,41 +83,39 @@ fn handle_uninit_vec_pair<'tcx>(
     maybe_init_or_reserve: &'tcx Stmt<'tcx>,
     maybe_set_len: &'tcx Expr<'tcx>,
 ) {
-    if_chain! {
-        if let Some(vec) = extract_init_or_reserve_target(cx, maybe_init_or_reserve);
-        if let Some((set_len_self, call_span)) = extract_set_len_self(cx, maybe_set_len);
-        if vec.location.eq_expr(cx, set_len_self);
-        if let ty::Ref(_, vec_ty, _) = cx.typeck_results().expr_ty_adjusted(set_len_self).kind();
-        if let ty::Adt(_, args) = vec_ty.kind();
+    if let Some(vec) = extract_init_or_reserve_target(cx, maybe_init_or_reserve)
+        && let Some((set_len_self, call_span)) = extract_set_len_self(cx, maybe_set_len)
+        && vec.location.eq_expr(cx, set_len_self)
+        && let ty::Ref(_, vec_ty, _) = cx.typeck_results().expr_ty_adjusted(set_len_self).kind()
+        && let ty::Adt(_, args) = vec_ty.kind()
         // `#[allow(...)]` attribute can be set on enclosing unsafe block of `set_len()`
-        if !is_lint_allowed(cx, UNINIT_VEC, maybe_set_len.hir_id);
-        then {
-            if vec.has_capacity() {
-                // with_capacity / reserve -> set_len
+        && !is_lint_allowed(cx, UNINIT_VEC, maybe_set_len.hir_id)
+    {
+        if vec.has_capacity() {
+            // with_capacity / reserve -> set_len
 
-                // Check T of Vec<T>
-                if !is_uninit_value_valid_for_ty(cx, args.type_at(0)) {
-                    // FIXME: #7698, false positive of the internal lints
-                    #[expect(clippy::collapsible_span_lint_calls)]
-                    span_lint_and_then(
-                        cx,
-                        UNINIT_VEC,
-                        vec![call_span, maybe_init_or_reserve.span],
-                        "calling `set_len()` immediately after reserving a buffer creates uninitialized values",
-                        |diag| {
-                            diag.help("initialize the buffer or wrap the content in `MaybeUninit`");
-                        },
-                    );
-                }
-            } else {
-                // new / default -> set_len
-                span_lint(
+            // Check T of Vec<T>
+            if !is_uninit_value_valid_for_ty(cx, args.type_at(0)) {
+                // FIXME: #7698, false positive of the internal lints
+                #[expect(clippy::collapsible_span_lint_calls)]
+                span_lint_and_then(
                     cx,
                     UNINIT_VEC,
                     vec![call_span, maybe_init_or_reserve.span],
-                    "calling `set_len()` on empty `Vec` creates out-of-bound values",
+                    "calling `set_len()` immediately after reserving a buffer creates uninitialized values",
+                    |diag| {
+                        diag.help("initialize the buffer or wrap the content in `MaybeUninit`");
+                    },
                 );
             }
+        } else {
+            // new / default -> set_len
+            span_lint(
+                cx,
+                UNINIT_VEC,
+                vec![call_span, maybe_init_or_reserve.span],
+                "calling `set_len()` on empty `Vec` creates out-of-bound values",
+            );
         }
     }
 }
@@ -156,16 +154,14 @@ impl<'tcx> VecLocation<'tcx> {
 fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> Option<TargetVec<'tcx>> {
     match stmt.kind {
         StmtKind::Local(local) => {
-            if_chain! {
-                if let Some(init_expr) = local.init;
-                if let PatKind::Binding(_, hir_id, _, None) = local.pat.kind;
-                if let Some(init_kind) = get_vec_init_kind(cx, init_expr);
-                then {
-                    return Some(TargetVec {
-                        location: VecLocation::Local(hir_id),
-                        init_kind: Some(init_kind),
-                    })
-                }
+            if let Some(init_expr) = local.init
+                && let PatKind::Binding(_, hir_id, _, None) = local.pat.kind
+                && let Some(init_kind) = get_vec_init_kind(cx, init_expr)
+            {
+                return Some(TargetVec {
+                    location: VecLocation::Local(hir_id),
+                    init_kind: Some(init_kind),
+                });
             }
         },
         StmtKind::Expr(expr) | StmtKind::Semi(expr) => match expr.kind {
diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs
index e76cc65fd46..385f8255a39 100644
--- a/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/clippy_lints/src/unit_return_expecting_ord.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use if_chain::if_chain;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Closure, Expr, ExprKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -44,14 +43,12 @@ fn get_trait_predicates_for_trait_id<'tcx>(
 ) -> Vec<TraitPredicate<'tcx>> {
     let mut preds = Vec::new();
     for (pred, _) in generics.predicates {
-        if_chain! {
-            if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder();
-            let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred));
-            if let Some(trait_def_id) = trait_id;
-            if trait_def_id == trait_pred.trait_ref.def_id;
-            then {
-                preds.push(trait_pred);
-            }
+        if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder()
+            && let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred))
+            && let Some(trait_def_id) = trait_id
+            && trait_def_id == trait_pred.trait_ref.def_id
+        {
+            preds.push(trait_pred);
         }
     }
     preds
@@ -94,21 +91,19 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
             .enumerate()
             .for_each(|(i, inp)| {
                 for trait_pred in &fn_mut_preds {
-                    if_chain! {
-                        if trait_pred.self_ty() == inp;
-                        if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
-                        then {
-                            if ord_preds
-                                .iter()
-                                .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty())
-                            {
-                                args_to_check.push((i, "Ord".to_string()));
-                            } else if partial_ord_preds
-                                .iter()
-                                .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap())
-                            {
-                                args_to_check.push((i, "PartialOrd".to_string()));
-                            }
+                    if trait_pred.self_ty() == inp
+                        && let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred)
+                    {
+                        if ord_preds
+                            .iter()
+                            .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty())
+                        {
+                            args_to_check.push((i, "Ord".to_string()));
+                        } else if partial_ord_preds
+                            .iter()
+                            .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap())
+                        {
+                            args_to_check.push((i, "PartialOrd".to_string()));
                         }
                     }
                 }
@@ -118,30 +113,26 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
 }
 
 fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Span, Option<Span>)> {
-    if_chain! {
-        if let ExprKind::Closure(&Closure { body, fn_decl_span, .. }) = arg.kind;
-        if let ty::Closure(_def_id, args) = &cx.typeck_results().node_type(arg.hir_id).kind();
-        let ret_ty = args.as_closure().sig().output();
-        let ty = cx.tcx.erase_late_bound_regions(ret_ty);
-        if ty.is_unit();
-        then {
-            let body = cx.tcx.hir().body(body);
-            if_chain! {
-                if let ExprKind::Block(block, _) = body.value.kind;
-                if block.expr.is_none();
-                if let Some(stmt) = block.stmts.last();
-                if let StmtKind::Semi(_) = stmt.kind;
-                then {
-                    let data = stmt.span.data();
-                    // Make a span out of the semicolon for the help message
-                    Some((fn_decl_span, Some(data.with_lo(data.hi-BytePos(1)))))
-                } else {
-                    Some((fn_decl_span, None))
-                }
-            }
+    if let ExprKind::Closure(&Closure { body, fn_decl_span, .. }) = arg.kind
+        && let ty::Closure(_def_id, args) = &cx.typeck_results().node_type(arg.hir_id).kind()
+        && let ret_ty = args.as_closure().sig().output()
+        && let ty = cx.tcx.erase_late_bound_regions(ret_ty)
+        && ty.is_unit()
+    {
+        let body = cx.tcx.hir().body(body);
+        if let ExprKind::Block(block, _) = body.value.kind
+            && block.expr.is_none()
+            && let Some(stmt) = block.stmts.last()
+            && let StmtKind::Semi(_) = stmt.kind
+        {
+            let data = stmt.span.data();
+            // Make a span out of the semicolon for the help message
+            Some((fn_decl_span, Some(data.with_lo(data.hi - BytePos(1)))))
         } else {
-            None
+            Some((fn_decl_span, None))
         }
+    } else {
+        None
     }
 }
 
diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs
index 462b1aa8153..44cff78a793 100644
--- a/clippy_lints/src/unit_types/unit_arg.rs
+++ b/clippy_lints/src/unit_types/unit_arg.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, Block, Expr, ExprKind, MatchSource, Node, StmtKind};
 use rustc_lint::LateContext;
@@ -22,12 +21,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
     }
     let map = &cx.tcx.hir();
     let opt_parent_node = map.find_parent(expr.hir_id);
-    if_chain! {
-        if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
-        if is_questionmark_desugar_marked_call(parent_expr);
-        then {
-            return;
-        }
+    if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node
+        && is_questionmark_desugar_marked_call(parent_expr)
+    {
+        return;
     }
 
     let args: Vec<_> = match expr.kind {
@@ -80,21 +77,15 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
             args_to_recover
                 .iter()
                 .filter_map(|arg| {
-                    if_chain! {
-                        if let ExprKind::Block(block, _) = arg.kind;
-                        if block.expr.is_none();
-                        if let Some(last_stmt) = block.stmts.iter().last();
-                        if let StmtKind::Semi(last_expr) = last_stmt.kind;
-                        if let Some(snip) = snippet_opt(cx, last_expr.span);
-                        then {
-                            Some((
-                                last_stmt.span,
-                                snip,
-                            ))
-                        }
-                        else {
-                            None
-                        }
+                    if let ExprKind::Block(block, _) = arg.kind
+                        && block.expr.is_none()
+                        && let Some(last_stmt) = block.stmts.iter().last()
+                        && let StmtKind::Semi(last_expr) = last_stmt.kind
+                        && let Some(snip) = snippet_opt(cx, last_expr.span)
+                    {
+                        Some((last_stmt.span, snip))
+                    } else {
+                        None
                     }
                 })
                 .for_each(|(span, sugg)| {
diff --git a/clippy_lints/src/unnamed_address.rs b/clippy_lints/src/unnamed_address.rs
index e7355f92304..2223cbcb060 100644
--- a/clippy_lints/src/unnamed_address.rs
+++ b/clippy_lints/src/unnamed_address.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
@@ -76,55 +75,50 @@ impl LateLintPass<'_> for UnnamedAddress {
             matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
         }
 
-        if_chain! {
-            if let ExprKind::Binary(binop, left, right) = expr.kind;
-            if is_comparison(binop.node);
-            if is_trait_ptr(cx, left) && is_trait_ptr(cx, right);
-            then {
-                span_lint_and_help(
-                    cx,
-                    VTABLE_ADDRESS_COMPARISONS,
-                    expr.span,
-                    "comparing trait object pointers compares a non-unique vtable address",
-                    None,
-                    "consider extracting and comparing data pointers only",
-                );
-            }
+        if let ExprKind::Binary(binop, left, right) = expr.kind
+            && is_comparison(binop.node)
+            && is_trait_ptr(cx, left)
+            && is_trait_ptr(cx, right)
+        {
+            span_lint_and_help(
+                cx,
+                VTABLE_ADDRESS_COMPARISONS,
+                expr.span,
+                "comparing trait object pointers compares a non-unique vtable address",
+                None,
+                "consider extracting and comparing data pointers only",
+            );
         }
 
-        if_chain! {
-            if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind;
-            if let ExprKind::Path(ref func_qpath) = func.kind;
-            if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
-            if cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id);
-            let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0);
-            if ty_param.is_trait();
-            then {
-                span_lint_and_help(
-                    cx,
-                    VTABLE_ADDRESS_COMPARISONS,
-                    expr.span,
-                    "comparing trait object pointers compares a non-unique vtable address",
-                    None,
-                    "consider extracting and comparing data pointers only",
-                );
-            }
+        if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind
+            && 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::ptr_eq, def_id)
+            && let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0)
+            && ty_param.is_trait()
+        {
+            span_lint_and_help(
+                cx,
+                VTABLE_ADDRESS_COMPARISONS,
+                expr.span,
+                "comparing trait object pointers compares a non-unique vtable address",
+                None,
+                "consider extracting and comparing data pointers only",
+            );
         }
 
-        if_chain! {
-            if let ExprKind::Binary(binop, left, right) = expr.kind;
-            if is_comparison(binop.node);
-            if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr();
-            if cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr();
-            if is_fn_def(cx, left) || is_fn_def(cx, right);
-            then {
-                span_lint(
-                    cx,
-                    FN_ADDRESS_COMPARISONS,
-                    expr.span,
-                    "comparing with a non-unique address of a function item",
-                );
-            }
+        if let ExprKind::Binary(binop, left, right) = expr.kind
+            && is_comparison(binop.node)
+            && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
+            && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
+            && (is_fn_def(cx, left) || is_fn_def(cx, right))
+        {
+            span_lint(
+                cx,
+                FN_ADDRESS_COMPARISONS,
+                expr.span,
+                "comparing with a non-unique address of a function item",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/unnecessary_owned_empty_strings.rs b/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 28ea02e4d9a..14694bb3a28 100644
--- a/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{match_def_path, paths};
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
@@ -36,46 +35,40 @@ declare_lint_pass!(UnnecessaryOwnedEmptyStrings => [UNNECESSARY_OWNED_EMPTY_STRI
 
 impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if_chain! {
-            if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner_expr) = expr.kind;
-            if let ExprKind::Call(fun, args) = inner_expr.kind;
-            if let ExprKind::Path(ref qpath) = fun.kind;
-            if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
-            if let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind();
-            if inner_str.is_str();
-            then {
-                if match_def_path(cx, fun_def_id, &paths::STRING_NEW) {
-                     span_lint_and_sugg(
-                            cx,
-                            UNNECESSARY_OWNED_EMPTY_STRINGS,
-                            expr.span,
-                            "usage of `&String::new()` for a function expecting a `&str` argument",
-                            "try",
-                            "\"\"".to_owned(),
-                            Applicability::MachineApplicable,
-                        );
-                } else {
-                    if_chain! {
-                        if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id);
-                        if let [.., last_arg] = args;
-                        if let ExprKind::Lit(spanned) = &last_arg.kind;
-                        if let LitKind::Str(symbol, _) = spanned.node;
-                        if symbol.is_empty();
-                        let inner_expr_type = cx.typeck_results().expr_ty(inner_expr);
-                        if is_type_lang_item(cx, inner_expr_type, LangItem::String);
-                        then {
-                            span_lint_and_sugg(
-                                cx,
-                                UNNECESSARY_OWNED_EMPTY_STRINGS,
-                                expr.span,
-                                "usage of `&String::from(\"\")` for a function expecting a `&str` argument",
-                                "try",
-                                "\"\"".to_owned(),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
+        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner_expr) = expr.kind
+            && let ExprKind::Call(fun, args) = inner_expr.kind
+            && let ExprKind::Path(ref qpath) = fun.kind
+            && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
+            && let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind()
+            && inner_str.is_str()
+        {
+            if match_def_path(cx, fun_def_id, &paths::STRING_NEW) {
+                span_lint_and_sugg(
+                    cx,
+                    UNNECESSARY_OWNED_EMPTY_STRINGS,
+                    expr.span,
+                    "usage of `&String::new()` for a function expecting a `&str` argument",
+                    "try",
+                    "\"\"".to_owned(),
+                    Applicability::MachineApplicable,
+                );
+            } else if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id)
+                && let [.., last_arg] = args
+                && let ExprKind::Lit(spanned) = &last_arg.kind
+                && let LitKind::Str(symbol, _) = spanned.node
+                && symbol.is_empty()
+                && let inner_expr_type = cx.typeck_results().expr_ty(inner_expr)
+                && is_type_lang_item(cx, inner_expr_type, LangItem::String)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    UNNECESSARY_OWNED_EMPTY_STRINGS,
+                    expr.span,
+                    "usage of `&String::from(\"\")` for a function expecting a `&str` argument",
+                    "try",
+                    "\"\"".to_owned(),
+                    Applicability::MachineApplicable,
+                );
             }
         }
     }
diff --git a/clippy_lints/src/unnecessary_self_imports.rs b/clippy_lints/src/unnecessary_self_imports.rs
index a1083a0a68e..1e2b20469ef 100644
--- a/clippy_lints/src/unnecessary_self_imports.rs
+++ b/clippy_lints/src/unnecessary_self_imports.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use if_chain::if_chain;
 use rustc_ast::{Item, ItemKind, UseTreeKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -36,35 +35,36 @@ declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]);
 
 impl EarlyLintPass for UnnecessarySelfImports {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if_chain! {
-            if let ItemKind::Use(use_tree) = &item.kind;
-            if let UseTreeKind::Nested(nodes) = &use_tree.kind;
-            if let [(self_tree, _)] = &**nodes;
-            if let [self_seg] = &*self_tree.prefix.segments;
-            if self_seg.ident.name == kw::SelfLower;
-            if let Some(last_segment) = use_tree.prefix.segments.last();
-
-            then {
-                span_lint_and_then(
-                    cx,
-                    UNNECESSARY_SELF_IMPORTS,
-                    item.span,
-                    "import ending with `::{self}`",
-                    |diag| {
-                        diag.span_suggestion(
-                            last_segment.span().with_hi(item.span.hi()),
-                            "consider omitting `::{self}`",
-                            format!(
-                                "{}{};",
-                                last_segment.ident,
-                                if let UseTreeKind::Simple(Some(alias)) = self_tree.kind { format!(" as {alias}") } else { String::new() },
-                            ),
-                            Applicability::MaybeIncorrect,
-                        );
-                        diag.note("this will slightly change semantics; any non-module items at the same path will also be imported");
-                    },
-                );
-            }
+        if let ItemKind::Use(use_tree) = &item.kind
+            && let UseTreeKind::Nested(nodes) = &use_tree.kind
+            && let [(self_tree, _)] = &**nodes
+            && let [self_seg] = &*self_tree.prefix.segments
+            && self_seg.ident.name == kw::SelfLower
+            && let Some(last_segment) = use_tree.prefix.segments.last()
+        {
+            span_lint_and_then(
+                cx,
+                UNNECESSARY_SELF_IMPORTS,
+                item.span,
+                "import ending with `::{self}`",
+                |diag| {
+                    diag.span_suggestion(
+                        last_segment.span().with_hi(item.span.hi()),
+                        "consider omitting `::{self}`",
+                        format!(
+                            "{}{};",
+                            last_segment.ident,
+                            if let UseTreeKind::Simple(Some(alias)) = self_tree.kind {
+                                format!(" as {alias}")
+                            } else {
+                                String::new()
+                            },
+                        ),
+                        Applicability::MaybeIncorrect,
+                    );
+                    diag.note("this will slightly change semantics; any non-module items at the same path will also be imported");
+                },
+            );
         }
     }
 }
diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs
index ab8de17b091..5599a9dc4e8 100644
--- a/clippy_lints/src/unnecessary_wraps.rs
+++ b/clippy_lints/src/unnecessary_wraps.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::LangItem::{OptionSome, ResultOk};
@@ -119,28 +118,24 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
         // Check if all return expression respect the following condition and collect them.
         let mut suggs = Vec::new();
         let can_sugg = find_all_ret_expressions(cx, body.value, |ret_expr| {
-            if_chain! {
-                if !ret_expr.span.from_expansion();
+            if !ret_expr.span.from_expansion()
                 // Check if a function call.
-                if let ExprKind::Call(func, [arg]) = ret_expr.kind;
-                if is_res_lang_ctor(cx, path_res(cx, func), lang_item);
+                && let ExprKind::Call(func, [arg]) = ret_expr.kind
+                && is_res_lang_ctor(cx, path_res(cx, func), lang_item)
                 // Make sure the function argument does not contain a return expression.
-                if !contains_return(arg);
-                then {
-                    suggs.push(
-                        (
-                            ret_expr.span,
-                            if inner_type.is_unit() {
-                                String::new()
-                            } else {
-                                snippet(cx, arg.span.source_callsite(), "..").to_string()
-                            }
-                        )
-                    );
-                    true
-                } else {
-                    false
-                }
+                && !contains_return(arg)
+            {
+                suggs.push((
+                    ret_expr.span,
+                    if inner_type.is_unit() {
+                        String::new()
+                    } else {
+                        snippet(cx, arg.span.source_callsite(), "..").to_string()
+                    },
+                ));
+                true
+            } else {
+                false
             }
         });
 
diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs
index f864c520302..532207310bc 100644
--- a/clippy_lints/src/unused_self.rs
+++ b/clippy_lints/src/unused_self.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::visitors::is_local_used;
-use if_chain::if_chain;
 use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -73,25 +72,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             })
             .is_some()
         };
-        if_chain! {
-            if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
-            if assoc_item.fn_has_self_parameter;
-            if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
-            if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api;
-            let body = cx.tcx.hir().body(*body_id);
-            if let [self_param, ..] = body.params;
-            if !is_local_used(cx, body, self_param.pat.hir_id);
-            if !contains_todo(cx, body);
-            then {
-                span_lint_and_help(
-                    cx,
-                    UNUSED_SELF,
-                    self_param.span,
-                    "unused `self` argument",
-                    None,
-                    "consider refactoring to an associated function",
-                );
-            }
+        if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind
+            && assoc_item.fn_has_self_parameter
+            && let ImplItemKind::Fn(.., body_id) = &impl_item.kind
+            && (!cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api)
+            && let body = cx.tcx.hir().body(*body_id)
+            && let [self_param, ..] = body.params
+            && !is_local_used(cx, body, self_param.pat.hir_id)
+            && !contains_todo(cx, body)
+        {
+            span_lint_and_help(
+                cx,
+                UNUSED_SELF,
+                self_param.span,
+                "unused `self` argument",
+                None,
+                "consider refactoring to an associated function",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs
index ae844673b15..633040f2633 100644
--- a/clippy_lints/src/unused_unit.rs
+++ b/clippy_lints/src/unused_unit.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{position_before_rarrow, snippet_opt};
-use if_chain::if_chain;
 use rustc_ast::visit::FnKind;
 use rustc_ast::{ast, ClosureBinder};
 use rustc_errors::Applicability;
@@ -38,40 +37,39 @@ declare_lint_pass!(UnusedUnit => [UNUSED_UNIT]);
 
 impl EarlyLintPass for UnusedUnit {
     fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) {
-        if_chain! {
-            if let ast::FnRetTy::Ty(ref ty) = kind.decl().output;
-            if let ast::TyKind::Tup(ref vals) = ty.kind;
-            if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span);
-            then {
-                // implicit types in closure signatures are forbidden when `for<...>` is present
-                if let FnKind::Closure(&ClosureBinder::For { .. }, ..) = kind {
-                    return;
-                }
-
-                lint_unneeded_unit_return(cx, ty, span);
+        if let ast::FnRetTy::Ty(ref ty) = kind.decl().output
+            && let ast::TyKind::Tup(ref vals) = ty.kind
+            && vals.is_empty()
+            && !ty.span.from_expansion()
+            && get_def(span) == get_def(ty.span)
+        {
+            // implicit types in closure signatures are forbidden when `for<...>` is present
+            if let FnKind::Closure(&ClosureBinder::For { .. }, ..) = kind {
+                return;
             }
+
+            lint_unneeded_unit_return(cx, ty, span);
         }
     }
 
     fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
-        if_chain! {
-            if let Some(stmt) = block.stmts.last();
-            if let ast::StmtKind::Expr(ref expr) = stmt.kind;
-            if is_unit_expr(expr);
-            let ctxt = block.span.ctxt();
-            if stmt.span.ctxt() == ctxt && expr.span.ctxt() == ctxt;
-            then {
-                let sp = expr.span;
-                span_lint_and_sugg(
-                    cx,
-                    UNUSED_UNIT,
-                    sp,
-                    "unneeded unit expression",
-                    "remove the final `()`",
-                    String::new(),
-                    Applicability::MachineApplicable,
-                );
-            }
+        if let Some(stmt) = block.stmts.last()
+            && let ast::StmtKind::Expr(ref expr) = stmt.kind
+            && is_unit_expr(expr)
+            && let ctxt = block.span.ctxt()
+            && stmt.span.ctxt() == ctxt
+            && expr.span.ctxt() == ctxt
+        {
+            let sp = expr.span;
+            span_lint_and_sugg(
+                cx,
+                UNUSED_UNIT,
+                sp,
+                "unneeded unit expression",
+                "remove the final `()`",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
         }
     }
 
@@ -97,16 +95,14 @@ impl EarlyLintPass for UnusedUnit {
     fn check_poly_trait_ref(&mut self, cx: &EarlyContext<'_>, poly: &ast::PolyTraitRef) {
         let segments = &poly.trait_ref.path.segments;
 
-        if_chain! {
-            if segments.len() == 1;
-            if ["Fn", "FnMut", "FnOnce"].contains(&segments[0].ident.name.as_str());
-            if let Some(args) = &segments[0].args;
-            if let ast::GenericArgs::Parenthesized(generic_args) = &**args;
-            if let ast::FnRetTy::Ty(ty) = &generic_args.output;
-            if ty.kind.is_unit();
-            then {
-                lint_unneeded_unit_return(cx, ty, generic_args.span);
-            }
+        if segments.len() == 1
+            && ["Fn", "FnMut", "FnOnce"].contains(&segments[0].ident.name.as_str())
+            && let Some(args) = &segments[0].args
+            && let ast::GenericArgs::Parenthesized(generic_args) = &**args
+            && let ast::FnRetTy::Ty(ty) = &generic_args.output
+            && ty.kind.is_unit()
+        {
+            lint_unneeded_unit_return(cx, ty, generic_args.span);
         }
     }
 }
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index e52cfb29fe5..5e5b1ab38e0 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -2,7 +2,6 @@ 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 if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
@@ -156,41 +155,35 @@ fn collect_unwrap_info<'tcx>(
         }
     } else if let ExprKind::Unary(UnOp::Not, expr) = &expr.kind {
         return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false);
-    } else {
-        if_chain! {
-            if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind;
-            if let Some(local_id) = path_to_local(receiver);
-            let ty = cx.typeck_results().expr_ty(receiver);
-            let name = method_name.ident.as_str();
-            if is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name);
-            then {
-                assert!(args.is_empty());
-                let unwrappable = match name {
-                    "is_some" | "is_ok" => true,
-                    "is_err" | "is_none" => false,
-                    _ => unreachable!(),
-                };
-                let safe_to_unwrap = unwrappable != invert;
-                let kind = if is_type_diagnostic_item(cx, ty, sym::Option) {
-                    UnwrappableKind::Option
-                } else {
-                    UnwrappableKind::Result
-                };
+    } else if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind
+        && let Some(local_id) = path_to_local(receiver)
+        && let ty = cx.typeck_results().expr_ty(receiver)
+        && let name = method_name.ident.as_str()
+        && (is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name))
+    {
+        assert!(args.is_empty());
+        let unwrappable = match name {
+            "is_some" | "is_ok" => true,
+            "is_err" | "is_none" => false,
+            _ => unreachable!(),
+        };
+        let safe_to_unwrap = unwrappable != invert;
+        let kind = if is_type_diagnostic_item(cx, ty, sym::Option) {
+            UnwrappableKind::Option
+        } else {
+            UnwrappableKind::Result
+        };
 
-                return vec![
-                    UnwrapInfo {
-                        local_id,
-                        if_expr,
-                        check: expr,
-                        check_name: method_name,
-                        branch,
-                        safe_to_unwrap,
-                        kind,
-                        is_entire_condition,
-                    }
-                ]
-            }
-        }
+        return vec![UnwrapInfo {
+            local_id,
+            if_expr,
+            check: expr,
+            check_name: method_name,
+            branch,
+            safe_to_unwrap,
+            kind,
+            is_entire_condition,
+        }];
     }
     Vec::new()
 }
@@ -320,73 +313,72 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
             }
         } else {
             // find `unwrap[_err]()` calls:
-            if_chain! {
-                if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind;
-                let (self_arg, as_ref_kind) = consume_option_as_ref(self_arg);
-                if let Some(id) = path_to_local(self_arg);
-                if [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);
-                if let Some(unwrappable) = self.unwrappables.iter()
-                    .find(|u| u.local_id == id);
+            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)
+                && let Some(unwrappable) = self.unwrappables.iter()
+                    .find(|u| u.local_id == id)
                 // Span contexts should not differ with the conditional branch
-                let span_ctxt = expr.span.ctxt();
-                if unwrappable.branch.span.ctxt() == span_ctxt;
-                if unwrappable.check.span.ctxt() == span_ctxt;
-                then {
-                    if call_to_unwrap == unwrappable.safe_to_unwrap {
-                        let is_entire_condition = unwrappable.is_entire_condition;
-                        let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
-                        let suggested_pattern = if call_to_unwrap {
-                            unwrappable.kind.success_variant_pattern()
-                        } else {
-                            unwrappable.kind.error_variant_pattern()
-                        };
-
-                        span_lint_hir_and_then(
-                            self.cx,
-                            UNNECESSARY_UNWRAP,
-                            expr.hir_id,
-                            expr.span,
-                            &format!(
-                                "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`",
-                                method_name.ident.name,
-                                unwrappable.check_name.ident.as_str(),
-                            ),
-                            |diag| {
-                                if is_entire_condition {
-                                    diag.span_suggestion(
-                                        unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()),
-                                        "try",
-                                        format!(
-                                            "if let {suggested_pattern} = {borrow_prefix}{unwrappable_variable_name}",
-                                            borrow_prefix = match as_ref_kind {
-                                                Some(AsRefKind::AsRef) => "&",
-                                                Some(AsRefKind::AsMut) => "&mut ",
-                                                None => "",
-                                            },
-                                        ),
-                                        // We don't track how the unwrapped value is used inside the
-                                        // block or suggest deleting the unwrap, so we can't offer a
-                                        // fixable solution.
-                                        Applicability::Unspecified,
-                                    );
-                                } else {
-                                    diag.span_label(unwrappable.check.span, "the check is happening here");
-                                    diag.help("try using `if let` or `match`");
-                                }
-                            },
-                        );
+                && let span_ctxt = expr.span.ctxt()
+                && unwrappable.branch.span.ctxt() == span_ctxt
+                && unwrappable.check.span.ctxt() == span_ctxt
+            {
+                if call_to_unwrap == unwrappable.safe_to_unwrap {
+                    let is_entire_condition = unwrappable.is_entire_condition;
+                    let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
+                    let suggested_pattern = if call_to_unwrap {
+                        unwrappable.kind.success_variant_pattern()
                     } else {
-                        span_lint_hir_and_then(
-                            self.cx,
-                            PANICKING_UNWRAP,
-                            expr.hir_id,
-                            expr.span,
-                            &format!("this call to `{}()` will always panic",
-                            method_name.ident.name),
-                            |diag| { diag.span_label(unwrappable.check.span, "because of this check"); },
-                        );
-                    }
+                        unwrappable.kind.error_variant_pattern()
+                    };
+
+                    span_lint_hir_and_then(
+                        self.cx,
+                        UNNECESSARY_UNWRAP,
+                        expr.hir_id,
+                        expr.span,
+                        &format!(
+                            "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`",
+                            method_name.ident.name,
+                            unwrappable.check_name.ident.as_str(),
+                        ),
+                        |diag| {
+                            if is_entire_condition {
+                                diag.span_suggestion(
+                                    unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()),
+                                    "try",
+                                    format!(
+                                        "if let {suggested_pattern} = {borrow_prefix}{unwrappable_variable_name}",
+                                        borrow_prefix = match as_ref_kind {
+                                            Some(AsRefKind::AsRef) => "&",
+                                            Some(AsRefKind::AsMut) => "&mut ",
+                                            None => "",
+                                        },
+                                    ),
+                                    // We don't track how the unwrapped value is used inside the
+                                    // block or suggest deleting the unwrap, so we can't offer a
+                                    // fixable solution.
+                                    Applicability::Unspecified,
+                                );
+                            } else {
+                                diag.span_label(unwrappable.check.span, "the check is happening here");
+                                diag.help("try using `if let` or `match`");
+                            }
+                        },
+                    );
+                } else {
+                    span_lint_hir_and_then(
+                        self.cx,
+                        PANICKING_UNWRAP,
+                        expr.hir_id,
+                        expr.span,
+                        &format!("this call to `{}()` will always panic", method_name.ident.name),
+                        |diag| {
+                            diag.span_label(unwrappable.check.span, "because of this check");
+                        },
+                    );
                 }
             }
             walk_expr(self, expr);
diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs
index 21592abbf16..df4b42133f8 100644
--- a/clippy_lints/src/unwrap_in_result.rs
+++ b/clippy_lints/src/unwrap_in_result.rs
@@ -3,7 +3,6 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{method_chain_args, return_ty};
 use core::ops::ControlFlow;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::ImplItemKind;
 use rustc_lint::{LateContext, LateLintPass};
@@ -60,15 +59,13 @@ declare_lint_pass!(UnwrapInResult=> [UNWRAP_IN_RESULT]);
 
 impl<'tcx> LateLintPass<'tcx> for UnwrapInResult {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
-        if_chain! {
+        if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind
             // first check if it's a method or function
-            if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind;
             // checking if its return type is `result` or `option`
-            if is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result)
-                || is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Option);
-            then {
-                lint_impl_body(cx, impl_item.span, impl_item);
-            }
+            && (is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result)
+                || is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Option))
+        {
+            lint_impl_body(cx, impl_item.span, impl_item);
         }
     }
 }
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index c3fe16ad5c3..f058fe5f831 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -2,7 +2,6 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::same_type_and_consts;
-use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -93,32 +92,40 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
         // relevant for linting, since this is the self type of the `impl` we're currently in. To
         // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that
         // we're in an `impl` or nested item, that we don't want to lint
-        let stack_item = if_chain! {
-            if let ItemKind::Impl(Impl { self_ty, generics,.. }) = item.kind;
-            if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind;
-            let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
-            if parameters.as_ref().map_or(true, |params| {
-                params.parenthesized  == GenericArgsParentheses::No
+        let stack_item = if let ItemKind::Impl(Impl { self_ty, generics, .. }) = item.kind
+            && let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind
+            && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args
+            && parameters.as_ref().map_or(true, |params| {
+                params.parenthesized == GenericArgsParentheses::No
                     && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
-            });
-            if !item.span.from_expansion();
-            if !is_from_proc_macro(cx, item); // expensive, should be last check
-            then {
-                // Self cannot be used inside const generic parameters
-                let types_to_skip = generics.params.iter().filter_map(|param| {
-                    match param {
-                        GenericParam { kind: GenericParamKind::Const { ty: Ty { hir_id, ..}, ..}, ..} => Some(*hir_id),
-                        _ => None,
-                    }
-                }).chain(std::iter::once(self_ty.hir_id)).collect();
-                StackItem::Check {
-                    impl_id: item.owner_id.def_id,
-                    in_body: 0,
-                    types_to_skip,
-                }
-            } else {
-                StackItem::NoCheck
+            })
+            && !item.span.from_expansion()
+            && !is_from_proc_macro(cx, item)
+        // expensive, should be last check
+        {
+            // Self cannot be used inside const generic parameters
+            let types_to_skip = generics
+                .params
+                .iter()
+                .filter_map(|param| match param {
+                    GenericParam {
+                        kind:
+                            GenericParamKind::Const {
+                                ty: Ty { hir_id, .. }, ..
+                            },
+                        ..
+                    } => Some(*hir_id),
+                    _ => None,
+                })
+                .chain(std::iter::once(self_ty.hir_id))
+                .collect();
+            StackItem::Check {
+                impl_id: item.owner_id.def_id,
+                in_body: 0,
+                types_to_skip,
             }
+        } else {
+            StackItem::NoCheck
         };
         self.stack.push(stack_item);
     }
@@ -132,56 +139,54 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
         // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait
         // declaration. The collection of those types is all this method implementation does.
-        if_chain! {
-            if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind;
-            if let Some(&mut StackItem::Check {
+        if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind
+            && let Some(&mut StackItem::Check {
                 impl_id,
                 ref mut types_to_skip,
                 ..
-            }) = self.stack.last_mut();
-            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id);
-            then {
-                // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
-                // `Self`.
-                let self_ty = impl_trait_ref.instantiate_identity().self_ty();
+            }) = self.stack.last_mut()
+            && let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id)
+        {
+            // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
+            // `Self`.
+            let self_ty = impl_trait_ref.instantiate_identity().self_ty();
 
-                // `trait_method_sig` is the signature of the function, how it is declared in the
-                // trait, not in the impl of the trait.
-                let trait_method = cx
-                    .tcx
-                    .associated_item(impl_item.owner_id)
-                    .trait_item_def_id
-                    .expect("impl method matches a trait method");
-                let trait_method_sig = cx.tcx.fn_sig(trait_method).instantiate_identity();
-                let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig);
+            // `trait_method_sig` is the signature of the function, how it is declared in the
+            // trait, not in the impl of the trait.
+            let trait_method = cx
+                .tcx
+                .associated_item(impl_item.owner_id)
+                .trait_item_def_id
+                .expect("impl method matches a trait method");
+            let trait_method_sig = cx.tcx.fn_sig(trait_method).instantiate_identity();
+            let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig);
 
-                // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the
-                // implementation of the trait.
-                let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output {
-                    Some(&**ty)
-                } else {
-                    None
-                };
-                let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty);
+            // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the
+            // implementation of the trait.
+            let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output {
+                Some(&**ty)
+            } else {
+                None
+            };
+            let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty);
 
-                // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature.
-                //
-                // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the
-                // trait declaration. This is used to check if `Self` was used in the trait
-                // declaration.
-                //
-                // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed
-                // to `Self`), we want to skip linting that type and all subtypes of it. This
-                // avoids suggestions to e.g. replace `Vec<u8>` with `Vec<Self>`, in an `impl Trait
-                // for u8`, when the trait always uses `Vec<u8>`.
-                //
-                // See also https://github.com/rust-lang/rust-clippy/issues/2894.
-                for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
-                    if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
-                        let mut visitor = SkipTyCollector::default();
-                        visitor.visit_ty(impl_hir_ty);
-                        types_to_skip.extend(visitor.types_to_skip);
-                    }
+            // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature.
+            //
+            // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the
+            // trait declaration. This is used to check if `Self` was used in the trait
+            // declaration.
+            //
+            // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed
+            // to `Self`), we want to skip linting that type and all subtypes of it. This
+            // avoids suggestions to e.g. replace `Vec<u8>` with `Vec<Self>`, in an `impl Trait
+            // for u8`, when the trait always uses `Vec<u8>`.
+            //
+            // See also https://github.com/rust-lang/rust-clippy/issues/2894.
+            for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
+                if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
+                    let mut visitor = SkipTyCollector::default();
+                    visitor.visit_ty(impl_hir_ty);
+                    types_to_skip.extend(visitor.types_to_skip);
                 }
             }
         }
@@ -203,41 +208,38 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
     }
 
     fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
-        if_chain! {
-            if !hir_ty.span.from_expansion();
-            if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
-            if let Some(&StackItem::Check {
+        if !hir_ty.span.from_expansion()
+            && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
+            && let Some(&StackItem::Check {
                 impl_id,
                 in_body,
                 ref types_to_skip,
-            }) = self.stack.last();
-            if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
-            if !matches!(
+            }) = self.stack.last()
+            && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
+            && !matches!(
                 path.res,
-                Res::SelfTyParam { .. }
-                | Res::SelfTyAlias { .. }
-                | Res::Def(DefKind::TyParam, _)
-            );
-            if !types_to_skip.contains(&hir_ty.hir_id);
-            let ty = if in_body > 0 {
+                Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
+            )
+            && !types_to_skip.contains(&hir_ty.hir_id)
+            && let ty = if in_body > 0 {
                 cx.typeck_results().node_type(hir_ty.hir_id)
             } else {
                 hir_ty_to_ty(cx.tcx, hir_ty)
-            };
-            if same_type_and_consts(ty, cx.tcx.type_of(impl_id).instantiate_identity());
-            then {
-                span_lint(cx, hir_ty.span);
             }
+            && same_type_and_consts(ty, cx.tcx.type_of(impl_id).instantiate_identity())
+        {
+            span_lint(cx, hir_ty.span);
         }
     }
 
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if_chain! {
-            if !expr.span.from_expansion();
-            if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
-            if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
-            if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity();
-            then {} else { return; }
+        if !expr.span.from_expansion()
+            && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
+            && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last()
+            && cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity()
+        {
+        } else {
+            return;
         }
         match expr.kind {
             ExprKind::Struct(QPath::Resolved(_, path), ..) => check_path(cx, path),
@@ -252,18 +254,16 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
     }
 
     fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
-        if_chain! {
-            if !pat.span.from_expansion();
-            if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
-            if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
+        if !pat.span.from_expansion()
+            && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
+            && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last()
             // get the path from the pattern
-            if let PatKind::Path(QPath::Resolved(_, path))
+            && let PatKind::Path(QPath::Resolved(_, path))
                  | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
-                 | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind;
-            if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity();
-            then {
-                check_path(cx, path);
-            }
+                 | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind
+            && cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity()
+        {
+            check_path(cx, path);
         }
     }
 
diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs
index 28f1d487eb5..52327b82e84 100644
--- a/clippy_lints/src/useless_conversion.rs
+++ b/clippy_lints/src/useless_conversion.rs
@@ -3,7 +3,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_con
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, path_to_local};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
@@ -311,76 +310,63 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         );
                     }
                 }
-                if_chain! {
-                    if is_trait_method(cx, e, sym::TryInto) && name.ident.name == sym::try_into;
-                    let a = cx.typeck_results().expr_ty(e);
-                    let b = cx.typeck_results().expr_ty(recv);
-                    if is_type_diagnostic_item(cx, a, sym::Result);
-                    if let ty::Adt(_, args) = a.kind();
-                    if let Some(a_type) = args.types().next();
-                    if same_type_and_consts(a_type, b);
+                if is_trait_method(cx, e, sym::TryInto)
+                    && name.ident.name == sym::try_into
+                    && let a = cx.typeck_results().expr_ty(e)
+                    && let b = cx.typeck_results().expr_ty(recv)
+                    && is_type_diagnostic_item(cx, a, sym::Result)
+                    && let ty::Adt(_, args) = a.kind()
+                    && let Some(a_type) = args.types().next()
+                    && same_type_and_consts(a_type, b)
+                {
+                    span_lint_and_help(
+                        cx,
+                        USELESS_CONVERSION,
+                        e.span,
+                        &format!("useless conversion to the same type: `{b}`"),
+                        None,
+                        "consider removing `.try_into()`",
+                    );
+                }
+            },
 
-                    then {
+            ExprKind::Call(path, [arg]) => {
+                if let ExprKind::Path(ref qpath) = path.kind
+                    && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                    && !is_ty_alias(qpath)
+                {
+                    let a = cx.typeck_results().expr_ty(e);
+                    let b = cx.typeck_results().expr_ty(arg);
+                    if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id)
+                        && is_type_diagnostic_item(cx, a, sym::Result)
+                        && let ty::Adt(_, args) = a.kind()
+                        && let Some(a_type) = args.types().next()
+                        && same_type_and_consts(a_type, b)
+                    {
+                        let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from"));
                         span_lint_and_help(
                             cx,
                             USELESS_CONVERSION,
                             e.span,
                             &format!("useless conversion to the same type: `{b}`"),
                             None,
-                            "consider removing `.try_into()`",
+                            &hint,
                         );
                     }
-                }
-            },
-
-            ExprKind::Call(path, [arg]) => {
-                if_chain! {
-                    if let ExprKind::Path(ref qpath) = path.kind;
-                    if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
-                    if !is_ty_alias(qpath);
-                    then {
-                        let a = cx.typeck_results().expr_ty(e);
-                        let b = cx.typeck_results().expr_ty(arg);
-                        if_chain! {
-                            if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id);
-                            if is_type_diagnostic_item(cx, a, sym::Result);
-                            if let ty::Adt(_, args) = a.kind();
-                            if let Some(a_type) = args.types().next();
-                            if same_type_and_consts(a_type, b);
 
-                            then {
-                                let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from"));
-                                span_lint_and_help(
-                                    cx,
-                                    USELESS_CONVERSION,
-                                    e.span,
-                                    &format!("useless conversion to the same type: `{b}`"),
-                                    None,
-                                    &hint,
-                                );
-                            }
-                        }
-
-                        if_chain! {
-                            if cx.tcx.is_diagnostic_item(sym::from_fn, def_id);
-                            if same_type_and_consts(a, b);
-
-                            then {
-                                let mut app = Applicability::MachineApplicable;
-                                let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "<expr>", &mut app).maybe_par();
-                                let sugg_msg =
-                                    format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
-                                span_lint_and_sugg(
-                                    cx,
-                                    USELESS_CONVERSION,
-                                    e.span,
-                                    &format!("useless conversion to the same type: `{b}`"),
-                                    &sugg_msg,
-                                    sugg.to_string(),
-                                    app,
-                                );
-                            }
-                        }
+                    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_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
+                        span_lint_and_sugg(
+                            cx,
+                            USELESS_CONVERSION,
+                            e.span,
+                            &format!("useless conversion to the same type: `{b}`"),
+                            &sugg_msg,
+                            sugg.to_string(),
+                            app,
+                        );
                     }
                 }
             },
diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
index ddcb9f27c6c..877a77fd6d2 100644
--- a/clippy_lints/src/utils/internal_lints.rs
+++ b/clippy_lints/src/utils/internal_lints.rs
@@ -1,7 +1,6 @@
 pub mod almost_standard_lint_formulation;
 pub mod collapsible_calls;
 pub mod compiler_lint_functions;
-pub mod if_chain_style;
 pub mod interning_defined_symbol;
 pub mod invalid_paths;
 pub mod lint_without_lint_pass;
diff --git a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
index d7666b77f6e..f514f166cff 100644
--- a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::{is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt, SpanlessEq};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{Closure, Expr, ExprKind};
@@ -78,45 +77,43 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
             return;
         }
 
-        if_chain! {
-            if let ExprKind::Call(func, and_then_args) = expr.kind;
-            if is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]);
-            if and_then_args.len() == 5;
-            if let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind;
-            let body = cx.tcx.hir().body(body);
-            let only_expr = peel_blocks_with_stmt(body.value);
-            if let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind;
-            if let ExprKind::Path(..) = recv.kind;
-            then {
-                let and_then_snippets = get_and_then_snippets(cx, and_then_args);
-                let mut sle = SpanlessEq::new(cx).deny_side_effects();
-                match ps.ident.as_str() {
-                    "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
-                        suggest_suggestion(
-                            cx,
-                            expr,
-                            &and_then_snippets,
-                            &span_suggestion_snippets(cx, span_call_args),
-                        );
-                    },
-                    "span_help" if sle.eq_expr(&and_then_args[2], &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(&and_then_args[2], &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);
-                    },
-                    _ => (),
-                }
+        if let ExprKind::Call(func, and_then_args) = expr.kind
+            && is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"])
+            && and_then_args.len() == 5
+            && let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].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, and_then_args);
+            let mut sle = SpanlessEq::new(cx).deny_side_effects();
+            match ps.ident.as_str() {
+                "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
+                    suggest_suggestion(
+                        cx,
+                        expr,
+                        &and_then_snippets,
+                        &span_suggestion_snippets(cx, span_call_args),
+                    );
+                },
+                "span_help" if sle.eq_expr(&and_then_args[2], &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(&and_then_args[2], &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);
+                },
+                _ => (),
             }
         }
     }
diff --git a/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs b/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
index cacd05262a2..5aa1417cfb4 100644
--- a/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
+++ b/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::match_type;
 use clippy_utils::{is_lint_allowed, paths};
-use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -56,22 +55,20 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
             return;
         }
 
-        if_chain! {
-            if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind;
-            let fn_name = path.ident;
-            if let Some(sugg) = self.map.get(fn_name.as_str());
-            let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
-            if match_type(cx, ty, &paths::EARLY_CONTEXT) || match_type(cx, ty, &paths::LATE_CONTEXT);
-            then {
-                span_lint_and_help(
-                    cx,
-                    COMPILER_LINT_FUNCTIONS,
-                    path.ident.span,
-                    "usage of a compiler lint function",
-                    None,
-                    &format!("please use the Clippy variant of this function: `{sugg}`"),
-                );
-            }
+        if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind
+            && let fn_name = path.ident
+            && let Some(sugg) = self.map.get(fn_name.as_str())
+            && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
+            && (match_type(cx, ty, &paths::EARLY_CONTEXT) || match_type(cx, ty, &paths::LATE_CONTEXT))
+        {
+            span_lint_and_help(
+                cx,
+                COMPILER_LINT_FUNCTIONS,
+                path.ident.span,
+                "usage of a compiler lint function",
+                None,
+                &format!("please use the Clippy variant of this function: `{sugg}`"),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/utils/internal_lints/if_chain_style.rs b/clippy_lints/src/utils/internal_lints/if_chain_style.rs
deleted file mode 100644
index 8cdd5ea8903..00000000000
--- a/clippy_lints/src/utils/internal_lints/if_chain_style.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::{higher, is_else_clause, is_expn_of};
-use if_chain::if_chain;
-use rustc_hir as hir;
-use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Local, Node, Stmt, StmtKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{BytePos, Span};
-
-declare_clippy_lint! {
-    /// Finds unidiomatic usage of `if_chain!`
-    pub IF_CHAIN_STYLE,
-    internal,
-    "non-idiomatic `if_chain!` usage"
-}
-
-declare_lint_pass!(IfChainStyle => [IF_CHAIN_STYLE]);
-
-impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
-    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
-        let (local, after, if_chain_span) = if_chain! {
-            if let [Stmt { kind: StmtKind::Local(local), .. }, after @ ..] = block.stmts;
-            if let Some(if_chain_span) = is_expn_of(block.span, "if_chain");
-            then { (local, after, if_chain_span) } else { return }
-        };
-        if is_first_if_chain_expr(cx, block.hir_id, if_chain_span) {
-            span_lint(
-                cx,
-                IF_CHAIN_STYLE,
-                if_chain_local_span(cx, local, if_chain_span),
-                "`let` expression should be above the `if_chain!`",
-            );
-        } else if local.span.eq_ctxt(block.span) && is_if_chain_then(after, block.expr, if_chain_span) {
-            span_lint(
-                cx,
-                IF_CHAIN_STYLE,
-                if_chain_local_span(cx, local, if_chain_span),
-                "`let` expression should be inside `then { .. }`",
-            );
-        }
-    }
-
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        let (cond, then, els) = if let Some(higher::IfOrIfLet { cond, r#else, then }) = higher::IfOrIfLet::hir(expr) {
-            (cond, then, r#else.is_some())
-        } else {
-            return;
-        };
-        let ExprKind::Block(then_block, _) = then.kind else {
-            return;
-        };
-        let if_chain_span = is_expn_of(expr.span, "if_chain");
-        if !els {
-            check_nested_if_chains(cx, expr, then_block, if_chain_span);
-        }
-        let Some(if_chain_span) = if_chain_span else { return };
-        // check for `if a && b;`
-        if_chain! {
-            if let ExprKind::Binary(op, _, _) = cond.kind;
-            if op.node == BinOpKind::And;
-            if cx.sess().source_map().is_multiline(cond.span);
-            then {
-                span_lint(cx, IF_CHAIN_STYLE, cond.span, "`if a && b;` should be `if a; if b;`");
-            }
-        }
-        if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span)
-            && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span)
-        {
-            span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`");
-        }
-    }
-}
-
-fn check_nested_if_chains(
-    cx: &LateContext<'_>,
-    if_expr: &Expr<'_>,
-    then_block: &Block<'_>,
-    if_chain_span: Option<Span>,
-) {
-    #[rustfmt::skip]
-    let (head, tail) = match *then_block {
-        Block { stmts, expr: Some(tail), .. } => (stmts, tail),
-        Block {
-            stmts: &[
-                ref head @ ..,
-                Stmt { kind: StmtKind::Expr(tail) | StmtKind::Semi(tail), .. }
-            ],
-            ..
-        } => (head, tail),
-        _ => return,
-    };
-    if_chain! {
-        if let Some(higher::IfOrIfLet { r#else: None, .. }) = higher::IfOrIfLet::hir(tail);
-        let sm = cx.sess().source_map();
-        if head
-            .iter()
-            .all(|stmt| matches!(stmt.kind, StmtKind::Local(..)) && !sm.is_multiline(stmt.span));
-        if if_chain_span.is_some() || !is_else_clause(cx.tcx, if_expr);
-        then {
-        } else {
-            return;
-        }
-    }
-    let (span, msg) = match (if_chain_span, is_expn_of(tail.span, "if_chain")) {
-        (None, Some(_)) => (if_expr.span, "this `if` can be part of the inner `if_chain!`"),
-        (Some(_), None) => (tail.span, "this `if` can be part of the outer `if_chain!`"),
-        (Some(a), Some(b)) if a != b => (b, "this `if_chain!` can be merged with the outer `if_chain!`"),
-        _ => return,
-    };
-    span_lint_and_then(cx, IF_CHAIN_STYLE, span, msg, |diag| {
-        let (span, msg) = match head {
-            [] => return,
-            [stmt] => (stmt.span, "this `let` statement can also be in the `if_chain!`"),
-            [a, .., b] => (
-                a.span.to(b.span),
-                "these `let` statements can also be in the `if_chain!`",
-            ),
-        };
-        diag.span_help(span, msg);
-    });
-}
-
-fn is_first_if_chain_expr(cx: &LateContext<'_>, hir_id: HirId, if_chain_span: Span) -> bool {
-    cx.tcx
-        .hir()
-        .parent_iter(hir_id)
-        .find(|(_, node)| {
-            #[rustfmt::skip]
-            !matches!(node, Node::Expr(Expr { kind: ExprKind::Block(..), .. }) | Node::Stmt(_))
-        })
-        .map_or(false, |(id, _)| {
-            is_expn_of(cx.tcx.hir().span(id), "if_chain") != Some(if_chain_span)
-        })
-}
-
-/// Checks a trailing slice of statements and expression of a `Block` to see if they are part
-/// of the `then {..}` portion of an `if_chain!`
-fn is_if_chain_then(stmts: &[Stmt<'_>], expr: Option<&Expr<'_>>, if_chain_span: Span) -> bool {
-    let span = if let [stmt, ..] = stmts {
-        stmt.span
-    } else if let Some(expr) = expr {
-        expr.span
-    } else {
-        // empty `then {}`
-        return true;
-    };
-    is_expn_of(span, "if_chain").map_or(true, |span| span != if_chain_span)
-}
-
-/// Creates a `Span` for `let x = ..;` in an `if_chain!` call.
-fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: Span) -> Span {
-    let mut span = local.pat.span;
-    if let Some(init) = local.init {
-        span = span.to(init.span);
-    }
-    span.adjust(if_chain_span.ctxt().outer_expn());
-    let sm = cx.sess().source_map();
-    let span = sm.span_extend_to_prev_str(span, "let", false, true).unwrap_or(span);
-    let span = sm.span_extend_to_next_char(span, ';', false);
-    Span::new(
-        span.lo() - BytePos(3),
-        span.hi() + BytePos(1),
-        span.ctxt(),
-        span.parent(),
-    )
-}
diff --git a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index fc9afe5ca8b..16d0636b834 100644
--- a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -3,7 +3,6 @@ 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 if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -77,15 +76,13 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
         for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
             for def_id in def_path_def_ids(cx, module) {
                 for item in cx.tcx.module_children(def_id) {
-                    if_chain! {
-                        if let Res::Def(DefKind::Const, item_def_id) = item.res;
-                        let ty = cx.tcx.type_of(item_def_id).instantiate_identity();
-                        if match_type(cx, ty, &paths::SYMBOL);
-                        if let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id);
-                        if let Ok(value) = value.to_u32();
-                        then {
-                            self.symbol_map.insert(value, item_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 Ok(value) = value.to_u32()
+                    {
+                        self.symbol_map.insert(value, item_def_id);
                     }
                 }
             }
@@ -93,24 +90,22 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Call(func, [arg]) = &expr.kind;
-            if let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind();
-            if match_def_path(cx, *def_id, &paths::SYMBOL_INTERN);
-            if let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg);
-            let value = Symbol::intern(&arg).as_u32();
-            if let Some(&def_id) = self.symbol_map.get(&value);
-            then {
-                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::Call(func, [arg]) = &expr.kind
+            && let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
+            && match_def_path(cx, *def_id, &paths::SYMBOL_INTERN)
+            && let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), 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) {
@@ -163,27 +158,28 @@ 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_chain! {
-            if let ExprKind::AddrOf(_, _, e) = expr.kind;
-            if let ExprKind::Unary(UnOp::Deref, e) = e.kind;
-            then { e } else { expr }
+        let call = if let ExprKind::AddrOf(_, _, e) = expr.kind
+            && let ExprKind::Unary(UnOp::Deref, e) = e.kind
+        {
+            e
+        } else {
+            expr
         };
-        if_chain! {
+        if let ExprKind::MethodCall(_, item, [], _) = call.kind
             // is a method call
-            if let ExprKind::MethodCall(_, item, [], _) = call.kind;
-            if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id);
-            let ty = cx.typeck_results().expr_ty(item);
+            && 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
-            if let Some(is_ident) = if match_type(cx, ty, &paths::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 };
-            if let Some(is_to_owned) = paths
+            && 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)
@@ -194,14 +190,13 @@ impl InterningDefinedSymbol {
                     Some(true)
                 } else {
                     None
-                });
-            then {
-                return Some(SymbolStrExpr::Expr {
-                    item,
-                    is_ident,
-                    is_to_owned,
-                });
-            }
+                })
+        {
+            return Some(SymbolStrExpr::Expr {
+                item,
+                is_ident,
+                is_to_owned,
+            });
         }
         // is a string constant
         if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) {
diff --git a/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 25077223885..66d32087fcd 100644
--- a/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -1,7 +1,6 @@
 use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::def_path_res;
 use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::Item;
@@ -31,13 +30,12 @@ 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_chain! {
-            if mod_name.as_str() == "paths";
-            if let hir::ItemKind::Const(.., body_id) = item.kind;
-            let body = cx.tcx.hir().body(body_id);
-            let typeck_results = cx.tcx.typeck_body(body_id);
-            if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value);
-            if let Some(path) = path
+        if mod_name.as_str() == "paths"
+            && let hir::ItemKind::Const(.., body_id) = item.kind
+            && let body = cx.tcx.hir().body(body_id)
+            && let typeck_results = cx.tcx.typeck_body(body_id)
+            && let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value)
+            && let Some(path) = path
                 .iter()
                 .map(|x| {
                     if let Constant::Str(s) = x {
@@ -46,11 +44,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
                         None
                     }
                 })
-                .collect::<Option<Vec<&str>>>();
-            if !check_path(cx, &path[..]);
-            then {
-                span_lint(cx, INVALID_PATHS, item.span, "invalid path");
-            }
+                .collect::<Option<Vec<&str>>>()
+            && !check_path(cx, &path[..])
+        {
+            span_lint(cx, INVALID_PATHS, item.span, "invalid path");
         }
     }
 }
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
index 00e352961bd..486e8220484 100644
--- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -2,7 +2,6 @@ use crate::utils::internal_lints::metadata_collector::is_deprecated_lint;
 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 if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def::{DefKind, Res};
@@ -309,14 +308,16 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
 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_chain! {
+        if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind
             // Identify attribute
-            if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind;
-            if let [tool_name, attr_name] = &attr_kind.item.path.segments[..];
-            if tool_name.ident.name == sym::clippy;
-            if attr_name.ident.name == sym::version;
-            if let Some(version) = attr.value_str();
-            then { Some(version) } else { None }
+            && let [tool_name, attr_name] = &attr_kind.item.path.segments[..]
+            && tool_name.ident.name == sym::clippy
+            && attr_name.ident.name == sym::version
+            && let Some(version) = attr.value_str()
+        {
+            Some(version)
+        } else {
+            None
         }
     })
 }
diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 51abe0c1dc3..8ecdba47f89 100644
--- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -14,7 +14,6 @@ use clippy_config::{get_configuration_metadata, ClippyConfiguration};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
 use clippy_utils::{last_path_segment, match_def_path, match_function_call, match_path, paths};
-use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
@@ -543,49 +542,45 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
     fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) {
         if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
             // Normal lint
-            if_chain! {
+            if is_lint_ref_type(cx, ty)
                 // item validation
-                if is_lint_ref_type(cx, ty);
                 // disallow check
-                let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
+                && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase()
                 // metadata extraction
-                if let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item);
-                if let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item);
-                then {
-                    if let Some(configuration_section) = self.get_lint_configs(&lint_name) {
-                        raw_docs.push_str(&configuration_section);
-                    }
-                    let version = get_lint_version(cx, item);
-
-                    self.lints.push(LintMetadata::new(
-                        lint_name,
-                        SerializableSpan::from_item(cx, item),
-                        group,
-                        level,
-                        version,
-                        raw_docs,
-                    ));
+                && let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item)
+                && let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item)
+            {
+                if let Some(configuration_section) = self.get_lint_configs(&lint_name) {
+                    raw_docs.push_str(&configuration_section);
                 }
+                let version = get_lint_version(cx, item);
+
+                self.lints.push(LintMetadata::new(
+                    lint_name,
+                    SerializableSpan::from_item(cx, item),
+                    group,
+                    level,
+                    version,
+                    raw_docs,
+                ));
             }
 
-            if_chain! {
-                if is_deprecated_lint(cx, ty);
+            if is_deprecated_lint(cx, ty)
                 // disallow check
-                let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
+                && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase()
                 // Metadata the little we can get from a deprecated lint
-                if let Some(raw_docs) = extract_attr_docs_or_lint(cx, item);
-                then {
-                    let version = get_lint_version(cx, item);
-
-                    self.lints.push(LintMetadata::new(
-                        lint_name,
-                        SerializableSpan::from_item(cx, item),
-                        DEPRECATED_LINT_GROUP_STR.to_string(),
-                        DEPRECATED_LINT_LEVEL,
-                        version,
-                        raw_docs,
-                    ));
-                }
+                && let Some(raw_docs) = extract_attr_docs_or_lint(cx, item)
+            {
+                let version = get_lint_version(cx, item);
+
+                self.lints.push(LintMetadata::new(
+                    lint_name,
+                    SerializableSpan::from_item(cx, item),
+                    DEPRECATED_LINT_GROUP_STR.to_string(),
+                    DEPRECATED_LINT_LEVEL,
+                    version,
+                    raw_docs,
+                ));
             }
         }
     }
@@ -789,15 +784,13 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
         loop {
             if let Some(lint_name) = names.pop() {
                 for (k, v) in RENAMED_LINTS {
-                    if_chain! {
-                        if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
-                        if name == lint_name;
-                        if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
-                        then {
-                            lint.former_ids.insert(past_name.to_owned());
-                            writeln!(collected, "* `{past_name}`").unwrap();
-                            names.push(past_name.to_string());
-                        }
+                    if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX)
+                        && name == lint_name
+                        && let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX)
+                    {
+                        lint.former_ids.insert(past_name.to_owned());
+                        writeln!(collected, "* `{past_name}`").unwrap();
+                        names.push(past_name.to_string());
                     }
                 }
 
@@ -927,20 +920,17 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
     }
 
     fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
-        if_chain! {
-            if let ExprKind::Path(qpath) = &expr.kind;
-            if let QPath::Resolved(_, path) = qpath;
-
-            let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
-            if match_type(self.cx, expr_ty, &paths::LINT);
-            then {
-                if let hir::def::Res::Def(DefKind::Static(..), _) = path.res {
-                    let lint_name = last_path_segment(qpath).ident.name;
-                    self.lints.push(sym_to_string(lint_name).to_ascii_lowercase());
-                } else if let Some(local) = get_parent_local(self.cx, expr) {
-                    if let Some(local_init) = local.init {
-                        intravisit::walk_expr(self, local_init);
-                    }
+        if let ExprKind::Path(qpath) = &expr.kind
+            && let QPath::Resolved(_, path) = qpath
+            && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr))
+            && match_type(self.cx, expr_ty, &paths::LINT)
+        {
+            if let hir::def::Res::Def(DefKind::Static(..), _) = path.res {
+                let lint_name = last_path_segment(qpath).ident.name;
+                self.lints.push(sym_to_string(lint_name).to_ascii_lowercase());
+            } else if let Some(local) = get_parent_local(self.cx, expr) {
+                if let Some(local_init) = local.init {
+                    intravisit::walk_expr(self, local_init);
                 }
             }
         }
@@ -992,13 +982,11 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
     fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
         let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
 
-        if_chain! {
-            if match_type(self.cx, expr_ty, &paths::APPLICABILITY);
-            if let Some(local) = get_parent_local(self.cx, expr);
-            if let Some(local_init) = local.init;
-            then {
-                intravisit::walk_expr(self, local_init);
-            }
+        if match_type(self.cx, expr_ty, &paths::APPLICABILITY)
+            && let Some(local) = get_parent_local(self.cx, expr)
+            && let Some(local_init) = local.init
+        {
+            intravisit::walk_expr(self, local_init);
         };
 
         intravisit::walk_expr(self, expr);
diff --git a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
index 86b77a77f17..86b1a0ae624 100644
--- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
@@ -2,7 +2,6 @@ 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 if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -22,40 +21,41 @@ declare_lint_pass!(MsrvAttrImpl => [MISSING_MSRV_ATTR_IMPL]);
 
 impl LateLintPass<'_> for MsrvAttrImpl {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if_chain! {
-            if let hir::ItemKind::Impl(hir::Impl {
-                of_trait: Some(_),
-                items,
-                ..
-            }) = &item.kind;
-            if let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::instantiate_identity);
-            let is_late_pass = match_def_path(cx, trait_ref.def_id, &paths::LATE_LINT_PASS);
-            if is_late_pass || match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS);
-            if let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind();
-            if self_ty_def.is_struct();
-            if self_ty_def.all_fields().any(|f| {
+        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)
+            && let is_late_pass = match_def_path(cx, trait_ref.def_id, &paths::LATE_LINT_PASS)
+            && (is_late_pass || 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))
-            });
-            if !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs));
-            then {
-                let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
-                let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
-                let span = cx.sess().source_map().span_through_char(item.span, '{');
-                span_lint_and_sugg(
-                    cx,
-                    MISSING_MSRV_ATTR_IMPL,
-                    span,
-                    &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"),
-                    &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"),
-                    format!("{}\n    extract_msrv_attr!({context});", snippet(cx, span, "..")),
-                    Applicability::MachineApplicable,
-                );
-            }
+            })
+            && !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs))
+        {
+            let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
+            let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
+            let span = cx.sess().source_map().span_through_char(item.span, '{');
+            span_lint_and_sugg(
+                cx,
+                MISSING_MSRV_ATTR_IMPL,
+                span,
+                &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"),
+                &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"),
+                format!("{}\n    extract_msrv_attr!({context});", 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
index 2b13fad8066..77b95e51f62 100644
--- a/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
+++ b/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::match_type;
 use clippy_utils::{is_lint_allowed, method_calls, paths};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
@@ -40,23 +39,21 @@ impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass {
 
         let (method_names, arg_lists, spans) = method_calls(expr, 2);
         let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect();
-        if_chain! {
-            if let ["expn_data", "outer_expn"] = method_names.as_slice();
-            let (self_arg, args) = arg_lists[1];
-            if args.is_empty();
-            let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
-            if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
-            then {
-                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,
-                );
-            }
+        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/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 81be04659b9..9aa23b6efe3 100644
--- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -1,7 +1,6 @@
 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 if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::Applicability;
@@ -102,108 +101,106 @@ impl UnnecessaryDefPath {
             &["clippy_utils", "is_expr_path_def_path"],
         ];
 
-        if_chain! {
-            if let [cx_arg, def_arg, args @ ..] = args;
-            if let ExprKind::Path(path) = &func.kind;
-            if let Some(id) = cx.qpath_res(path, func.hir_id).opt_def_id();
-            if let Some(which_path) = match_any_def_paths(cx, id, PATHS);
-            let item_arg = if which_path == 4 { &args[1] } else { &args[0] };
+        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
-            if let Some(segments) = path_to_matched_type(cx, item_arg);
-            let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect();
-            if let Some(def_id) = def_path_def_ids(cx, &segments[..]).next();
-            then {
-                // 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 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, &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 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,
+            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))",
                     ),
-                    _ => return,
-                };
+                    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",
-                        );
-                    }
-                });
+            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);
-            }
+            self.linted_def_ids.insert(def_id);
         }
     }
 
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index a9dd44afaf7..9ad2ad2d195 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -7,7 +7,6 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_copy;
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{get_parent_expr, higher, is_trait_method};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -72,21 +71,19 @@ fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 impl<'tcx> LateLintPass<'tcx> for UselessVec {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
-        if_chain! {
-            if adjusts_to_slice(cx, expr);
-            if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows());
-            then {
-                let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind {
-                    // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
-                    (SuggestedType::SliceRef(mutability), expr.span)
-                } else {
-                    // `expr` is the `vec![_]` expansion, so suggest `[_]`
-                    // and also use the span of the actual `vec![_]` expression
-                    (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site)
-                };
-
-                self.check_vec_macro(cx, &vec_args, span, suggest_slice);
-            }
+        if adjusts_to_slice(cx, expr)
+            && let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows())
+        {
+            let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind {
+                // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
+                (SuggestedType::SliceRef(mutability), expr.span)
+            } else {
+                // `expr` is the `vec![_]` expansion, so suggest `[_]`
+                // and also use the span of the actual `vec![_]` expression
+                (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site)
+            };
+
+            self.check_vec_macro(cx, &vec_args, span, suggest_slice);
         }
 
         // search for `let foo = vec![_]` expressions where all uses of `foo`
@@ -124,15 +121,13 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
         }
 
         // search for `for _ in vec![…]`
-        if_chain! {
-            if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr);
-            if let Some(vec_args) = higher::VecArgs::hir(cx, arg);
-            if self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR);
-            then {
-                // report the error around the `vec!` not inside `<std macros>:`
-                let span = arg.span.ctxt().outer_expn_data().call_site;
-                self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array);
-            }
+        if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr)
+            && let Some(vec_args) = higher::VecArgs::hir(cx, arg)
+            && self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR)
+        {
+            // report the error around the `vec!` not inside `<std macros>:`
+            let span = arg.span.ctxt().outer_expn_data().call_site;
+            self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array);
         }
     }
 
diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs
index d88ede76398..5c1bea74486 100644
--- a/clippy_lints/src/wildcard_imports.rs
+++ b/clippy_lints/src/wildcard_imports.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_test_module_or_function;
 use clippy_utils::source::{snippet, snippet_with_applicability};
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Item, ItemKind, PathSegment, UseKind};
@@ -127,70 +126,55 @@ impl LateLintPass<'_> for WildcardImports {
         if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
             return;
         }
-        if_chain! {
-            if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind;
-            if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
-            let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id);
-            if !used_imports.is_empty(); // Already handled by `unused_imports`
-            if !used_imports.contains(&kw::Underscore);
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability);
-                let (span, braced_glob) = if import_source_snippet.is_empty() {
-                    // This is a `_::{_, *}` import
-                    // In this case `use_path.span` is empty and ends directly in front of the `*`,
-                    // so we need to extend it by one byte.
-                    (
-                        use_path.span.with_hi(use_path.span.hi() + BytePos(1)),
-                        true,
-                    )
-                } else {
-                    // In this case, the `use_path.span` ends right before the `::*`, so we need to
-                    // extend it up to the `*`. Since it is hard to find the `*` in weird
-                    // formattings like `use _ ::  *;`, we extend it up to, but not including the
-                    // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
-                    // can just use the end of the item span
-                    let mut span = use_path.span.with_hi(item.span.hi());
-                    if snippet(cx, span, "").ends_with(';') {
-                        span = use_path.span.with_hi(item.span.hi() - BytePos(1));
-                    }
-                    (
-                        span, false,
-                    )
-                };
+        if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind
+            && (self.warn_on_all || !self.check_exceptions(item, use_path.segments))
+            && let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id)
+            && !used_imports.is_empty() // Already handled by `unused_imports`
+            && !used_imports.contains(&kw::Underscore)
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability);
+            let (span, braced_glob) = if import_source_snippet.is_empty() {
+                // This is a `_::{_, *}` import
+                // In this case `use_path.span` is empty and ends directly in front of the `*`,
+                // so we need to extend it by one byte.
+                (use_path.span.with_hi(use_path.span.hi() + BytePos(1)), true)
+            } else {
+                // In this case, the `use_path.span` ends right before the `::*`, so we need to
+                // extend it up to the `*`. Since it is hard to find the `*` in weird
+                // formattings like `use _ ::  *;`, we extend it up to, but not including the
+                // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
+                // can just use the end of the item span
+                let mut span = use_path.span.with_hi(item.span.hi());
+                if snippet(cx, span, "").ends_with(';') {
+                    span = use_path.span.with_hi(item.span.hi() - BytePos(1));
+                }
+                (span, false)
+            };
 
-                let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord();
-                let imports_string = if imports.len() == 1 {
-                    imports.pop().unwrap()
-                } else if braced_glob {
-                    imports.join(", ")
-                } else {
-                    format!("{{{}}}", imports.join(", "))
-                };
+            let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord();
+            let imports_string = if imports.len() == 1 {
+                imports.pop().unwrap()
+            } else if braced_glob {
+                imports.join(", ")
+            } else {
+                format!("{{{}}}", imports.join(", "))
+            };
 
-                let sugg = if braced_glob {
-                    imports_string
-                } else {
-                    format!("{import_source_snippet}::{imports_string}")
-                };
+            let sugg = if braced_glob {
+                imports_string
+            } else {
+                format!("{import_source_snippet}::{imports_string}")
+            };
 
-                // Glob imports always have a single resolution.
-                let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] {
-                    (ENUM_GLOB_USE, "usage of wildcard import for enum variants")
-                } else {
-                    (WILDCARD_IMPORTS, "usage of wildcard import")
-                };
+            // Glob imports always have a single resolution.
+            let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] {
+                (ENUM_GLOB_USE, "usage of wildcard import for enum variants")
+            } else {
+                (WILDCARD_IMPORTS, "usage of wildcard import")
+            };
 
-                span_lint_and_sugg(
-                    cx,
-                    lint,
-                    span,
-                    message,
-                    "try",
-                    sugg,
-                    applicability,
-                );
-            }
+            span_lint_and_sugg(cx, lint, span, message, "try", sugg, applicability);
         }
     }
 
diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs
index f2f0699ef48..1d6217d186c 100644
--- a/clippy_lints/src/zero_div_zero.rs
+++ b/clippy_lints/src/zero_div_zero.rs
@@ -1,6 +1,5 @@
 use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
-use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -32,35 +31,30 @@ declare_lint_pass!(ZeroDiv => [ZERO_DIVIDED_BY_ZERO]);
 impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         // check for instances of 0.0/0.0
-        if_chain! {
-            if let ExprKind::Binary(ref op, left, right) = expr.kind;
-            if op.node == BinOpKind::Div;
+        if let ExprKind::Binary(ref op, left, right) = expr.kind
+            && op.node == BinOpKind::Div
             // TODO - constant_simple does not fold many operations involving floats.
             // That's probably fine for this lint - it's pretty unlikely that someone would
             // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
-            if let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left);
-            if let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right);
-            if Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value;
-            if Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value;
-            then {
-                // since we're about to suggest a use of f32::NAN or f64::NAN,
-                // match the precision of the literals that are given.
-                let float_type = match (lhs_value, rhs_value) {
-                    (Constant::F64(_), _)
-                    | (_, Constant::F64(_)) => "f64",
-                    _ => "f32"
-                };
-                span_lint_and_help(
-                    cx,
-                    ZERO_DIVIDED_BY_ZERO,
-                    expr.span,
-                    "constant division of `0.0` with `0.0` will always result in NaN",
-                    None,
-                    &format!(
-                        "consider using `{float_type}::NAN` if you would like a constant representing NaN",
-                    ),
-                );
-            }
+            && let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left)
+            && let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right)
+            && (Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value)
+            && (Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value)
+        {
+            // since we're about to suggest a use of f32::NAN or f64::NAN,
+            // match the precision of the literals that are given.
+            let float_type = match (lhs_value, rhs_value) {
+                (Constant::F64(_), _) | (_, Constant::F64(_)) => "f64",
+                _ => "f32",
+            };
+            span_lint_and_help(
+                cx,
+                ZERO_DIVIDED_BY_ZERO,
+                expr.span,
+                "constant division of `0.0` with `0.0` will always result in NaN",
+                None,
+                &format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",),
+            );
         }
     }
 }
diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs
index fee100fe1ea..41c1757fde8 100644
--- a/clippy_lints/src/zero_sized_map_values.rs
+++ b/clippy_lints/src/zero_sized_map_values.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item};
-use if_chain::if_chain;
 use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
@@ -46,23 +45,28 @@ declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]);
 
 impl LateLintPass<'_> for ZeroSizedMapValues {
     fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
-        if_chain! {
-            if !hir_ty.span.from_expansion();
-            if !in_trait_impl(cx, hir_ty.hir_id);
-            let ty = ty_from_hir_ty(cx, hir_ty);
-            if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap);
-            if let Adt(_, args) = ty.kind();
-            let ty = args.type_at(1);
+        if !hir_ty.span.from_expansion()
+            && !in_trait_impl(cx, hir_ty.hir_id)
+            && let ty = ty_from_hir_ty(cx, hir_ty)
+            && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
+            && let Adt(_, args) = ty.kind()
+            && let ty = args.type_at(1)
             // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of
             // https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968
-            if !ty.has_escaping_bound_vars();
+            && !ty.has_escaping_bound_vars()
             // Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`.
-            if is_normalizable(cx, cx.param_env, ty);
-            if let Ok(layout) = cx.layout_of(ty);
-            if layout.is_zst();
-            then {
-                span_lint_and_help(cx, ZERO_SIZED_MAP_VALUES, hir_ty.span, "map with zero-sized value type", None, "consider using a set instead");
-            }
+            && is_normalizable(cx, cx.param_env, ty)
+            && let Ok(layout) = cx.layout_of(ty)
+            && layout.is_zst()
+        {
+            span_lint_and_help(
+                cx,
+                ZERO_SIZED_MAP_VALUES,
+                hir_ty.span,
+                "map with zero-sized value type",
+                None,
+                "consider using a set instead",
+            );
         }
     }
 }
diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml
index c9b01a68f42..1f9802dc5ee 100644
--- a/clippy_utils/Cargo.toml
+++ b/clippy_utils/Cargo.toml
@@ -7,7 +7,6 @@ publish = false
 [dependencies]
 clippy_config = { path = "../clippy_config" }
 arrayvec = { version = "0.7", default-features = false }
-if_chain = "1.0"
 itertools = "0.10.1"
 rustc-semver = "1.1"
 
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index b7d8c0a8fd7..3748e2a26d1 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -2,7 +2,7 @@
 
 use crate::source::{get_source_text, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
-use if_chain::if_chain;
+
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
@@ -372,27 +372,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
             ExprKind::Binary(op, left, right) => self.binop(op, left, right),
             ExprKind::Call(callee, args) => {
                 // We only handle a few const functions for now.
-                if_chain! {
-                    if args.is_empty();
-                    if let ExprKind::Path(qpath) = &callee.kind;
-                    let res = self.typeck_results.qpath_res(qpath, callee.hir_id);
-                    if let Some(def_id) = res.opt_def_id();
-                    let def_path = self.lcx.get_def_path(def_id);
-                    let def_path: Vec<&str> = def_path.iter().take(4).map(Symbol::as_str).collect();
-                    if let ["core", "num", int_impl, "max_value"] = *def_path;
-                    then {
-                        let value = match int_impl {
-                            "<impl i8>" => i8::MAX as u128,
-                            "<impl i16>" => i16::MAX as u128,
-                            "<impl i32>" => i32::MAX as u128,
-                            "<impl i64>" => i64::MAX as u128,
-                            "<impl i128>" => i128::MAX as u128,
-                            _ => return None,
-                        };
-                        Some(Constant::Int(value))
-                    } else {
-                        None
-                    }
+                if args.is_empty()
+                    && let ExprKind::Path(qpath) = &callee.kind
+                    && let res = self.typeck_results.qpath_res(qpath, callee.hir_id)
+                    && let Some(def_id) = res.opt_def_id()
+                    && let def_path = self.lcx.get_def_path(def_id)
+                    && let def_path = def_path.iter().take(4).map(Symbol::as_str).collect::<Vec<_>>()
+                    && let ["core", "num", int_impl, "max_value"] = *def_path
+                {
+                    let value = match int_impl {
+                        "<impl i8>" => i8::MAX as u128,
+                        "<impl i16>" => i16::MAX as u128,
+                        "<impl i32>" => i32::MAX as u128,
+                        "<impl i64>" => i64::MAX as u128,
+                        "<impl i128>" => i128::MAX as u128,
+                        _ => return None,
+                    };
+                    Some(Constant::Int(value))
+                } else {
+                    None
                 }
             },
             ExprKind::Index(arr, index, _) => self.index(arr, index),
diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs
index edea4b3667f..3135a033648 100644
--- a/clippy_utils/src/higher.rs
+++ b/clippy_utils/src/higher.rs
@@ -5,7 +5,7 @@
 use crate::consts::{constant_simple, Constant};
 use crate::ty::is_type_diagnostic_item;
 use crate::{is_expn_of, match_def_path, paths};
-use if_chain::if_chain;
+
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath};
@@ -30,24 +30,22 @@ pub struct ForLoop<'tcx> {
 impl<'tcx> ForLoop<'tcx> {
     /// Parses a desugared `for` loop
     pub fn hir(expr: &Expr<'tcx>) -> Option<Self> {
-        if_chain! {
-            if let hir::ExprKind::DropTemps(e) = expr.kind;
-            if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind;
-            if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind;
-            if let hir::ExprKind::Loop(block, ..) = arm.body.kind;
-            if let [stmt] = block.stmts;
-            if let hir::StmtKind::Expr(e) = stmt.kind;
-            if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind;
-            if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind;
-            then {
-                return Some(Self {
-                    pat: field.pat,
-                    arg,
-                    body: some_arm.body,
-                    loop_id: arm.body.hir_id,
-                    span: expr.span.ctxt().outer_expn_data().call_site,
-                });
-            }
+        if let hir::ExprKind::DropTemps(e) = expr.kind
+            && let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind
+            && let hir::ExprKind::Call(_, [arg]) = iterexpr.kind
+            && let hir::ExprKind::Loop(block, ..) = arm.body.kind
+            && let [stmt] = block.stmts
+            && let hir::StmtKind::Expr(e) = stmt.kind
+            && let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind
+            && let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind
+        {
+            return Some(Self {
+                pat: field.pat,
+                arg,
+                body: some_arm.body,
+                loop_id: arm.body.hir_id,
+                span: expr.span.ctxt().outer_expn_data().call_site,
+            });
         }
         None
     }
@@ -277,29 +275,28 @@ impl<'a> VecArgs<'a> {
     /// Returns the arguments of the `vec!` macro if this expression was expanded
     /// from `vec!`.
     pub fn hir(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option<VecArgs<'a>> {
-        if_chain! {
-            if let hir::ExprKind::Call(fun, args) = expr.kind;
-            if let hir::ExprKind::Path(ref qpath) = fun.kind;
-            if is_expn_of(fun.span, "vec").is_some();
-            if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
-            then {
-                return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
-                    // `vec![elem; size]` case
-                    Some(VecArgs::Repeat(&args[0], &args[1]))
-                } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
-                    // `vec![a, b, c]` case
-                    if let hir::ExprKind::Call(_, [arg]) = &args[0].kind
-                        && let hir::ExprKind::Array(args) = arg.kind {
-                        Some(VecArgs::Vec(args))
-                    } else {
-                        None
-                    }
-                } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
-                    Some(VecArgs::Vec(&[]))
+        if let hir::ExprKind::Call(fun, args) = expr.kind
+            && let hir::ExprKind::Path(ref qpath) = fun.kind
+            && is_expn_of(fun.span, "vec").is_some()
+            && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
+        {
+            return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
+                // `vec![elem; size]` case
+                Some(VecArgs::Repeat(&args[0], &args[1]))
+            } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
+                // `vec![a, b, c]` case
+                if let hir::ExprKind::Call(_, [arg]) = &args[0].kind
+                    && let hir::ExprKind::Array(args) = arg.kind
+                {
+                    Some(VecArgs::Vec(args))
                 } else {
                     None
-                };
-            }
+                }
+            } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
+                Some(VecArgs::Vec(&[]))
+            } else {
+                None
+            };
         }
 
         None
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 2a8b2ebd5fb..8031e6faa74 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -247,7 +247,7 @@ impl HirEqInterExpr<'_, '_, '_> {
         res
     }
 
-    #[expect(clippy::similar_names)]
+    #[expect(clippy::similar_names, clippy::too_many_lines)]
     pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
         if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) {
             return false;
@@ -271,9 +271,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
                 lb == rb && l_mut == r_mut && self.eq_expr(le, re)
             },
-            (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
-                both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
-            },
+            (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
             (&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => {
                 self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
             },
@@ -294,9 +292,15 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
                 self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
             },
-            (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) | (&ExprKind::Type(lx, lt), &ExprKind::Type(rx, rt)) => {
+            (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) => {
                 self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
             },
+            (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false,
+            (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
+            (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
+                both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
+            },
+            (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
             (&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => {
                 l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp)
             },
@@ -329,24 +333,70 @@ impl HirEqInterExpr<'_, '_, '_> {
                     && self.eq_expr(l_receiver, r_receiver)
                     && self.eq_exprs(l_args, r_args)
             },
+            (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
+                self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
+            },
+            (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
             (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
                 self.eq_expr(le, re) && self.eq_array_length(ll, rl)
             },
             (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l, r, |l, r| self.eq_expr(l, r)),
-            (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
             (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
                 self.eq_qpath(l_path, r_path)
                     && both(lo, ro, |l, r| self.eq_expr(l, r))
                     && over(lf, rf, |l, r| self.eq_expr_field(l, r))
             },
             (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
+            (&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
             (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
-            (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
-            (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
-            (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
-                self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
-            },
-            _ => false,
+            (&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
+            (
+                // Else branches for branches above, grouped as per `match_same_arms`.
+                | &ExprKind::AddrOf(..)
+                | &ExprKind::Array(..)
+                | &ExprKind::Assign(..)
+                | &ExprKind::AssignOp(..)
+                | &ExprKind::Binary(..)
+                | &ExprKind::Become(..)
+                | &ExprKind::Block(..)
+                | &ExprKind::Break(..)
+                | &ExprKind::Call(..)
+                | &ExprKind::Cast(..)
+                | &ExprKind::ConstBlock(..)
+                | &ExprKind::Continue(..)
+                | &ExprKind::DropTemps(..)
+                | &ExprKind::Field(..)
+                | &ExprKind::Index(..)
+                | &ExprKind::If(..)
+                | &ExprKind::Let(..)
+                | &ExprKind::Lit(..)
+                | &ExprKind::Loop(..)
+                | &ExprKind::Match(..)
+                | &ExprKind::MethodCall(..)
+                | &ExprKind::OffsetOf(..)
+                | &ExprKind::Path(..)
+                | &ExprKind::Repeat(..)
+                | &ExprKind::Ret(..)
+                | &ExprKind::Struct(..)
+                | &ExprKind::Tup(..)
+                | &ExprKind::Type(..)
+                | &ExprKind::Unary(..)
+                | &ExprKind::Yield(..)
+
+                // --- Special cases that do not have a positive branch.
+
+                // `Err` represents an invalid expression, so let's never assume that
+                // an invalid expressions is equal to anything.
+                | &ExprKind::Err(..)
+
+                // For the time being, we always consider that two closures are unequal.
+                // This behavior may change in the future.
+                | &ExprKind::Closure(..)
+                // For the time being, we always consider that two instances of InlineAsm are different.
+                // This behavior may change in the future.
+                | &ExprKind::InlineAsm(_)
+                , _
+            ) => false,
         };
         (is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
             || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right))
@@ -684,6 +734,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_name(i.ident.name);
                 }
             },
+            ExprKind::Array(v) => {
+                self.hash_exprs(v);
+            },
             ExprKind::Assign(l, r, _) => {
                 self.hash_expr(l);
                 self.hash_expr(r);
@@ -693,6 +746,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(l);
                 self.hash_expr(r);
             },
+            ExprKind::Become(f) => {
+                self.hash_expr(f);
+            },
             ExprKind::Block(b, _) => {
                 self.hash_block(b);
             },
@@ -709,9 +765,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_expr(j);
                 }
             },
-            ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
-                self.hash_expr(e);
-            },
             ExprKind::Call(fun, args) => {
                 self.hash_expr(fun);
                 self.hash_exprs(args);
@@ -727,6 +780,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 // closures inherit TypeckResults
                 self.hash_expr(self.cx.tcx.hir().body(body).value);
             },
+            ExprKind::ConstBlock(ref l_id) => {
+                self.hash_body(l_id.body);
+            },
+            ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
+                self.hash_expr(e);
+            },
             ExprKind::Field(e, ref f) => {
                 self.hash_expr(e);
                 self.hash_name(f.name);
@@ -788,12 +847,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     }
                 }
             },
-            ExprKind::OffsetOf(container, fields) => {
-                self.hash_ty(container);
-                for field in fields {
-                    self.hash_name(field.name);
-                }
-            },
             ExprKind::Let(Let { pat, init, ty, .. }) => {
                 self.hash_expr(init);
                 if let Some(ty) = ty {
@@ -801,7 +854,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 }
                 self.hash_pat(pat);
             },
-            ExprKind::Err(_) => {},
             ExprKind::Lit(l) => {
                 l.node.hash(&mut self.s);
             },
@@ -836,8 +888,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_expr(receiver);
                 self.hash_exprs(args);
             },
-            ExprKind::ConstBlock(ref l_id) => {
-                self.hash_body(l_id.body);
+            ExprKind::OffsetOf(container, fields) => {
+                self.hash_ty(container);
+                for field in fields {
+                    self.hash_name(field.name);
+                }
+            },
+            ExprKind::Path(ref qpath) => {
+                self.hash_qpath(qpath);
             },
             ExprKind::Repeat(e, len) => {
                 self.hash_expr(e);
@@ -848,12 +906,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_expr(e);
                 }
             },
-            ExprKind::Become(f) => {
-                self.hash_expr(f);
-            },
-            ExprKind::Path(ref qpath) => {
-                self.hash_qpath(qpath);
-            },
             ExprKind::Struct(path, fields, ref expr) => {
                 self.hash_qpath(path);
 
@@ -869,13 +921,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             ExprKind::Tup(tup) => {
                 self.hash_exprs(tup);
             },
-            ExprKind::Array(v) => {
-                self.hash_exprs(v);
-            },
             ExprKind::Unary(lop, le) => {
                 std::mem::discriminant(&lop).hash(&mut self.s);
                 self.hash_expr(le);
             },
+            ExprKind::Err(_) => {},
         }
     }
 
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 1181dfc0ef9..2445c4e0672 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -71,12 +71,12 @@ pub use self::hir_utils::{
     both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
 };
 
+use core::mem;
 use core::ops::ControlFlow;
 use std::collections::hash_map::Entry;
 use std::hash::BuildHasherDefault;
 use std::sync::{Mutex, MutexGuard, OnceLock};
 
-use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_data_structures::fx::FxHashMap;
@@ -176,14 +176,12 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr
 /// canonical binding `HirId`.
 pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
     let hir = cx.tcx.hir();
-    if_chain! {
-        if let Some(Node::Pat(pat)) = hir.find(hir_id);
-        if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..));
-        let parent = hir.parent_id(hir_id);
-        if let Some(Node::Local(local)) = hir.find(parent);
-        then {
-            return local.init;
-        }
+    if let Some(Node::Pat(pat)) = hir.find(hir_id)
+        && matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..))
+        && let parent = hir.parent_id(hir_id)
+        && let Some(Node::Local(local)) = hir.find(parent)
+    {
+        return local.init;
     }
     None
 }
@@ -713,13 +711,11 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) ->
     // Get the implemented trait for the current function
     let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
     let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
-    if_chain! {
-        if parent_impl != hir::CRATE_OWNER_ID;
-        if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id);
-        if let hir::ItemKind::Impl(impl_) = &item.kind;
-        then {
-            return impl_.of_trait.as_ref();
-        }
+    if parent_impl != hir::CRATE_OWNER_ID
+        && let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id)
+        && let hir::ItemKind::Impl(impl_) = &item.kind
+    {
+        return impl_.of_trait.as_ref();
     }
     None
 }
@@ -823,12 +819,14 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
 
 /// Returns true if the expr is equal to `Default::default` when evaluated.
 pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool {
-    if_chain! {
-        if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
-        if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
-        if is_diag_trait_item(cx, repl_def_id, sym::Default)
-            || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
-        then { true } else { false }
+    if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind
+        && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id()
+        && (is_diag_trait_item(cx, repl_def_id, sym::Default)
+            || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath))
+    {
+        true
+    } else {
+        false
     }
 }
 
@@ -843,14 +841,14 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
             _ => false,
         },
         ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
-        ExprKind::Repeat(x, ArrayLen::Body(len)) => if_chain! {
-            if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind;
-            if let LitKind::Int(v, _) = const_lit.node;
-            if v <= 32 && is_default_equivalent(cx, x);
-            then {
+        ExprKind::Repeat(x, ArrayLen::Body(len)) => {
+            if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
+                && let LitKind::Int(v, _) = const_lit.node
+                && v <= 32
+                && is_default_equivalent(cx, x)
+            {
                 true
-            }
-            else {
+            } else {
                 false
             }
         },
@@ -1736,15 +1734,13 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It
 /// operator or the `try` macro.
 pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
-        if_chain! {
-            if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
-            if ddpos.as_opt_usize().is_none();
-            if is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk);
-            if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
-            if path_to_local_id(arm.body, hir_id);
-            then {
-                return true;
-            }
+        if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind
+            && ddpos.as_opt_usize().is_none()
+            && is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk)
+            && let PatKind::Binding(_, hir_id, _, None) = pat[0].kind
+            && path_to_local_id(arm.body, hir_id)
+        {
+            return true;
         }
         false
     }
@@ -1763,14 +1759,12 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
             return Some(expr);
         }
 
-        if_chain! {
-            if arms.len() == 2;
-            if arms[0].guard.is_none();
-            if arms[1].guard.is_none();
-            if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || (is_ok(cx, &arms[1]) && is_err(cx, &arms[0]));
-            then {
-                return Some(expr);
-            }
+        if arms.len() == 2
+            && arms[0].guard.is_none()
+            && arms[1].guard.is_none()
+            && ((is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || (is_ok(cx, &arms[1]) && is_err(cx, &arms[0])))
+        {
+            return Some(expr);
         }
     }
 
@@ -1887,14 +1881,12 @@ pub fn match_function_call<'tcx>(
     expr: &'tcx Expr<'_>,
     path: &[&str],
 ) -> Option<&'tcx [Expr<'tcx>]> {
-    if_chain! {
-        if let ExprKind::Call(fun, args) = expr.kind;
-        if let ExprKind::Path(ref qpath) = fun.kind;
-        if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
-        if match_def_path(cx, fun_def_id, path);
-        then {
-            return Some(args);
-        }
+    if let ExprKind::Call(fun, args) = expr.kind
+        && let ExprKind::Path(ref qpath) = fun.kind
+        && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
+        && match_def_path(cx, fun_def_id, path)
+    {
+        return Some(args);
     };
     None
 }
@@ -1904,13 +1896,11 @@ pub fn match_function_call_with_def_id<'tcx>(
     expr: &'tcx Expr<'_>,
     fun_def_id: DefId,
 ) -> Option<&'tcx [Expr<'tcx>]> {
-    if_chain! {
-        if let ExprKind::Call(fun, args) = expr.kind;
-        if let ExprKind::Path(ref qpath) = fun.kind;
-        if cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id);
-        then {
-            return Some(args);
-        }
+    if let ExprKind::Call(fun, args) = expr.kind
+        && let ExprKind::Path(ref qpath) = fun.kind
+        && cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id)
+    {
+        return Some(args);
     };
     None
 }
@@ -2008,10 +1998,10 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t
 // check if expr is calling method or function with #[must_use] attribute
 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let did = match expr.kind {
-        ExprKind::Call(path, _) => if_chain! {
-            if let ExprKind::Path(ref qpath) = path.kind;
-            if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
-            then {
+        ExprKind::Call(path, _) => {
+            if let ExprKind::Path(ref qpath) = path.kind
+                && let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id)
+            {
                 Some(did)
             } else {
                 None
@@ -2034,6 +2024,18 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 /// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
 fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
     fn check_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
+        if cx
+            .typeck_results()
+            .pat_binding_modes()
+            .get(pat.hir_id)
+            .is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_)))
+        {
+            // If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics,
+            // the inner patterns become references. Don't consider this the identity function
+            // as that changes types.
+            return false;
+        }
+
         match (pat.kind, expr.kind) {
             (PatKind::Binding(_, id, _, _), _) => {
                 path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty()
@@ -2071,14 +2073,12 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
                 },
                 _,
             ) => {
-                if_chain! {
-                    if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
-                    if let ExprKind::Ret(Some(ret_val)) = e.kind;
-                    then {
-                        expr = ret_val;
-                    } else {
-                        return false;
-                    }
+                if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind
+                    && let ExprKind::Ret(Some(ret_val)) = e.kind
+                {
+                    expr = ret_val;
+                } else {
+                    return false;
                 }
             },
             _ => return check_pat(cx, param.pat, expr),
@@ -2974,3 +2974,248 @@ pub fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: i
         _ => false,
     }
 }
+
+#[derive(Clone, Copy)]
+pub enum RequiresSemi {
+    Yes,
+    No,
+}
+impl RequiresSemi {
+    pub fn requires_semi(self) -> bool {
+        matches!(self, Self::Yes)
+    }
+}
+
+/// Check if the expression return `!`, a type coerced from `!`, or could return `!` if the final
+/// expression were turned into a statement.
+#[expect(clippy::too_many_lines)]
+pub fn is_never_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<RequiresSemi> {
+    struct BreakTarget {
+        id: HirId,
+        unused: bool,
+    }
+
+    struct V<'cx, 'tcx> {
+        cx: &'cx LateContext<'tcx>,
+        break_targets: Vec<BreakTarget>,
+        break_targets_for_result_ty: u32,
+        in_final_expr: bool,
+        requires_semi: bool,
+        is_never: bool,
+    }
+
+    impl<'tcx> V<'_, 'tcx> {
+        fn push_break_target(&mut self, id: HirId) {
+            self.break_targets.push(BreakTarget { id, unused: true });
+            self.break_targets_for_result_ty += u32::from(self.in_final_expr);
+        }
+    }
+
+    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
+        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
+            // Note: Part of the complexity here comes from the fact that
+            // coercions are applied to the innermost expression.
+            // e.g. In `let x: u32 = { break () };` the never-to-any coercion
+            // is applied to the break expression. This means we can't just
+            // check the block's type as it will be `u32` despite the fact
+            // that the block always diverges.
+
+            // The rest of the complexity comes from checking blocks which
+            // syntactically return a value, but will always diverge before
+            // reaching that point.
+            // e.g. In `let x = { foo(panic!()) };` the block's type will be the
+            // return type of `foo` even though it will never actually run. This
+            // can be trivially fixed by adding a semicolon after the call, but
+            // we must first detect that a semicolon is needed to make that
+            // suggestion.
+
+            if self.is_never && self.break_targets.is_empty() {
+                if self.in_final_expr && !self.requires_semi {
+                    // This expression won't ever run, but we still need to check
+                    // if it can affect the type of the final expression.
+                    match e.kind {
+                        ExprKind::DropTemps(e) => self.visit_expr(e),
+                        ExprKind::If(_, then, Some(else_)) => {
+                            self.visit_expr(then);
+                            self.visit_expr(else_);
+                        },
+                        ExprKind::Match(_, arms, _) => {
+                            for arm in arms {
+                                self.visit_expr(arm.body);
+                            }
+                        },
+                        ExprKind::Loop(b, ..) => {
+                            self.push_break_target(e.hir_id);
+                            self.in_final_expr = false;
+                            self.visit_block(b);
+                            self.break_targets.pop();
+                        },
+                        ExprKind::Block(b, _) => {
+                            if b.targeted_by_break {
+                                self.push_break_target(b.hir_id);
+                                self.visit_block(b);
+                                self.break_targets.pop();
+                            } else {
+                                self.visit_block(b);
+                            }
+                        },
+                        _ => {
+                            self.requires_semi = !self.cx.typeck_results().expr_ty(e).is_never();
+                        },
+                    }
+                }
+                return;
+            }
+            match e.kind {
+                ExprKind::DropTemps(e) => self.visit_expr(e),
+                ExprKind::Ret(None) | ExprKind::Continue(_) => self.is_never = true,
+                ExprKind::Ret(Some(e)) | ExprKind::Become(e) => {
+                    self.in_final_expr = false;
+                    self.visit_expr(e);
+                    self.is_never = true;
+                },
+                ExprKind::Break(dest, e) => {
+                    if let Some(e) = e {
+                        self.in_final_expr = false;
+                        self.visit_expr(e);
+                    }
+                    if let Ok(id) = dest.target_id
+                        && let Some((i, target)) = self
+                            .break_targets
+                            .iter_mut()
+                            .enumerate()
+                            .find(|(_, target)| target.id == id)
+                    {
+                        target.unused &= self.is_never;
+                        if i < self.break_targets_for_result_ty as usize {
+                            self.requires_semi = true;
+                        }
+                    }
+                    self.is_never = true;
+                },
+                ExprKind::If(cond, then, else_) => {
+                    let in_final_expr = mem::replace(&mut self.in_final_expr, false);
+                    self.visit_expr(cond);
+                    self.in_final_expr = in_final_expr;
+
+                    if self.is_never {
+                        self.visit_expr(then);
+                        if let Some(else_) = else_ {
+                            self.visit_expr(else_);
+                        }
+                    } else {
+                        self.visit_expr(then);
+                        let is_never = mem::replace(&mut self.is_never, false);
+                        if let Some(else_) = else_ {
+                            self.visit_expr(else_);
+                            self.is_never &= is_never;
+                        }
+                    }
+                },
+                ExprKind::Match(scrutinee, arms, _) => {
+                    let in_final_expr = mem::replace(&mut self.in_final_expr, false);
+                    self.visit_expr(scrutinee);
+                    self.in_final_expr = in_final_expr;
+
+                    if self.is_never {
+                        for arm in arms {
+                            self.visit_arm(arm);
+                        }
+                    } else {
+                        let mut is_never = true;
+                        for arm in arms {
+                            self.is_never = false;
+                            if let Some(guard) = arm.guard {
+                                let in_final_expr = mem::replace(&mut self.in_final_expr, false);
+                                self.visit_expr(guard.body());
+                                self.in_final_expr = in_final_expr;
+                                // The compiler doesn't consider diverging guards as causing the arm to diverge.
+                                self.is_never = false;
+                            }
+                            self.visit_expr(arm.body);
+                            is_never &= self.is_never;
+                        }
+                        self.is_never = is_never;
+                    }
+                },
+                ExprKind::Loop(b, _, _, _) => {
+                    self.push_break_target(e.hir_id);
+                    self.in_final_expr = false;
+                    self.visit_block(b);
+                    self.is_never = self.break_targets.pop().unwrap().unused;
+                },
+                ExprKind::Block(b, _) => {
+                    if b.targeted_by_break {
+                        self.push_break_target(b.hir_id);
+                        self.visit_block(b);
+                        self.is_never &= self.break_targets.pop().unwrap().unused;
+                    } else {
+                        self.visit_block(b);
+                    }
+                },
+                _ => {
+                    self.in_final_expr = false;
+                    walk_expr(self, e);
+                    self.is_never |= self.cx.typeck_results().expr_ty(e).is_never();
+                },
+            }
+        }
+
+        fn visit_block(&mut self, b: &'tcx Block<'_>) {
+            let in_final_expr = mem::replace(&mut self.in_final_expr, false);
+            for s in b.stmts {
+                self.visit_stmt(s);
+            }
+            self.in_final_expr = in_final_expr;
+            if let Some(e) = b.expr {
+                self.visit_expr(e);
+            }
+        }
+
+        fn visit_local(&mut self, l: &'tcx Local<'_>) {
+            if let Some(e) = l.init {
+                self.visit_expr(e);
+            }
+            if let Some(else_) = l.els {
+                let is_never = self.is_never;
+                self.visit_block(else_);
+                self.is_never = is_never;
+            }
+        }
+
+        fn visit_arm(&mut self, arm: &Arm<'tcx>) {
+            if let Some(guard) = arm.guard {
+                let in_final_expr = mem::replace(&mut self.in_final_expr, false);
+                self.visit_expr(guard.body());
+                self.in_final_expr = in_final_expr;
+            }
+            self.visit_expr(arm.body);
+        }
+    }
+
+    if cx.typeck_results().expr_ty(e).is_never() {
+        Some(RequiresSemi::No)
+    } else if let ExprKind::Block(b, _) = e.kind
+        && !b.targeted_by_break
+        && b.expr.is_none()
+    {
+        // If a block diverges without a final expression then it's type is `!`.
+        None
+    } else {
+        let mut v = V {
+            cx,
+            break_targets: Vec::new(),
+            break_targets_for_result_ty: 0,
+            in_final_expr: true,
+            requires_semi: false,
+            is_never: false,
+        };
+        v.visit_expr(e);
+        v.is_never
+            .then_some(if v.requires_semi && matches!(e.kind, ExprKind::Block(..)) {
+                RequiresSemi::Yes
+            } else {
+                RequiresSemi::No
+            })
+    }
+}
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 5bca554378e..859bffd6c9c 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -99,3 +99,4 @@ pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
 pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
 #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so
 pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
+pub const ALLOCATOR_GLOBAL: [&str; 3] = ["alloc", "alloc", "Global"];
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 842a206f96b..4d50242d81d 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -1276,3 +1276,8 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>
         Err(_) => ty,
     }
 }
+
+/// Checks if the type is `core::mem::ManuallyDrop<_>`
+pub fn is_manually_drop(ty: Ty<'_>) -> bool {
+    ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop)
+}
diff --git a/src/driver.rs b/src/driver.rs
index 7bb49d08da6..1ae8ac81695 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -148,7 +148,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
             }
 
             let conf = clippy_config::Conf::read(sess, &conf_path);
-            clippy_lints::register_plugins(lint_store, sess, conf);
+            clippy_lints::register_lints(lint_store, conf);
             clippy_lints::register_pre_expansion_lints(lint_store, conf);
             clippy_lints::register_renamed(lint_store);
         }));
diff --git a/tests/ui-internal/if_chain_style.rs b/tests/ui-internal/if_chain_style.rs
deleted file mode 100644
index b462b20e04c..00000000000
--- a/tests/ui-internal/if_chain_style.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-#![warn(clippy::if_chain_style)]
-#![allow(
-    clippy::needless_if,
-    clippy::no_effect,
-    clippy::nonminimal_bool,
-    clippy::missing_clippy_version_attribute
-)]
-
-extern crate if_chain;
-
-use if_chain::if_chain;
-
-fn main() {
-    if true {
-        let x = "";
-        // `if_chain!` inside `if`
-        if_chain! {
-            if true;
-            if true;
-            then {}
-        }
-    }
-    if_chain! {
-        if true
-            // multi-line AND'ed conditions
-            && false;
-        if let Some(1) = Some(1);
-        // `let` before `then`
-        let x = "";
-        then {
-            ();
-        }
-    }
-    if_chain! {
-        // single `if` condition
-        if true;
-        then {
-            let x = "";
-            // nested if
-            if true {}
-        }
-    }
-    if_chain! {
-        // starts with `let ..`
-        let x = "";
-        if let Some(1) = Some(1);
-        then {
-            let x = "";
-            let x = "";
-            // nested if_chain!
-            if_chain! {
-                if true;
-                if true;
-                then {}
-            }
-        }
-    }
-}
-
-fn negative() {
-    if true {
-        ();
-        if_chain! {
-            if true;
-            if true;
-            then { (); }
-        }
-    }
-    if_chain! {
-        if true;
-        let x = "";
-        if true;
-        then { (); }
-    }
-    if_chain! {
-        if true;
-        if true;
-        then {
-            if true { 1 } else { 2 }
-        } else {
-            3
-        }
-    };
-    if true {
-        if_chain! {
-            if true;
-            if true;
-            then {}
-        }
-    } else if false {
-        if_chain! {
-            if true;
-            if false;
-            then {}
-        }
-    }
-}
diff --git a/tests/ui-internal/if_chain_style.stderr b/tests/ui-internal/if_chain_style.stderr
deleted file mode 100644
index ea04955323d..00000000000
--- a/tests/ui-internal/if_chain_style.stderr
+++ /dev/null
@@ -1,86 +0,0 @@
-error: this `if` can be part of the inner `if_chain!`
-  --> $DIR/if_chain_style.rs:14:5
-   |
-LL | /     if true {
-LL | |         let x = "";
-LL | |         // `if_chain!` inside `if`
-LL | |         if_chain! {
-...  |
-LL | |         }
-LL | |     }
-   | |_____^
-   |
-help: this `let` statement can also be in the `if_chain!`
-  --> $DIR/if_chain_style.rs:15:9
-   |
-LL |         let x = "";
-   |         ^^^^^^^^^^^
-   = note: `-D clippy::if-chain-style` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::if_chain_style)]`
-
-error: `if a && b;` should be `if a; if b;`
-  --> $DIR/if_chain_style.rs:24:12
-   |
-LL |           if true
-   |  ____________^
-LL | |             // multi-line AND'ed conditions
-LL | |             && false;
-   | |____________________^
-
-error: `let` expression should be inside `then { .. }`
-  --> $DIR/if_chain_style.rs:29:9
-   |
-LL |         let x = "";
-   |         ^^^^^^^^^^^
-
-error: this `if` can be part of the outer `if_chain!`
-  --> $DIR/if_chain_style.rs:40:13
-   |
-LL |             if true {}
-   |             ^^^^^^^^^^
-   |
-help: this `let` statement can also be in the `if_chain!`
-  --> $DIR/if_chain_style.rs:38:13
-   |
-LL |             let x = "";
-   |             ^^^^^^^^^^^
-
-error: `if_chain!` only has one `if`
-  --> $DIR/if_chain_style.rs:34:5
-   |
-LL | /     if_chain! {
-LL | |         // single `if` condition
-LL | |         if true;
-LL | |         then {
-...  |
-LL | |         }
-LL | |     }
-   | |_____^
-   |
-   = note: this error originates in the macro `__if_chain` which comes from the expansion of the macro `if_chain` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: `let` expression should be above the `if_chain!`
-  --> $DIR/if_chain_style.rs:45:9
-   |
-LL |         let x = "";
-   |         ^^^^^^^^^^^
-
-error: this `if_chain!` can be merged with the outer `if_chain!`
-  --> $DIR/if_chain_style.rs:51:13
-   |
-LL | /             if_chain! {
-LL | |                 if true;
-LL | |                 if true;
-LL | |                 then {}
-LL | |             }
-   | |_____________^
-   |
-help: these `let` statements can also be in the `if_chain!`
-  --> $DIR/if_chain_style.rs:48:13
-   |
-LL | /             let x = "";
-LL | |             let x = "";
-   | |_______________________^
-
-error: aborting due to 7 previous errors
-
diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs
index d03a577c454..349e81912e3 100644
--- a/tests/ui/arc_with_non_send_sync.rs
+++ b/tests/ui/arc_with_non_send_sync.rs
@@ -33,16 +33,16 @@ fn main() {
     let _ = Arc::new(42);
 
     let _ = Arc::new(RefCell::new(42));
-    //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync`
+    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
     //~| NOTE: the trait `Sync` is not implemented for `RefCell<i32>`
 
     let mutex = Mutex::new(1);
     let _ = Arc::new(mutex.lock().unwrap());
-    //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync`
+    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
     //~| NOTE: the trait `Send` is not implemented for `MutexGuard<'_, i32>`
 
     let _ = Arc::new(&42 as *const i32);
-    //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync`
+    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
     //~| NOTE: the trait `Send` is not implemented for `*const i32`
     //~| NOTE: the trait `Sync` is not implemented for `*const i32`
 }
diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr
index fd239580d28..a7f91abda4e 100644
--- a/tests/ui/arc_with_non_send_sync.stderr
+++ b/tests/ui/arc_with_non_send_sync.stderr
@@ -1,35 +1,41 @@
-error: usage of an `Arc` that is not `Send` or `Sync`
+error: usage of an `Arc` that is not `Send` and `Sync`
   --> $DIR/arc_with_non_send_sync.rs:35:13
    |
 LL |     let _ = Arc::new(RefCell::new(42));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the trait `Sync` is not implemented for `RefCell<i32>`
-   = note: required for `Arc<RefCell<i32>>` to implement `Send` and `Sync`
-   = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
+   = note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as:
+   = note: - the trait `Sync` is not implemented for `RefCell<i32>`
+   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
+   = note: if you intend to use `Arc` with `Send` and `Sync` traits
+   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `RefCell<i32>`
    = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]`
 
-error: usage of an `Arc` that is not `Send` or `Sync`
+error: usage of an `Arc` that is not `Send` and `Sync`
   --> $DIR/arc_with_non_send_sync.rs:40:13
    |
 LL |     let _ = Arc::new(mutex.lock().unwrap());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the trait `Send` is not implemented for `MutexGuard<'_, i32>`
-   = note: required for `Arc<MutexGuard<'_, i32>>` to implement `Send` and `Sync`
-   = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
+   = note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as:
+   = note: - the trait `Send` is not implemented for `MutexGuard<'_, i32>`
+   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
+   = note: if you intend to use `Arc` with `Send` and `Sync` traits
+   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `MutexGuard<'_, i32>`
 
-error: usage of an `Arc` that is not `Send` or `Sync`
+error: usage of an `Arc` that is not `Send` and `Sync`
   --> $DIR/arc_with_non_send_sync.rs:44:13
    |
 LL |     let _ = Arc::new(&42 as *const i32);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the trait `Send` is not implemented for `*const i32`
-   = note: the trait `Sync` is not implemented for `*const i32`
-   = note: required for `Arc<*const i32>` to implement `Send` and `Sync`
-   = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
+   = note: `Arc<*const i32>` is not `Send` and `Sync` as:
+   = note: - the trait `Send` is not implemented for `*const i32`
+   = note: - the trait `Sync` is not implemented for `*const i32`
+   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
+   = note: if you intend to use `Arc` with `Send` and `Sync` traits
+   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `*const i32`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed
index 12158d0d12a..e6ca4bb66cc 100644
--- a/tests/ui/explicit_auto_deref.fixed
+++ b/tests/ui/explicit_auto_deref.fixed
@@ -301,24 +301,47 @@ fn main() {
     };
 
     // Issue #11474
-    pub struct Variant {
-        pub anonymous: Variant0,
+    #[derive(Clone, Copy)]
+    struct Wrap<T>(T);
+    impl<T> core::ops::Deref for Wrap<T> {
+        type Target = T;
+        fn deref(&self) -> &T {
+            &self.0
+        }
     }
-
-    pub union Variant0 {
-        pub anonymous: std::mem::ManuallyDrop<Variant00>,
+    impl<T> core::ops::DerefMut for Wrap<T> {
+        fn deref_mut(&mut self) -> &mut T {
+            &mut self.0
+        }
     }
 
-    pub struct Variant00 {
-        pub anonymous: Variant000,
+    union U<T: Copy> {
+        u: T,
     }
 
-    pub union Variant000 {
-        pub val: i32,
+    #[derive(Clone, Copy)]
+    struct S8 {
+        x: &'static str,
     }
 
     unsafe {
-        let mut p = core::mem::zeroed::<Variant>();
-        (*p.anonymous.anonymous).anonymous.val = 1;
+        let mut x = U {
+            u: core::mem::ManuallyDrop::new(S8 { x: "" }),
+        };
+        let _ = &mut (*x.u).x;
+        let _ = &mut { x.u }.x;
+        let _ = &mut ({ *x.u }).x;
+
+        let mut x = U {
+            u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })),
+        };
+        let _ = &mut (*x.u).x;
+        let _ = &mut { x.u }.x;
+        let _ = &mut ({ **x.u }).x;
+
+        let mut x = U { u: Wrap(S8 { x: "" }) };
+        let _ = &mut x.u.x;
+        let _ = &mut { x.u }.x;
+        let _ = &mut ({ *x.u }).x;
     }
 }
diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs
index dec021c1834..7531e1f87b7 100644
--- a/tests/ui/explicit_auto_deref.rs
+++ b/tests/ui/explicit_auto_deref.rs
@@ -301,24 +301,47 @@ fn main() {
     };
 
     // Issue #11474
-    pub struct Variant {
-        pub anonymous: Variant0,
+    #[derive(Clone, Copy)]
+    struct Wrap<T>(T);
+    impl<T> core::ops::Deref for Wrap<T> {
+        type Target = T;
+        fn deref(&self) -> &T {
+            &self.0
+        }
     }
-
-    pub union Variant0 {
-        pub anonymous: std::mem::ManuallyDrop<Variant00>,
+    impl<T> core::ops::DerefMut for Wrap<T> {
+        fn deref_mut(&mut self) -> &mut T {
+            &mut self.0
+        }
     }
 
-    pub struct Variant00 {
-        pub anonymous: Variant000,
+    union U<T: Copy> {
+        u: T,
     }
 
-    pub union Variant000 {
-        pub val: i32,
+    #[derive(Clone, Copy)]
+    struct S8 {
+        x: &'static str,
     }
 
     unsafe {
-        let mut p = core::mem::zeroed::<Variant>();
-        (*p.anonymous.anonymous).anonymous.val = 1;
+        let mut x = U {
+            u: core::mem::ManuallyDrop::new(S8 { x: "" }),
+        };
+        let _ = &mut (*x.u).x;
+        let _ = &mut (*{ x.u }).x;
+        let _ = &mut ({ *x.u }).x;
+
+        let mut x = U {
+            u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })),
+        };
+        let _ = &mut (**x.u).x;
+        let _ = &mut (**{ x.u }).x;
+        let _ = &mut ({ **x.u }).x;
+
+        let mut x = U { u: Wrap(S8 { x: "" }) };
+        let _ = &mut (*x.u).x;
+        let _ = &mut (*{ x.u }).x;
+        let _ = &mut ({ *x.u }).x;
     }
 }
diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr
index 3d2a7b0d9f4..cc9eeeb5042 100644
--- a/tests/ui/explicit_auto_deref.stderr
+++ b/tests/ui/explicit_auto_deref.stderr
@@ -241,5 +241,35 @@ error: deref which would be done by auto-deref
 LL |         Some(x) => &mut *x,
    |                    ^^^^^^^ help: try: `x`
 
-error: aborting due to 40 previous errors
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:332:22
+   |
+LL |         let _ = &mut (*{ x.u }).x;
+   |                      ^^^^^^^^^^ help: try: `{ x.u }`
+
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:338:22
+   |
+LL |         let _ = &mut (**x.u).x;
+   |                      ^^^^^^^ help: try: `(*x.u)`
+
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:339:22
+   |
+LL |         let _ = &mut (**{ x.u }).x;
+   |                      ^^^^^^^^^^^ help: try: `{ x.u }`
+
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:343:22
+   |
+LL |         let _ = &mut (*x.u).x;
+   |                      ^^^^^^ help: try: `x.u`
+
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:344:22
+   |
+LL |         let _ = &mut (*{ x.u }).x;
+   |                      ^^^^^^^^^^ help: try: `{ x.u }`
+
+error: aborting due to 45 previous errors
 
diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs
index 27717ab3a73..5d94660ec89 100644
--- a/tests/ui/manual_let_else.rs
+++ b/tests/ui/manual_let_else.rs
@@ -5,7 +5,9 @@
     clippy::let_unit_value,
     clippy::match_single_binding,
     clippy::never_loop,
-    clippy::needless_if
+    clippy::needless_if,
+    clippy::diverging_sub_expression,
+    clippy::single_match
 )]
 #![warn(clippy::manual_let_else)]
 //@no-rustfix
@@ -24,7 +26,7 @@ fn main() {}
 fn fire() {
     let v = if let Some(v_some) = g() { v_some } else { return };
     //~^ ERROR: this could be rewritten as `let...else`
-    //~| NOTE: `-D clippy::manual-let-else` implied by `-D warnings`
+
     let v = if let Some(v_some) = g() {
         //~^ ERROR: this could be rewritten as `let...else`
         v_some
@@ -79,22 +81,76 @@ fn fire() {
         panic!();
     };
 
+    // The final expression will need to be turned into a statement.
+    let v = if let Some(v_some) = g() {
+        //~^ ERROR: this could be rewritten as `let...else`
+        v_some
+    } else {
+        panic!();
+        ()
+    };
+
+    // Even if the result is buried multiple expressions deep.
+    let v = if let Some(v_some) = g() {
+        //~^ ERROR: this could be rewritten as `let...else`
+        v_some
+    } else {
+        panic!();
+        if true {
+            match 0 {
+                0 => (),
+                _ => (),
+            }
+        } else {
+            panic!()
+        }
+    };
+
+    // Or if a break gives the value.
+    let v = if let Some(v_some) = g() {
+        //~^ ERROR: this could be rewritten as `let...else`
+        v_some
+    } else {
+        loop {
+            panic!();
+            break ();
+        }
+    };
+
+    // Even if the break is in a weird position.
+    let v = if let Some(v_some) = g() {
+        //~^ ERROR: this could be rewritten as `let...else`
+        v_some
+    } else {
+        'a: loop {
+            panic!();
+            loop {
+                match 0 {
+                    0 if (return break 'a ()) => {},
+                    _ => {},
+                }
+            }
+        }
+    };
+
     // A match diverges if all branches diverge:
-    // Note: the corresponding let-else requires a ; at the end of the match
-    // as otherwise the type checker does not turn it into a ! type.
     let v = if let Some(v_some) = g() {
         //~^ ERROR: this could be rewritten as `let...else`
         v_some
     } else {
-        match () {
-            _ if panic!() => {},
+        match 0 {
+            0 if true => panic!(),
             _ => panic!(),
-        }
+        };
     };
 
     // An if's expression can cause divergence:
-    let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
-    //~^ ERROR: this could be rewritten as `let...else`
+    let v = if let Some(v_some) = g() {
+        //~^ ERROR: this could be rewritten as `let...else`
+        v_some
+    } else {
+        if panic!() {};
+    };
 
     // An expression of a match can cause divergence:
     let v = if let Some(v_some) = g() {
@@ -103,7 +159,7 @@ fn fire() {
     } else {
         match panic!() {
             _ => {},
-        }
+        };
     };
 
     // Top level else if
@@ -342,6 +398,43 @@ fn not_fire() {
     } else {
         return;
     };
+
+    // A break that skips the divergent statement will cause the expression to be non-divergent.
+    let _x = if let Some(x) = Some(0) {
+        x
+    } else {
+        'foo: loop {
+            break 'foo 0;
+            panic!();
+        }
+    };
+
+    // Even in inner loops.
+    let _x = if let Some(x) = Some(0) {
+        x
+    } else {
+        'foo: {
+            loop {
+                break 'foo 0;
+            }
+            panic!();
+        }
+    };
+
+    // But a break that can't ever be reached still affects divergence checking.
+    let _x = if let Some(x) = g() {
+        x
+    } else {
+        'foo: {
+            'bar: loop {
+                loop {
+                    break 'bar ();
+                }
+                break 'foo ();
+            }
+            panic!();
+        };
+    };
 }
 
 struct S<T> {
diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr
index 2b6504a1827..3beaf766efb 100644
--- a/tests/ui/manual_let_else.stderr
+++ b/tests/ui/manual_let_else.stderr
@@ -1,5 +1,5 @@
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:25:5
+  --> $DIR/manual_let_else.rs:27:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
@@ -8,7 +8,7 @@ LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:28:5
+  --> $DIR/manual_let_else.rs:30:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -26,7 +26,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:35:5
+  --> $DIR/manual_let_else.rs:37:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |
@@ -47,25 +47,25 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:47:9
+  --> $DIR/manual_let_else.rs:49:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:49:9
+  --> $DIR/manual_let_else.rs:51:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:54:5
+  --> $DIR/manual_let_else.rs:56:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:58:5
+  --> $DIR/manual_let_else.rs:60:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -83,7 +83,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:66:5
+  --> $DIR/manual_let_else.rs:68:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -101,7 +101,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:74:5
+  --> $DIR/manual_let_else.rs:76:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -127,6 +127,26 @@ LL | /     let v = if let Some(v_some) = g() {
 LL | |
 LL | |         v_some
 LL | |     } else {
+LL | |         panic!();
+LL | |         ()
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
+LL +         panic!();
+LL +         ()
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:94:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |
+LL | |         v_some
+LL | |     } else {
 ...  |
 LL | |         }
 LL | |     };
@@ -135,21 +155,42 @@ LL | |     };
 help: consider writing
    |
 LL ~     let Some(v) = g() else {
-LL +         match () {
-LL +             _ if panic!() => {},
-LL +             _ => panic!(),
+LL +         panic!();
+LL +         if true {
+LL +             match 0 {
+LL +                 0 => (),
+LL +                 _ => (),
+LL +             }
+LL +         } else {
+LL +             panic!()
 LL +         }
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:96:5
+  --> $DIR/manual_let_else.rs:110:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |
+LL | |         v_some
+LL | |     } else {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
+LL +         loop {
+LL +             panic!();
+LL +             break ();
+LL +         }
+LL +     };
    |
-LL |     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:100:5
+  --> $DIR/manual_let_else.rs:121:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -163,14 +204,81 @@ LL | |     };
 help: consider writing
    |
 LL ~     let Some(v) = g() else {
+LL +         'a: loop {
+LL +             panic!();
+LL +             loop {
+LL +                 match 0 {
+LL +                     0 if (return break 'a ()) => {},
+LL +                     _ => {},
+LL +                 }
+LL +             }
+LL +         }
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:137:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |
+LL | |         v_some
+LL | |     } else {
+...  |
+LL | |         };
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
+LL +         match 0 {
+LL +             0 if true => panic!(),
+LL +             _ => panic!(),
+LL +         };
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:148:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |
+LL | |         v_some
+LL | |     } else {
+LL | |         if panic!() {};
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
+LL +         if panic!() {};
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:156:5
+   |
+LL | /     let v = if let Some(v_some) = g() {
+LL | |
+LL | |         v_some
+LL | |     } else {
+...  |
+LL | |         };
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(v) = g() else {
 LL +         match panic!() {
 LL +             _ => {},
-LL +         }
+LL +         };
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:110:5
+  --> $DIR/manual_let_else.rs:166:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -191,7 +299,7 @@ LL +     } };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:120:5
+  --> $DIR/manual_let_else.rs:176:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -220,7 +328,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:138:5
+  --> $DIR/manual_let_else.rs:194:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |
@@ -238,7 +346,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:146:5
+  --> $DIR/manual_let_else.rs:202:5
    |
 LL | /     let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
 LL | |
@@ -256,7 +364,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:156:13
+  --> $DIR/manual_let_else.rs:212:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
@@ -267,19 +375,19 @@ LL |     create_binding_if_some!(w, g());
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:165:5
+  --> $DIR/manual_let_else.rs:221:5
    |
 LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:169:5
+  --> $DIR/manual_let_else.rs:225:5
    |
 LL |     let mut v = if let Variant::B(b) = e() { b } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:174:5
+  --> $DIR/manual_let_else.rs:230:5
    |
 LL | /     let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
 LL | |
@@ -297,19 +405,19 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:181:5
+  --> $DIR/manual_let_else.rs:237:5
    |
 LL |     let v = if let Variant::A(.., a) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:185:5
+  --> $DIR/manual_let_else.rs:241:5
    |
 LL |     let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:189:5
+  --> $DIR/manual_let_else.rs:245:5
    |
 LL | /     let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
 LL | |
@@ -327,7 +435,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:197:5
+  --> $DIR/manual_let_else.rs:253:5
    |
 LL | /     let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
 LL | |
@@ -345,7 +453,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:205:5
+  --> $DIR/manual_let_else.rs:261:5
    |
 LL | /     let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
 LL | |
@@ -363,7 +471,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:322:5
+  --> $DIR/manual_let_else.rs:378:5
    |
 LL | /     let _ = match ff {
 LL | |
@@ -372,5 +480,5 @@ LL | |         _ => macro_call!(),
 LL | |     };
    | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
-error: aborting due to 26 previous errors
+error: aborting due to 30 previous errors
 
diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed
index 62b0ba01860..53ebfb40ba0 100644
--- a/tests/ui/map_identity.fixed
+++ b/tests/ui/map_identity.fixed
@@ -24,28 +24,40 @@ fn main() {
 
 fn issue7189() {
     // should lint
-    let x = [(1, 2), (3, 4)];
-    let _ = x.iter();
-    let _ = x.iter();
-    let _ = x.iter();
+    let x = [(1, 2), (3, 4)].iter().copied();
+    let _ = x.clone();
+    let _ = x.clone();
+    let _ = x.clone();
 
-    let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))];
-    let _ = y.iter();
+    let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied();
+    let _ = y.clone();
 
     // should not lint
-    let _ = x.iter().map(|(x, y)| (x, y, y));
-    let _ = x.iter().map(|(x, _y)| (x,));
-    let _ = x.iter().map(|(x, _)| (x,));
-    let _ = x.iter().map(|(x, ..)| (x,));
-    let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z)));
+    let _ = x.clone().map(|(x, y)| (x, y, y));
+    let _ = x.clone().map(|(x, _y)| (x,));
+    let _ = x.clone().map(|(x, _)| (x,));
+    let _ = x.clone().map(|(x, ..)| (x,));
+    let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z)));
     let _ = y
-        .iter()
-        .map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z)));
+        .clone()
+        .map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z)));
     let _ = y
-        .iter()
-        .map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
+        .clone()
+        .map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
 }
 
 fn not_identity(x: &u16) -> u16 {
     *x
 }
+
+fn issue11764() {
+    let x = [(1, 2), (3, 4)];
+    // don't lint: this is an `Iterator<Item = &(i32, i32)>`
+    // match ergonomics makes the binding patterns into references
+    // so that its type changes to `Iterator<Item = (&i32, &i32)>`
+    let _ = x.iter().map(|(x, y)| (x, y));
+    let _ = x.iter().map(|x| (x.0,)).map(|(x,)| x);
+
+    // no match ergonomics for `(i32, i32)`
+    let _ = x.iter().copied();
+}
diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs
index b7f4c99f273..c646c056859 100644
--- a/tests/ui/map_identity.rs
+++ b/tests/ui/map_identity.rs
@@ -26,30 +26,42 @@ fn main() {
 
 fn issue7189() {
     // should lint
-    let x = [(1, 2), (3, 4)];
-    let _ = x.iter().map(|(x, y)| (x, y));
-    let _ = x.iter().map(|(x, y)| {
+    let x = [(1, 2), (3, 4)].iter().copied();
+    let _ = x.clone().map(|(x, y)| (x, y));
+    let _ = x.clone().map(|(x, y)| {
         return (x, y);
     });
-    let _ = x.iter().map(|(x, y)| return (x, y));
+    let _ = x.clone().map(|(x, y)| return (x, y));
 
-    let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))];
-    let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
+    let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied();
+    let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
 
     // should not lint
-    let _ = x.iter().map(|(x, y)| (x, y, y));
-    let _ = x.iter().map(|(x, _y)| (x,));
-    let _ = x.iter().map(|(x, _)| (x,));
-    let _ = x.iter().map(|(x, ..)| (x,));
-    let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z)));
+    let _ = x.clone().map(|(x, y)| (x, y, y));
+    let _ = x.clone().map(|(x, _y)| (x,));
+    let _ = x.clone().map(|(x, _)| (x,));
+    let _ = x.clone().map(|(x, ..)| (x,));
+    let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z)));
     let _ = y
-        .iter()
-        .map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z)));
+        .clone()
+        .map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z)));
     let _ = y
-        .iter()
-        .map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
+        .clone()
+        .map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,))));
 }
 
 fn not_identity(x: &u16) -> u16 {
     *x
 }
+
+fn issue11764() {
+    let x = [(1, 2), (3, 4)];
+    // don't lint: this is an `Iterator<Item = &(i32, i32)>`
+    // match ergonomics makes the binding patterns into references
+    // so that its type changes to `Iterator<Item = (&i32, &i32)>`
+    let _ = x.iter().map(|(x, y)| (x, y));
+    let _ = x.iter().map(|x| (x.0,)).map(|(x,)| x);
+
+    // no match ergonomics for `(i32, i32)`
+    let _ = x.iter().copied().map(|(x, y)| (x, y));
+}
diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr
index 4ca24b0b04c..ea077d66d64 100644
--- a/tests/ui/map_identity.stderr
+++ b/tests/ui/map_identity.stderr
@@ -41,31 +41,37 @@ LL |     let _: Result<u32, u32> = Ok(1).map_err(|a| a);
    |                                    ^^^^^^^^^^^^^^^ help: remove the call to `map_err`
 
 error: unnecessary map of the identity function
-  --> $DIR/map_identity.rs:30:21
+  --> $DIR/map_identity.rs:30:22
    |
-LL |     let _ = x.iter().map(|(x, y)| (x, y));
-   |                     ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+LL |     let _ = x.clone().map(|(x, y)| (x, y));
+   |                      ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
 
 error: unnecessary map of the identity function
-  --> $DIR/map_identity.rs:31:21
+  --> $DIR/map_identity.rs:31:22
    |
-LL |       let _ = x.iter().map(|(x, y)| {
-   |  _____________________^
+LL |       let _ = x.clone().map(|(x, y)| {
+   |  ______________________^
 LL | |         return (x, y);
 LL | |     });
    | |______^ help: remove the call to `map`
 
 error: unnecessary map of the identity function
-  --> $DIR/map_identity.rs:34:21
+  --> $DIR/map_identity.rs:34:22
    |
-LL |     let _ = x.iter().map(|(x, y)| return (x, y));
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+LL |     let _ = x.clone().map(|(x, y)| return (x, y));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
 
 error: unnecessary map of the identity function
-  --> $DIR/map_identity.rs:37:21
+  --> $DIR/map_identity.rs:37:22
    |
-LL |     let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+LL |     let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,))));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
 
-error: aborting due to 10 previous errors
+error: unnecessary map of the identity function
+  --> $DIR/map_identity.rs:66:30
+   |
+LL |     let _ = x.iter().copied().map(|(x, y)| (x, y));
+   |                              ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map`
+
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index c2c5f765abf..ff1e2dc8875 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -190,27 +190,48 @@ fn issue9383() {
     // Should not lint because unions need explicit deref when accessing field
     use std::mem::ManuallyDrop;
 
-    union Coral {
-        crab: ManuallyDrop<Vec<i32>>,
+    #[derive(Clone, Copy)]
+    struct Wrap<T>(T);
+    impl<T> core::ops::Deref for Wrap<T> {
+        type Target = T;
+        fn deref(&self) -> &T {
+            &self.0
+        }
+    }
+    impl<T> core::ops::DerefMut for Wrap<T> {
+        fn deref_mut(&mut self) -> &mut T {
+            &mut self.0
+        }
     }
 
-    union Ocean {
-        coral: ManuallyDrop<Coral>,
+    union U<T: Copy> {
+        u: T,
     }
 
-    let mut ocean = Ocean {
-        coral: ManuallyDrop::new(Coral {
-            crab: ManuallyDrop::new(vec![1, 2, 3]),
-        }),
-    };
+    #[derive(Clone, Copy)]
+    struct Foo {
+        x: u32,
+    }
 
     unsafe {
-        ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
-
-        (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
-        ManuallyDrop::drop(&mut (*ocean.coral).crab);
-
-        ManuallyDrop::drop(&mut ocean.coral);
+        let mut x = U {
+            u: ManuallyDrop::new(Foo { x: 0 }),
+        };
+        let _ = &mut (&mut x.u).x;
+        let _ = &mut { x.u }.x;
+        let _ = &mut ({ &mut x.u }).x;
+
+        let mut x = U {
+            u: Wrap(ManuallyDrop::new(Foo { x: 0 })),
+        };
+        let _ = &mut (&mut x.u).x;
+        let _ = &mut { x.u }.x;
+        let _ = &mut ({ &mut x.u }).x;
+
+        let mut x = U { u: Wrap(Foo { x: 0 }) };
+        let _ = &mut x.u.x;
+        let _ = &mut { x.u }.x;
+        let _ = &mut ({ &mut x.u }).x;
     }
 }
 
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index 0cd6e41b8a4..597021539ac 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -190,27 +190,48 @@ fn issue9383() {
     // Should not lint because unions need explicit deref when accessing field
     use std::mem::ManuallyDrop;
 
-    union Coral {
-        crab: ManuallyDrop<Vec<i32>>,
+    #[derive(Clone, Copy)]
+    struct Wrap<T>(T);
+    impl<T> core::ops::Deref for Wrap<T> {
+        type Target = T;
+        fn deref(&self) -> &T {
+            &self.0
+        }
+    }
+    impl<T> core::ops::DerefMut for Wrap<T> {
+        fn deref_mut(&mut self) -> &mut T {
+            &mut self.0
+        }
     }
 
-    union Ocean {
-        coral: ManuallyDrop<Coral>,
+    union U<T: Copy> {
+        u: T,
     }
 
-    let mut ocean = Ocean {
-        coral: ManuallyDrop::new(Coral {
-            crab: ManuallyDrop::new(vec![1, 2, 3]),
-        }),
-    };
+    #[derive(Clone, Copy)]
+    struct Foo {
+        x: u32,
+    }
 
     unsafe {
-        ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
-
-        (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
-        ManuallyDrop::drop(&mut (*ocean.coral).crab);
-
-        ManuallyDrop::drop(&mut ocean.coral);
+        let mut x = U {
+            u: ManuallyDrop::new(Foo { x: 0 }),
+        };
+        let _ = &mut (&mut x.u).x;
+        let _ = &mut (&mut { x.u }).x;
+        let _ = &mut ({ &mut x.u }).x;
+
+        let mut x = U {
+            u: Wrap(ManuallyDrop::new(Foo { x: 0 })),
+        };
+        let _ = &mut (&mut x.u).x;
+        let _ = &mut (&mut { x.u }).x;
+        let _ = &mut ({ &mut x.u }).x;
+
+        let mut x = U { u: Wrap(Foo { x: 0 }) };
+        let _ = &mut (&mut x.u).x;
+        let _ = &mut (&mut { x.u }).x;
+        let _ = &mut ({ &mut x.u }).x;
     }
 }
 
diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr
index e91b78b0a15..44552ee6abe 100644
--- a/tests/ui/needless_borrow.stderr
+++ b/tests/ui/needless_borrow.stderr
@@ -133,5 +133,29 @@ error: this expression borrows a value the compiler would automatically borrow
 LL |             (&mut self.f)()
    |             ^^^^^^^^^^^^^ help: change this to: `(self.f)`
 
-error: aborting due to 22 previous errors
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:221:22
+   |
+LL |         let _ = &mut (&mut { x.u }).x;
+   |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:228:22
+   |
+LL |         let _ = &mut (&mut { x.u }).x;
+   |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:232:22
+   |
+LL |         let _ = &mut (&mut x.u).x;
+   |                      ^^^^^^^^^^ help: change this to: `x.u`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:233:22
+   |
+LL |         let _ = &mut (&mut { x.u }).x;
+   |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
+
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/unnecessary_fallible_conversions.stderr b/tests/ui/unnecessary_fallible_conversions.stderr
index b918fdf774b..26b152515ac 100644
--- a/tests/ui/unnecessary_fallible_conversions.stderr
+++ b/tests/ui/unnecessary_fallible_conversions.stderr
@@ -4,6 +4,7 @@ error: use of a fallible conversion when an infallible one could be used
 LL |     let _: i64 = 0i32.try_into().unwrap();
    |                       ^^^^^^^^^^^^^^^^^^^ help: use: `into()`
    |
+   = note: converting `i32` to `i64` cannot fail
    = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`
 
@@ -12,6 +13,8 @@ error: use of a fallible conversion when an infallible one could be used
    |
 LL |     let _: i64 = 0i32.try_into().expect("can't happen");
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `into()`
+   |
+   = note: converting `i32` to `i64` cannot fail
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/unnecessary_fallible_conversions_unfixable.stderr b/tests/ui/unnecessary_fallible_conversions_unfixable.stderr
index 286decf8f35..033de0e9250 100644
--- a/tests/ui/unnecessary_fallible_conversions_unfixable.stderr
+++ b/tests/ui/unnecessary_fallible_conversions_unfixable.stderr
@@ -4,6 +4,7 @@ error: use of a fallible conversion when an infallible one could be used
 LL |     let _: Result<Foo, _> = 0i64.try_into();
    |                                  ^^^^^^^^ help: use: `into`
    |
+   = note: converting `i64` to `Foo` cannot fail
    = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`
 
@@ -12,30 +13,40 @@ error: use of a fallible conversion when an infallible one could be used
    |
 LL |     let _: Result<Foo, _> = i64::try_into(0i64);
    |                             ^^^^^^^^^^^^^ help: use: `Into::into`
+   |
+   = note: converting `i64` to `Foo` cannot fail
 
 error: use of a fallible conversion when an infallible one could be used
   --> $DIR/unnecessary_fallible_conversions_unfixable.rs:31:29
    |
 LL |     let _: Result<Foo, _> = Foo::try_from(0i64);
    |                             ^^^^^^^^^^^^^ help: use: `From::from`
+   |
+   = note: converting `i64` to `Foo` cannot fail
 
 error: use of a fallible conversion when an infallible one could be used
   --> $DIR/unnecessary_fallible_conversions_unfixable.rs:34:34
    |
 LL |     let _: Result<i64, _> = 0i32.try_into();
    |                                  ^^^^^^^^ help: use: `into`
+   |
+   = note: converting `i32` to `i64` cannot fail
 
 error: use of a fallible conversion when an infallible one could be used
   --> $DIR/unnecessary_fallible_conversions_unfixable.rs:36:29
    |
 LL |     let _: Result<i64, _> = i32::try_into(0i32);
    |                             ^^^^^^^^^^^^^ help: use: `Into::into`
+   |
+   = note: converting `i32` to `i64` cannot fail
 
 error: use of a fallible conversion when an infallible one could be used
   --> $DIR/unnecessary_fallible_conversions_unfixable.rs:38:29
    |
 LL |     let _: Result<i64, _> = <_>::try_from(0i32);
    |                             ^^^^^^^^^^^^^ help: use: `From::from`
+   |
+   = note: converting `i32` to `i64` cannot fail
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/vec_box_sized.fixed b/tests/ui/vec_box_sized.fixed
deleted file mode 100644
index 4363d2224af..00000000000
--- a/tests/ui/vec_box_sized.fixed
+++ /dev/null
@@ -1,57 +0,0 @@
-#![allow(dead_code)]
-
-struct SizedStruct(i32);
-struct UnsizedStruct([i32]);
-struct BigStruct([i32; 10000]);
-
-/// The following should trigger the lint
-mod should_trigger {
-    use super::SizedStruct;
-    const C: Vec<i32> = Vec::new();
-    static S: Vec<i32> = Vec::new();
-
-    struct StructWithVecBox {
-        sized_type: Vec<SizedStruct>,
-    }
-
-    struct A(Vec<SizedStruct>);
-    struct B(Vec<Vec<u32>>);
-}
-
-/// The following should not trigger the lint
-mod should_not_trigger {
-    use super::{BigStruct, UnsizedStruct};
-
-    struct C(Vec<Box<UnsizedStruct>>);
-    struct D(Vec<Box<BigStruct>>);
-
-    struct StructWithVecBoxButItsUnsized {
-        unsized_type: Vec<Box<UnsizedStruct>>,
-    }
-
-    struct TraitVec<T: ?Sized> {
-        // Regression test for #3720. This was causing an ICE.
-        inner: Vec<Box<T>>,
-    }
-}
-
-mod inner_mod {
-    mod inner {
-        pub struct S;
-    }
-
-    mod inner2 {
-        use super::inner::S;
-
-        pub fn f() -> Vec<S> {
-            vec![]
-        }
-    }
-}
-
-// https://github.com/rust-lang/rust-clippy/issues/11417
-fn in_closure() {
-    let _ = |_: Vec<Box<dyn ToString>>| {};
-}
-
-fn main() {}
diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs
index f4e27fe4bd5..49eaf8e062a 100644
--- a/tests/ui/vec_box_sized.rs
+++ b/tests/ui/vec_box_sized.rs
@@ -1,12 +1,28 @@
+//@no-rustfix
+
 #![allow(dead_code)]
+#![feature(allocator_api)]
+
+use std::alloc::{AllocError, Allocator, Layout};
+use std::ptr::NonNull;
 
 struct SizedStruct(i32);
 struct UnsizedStruct([i32]);
 struct BigStruct([i32; 10000]);
 
+struct DummyAllocator;
+unsafe impl Allocator for DummyAllocator {
+    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+        todo!()
+    }
+    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+        todo!()
+    }
+}
+
 /// The following should trigger the lint
 mod should_trigger {
-    use super::SizedStruct;
+    use super::{DummyAllocator, SizedStruct};
     const C: Vec<Box<i32>> = Vec::new();
     static S: Vec<Box<i32>> = Vec::new();
 
@@ -16,11 +32,21 @@ mod should_trigger {
 
     struct A(Vec<Box<SizedStruct>>);
     struct B(Vec<Vec<Box<(u32)>>>);
+
+    fn allocator_global_defined_vec() -> Vec<Box<i32>, std::alloc::Global> {
+        Vec::new()
+    }
+    fn allocator_global_defined_box() -> Vec<Box<i32, std::alloc::Global>> {
+        Vec::new()
+    }
+    fn allocator_match() -> Vec<Box<i32, DummyAllocator>, DummyAllocator> {
+        Vec::new_in(DummyAllocator)
+    }
 }
 
 /// The following should not trigger the lint
 mod should_not_trigger {
-    use super::{BigStruct, UnsizedStruct};
+    use super::{BigStruct, DummyAllocator, UnsizedStruct};
 
     struct C(Vec<Box<UnsizedStruct>>);
     struct D(Vec<Box<BigStruct>>);
@@ -33,6 +59,13 @@ mod should_not_trigger {
         // Regression test for #3720. This was causing an ICE.
         inner: Vec<Box<T>>,
     }
+
+    fn allocator_mismatch() -> Vec<Box<i32, DummyAllocator>> {
+        Vec::new()
+    }
+    fn allocator_mismatch_2() -> Vec<Box<i32>, DummyAllocator> {
+        Vec::new_in(DummyAllocator)
+    }
 }
 
 mod inner_mod {
diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr
index 9118f284bb9..d6479271fa6 100644
--- a/tests/ui/vec_box_sized.stderr
+++ b/tests/ui/vec_box_sized.stderr
@@ -1,5 +1,5 @@
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:10:14
+  --> $DIR/vec_box_sized.rs:26:14
    |
 LL |     const C: Vec<Box<i32>> = Vec::new();
    |              ^^^^^^^^^^^^^ help: try: `Vec<i32>`
@@ -8,34 +8,52 @@ LL |     const C: Vec<Box<i32>> = Vec::new();
    = help: to override `-D warnings` add `#[allow(clippy::vec_box)]`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:11:15
+  --> $DIR/vec_box_sized.rs:27:15
    |
 LL |     static S: Vec<Box<i32>> = Vec::new();
    |               ^^^^^^^^^^^^^ help: try: `Vec<i32>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:14:21
+  --> $DIR/vec_box_sized.rs:30:21
    |
 LL |         sized_type: Vec<Box<SizedStruct>>,
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:17:14
+  --> $DIR/vec_box_sized.rs:33:14
    |
 LL |     struct A(Vec<Box<SizedStruct>>);
    |              ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:18:18
+  --> $DIR/vec_box_sized.rs:34:18
    |
 LL |     struct B(Vec<Vec<Box<(u32)>>>);
    |                  ^^^^^^^^^^^^^^^ help: try: `Vec<u32>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:46:23
+  --> $DIR/vec_box_sized.rs:36:42
+   |
+LL |     fn allocator_global_defined_vec() -> Vec<Box<i32>, std::alloc::Global> {
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:39:42
+   |
+LL |     fn allocator_global_defined_box() -> Vec<Box<i32, std::alloc::Global>> {
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:42:29
+   |
+LL |     fn allocator_match() -> Vec<Box<i32, DummyAllocator>, DummyAllocator> {
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:79:23
    |
 LL |         pub fn f() -> Vec<Box<S>> {
    |                       ^^^^^^^^^^^ help: try: `Vec<S>`
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors