about summary refs log tree commit diff
path: root/src/tools/clippy/clippy_lints
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2022-10-06 09:44:38 +0200
committerPhilipp Krones <hello@philkrones.com>2022-10-06 09:44:38 +0200
commit27f2f0a04e94261cec9e48ed7c2b2b0d560f25db (patch)
tree4b22e01190bd8fed97a00401d6d2968592cb7115 /src/tools/clippy/clippy_lints
parent0152393048c4eb6c6d2aec63e9899cc86a269b44 (diff)
parentac0e10aa68325235069a842f47499852b2dee79e (diff)
downloadrust-27f2f0a04e94261cec9e48ed7c2b2b0d560f25db.tar.gz
rust-27f2f0a04e94261cec9e48ed7c2b2b0d560f25db.zip
Merge commit 'ac0e10aa68325235069a842f47499852b2dee79e' into clippyup
Diffstat (limited to 'src/tools/clippy/clippy_lints')
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/asm_syntax.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/feature_name.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs81
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs64
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs151
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_methods.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_types.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs92
-rw-r--r--src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/equatable_if_let.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs154
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs82
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs91
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_hasher.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs114
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_to_string.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/int_plus_one.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/let_if_seq.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_all.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_complexity.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_internal.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_lints.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_nursery.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_perf.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_style.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs56
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_collect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs713
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/match_result_ok.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_map.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/needless_match.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/try_err.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs72
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_next.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_first.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_count.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_flatten.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_identity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs87
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs73
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/minmax.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mod.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_question_mark.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/non_expressive_names.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/octal_escapes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs120
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/bit_mask.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/eq_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/self_assignment.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_to_none.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs212
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/to_digit_is_some.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/types/box_collection.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types/rc_buffer.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/uninit_vec.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_rounding.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs72
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs307
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs97
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_div_zero.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs7
290 files changed, 3300 insertions, 2318 deletions
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 738562ef855..6fbd6401ef3 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.65"
+version = "0.1.66"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 159f3b0cd01..724490fb495 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -92,7 +92,7 @@ impl ApproxConstant {
                         cx,
                         APPROX_CONSTANT,
                         e.span,
-                        &format!("approximate value of `{}::consts::{}` found", module, &name),
+                        &format!("approximate value of `{module}::consts::{}` found", &name),
                         None,
                         "consider using the constant directly",
                     );
@@ -126,7 +126,7 @@ fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {
         // The value is a truncated constant
         true
     } else {
-        let round_const = format!("{:.*}", value.len() - 2, constant);
+        let round_const = format!("{constant:.*}", value.len() - 2);
         value == round_const
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
index f419781dbc8..9717aa9e981 100644
--- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs
+++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
@@ -44,7 +44,7 @@ fn check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr
                 cx,
                 lint,
                 expr.span,
-                &format!("{} x86 assembly syntax used", style),
+                &format!("{style} x86 assembly syntax used"),
                 None,
                 &format!("use {} x86 assembly syntax", !style),
             );
@@ -64,6 +64,7 @@ declare_clippy_lint! {
     ///
     /// ```rust,no_run
     /// # #![feature(asm)]
+    /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     /// # unsafe { let ptr = "".as_ptr();
     /// # use std::arch::asm;
     /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
@@ -72,6 +73,7 @@ declare_clippy_lint! {
     /// Use instead:
     /// ```rust,no_run
     /// # #![feature(asm)]
+    /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     /// # unsafe { let ptr = "".as_ptr();
     /// # use std::arch::asm;
     /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
@@ -103,6 +105,7 @@ declare_clippy_lint! {
     ///
     /// ```rust,no_run
     /// # #![feature(asm)]
+    /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     /// # unsafe { let ptr = "".as_ptr();
     /// # use std::arch::asm;
     /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
@@ -111,6 +114,7 @@ declare_clippy_lint! {
     /// Use instead:
     /// ```rust,no_run
     /// # #![feature(asm)]
+    /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     /// # unsafe { let ptr = "".as_ptr();
     /// # use std::arch::asm;
     /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index 2705ffffdcb..a36df55d0bd 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -60,9 +60,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
                 cx,
                 ASSERTIONS_ON_CONSTANTS,
                 macro_call.span,
-                &format!("`assert!(false{})` should probably be replaced", assert_arg),
+                &format!("`assert!(false{assert_arg})` should probably be replaced"),
                 None,
-                &format!("use `panic!({})` or `unreachable!({0})`", panic_arg),
+                &format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"),
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
index 656dc5feeb5..f6d6c23bb6e 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
@@ -69,9 +69,8 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
                         "called `assert!` with `Result::is_ok`",
                         "replace with",
                         format!(
-                            "{}.unwrap(){}",
-                            snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0,
-                            semicolon
+                            "{}.unwrap(){semicolon}",
+                            snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
                         ),
                         app,
                     );
@@ -84,9 +83,8 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
                         "called `assert!` with `Result::is_err`",
                         "replace with",
                         format!(
-                            "{}.unwrap_err(){}",
-                            snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0,
-                            semicolon
+                            "{}.unwrap_err(){semicolon}",
+                            snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
                         ),
                         app,
                     );
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 732dc2b4330..5f45c69d7f9 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -541,10 +541,7 @@ fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribut
                     cx,
                     INLINE_ALWAYS,
                     attr.span,
-                    &format!(
-                        "you have declared `#[inline(always)]` on `{}`. This is usually a bad idea",
-                        name
-                    ),
+                    &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
                 );
             }
         }
@@ -720,7 +717,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
                 let mut unix_suggested = false;
 
                 for (os, span) in mismatched {
-                    let sugg = format!("target_os = \"{}\"", os);
+                    let sugg = format!("target_os = \"{os}\"");
                     diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
 
                     if !unix_suggested && is_unix(os) {
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index 1761360fb28..34717811866 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -1,14 +1,15 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{match_def_path, paths};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::{Namespace, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{def::Res, AsyncGeneratorKind, Body, BodyId, GeneratorKind};
+use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::GeneratorInteriorTypeCause;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 
-use crate::utils::conf::DisallowedType;
+use crate::utils::conf::DisallowedPath;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -171,12 +172,12 @@ impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF,
 
 #[derive(Debug)]
 pub struct AwaitHolding {
-    conf_invalid_types: Vec<DisallowedType>,
-    def_ids: FxHashMap<DefId, DisallowedType>,
+    conf_invalid_types: Vec<DisallowedPath>,
+    def_ids: FxHashMap<DefId, DisallowedPath>,
 }
 
 impl AwaitHolding {
-    pub(crate) fn new(conf_invalid_types: Vec<DisallowedType>) -> Self {
+    pub(crate) fn new(conf_invalid_types: Vec<DisallowedPath>) -> Self {
         Self {
             conf_invalid_types,
             def_ids: FxHashMap::default(),
@@ -187,11 +188,8 @@ impl AwaitHolding {
 impl LateLintPass<'_> for AwaitHolding {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for conf in &self.conf_invalid_types {
-            let path = match conf {
-                DisallowedType::Simple(path) | DisallowedType::WithReason { path, .. } => path,
-            };
-            let segs: Vec<_> = path.split("::").collect();
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs) {
+            let segs: Vec<_> = conf.path().split("::").collect();
+            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
                 self.def_ids.insert(id, conf.clone());
             }
         }
@@ -256,29 +254,27 @@ impl AwaitHolding {
     }
 }
 
-fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedType) {
-    let (type_name, reason) = match disallowed {
-        DisallowedType::Simple(path) => (path, &None),
-        DisallowedType::WithReason { path, reason } => (path, reason),
-    };
-
+fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPath) {
     span_lint_and_then(
         cx,
         AWAIT_HOLDING_INVALID_TYPE,
         span,
-        &format!("`{type_name}` may not be held across an `await` point per `clippy.toml`",),
+        &format!(
+            "`{}` may not be held across an `await` point per `clippy.toml`",
+            disallowed.path()
+        ),
         |diag| {
-            if let Some(reason) = reason {
-                diag.note(reason.clone());
+            if let Some(reason) = disallowed.reason() {
+                diag.note(reason);
             }
         },
     );
 }
 
 fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
-    match_def_path(cx, def_id, &paths::MUTEX_GUARD)
-        || match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD)
-        || match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD)
+    cx.tcx.is_diagnostic_item(sym::MutexGuard, def_id)
+        || cx.tcx.is_diagnostic_item(sym::RwLockReadGuard, def_id)
+        || cx.tcx.is_diagnostic_item(sym::RwLockWriteGuard, def_id)
         || match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
         || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
         || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index d9e2c9c8578..9c053247402 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
@@ -3,10 +3,11 @@ use clippy_utils::get_parent_expr;
 use clippy_utils::higher;
 use clippy_utils::source::snippet_block_with_applicability;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::visitors::{for_each_expr, Descend};
+use core::ops::ControlFlow;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{BlockCheckMode, Closure, Expr, ExprKind};
+use rustc_hir::{BlockCheckMode, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -44,39 +45,6 @@ declare_clippy_lint! {
 
 declare_lint_pass!(BlocksInIfConditions => [BLOCKS_IN_IF_CONDITIONS]);
 
-struct ExVisitor<'a, 'tcx> {
-    found_block: Option<&'tcx Expr<'tcx>>,
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::Closure(&Closure { body, .. }) = expr.kind {
-            // do not lint if the closure is called using an iterator (see #1141)
-            if_chain! {
-                if let Some(parent) = get_parent_expr(self.cx, expr);
-                if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind;
-                let caller = self.cx.typeck_results().expr_ty(self_arg);
-                if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
-                if implements_trait(self.cx, caller, iter_id, &[]);
-                then {
-                    return;
-                }
-            }
-
-            let body = self.cx.tcx.hir().body(body);
-            let ex = &body.value;
-            if let ExprKind::Block(block, _) = ex.kind {
-                if !body.value.span.from_expansion() && !block.stmts.is_empty() {
-                    self.found_block = Some(ex);
-                    return;
-                }
-            }
-        }
-        walk_expr(self, expr);
-    }
-}
-
 const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition";
 const COMPLEX_BLOCK_MESSAGE: &str = "in an `if` condition, avoid complex blocks or closures with blocks; \
                                     instead, move the block or closure higher and bind it with a `let`";
@@ -145,11 +113,31 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
                     }
                 }
             } else {
-                let mut visitor = ExVisitor { found_block: None, cx };
-                walk_expr(&mut visitor, cond);
-                if let Some(block) = visitor.found_block {
-                    span_lint(cx, BLOCKS_IN_IF_CONDITIONS, block.span, COMPLEX_BLOCK_MESSAGE);
-                }
+                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);
+                            }
+                        }
+
+                        let body = cx.tcx.hir().body(closure.body);
+                        let ex = &body.value;
+                        if let ExprKind::Block(block, _) = ex.kind {
+                            if !body.value.span.from_expansion() && !block.stmts.is_empty() {
+                                span_lint(cx, BLOCKS_IN_IF_CONDITIONS, ex.span, COMPLEX_BLOCK_MESSAGE);
+                                return ControlFlow::Continue(Descend::No);
+                            }
+                        }
+                    }
+                    ControlFlow::Continue(Descend::Yes)
+                });
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index 95abe8aa59f..4bd55c1429c 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -98,9 +98,9 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
             cx,
             BOOL_ASSERT_COMPARISON,
             macro_call.span,
-            &format!("used `{}!` with a literal bool", macro_name),
+            &format!("used `{macro_name}!` with a literal bool"),
             "replace it with",
-            format!("{}!(..)", non_eq_mac),
+            format!("{non_eq_mac}!(..)"),
             Applicability::MaybeIncorrect,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
index 51e98cda845..001d74c2605 100644
--- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
@@ -3,7 +3,7 @@ use rustc_hir::{Block, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, sugg::Sugg};
+use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, is_integer_literal, sugg::Sugg};
 use rustc_errors::Applicability;
 
 declare_clippy_lint! {
@@ -56,13 +56,9 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
         && let Some(then_lit) = int_literal(then)
         && let Some(else_lit) = int_literal(else_)
     {
-        let inverted = if
-            check_int_literal_equals_val(then_lit, 1)
-            && check_int_literal_equals_val(else_lit, 0) {
+        let inverted = if is_integer_literal(then_lit, 1) && is_integer_literal(else_lit, 0) {
             false
-        } else if
-            check_int_literal_equals_val(then_lit, 0)
-            && check_int_literal_equals_val(else_lit, 1) {
+        } else if is_integer_literal(then_lit, 0) && is_integer_literal(else_lit, 1) {
             true
         } else {
             // Expression isn't boolean, exit
@@ -123,14 +119,3 @@ fn int_literal<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>) -> Option<&'tcx rustc_hi
         None
     }
 }
-
-fn check_int_literal_equals_val<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>, expected_value: u128) -> bool {
-    if let ExprKind::Lit(lit) = &expr.kind
-        && let LitKind::Int(val, _) = lit.node
-        && val == expected_value
-    {
-        true
-    } else {
-        false
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 03d262d5a59..2a15cbc7a3c 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -263,9 +263,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
             }
             .and_then(|op| {
                 Some(format!(
-                    "{}{}{}",
+                    "{}{op}{}",
                     snippet_opt(cx, lhs.span)?,
-                    op,
                     snippet_opt(cx, rhs.span)?
                 ))
             })
@@ -285,7 +284,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                     let path: &str = path.ident.name.as_str();
                     a == path
                 })
-                .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, receiver.span)?, neg_method)))
+                .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", snippet_opt(cx, receiver.span)?)))
         },
         _ => None,
     }
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
new file mode 100644
index 00000000000..792183ac408
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -0,0 +1,61 @@
+use clippy_utils::{diagnostics::span_lint_and_help, is_default_equivalent, path_def_id};
+use rustc_hir::{Expr, ExprKind, QPath};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// checks for `Box::new(T::default())`, which is better written as
+    /// `Box::<T>::default()`.
+    ///
+    /// ### Why is this bad?
+    /// First, it's more complex, involving two calls instead of one.
+    /// Second, `Box::default()` can be faster
+    /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
+    ///
+    /// ### Known problems
+    /// The lint may miss some cases (e.g. Box::new(String::from(""))).
+    /// On the other hand, it will trigger on cases where the `default`
+    /// code comes from a macro that does something different based on
+    /// e.g. target operating system.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let x: Box<String> = Box::new(Default::default());
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let x: Box<String> = Box::default();
+    /// ```
+    #[clippy::version = "1.65.0"]
+    pub BOX_DEFAULT,
+    perf,
+    "Using Box::new(T::default()) instead of Box::default()"
+}
+
+declare_lint_pass!(BoxDefault => [BOX_DEFAULT]);
+
+impl LateLintPass<'_> for BoxDefault {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let ExprKind::Call(box_new, [arg]) = expr.kind
+            && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_new.kind
+            && let ExprKind::Call(..) = arg.kind
+            && !in_external_macro(cx.sess(), expr.span)
+            && expr.span.eq_ctxt(arg.span)
+            && seg.ident.name == sym::new
+            && path_def_id(cx, ty) == cx.tcx.lang_items().owned_box()
+            && is_default_equivalent(cx, arg)
+        {
+            span_lint_and_help(
+                cx,
+                BOX_DEFAULT,
+                expr.span,
+                "`Box::new(_)` of default value",
+                None,
+                "use `Box::default()` instead",
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
index e0442dda479..805121bcced 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
@@ -40,7 +40,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: b
 }
 
 fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
-    let message = format!("package `{}` is missing `{}` metadata", package.name, field);
+    let message = format!("package `{}` is missing `{field}` metadata", package.name);
     span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs b/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs
index 79a469a4258..37c169dbd95 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs
@@ -57,10 +57,8 @@ fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) {
         },
         DUMMY_SP,
         &format!(
-            "the \"{}\" {} in the feature name \"{}\" is {}",
-            substring,
+            "the \"{substring}\" {} in the feature name \"{feature}\" is {}",
             if is_prefix { "prefix" } else { "suffix" },
-            feature,
             if is_negative { "negative" } else { "redundant" }
         ),
         None,
diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
index 9f45db86a09..3a872e54c9a 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
@@ -196,7 +196,7 @@ impl LateLintPass<'_> for Cargo {
                 },
                 Err(e) => {
                     for lint in NO_DEPS_LINTS {
-                        span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {}", e));
+                        span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
                     }
                 },
             }
@@ -212,7 +212,7 @@ impl LateLintPass<'_> for Cargo {
                 },
                 Err(e) => {
                     for lint in WITH_DEPS_LINTS {
-                        span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {}", e));
+                        span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
                     }
                 },
             }
diff --git a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
index 76fd0819a39..f9b17d45e9f 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
@@ -37,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
                         cx,
                         MULTIPLE_CRATE_VERSIONS,
                         DUMMY_SP,
-                        &format!("multiple versions for dependency `{}`: {}", name, versions),
+                        &format!("multiple versions for dependency `{name}`: {versions}"),
                     );
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
index 6e1f8cd64f0..294d22d34de 100644
--- a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
             expr.span,
             "borrow as raw pointer",
             "try",
-            format!("{}::ptr::{}!({})", core_or_std, macro_name, snip),
+            format!("{core_or_std}::ptr::{macro_name}!({snip})"),
             Applicability::MachineApplicable,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index 938458e30ca..13c403234da 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -41,15 +41,9 @@ pub(super) fn check(
     );
 
     let message = if cast_from.is_bool() {
-        format!(
-            "casting `{0:}` to `{1:}` is more cleanly stated with `{1:}::from(_)`",
-            cast_from, cast_to
-        )
+        format!("casting `{cast_from:}` to `{cast_to:}` is more cleanly stated with `{cast_to:}::from(_)`")
     } else {
-        format!(
-            "casting `{}` to `{}` may become silently lossy if you later change the type",
-            cast_from, cast_to
-        )
+        format!("casting `{cast_from}` to `{cast_to}` may become silently lossy if you later change the type")
     };
 
     span_lint_and_sugg(
@@ -58,7 +52,7 @@ pub(super) fn check(
         expr.span,
         &message,
         "try",
-        format!("{}::from({})", cast_to, sugg),
+        format!("{cast_to}::from({sugg})"),
         applicability,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 406547a4454..88deb4565eb 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -103,10 +103,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                 return;
             }
 
-            format!(
-                "casting `{}` to `{}` may truncate the value{}",
-                cast_from, cast_to, suffix,
-            )
+            format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
         },
 
         (ty::Adt(def, _), true) if def.is_enum() => {
@@ -142,20 +139,17 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                     CAST_ENUM_TRUNCATION,
                     expr.span,
                     &format!(
-                        "casting `{}::{}` to `{}` will truncate the value{}",
-                        cast_from, variant.name, cast_to, suffix,
+                        "casting `{cast_from}::{}` to `{cast_to}` will truncate the value{suffix}",
+                        variant.name,
                     ),
                 );
                 return;
             }
-            format!(
-                "casting `{}` to `{}` may truncate the value{}",
-                cast_from, cast_to, suffix,
-            )
+            format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
         },
 
         (ty::Float(_), true) => {
-            format!("casting `{}` to `{}` may truncate the value", cast_from, cast_to)
+            format!("casting `{cast_from}` to `{cast_to}` may truncate the value")
         },
 
         (ty::Float(FloatTy::F64), false) if matches!(cast_to.kind(), &ty::Float(FloatTy::F32)) => {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
index 2c5c1d7cb46..28ecdea7ea0 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -35,10 +35,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
             cx,
             CAST_POSSIBLE_WRAP,
             expr.span,
-            &format!(
-                "casting `{}` to `{}` may wrap around the value{}",
-                cast_from, cast_to, suffix,
-            ),
+            &format!("casting `{cast_from}` to `{cast_to}` may wrap around the value{suffix}",),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
index da7b12f6726..97054a0d101 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -49,9 +49,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f
             CAST_PTR_ALIGNMENT,
             expr.span,
             &format!(
-                "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
-                cast_from,
-                cast_to,
+                "casting from `{cast_from}` to a more-strictly-aligned pointer (`{cast_to}`) ({} < {} bytes)",
                 from_layout.align.abi.bytes(),
                 to_layout.align.abi.bytes(),
             ),
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 5b59350be04..a20a97d4e56 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -14,10 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, c
             cx,
             CAST_SIGN_LOSS,
             expr.span,
-            &format!(
-                "casting `{}` to `{}` may lose the sign of the value",
-                cast_from, cast_to
-            ),
+            &format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
index 027c660ce3b..d31d10d22b9 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -35,8 +35,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Optio
                     CAST_SLICE_DIFFERENT_SIZES,
                     expr.span,
                     &format!(
-                        "casting between raw pointers to `[{}]` (element size {}) and `[{}]` (element size {}) does not adjust the count",
-                        start_ty.ty, from_size, end_ty.ty, to_size,
+                        "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count",
+                        start_ty.ty, end_ty.ty,
                     ),
                     |diag| {
                         let ptr_snippet = source::snippet(cx, left_cast.span, "..");
diff --git a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
index 7cc406018db..82e07c98a7e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
@@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
                         diag.span_suggestion(
                             expr.span,
                             "use a byte literal instead",
-                            format!("b{}", snippet),
+                            format!("b{snippet}"),
                             applicability,
                         );
                     }
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
index 35350d8a25b..a26bfab4e7c 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
@@ -25,9 +25,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                     cx,
                     FN_TO_NUMERIC_CAST,
                     expr.span,
-                    &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
+                    &format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
                     "try",
-                    format!("{} as usize", from_snippet),
+                    format!("{from_snippet} as usize"),
                     applicability,
                 );
             }
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
index 03621887a34..75654129408 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
@@ -23,9 +23,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                 cx,
                 FN_TO_NUMERIC_CAST_ANY,
                 expr.span,
-                &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
+                &format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
                 "did you mean to invoke the function?",
-                format!("{}() as {}", from_snippet, cast_to),
+                format!("{from_snippet}() as {cast_to}"),
                 applicability,
             );
         },
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
index 6287f479b5b..556be1d1506 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
@@ -24,12 +24,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                     cx,
                     FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
                     expr.span,
-                    &format!(
-                        "casting function pointer `{}` to `{}`, which truncates the value",
-                        from_snippet, cast_to
-                    ),
+                    &format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"),
                     "try",
-                    format!("{} as usize", from_snippet),
+                    format!("{from_snippet} as usize"),
                     applicability,
                 );
             }
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index 46d45d09661..c2b9253ec35 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -33,7 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option<RustcVer
             let turbofish = match &cast_to_hir_ty.kind {
                     TyKind::Infer => Cow::Borrowed(""),
                     TyKind::Ptr(mut_ty) if matches!(mut_ty.ty.kind, TyKind::Infer) => Cow::Borrowed(""),
-                    _ => Cow::Owned(format!("::<{}>", to_pointee_ty)),
+                    _ => Cow::Owned(format!("::<{to_pointee_ty}>")),
                 };
             span_lint_and_sugg(
                 cx,
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option<RustcVer
                 expr.span,
                 "`as` casting between raw pointers without changing its mutability",
                 "try `pointer::cast`, a safer alternative",
-                format!("{}.cast{}()", cast_expr_sugg.maybe_par(), turbofish),
+                format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
                 applicability,
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index 19d2e6e1d12..21ed7f4844c 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::get_parent_expr;
 use clippy_utils::numeric_literal::NumericLiteral;
 use clippy_utils::source::snippet_opt;
 use if_chain::if_chain;
@@ -30,8 +31,10 @@ pub(super) fn check<'tcx>(
         }
     }
 
+    let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
+
     if let Some(lit) = get_numeric_literal(cast_expr) {
-        let literal_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
+        let literal_str = &cast_str;
 
         if_chain! {
             if let LitKind::Int(n, _) = lit.node;
@@ -49,12 +52,16 @@ pub(super) fn check<'tcx>(
 
         match lit.node {
             LitKind::Int(_, LitIntType::Unsuffixed) if cast_to.is_integral() => {
-                lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
+                lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
+                return false;
             },
             LitKind::Float(_, LitFloatType::Unsuffixed) if cast_to.is_floating_point() => {
-                lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
+                lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
+                return false;
+            },
+            LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {
+                return false;
             },
-            LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {},
             LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_))
             | LitKind::Float(_, LitFloatType::Suffixed(_))
                 if cast_from.kind() == cast_to.kind() =>
@@ -62,48 +69,62 @@ pub(super) fn check<'tcx>(
                 if let Some(src) = snippet_opt(cx, cast_expr.span) {
                     if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
                         lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
+                        return true;
                     }
                 }
             },
-            _ => {
-                if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
-                    span_lint_and_sugg(
-                        cx,
-                        UNNECESSARY_CAST,
-                        expr.span,
-                        &format!(
-                            "casting to the same type is unnecessary (`{}` -> `{}`)",
-                            cast_from, cast_to
-                        ),
-                        "try",
-                        literal_str,
-                        Applicability::MachineApplicable,
-                    );
-                    return true;
-                }
-            },
+            _ => {},
         }
     }
 
+    if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_CAST,
+            expr.span,
+            &format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
+            "try",
+            cast_str,
+            Applicability::MachineApplicable,
+        );
+        return true;
+    }
+
     false
 }
 
-fn lint_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &str, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+fn lint_unnecessary_cast(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    raw_literal_str: &str,
+    cast_from: Ty<'_>,
+    cast_to: Ty<'_>,
+) {
     let literal_kind_name = if cast_from.is_integral() { "integer" } else { "float" };
-    let replaced_literal;
-    let matchless = if literal_str.contains(['(', ')']) {
-        replaced_literal = literal_str.replace(['(', ')'], "");
-        &replaced_literal
-    } else {
-        literal_str
+    // first we remove all matches so `-(1)` become `-1`, and remove trailing dots, so `1.` become `1`
+    let literal_str = raw_literal_str
+        .replace(['(', ')'], "")
+        .trim_end_matches('.')
+        .to_string();
+    // we know need to check if the parent is a method call, to add parenthesis accordingly (eg:
+    // (-1).foo() instead of -1.foo())
+    let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
+        && let ExprKind::MethodCall(..) = parent_expr.kind
+        && literal_str.starts_with('-')
+        {
+            format!("({literal_str}_{cast_to})")
+
+        } else {
+            format!("{literal_str}_{cast_to}")
     };
+
     span_lint_and_sugg(
         cx,
         UNNECESSARY_CAST,
         expr.span,
-        &format!("casting {} literal to `{}` is unnecessary", literal_kind_name, cast_to),
+        &format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
         "try",
-        format!("{}_{}", matchless.trim_end_matches('.'), cast_to),
+        sugg,
         Applicability::MachineApplicable,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index 37b2fdcff09..78e9921f036 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -2,9 +2,8 @@
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{in_constant, meets_msrv, msrvs, SpanlessEq};
+use clippy_utils::{in_constant, is_integer_literal, meets_msrv, msrvs, SpanlessEq};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -82,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
                     item.span,
                     "checked cast can be simplified",
                     "try",
-                    format!("{}::try_from({}).is_ok()", to_type, snippet),
+                    format!("{to_type}::try_from({snippet}).is_ok()"),
                     applicability,
                 );
             }
@@ -223,16 +222,7 @@ fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
 
 /// Check for `expr >= 0`
 fn check_lower_bound_zero<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> {
-    if_chain! {
-        if let ExprKind::Lit(ref lit) = &check.kind;
-        if let LitKind::Int(0, _) = &lit.node;
-
-        then {
-            Some(Conversion::new_any(candidate))
-        } else {
-            None
-        }
-    }
+    is_integer_literal(check, 0).then(|| Conversion::new_any(candidate))
 }
 
 /// Check for `expr >= (to_type::MIN as from_type)`
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 33c44f8b2db..77af3b53d63 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -3,10 +3,12 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::for_each_expr;
 use clippy_utils::LimitStack;
+use core::ops::ControlFlow;
 use rustc_ast::ast::Attribute;
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, ExprKind, FnDecl, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
@@ -61,11 +63,27 @@ impl CognitiveComplexity {
             return;
         }
 
-        let expr = &body.value;
+        let expr = body.value;
+
+        let mut cc = 1u64;
+        let mut returns = 0u64;
+        let _: Option<!> = for_each_expr(expr, |e| {
+            match e.kind {
+                ExprKind::If(_, _, _) => {
+                    cc += 1;
+                },
+                ExprKind::Match(_, arms, _) => {
+                    if arms.len() > 1 {
+                        cc += 1;
+                    }
+                    cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64;
+                },
+                ExprKind::Ret(_) => returns += 1,
+                _ => {},
+            }
+            ControlFlow::Continue(())
+        });
 
-        let mut helper = CcHelper { cc: 1, returns: 0 };
-        helper.visit_expr(expr);
-        let CcHelper { cc, returns } = helper;
         let ret_ty = cx.typeck_results().node_type(expr.hir_id);
         let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::Result) {
             returns
@@ -74,13 +92,12 @@ impl CognitiveComplexity {
             (returns / 2)
         };
 
-        let mut rust_cc = cc;
         // prevent degenerate cases where unreachable code contains `return` statements
-        if rust_cc >= ret_adjust {
-            rust_cc -= ret_adjust;
+        if cc >= ret_adjust {
+            cc -= ret_adjust;
         }
 
-        if rust_cc > self.limit.limit() {
+        if cc > self.limit.limit() {
             let fn_span = match kind {
                 FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
                 FnKind::Closure => {
@@ -107,8 +124,7 @@ impl CognitiveComplexity {
                 COGNITIVE_COMPLEXITY,
                 fn_span,
                 &format!(
-                    "the function has a cognitive complexity of ({}/{})",
-                    rust_cc,
+                    "the function has a cognitive complexity of ({cc}/{})",
                     self.limit.limit()
                 ),
                 None,
@@ -141,27 +157,3 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
         self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity");
     }
 }
-
-struct CcHelper {
-    cc: u64,
-    returns: u64,
-}
-
-impl<'tcx> Visitor<'tcx> for CcHelper {
-    fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
-        walk_expr(self, e);
-        match e.kind {
-            ExprKind::If(_, _, _) => {
-                self.cc += 1;
-            },
-            ExprKind::Match(_, arms, _) => {
-                if arms.len() > 1 {
-                    self.cc += 1;
-                }
-                self.cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64;
-            },
-            ExprKind::Ret(_) => self.returns += 1,
-            _ => {},
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 4e68d6810e2..7f937de1dd3 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                     cx,
                     DEFAULT_TRAIT_ACCESS,
                     expr.span,
-                    &format!("calling `{}` is more clear than this expression", replacement),
+                    &format!("calling `{replacement}` is more clear than this expression"),
                     "try",
                     replacement,
                     Applicability::Unspecified, // First resolve the TODO above
@@ -210,7 +210,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                     .map(|(field, rhs)| {
                         // extract and store the assigned value for help message
                         let value_snippet = snippet_with_macro_callsite(cx, rhs.span, "..");
-                        format!("{}: {}", field, value_snippet)
+                        format!("{field}: {value_snippet}")
                     })
                     .collect::<Vec<String>>()
                     .join(", ");
@@ -227,7 +227,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                             .map(ToString::to_string)
                             .collect::<Vec<_>>()
                             .join(", ");
-                        format!("{}::<{}>", adt_def_ty_name, &tys_str)
+                        format!("{adt_def_ty_name}::<{}>", &tys_str)
                     } else {
                         binding_type.to_string()
                     }
@@ -235,12 +235,12 @@ impl<'tcx> LateLintPass<'tcx> for Default {
 
                 let sugg = if ext_with_default {
                     if field_list.is_empty() {
-                        format!("{}::default()", binding_type)
+                        format!("{binding_type}::default()")
                     } else {
-                        format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
+                        format!("{binding_type} {{ {field_list}, ..Default::default() }}")
                     }
                 } else {
-                    format!("{} {{ {} }}", binding_type, field_list)
+                    format!("{binding_type} {{ {field_list} }}")
                 };
 
                 // span lint once per statement that binds default
@@ -250,10 +250,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                     first_assign.unwrap().span,
                     "field assignment outside of initializer for an instance created with Default::default()",
                     Some(local.span),
-                    &format!(
-                        "consider initializing the variable with `{}` and removing relevant reassignments",
-                        sugg
-                    ),
+                    &format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
                 );
                 self.reassigned_linted.insert(span);
             }
diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
index 3c996d3d2ae..1ad929864b2 100644
--- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -23,7 +23,7 @@ declare_clippy_lint! {
     /// let _ = std::iter::empty::<usize>();
     /// let iter: std::iter::Empty<usize> = std::iter::empty();
     /// ```
-    #[clippy::version = "1.63.0"]
+    #[clippy::version = "1.64.0"]
     pub DEFAULT_INSTEAD_OF_ITER_EMPTY,
     style,
     "check `std::iter::Empty::default()` and replace with `std::iter::empty()`"
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index be02f328e98..3ed9cd36a22 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -95,8 +95,8 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
                         src
                     } else {
                         match lit.node {
-                            LitKind::Int(src, _) => format!("{}", src),
-                            LitKind::Float(src, _) => format!("{}", src),
+                            LitKind::Int(src, _) => format!("{src}"),
+                            LitKind::Float(src, _) => format!("{src}"),
                             _ => return,
                         }
                     };
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index 3905a6c2e21..741edc13196 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{self as hir, HirId, Item, ItemKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index f0d5ed6f594..3cd8f236e7a 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -135,7 +135,7 @@ declare_clippy_lint! {
     /// let x = String::new();
     /// let y: &str = &x;
     /// ```
-    #[clippy::version = "1.60.0"]
+    #[clippy::version = "1.64.0"]
     pub EXPLICIT_AUTO_DEREF,
     complexity,
     "dereferencing when the compiler would automatically dereference"
@@ -184,6 +184,7 @@ impl Dereferencing {
     }
 }
 
+#[derive(Debug)]
 struct StateData {
     /// Span of the top level expression
     span: Span,
@@ -191,12 +192,14 @@ struct StateData {
     position: Position,
 }
 
+#[derive(Debug)]
 struct DerefedBorrow {
     count: usize,
     msg: &'static str,
     snip_expr: Option<HirId>,
 }
 
+#[derive(Debug)]
 enum State {
     // Any number of deref method calls.
     DerefMethod {
@@ -276,10 +279,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
             (None, kind) => {
                 let expr_ty = typeck.expr_ty(expr);
                 let (position, adjustments) = walk_parents(cx, expr, self.msrv);
-
                 match kind {
                     RefOp::Deref => {
-                        if let Position::FieldAccess(name) = position
+                        if let Position::FieldAccess {
+                            name,
+                            of_union: false,
+                        } = position
                             && !ty_contains_field(typeck.expr_ty(sub_expr), name)
                         {
                             self.state = Some((
@@ -451,7 +456,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
             (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
                 let position = data.position;
                 report(cx, expr, State::DerefedBorrow(state), data);
-                if let Position::FieldAccess(name) = position
+                if let Position::FieldAccess{name, ..} = position
                     && !ty_contains_field(typeck.expr_ty(sub_expr), name)
                 {
                     self.state = Some((
@@ -616,14 +621,17 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
 }
 
 /// The position of an expression relative to it's parent.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 enum Position {
     MethodReceiver,
     /// The method is defined on a reference type. e.g. `impl Foo for &T`
     MethodReceiverRefImpl,
     Callee,
     ImplArg(HirId),
-    FieldAccess(Symbol),
+    FieldAccess {
+        name: Symbol,
+        of_union: bool,
+    }, // union fields cannot be auto borrowed
     Postfix,
     Deref,
     /// Any other location which will trigger auto-deref to a specific time.
@@ -645,7 +653,10 @@ impl Position {
     }
 
     fn can_auto_borrow(self) -> bool {
-        matches!(self, Self::MethodReceiver | Self::FieldAccess(_) | Self::Callee)
+        matches!(
+            self,
+            Self::MethodReceiver | Self::FieldAccess { of_union: false, .. } | Self::Callee
+        )
     }
 
     fn lint_explicit_deref(self) -> bool {
@@ -657,7 +668,7 @@ impl Position {
             Self::MethodReceiver
             | Self::MethodReceiverRefImpl
             | Self::Callee
-            | Self::FieldAccess(_)
+            | Self::FieldAccess { .. }
             | Self::Postfix => PREC_POSTFIX,
             Self::ImplArg(_) | Self::Deref => PREC_PREFIX,
             Self::DerefStable(p, _) | Self::ReborrowStable(p) | Self::Other(p) => p,
@@ -844,7 +855,10 @@ fn walk_parents<'tcx>(
                         }
                     })
                 },
-                ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
+                ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess {
+                    name: name.name,
+                    of_union: is_union(cx.typeck_results(), child),
+                }),
                 ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
                 ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
                 | ExprKind::Index(child, _)
@@ -865,6 +879,13 @@ fn walk_parents<'tcx>(
     (position, adjustments)
 }
 
+fn is_union<'tcx>(typeck: &'tcx TypeckResults<'_>, path_expr: &'tcx Expr<'_>) -> bool {
+    typeck
+        .expr_ty_adjusted(path_expr)
+        .ty_adt_def()
+        .map_or(false, rustc_middle::ty::AdtDef::is_union)
+}
+
 fn closure_result_position<'tcx>(
     cx: &LateContext<'tcx>,
     closure: &'tcx Closure<'_>,
@@ -1308,7 +1329,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             };
 
             let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
-                format!("({})", expr_str)
+                format!("({expr_str})")
             } else {
                 expr_str.into_owned()
             };
@@ -1322,7 +1343,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
                     Mutability::Mut => "explicit `deref_mut` method call",
                 },
                 "try this",
-                format!("{}{}{}", addr_of_str, deref_str, expr_str),
+                format!("{addr_of_str}{deref_str}{expr_str}"),
                 app,
             );
         },
@@ -1336,7 +1357,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
                     && !has_enclosing_paren(&snip)
                     && (expr.precedence().order() < data.position.precedence() || calls_field)
                 {
-                    format!("({})", snip)
+                    format!("({snip})")
                 } else {
                     snip.into()
                 };
@@ -1379,9 +1400,9 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
                     let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
                     let sugg =
                         if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) {
-                            format!("{}({})", prefix, snip)
+                            format!("{prefix}({snip})")
                         } else {
-                            format!("{}{}", prefix, snip)
+                            format!("{prefix}{snip}")
                         };
                     diag.span_suggestion(data.span, "try this", sugg, app);
                 },
@@ -1460,14 +1481,14 @@ impl Dereferencing {
                             } else {
                                 pat.always_deref = false;
                                 let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
-                                pat.replacements.push((e.span, format!("&{}", snip)));
+                                pat.replacements.push((e.span, format!("&{snip}")));
                             }
                         },
                         _ if !e.span.from_expansion() => {
                             // Double reference might be needed at this point.
                             pat.always_deref = false;
                             let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
-                            pat.replacements.push((e.span, format!("&{}", snip)));
+                            pat.replacements.push((e.span, format!("&{snip}")));
                         },
                         // Edge case for macros. The span of the identifier will usually match the context of the
                         // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 751ca24d5f5..3fac93dcc90 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -191,7 +191,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.63.0"]
     pub DERIVE_PARTIAL_EQ_WITHOUT_EQ,
-    style,
+    nursery,
     "deriving `PartialEq` on a type that can implement `Eq`, without implementing `Eq`"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
new file mode 100644
index 00000000000..5ab7144e290
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -0,0 +1,151 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::macro_backtrace;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def_id::DefIdMap;
+use rustc_hir::{Expr, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{ExpnId, Span};
+
+use crate::utils::conf;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Denies the configured macros in clippy.toml
+    ///
+    /// Note: Even though this lint is warn-by-default, it will only trigger if
+    /// macros are defined in the clippy.toml file.
+    ///
+    /// ### Why is this bad?
+    /// Some macros are undesirable in certain contexts, and it's beneficial to
+    /// lint for them as needed.
+    ///
+    /// ### Example
+    /// An example clippy.toml configuration:
+    /// ```toml
+    /// # clippy.toml
+    /// disallowed-macros = [
+    ///     # Can use a string as the path of the disallowed macro.
+    ///     "std::print",
+    ///     # Can also use an inline table with a `path` key.
+    ///     { path = "std::println" },
+    ///     # When using an inline table, can add a `reason` for why the macro
+    ///     # is disallowed.
+    ///     { path = "serde::Serialize", reason = "no serializing" },
+    /// ]
+    /// ```
+    /// ```
+    /// use serde::Serialize;
+    ///
+    /// // Example code where clippy issues a warning
+    /// println!("warns");
+    ///
+    /// // The diagnostic will contain the message "no serializing"
+    /// #[derive(Serialize)]
+    /// struct Data {
+    ///     name: String,
+    ///     value: usize,
+    /// }
+    /// ```
+    #[clippy::version = "1.65.0"]
+    pub DISALLOWED_MACROS,
+    style,
+    "use of a disallowed macro"
+}
+
+pub struct DisallowedMacros {
+    conf_disallowed: Vec<conf::DisallowedPath>,
+    disallowed: DefIdMap<usize>,
+    seen: FxHashSet<ExpnId>,
+}
+
+impl DisallowedMacros {
+    pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
+        Self {
+            conf_disallowed,
+            disallowed: DefIdMap::default(),
+            seen: FxHashSet::default(),
+        }
+    }
+
+    fn check(&mut self, cx: &LateContext<'_>, span: Span) {
+        if self.conf_disallowed.is_empty() {
+            return;
+        }
+
+        for mac in macro_backtrace(span) {
+            if !self.seen.insert(mac.expn) {
+                return;
+            }
+
+            if let Some(&index) = self.disallowed.get(&mac.def_id) {
+                let conf = &self.conf_disallowed[index];
+
+                span_lint_and_then(
+                    cx,
+                    DISALLOWED_MACROS,
+                    mac.span,
+                    &format!("use of a disallowed macro `{}`", conf.path()),
+                    |diag| {
+                        if let Some(reason) = conf.reason() {
+                            diag.note(&format!("{reason} (from clippy.toml)"));
+                        }
+                    },
+                );
+            }
+        }
+    }
+}
+
+impl_lint_pass!(DisallowedMacros => [DISALLOWED_MACROS]);
+
+impl LateLintPass<'_> for DisallowedMacros {
+    fn check_crate(&mut self, cx: &LateContext<'_>) {
+        for (index, conf) in self.conf_disallowed.iter().enumerate() {
+            let segs: Vec<_> = conf.path().split("::").collect();
+            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::MacroNS)) {
+                self.disallowed.insert(id, index);
+            }
+        }
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        self.check(cx, expr.span);
+    }
+
+    fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+        self.check(cx, stmt.span);
+    }
+
+    fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_>) {
+        self.check(cx, ty.span);
+    }
+
+    fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
+        self.check(cx, pat.span);
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        self.check(cx, item.span);
+        self.check(cx, item.vis_span);
+    }
+
+    fn check_foreign_item(&mut self, cx: &LateContext<'_>, item: &ForeignItem<'_>) {
+        self.check(cx, item.span);
+        self.check(cx, item.vis_span);
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &ImplItem<'_>) {
+        self.check(cx, item.span);
+        self.check(cx, item.vis_span);
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
+        self.check(cx, item.span);
+    }
+
+    fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, _: HirId) {
+        self.check(cx, path.span);
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
index 53973ab792a..1a381f92c03 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
@@ -1,7 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
 
-use rustc_hir::{def::Res, def_id::DefIdMap, Expr, ExprKind};
+use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def_id::DefIdMap;
+use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
@@ -58,12 +60,12 @@ declare_clippy_lint! {
 
 #[derive(Clone, Debug)]
 pub struct DisallowedMethods {
-    conf_disallowed: Vec<conf::DisallowedMethod>,
+    conf_disallowed: Vec<conf::DisallowedPath>,
     disallowed: DefIdMap<usize>,
 }
 
 impl DisallowedMethods {
-    pub fn new(conf_disallowed: Vec<conf::DisallowedMethod>) -> Self {
+    pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
         Self {
             conf_disallowed,
             disallowed: DefIdMap::default(),
@@ -77,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for (index, conf) in self.conf_disallowed.iter().enumerate() {
             let segs: Vec<_> = conf.path().split("::").collect();
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs) {
+            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::ValueNS)) {
                 self.disallowed.insert(id, index);
             }
         }
@@ -102,11 +104,8 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
         };
         let msg = format!("use of a disallowed method `{}`", conf.path());
         span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
-            if let conf::DisallowedMethod::WithReason {
-                reason: Some(reason), ..
-            } = conf
-            {
-                diag.note(&format!("{} (from clippy.toml)", reason));
+            if let Some(reason) = conf.reason() {
+                diag.note(&format!("{reason} (from clippy.toml)"));
             }
         });
     }
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
index 0c27c3f9255..084190f0013 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
@@ -99,8 +99,7 @@ impl EarlyLintPass for DisallowedScriptIdents {
                         DISALLOWED_SCRIPT_IDENTS,
                         span,
                         &format!(
-                            "identifier `{}` has a Unicode script that is not allowed by configuration: {}",
-                            symbol_str,
+                            "identifier `{symbol_str}` has a Unicode script that is not allowed by configuration: {}",
                             script.full_name()
                         ),
                     );
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
index 28dbfbab2e1..c7131fc164d 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::{
-    def::Res, def_id::DefId, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind,
-};
+use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
@@ -52,13 +52,13 @@ declare_clippy_lint! {
 }
 #[derive(Clone, Debug)]
 pub struct DisallowedTypes {
-    conf_disallowed: Vec<conf::DisallowedType>,
+    conf_disallowed: Vec<conf::DisallowedPath>,
     def_ids: FxHashMap<DefId, Option<String>>,
     prim_tys: FxHashMap<PrimTy, Option<String>>,
 }
 
 impl DisallowedTypes {
-    pub fn new(conf_disallowed: Vec<conf::DisallowedType>) -> Self {
+    pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
         Self {
             conf_disallowed,
             def_ids: FxHashMap::default(),
@@ -88,15 +88,9 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
 impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for conf in &self.conf_disallowed {
-            let (path, reason) = match conf {
-                conf::DisallowedType::Simple(path) => (path, None),
-                conf::DisallowedType::WithReason { path, reason } => (
-                    path,
-                    reason.as_ref().map(|reason| format!("{} (from clippy.toml)", reason)),
-                ),
-            };
-            let segs: Vec<_> = path.split("::").collect();
-            match clippy_utils::def_path_res(cx, &segs) {
+            let segs: Vec<_> = conf.path().split("::").collect();
+            let reason = conf.reason().map(|reason| format!("{reason} (from clippy.toml)"));
+            match clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
                 Res::Def(_, id) => {
                     self.def_ids.insert(id, reason);
                 },
@@ -130,7 +124,7 @@ fn emit(cx: &LateContext<'_>, name: &str, span: Span, reason: Option<&str>) {
         cx,
         DISALLOWED_TYPES,
         span,
-        &format!("`{}` is not allowed according to config", name),
+        &format!("`{name}` is not allowed according to config"),
         |diag| {
             if let Some(reason) = reason {
                 diag.note(reason);
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index f48ba526d51..36dc7e3396b 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -198,6 +198,29 @@ declare_clippy_lint! {
     "presence of `fn main() {` in code examples"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks)
+    /// outside of code blocks
+    /// ### Why is this bad?
+    /// It is likely a typo when defining an intra-doc link
+    ///
+    /// ### Example
+    /// ```rust
+    /// /// See also: ['foo']
+    /// fn bar() {}
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// /// See also: [`foo`]
+    /// fn bar() {}
+    /// ```
+    #[clippy::version = "1.63.0"]
+    pub DOC_LINK_WITH_QUOTES,
+    pedantic,
+    "possible typo for an intra-doc link"
+}
+
 #[expect(clippy::module_name_repetitions)]
 #[derive(Clone)]
 pub struct DocMarkdown {
@@ -214,9 +237,14 @@ impl DocMarkdown {
     }
 }
 
-impl_lint_pass!(DocMarkdown =>
-    [DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, NEEDLESS_DOCTEST_MAIN]
-);
+impl_lint_pass!(DocMarkdown => [
+    DOC_LINK_WITH_QUOTES,
+    DOC_MARKDOWN,
+    MISSING_SAFETY_DOC,
+    MISSING_ERRORS_DOC,
+    MISSING_PANICS_DOC,
+    NEEDLESS_DOCTEST_MAIN
+]);
 
 impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
     fn check_crate(&mut self, cx: &LateContext<'tcx>) {
@@ -237,7 +265,15 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
                         panic_span: None,
                     };
                     fpu.visit_expr(body.value);
-                    lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
+                    lint_for_missing_headers(
+                        cx,
+                        item.def_id.def_id,
+                        item.span,
+                        sig,
+                        headers,
+                        Some(body_id),
+                        fpu.panic_span,
+                    );
                 }
             },
             hir::ItemKind::Impl(impl_) => {
@@ -287,7 +323,15 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
                 panic_span: None,
             };
             fpu.visit_expr(body.value);
-            lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
+            lint_for_missing_headers(
+                cx,
+                item.def_id.def_id,
+                item.span,
+                sig,
+                headers,
+                Some(body_id),
+                fpu.panic_span,
+            );
         }
     }
 }
@@ -416,7 +460,7 @@ pub fn strip_doc_comment_decoration(doc: &str, comment_kind: CommentKind, span:
     (no_stars, sizes)
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Default)]
 struct DocHeaders {
     safety: bool,
     errors: bool,
@@ -460,11 +504,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
     }
 
     if doc.is_empty() {
-        return DocHeaders {
-            safety: false,
-            errors: false,
-            panics: false,
-        };
+        return DocHeaders::default();
     }
 
     let mut cb = fake_broken_link_callback;
@@ -505,11 +545,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
     use pulldown_cmark::{CodeBlockKind, CowStr};
 
-    let mut headers = DocHeaders {
-        safety: false,
-        errors: false,
-        panics: false,
-    };
+    let mut headers = DocHeaders::default();
     let mut in_code = false;
     let mut in_link = None;
     let mut in_heading = false;
@@ -596,6 +632,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                         check_code(cx, &text, edition, span);
                     }
                 } else {
+                    check_link_quotes(cx, in_link.is_some(), trimmed_text, span, &range, begin, text.len());
                     // Adjust for the beginning of the current `Event`
                     let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin));
                     text_to_check.push((text, span));
@@ -606,6 +643,27 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     headers
 }
 
+fn check_link_quotes(
+    cx: &LateContext<'_>,
+    in_link: bool,
+    trimmed_text: &str,
+    span: Span,
+    range: &Range<usize>,
+    begin: usize,
+    text_len: usize,
+) {
+    if in_link && trimmed_text.starts_with('\'') && trimmed_text.ends_with('\'') {
+        // fix the span to only point at the text within the link
+        let lo = span.lo() + BytePos::from_usize(range.start - begin);
+        span_lint(
+            cx,
+            DOC_LINK_WITH_QUOTES,
+            span.with_lo(lo).with_hi(lo + BytePos::from_usize(text_len)),
+            "possible intra-doc link using quotes instead of backticks",
+        );
+    }
+}
+
 fn get_current_span(spans: &[(usize, Span)], idx: usize) -> (usize, Span) {
     let index = match spans.binary_search_by(|c| c.0.cmp(&idx)) {
         Ok(o) => o,
@@ -790,7 +848,7 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
                 diag.span_suggestion_with_style(
                     span,
                     "try",
-                    format!("`{}`", snippet),
+                    format!("`{snippet}`"),
                     applicability,
                     // always show the suggestion in a separate line, since the
                     // inline presentation adds another pair of backticks
diff --git a/src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs b/src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs
deleted file mode 100644
index 0ff1d2755da..00000000000
--- a/src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use itertools::Itertools;
-use rustc_ast::{AttrKind, Attribute};
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks)
-    /// outside of code blocks
-    /// ### Why is this bad?
-    /// It is likely a typo when defining an intra-doc link
-    ///
-    /// ### Example
-    /// ```rust
-    /// /// See also: ['foo']
-    /// fn bar() {}
-    /// ```
-    /// Use instead:
-    /// ```rust
-    /// /// See also: [`foo`]
-    /// fn bar() {}
-    /// ```
-    #[clippy::version = "1.63.0"]
-    pub DOC_LINK_WITH_QUOTES,
-    pedantic,
-    "possible typo for an intra-doc link"
-}
-declare_lint_pass!(DocLinkWithQuotes => [DOC_LINK_WITH_QUOTES]);
-
-impl EarlyLintPass for DocLinkWithQuotes {
-    fn check_attribute(&mut self, ctx: &EarlyContext<'_>, attr: &Attribute) {
-        if let AttrKind::DocComment(_, symbol) = attr.kind {
-            if contains_quote_link(symbol.as_str()) {
-                span_lint(
-                    ctx,
-                    DOC_LINK_WITH_QUOTES,
-                    attr.span,
-                    "possible intra-doc link using quotes instead of backticks",
-                );
-            }
-        }
-    }
-}
-
-fn contains_quote_link(s: &str) -> bool {
-    let mut in_backticks = false;
-    let mut found_opening = false;
-
-    for c in s.chars().tuple_windows::<(char, char)>() {
-        match c {
-            ('`', _) => in_backticks = !in_backticks,
-            ('[', '\'') if !in_backticks => found_opening = true,
-            ('\'', ']') if !in_backticks && found_opening => return true,
-            _ => {},
-        }
-    }
-
-    false
-}
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index b35f0b8ca52..4721a7b3705 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -1,7 +1,8 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
+use clippy_utils::get_parent_node;
 use clippy_utils::is_must_use_func_call;
 use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item};
-use rustc_hir::{Expr, ExprKind, LangItem};
+use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -202,11 +203,13 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
             && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
         {
             let arg_ty = cx.typeck_results().expr_ty(arg);
+            let is_copy = is_copy(cx, arg_ty);
+            let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             let (lint, msg) = match fn_name {
                 sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY),
                 sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
-                sym::mem_drop if is_copy(cx, arg_ty) => (DROP_COPY, DROP_COPY_SUMMARY),
-                sym::mem_forget if is_copy(cx, arg_ty) => (FORGET_COPY, FORGET_COPY_SUMMARY),
+                sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
+                sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
                 sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => {
                     span_lint_and_help(
                         cx,
@@ -221,7 +224,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                 sym::mem_drop
                     if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
                         || is_must_use_func_call(cx, arg)
-                        || is_must_use_ty(cx, arg_ty)) =>
+                        || is_must_use_ty(cx, arg_ty)
+                        || drop_is_single_call_in_arm
+                        ) =>
                 {
                     (DROP_NON_DROP, DROP_NON_DROP_SUMMARY)
                 },
@@ -236,8 +241,23 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                 expr.span,
                 msg,
                 Some(arg.span),
-                &format!("argument has type `{}`", arg_ty),
+                &format!("argument has type `{arg_ty}`"),
             );
         }
     }
 }
+
+// dropping returned value of a function like in the following snippet is considered idiomatic, see
+// #9482 for examples match <var> {
+//     <pat> => drop(fn_with_side_effect_and_returning_some_value()),
+//     ..
+// }
+fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool {
+    if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
+        let parent_node = get_parent_node(cx.tcx, drop_expr.hir_id);
+        if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
+            return body.hir_id == drop_expr.hir_id;
+        }
+    }
+    false
+}
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index e70df3f53c7..9c834cf0144 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -113,13 +113,8 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                     ),
                 };
                 format!(
-                    "if let {}::{} = {}.entry({}) {} else {}",
+                    "if let {}::{entry_kind} = {map_str}.entry({key_str}) {then_str} else {else_str}",
                     map_ty.entry_path(),
-                    entry_kind,
-                    map_str,
-                    key_str,
-                    then_str,
-                    else_str,
                 )
             } else {
                 // if .. { insert } else { insert }
@@ -137,16 +132,11 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 let indent_str = snippet_indent(cx, expr.span);
                 let indent_str = indent_str.as_deref().unwrap_or("");
                 format!(
-                    "match {}.entry({}) {{\n{indent}    {entry}::{} => {}\n\
-                        {indent}    {entry}::{} => {}\n{indent}}}",
-                    map_str,
-                    key_str,
-                    then_entry,
+                    "match {map_str}.entry({key_str}) {{\n{indent_str}    {entry}::{then_entry} => {}\n\
+                        {indent_str}    {entry}::{else_entry} => {}\n{indent_str}}}",
                     reindent_multiline(then_str.into(), true, Some(4 + indent_str.len())),
-                    else_entry,
                     reindent_multiline(else_str.into(), true, Some(4 + indent_str.len())),
                     entry = map_ty.entry_path(),
-                    indent = indent_str,
                 )
             }
         } else {
@@ -163,20 +153,16 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                     then_search.snippet_occupied(cx, then_expr.span, &mut app)
                 };
                 format!(
-                    "if let {}::{} = {}.entry({}) {}",
+                    "if let {}::{entry_kind} = {map_str}.entry({key_str}) {body_str}",
                     map_ty.entry_path(),
-                    entry_kind,
-                    map_str,
-                    key_str,
-                    body_str,
                 )
             } else if let Some(insertion) = then_search.as_single_insertion() {
                 let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0;
                 if contains_expr.negated {
                     if insertion.value.can_have_side_effects() {
-                        format!("{}.entry({}).or_insert_with(|| {});", map_str, key_str, value_str)
+                        format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});")
                     } else {
-                        format!("{}.entry({}).or_insert({});", map_str, key_str, value_str)
+                        format!("{map_str}.entry({key_str}).or_insert({value_str});")
                     }
                 } else {
                     // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
@@ -186,7 +172,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
             } else {
                 let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app);
                 if contains_expr.negated {
-                    format!("{}.entry({}).or_insert_with(|| {});", map_str, key_str, block_str)
+                    format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});")
                 } else {
                     // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
                     // This would need to be a different lint.
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index c39a909b3cc..b019d07d53d 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -202,12 +202,11 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
         cx,
         ENUM_VARIANT_NAMES,
         span,
-        &format!("all variants have the same {}fix: `{}`", what, value),
+        &format!("all variants have the same {what}fix: `{value}`"),
         None,
         &format!(
-            "remove the {}fixes and use full paths to \
-             the variants instead of glob imports",
-            what
+            "remove the {what}fixes and use full paths to \
+             the variants instead of glob imports"
         ),
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
index bce49165e5b..b40cb7cddaf 100644
--- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
+++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
@@ -51,9 +51,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
             false
         },
         PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
-        PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => {
-            !etc.as_opt_usize().is_some() && array_rec(a)
-        }
+        PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
         PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
         PatKind::Path(_) | PatKind::Lit(_) => true,
     }
@@ -93,9 +91,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
                     "this pattern matching can be expressed using equality",
                     "try",
                     format!(
-                        "{} == {}",
+                        "{} == {pat_str}",
                         snippet_with_context(cx, let_expr.init.span, expr.span.ctxt(), "..", &mut applicability).0,
-                        pat_str,
                     ),
                     applicability,
                 );
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 8ccc969646e..2e608fe527f 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_hir;
 use rustc_hir::intravisit;
 use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
@@ -10,7 +11,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::kw;
 use rustc_target::spec::abi::Abi;
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 #[derive(Copy, Clone)]
 pub struct BoxedLocal {
@@ -177,7 +177,13 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(
+        &mut self,
+        _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
+        _: FakeReadCause,
+        _: HirId,
+    ) {
+    }
 }
 
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 598f8c31859..3732410e71e 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::usage::local_used_after_expr;
 use clippy_utils::{higher, is_adjusted, path_to_local, path_to_local_id};
 use if_chain::if_chain;
@@ -11,7 +11,7 @@ use rustc_hir::{Closure, Expr, ExprKind, Param, PatKind, Unsafety};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::{self, ClosureKind, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
 
@@ -122,15 +122,12 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             then {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
                     if let Some(mut snippet) = snippet_opt(cx, callee.span) {
-                        if_chain! {
-                            if let ty::Closure(_, substs) = callee_ty.peel_refs().kind();
-                            if substs.as_closure().kind() == ClosureKind::FnMut;
-                            if path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr));
-
-                            then {
+                        if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait()
+                            && implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &[])
+                            && path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr))
+                        {
                                 // Mutable closure is used after current expr; we cannot consume it.
-                                snippet = format!("&mut {}", snippet);
-                            }
+                                snippet = format!("&mut {snippet}");
                         }
                         diag.span_suggestion(
                             expr.span,
@@ -157,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                     diag.span_suggestion(
                         expr.span,
                         "replace the closure with the method itself",
-                        format!("{}::{}", name, path.ident.name),
+                        format!("{name}::{}", path.ident.name),
                         Applicability::MachineApplicable,
                     );
                 })
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index f3d9ebc5f12..be6242bd20b 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -97,7 +97,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
                     item.span,
                     msg,
                     |diag| {
-                        let sugg = format!("#[non_exhaustive]\n{}", indent);
+                        let sugg = format!("#[non_exhaustive]\n{indent}");
                         diag.span_suggestion(suggestion_span,
                                              "try adding #[non_exhaustive]",
                                              sugg,
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index b9ed4af0219..c0ea6f338a2 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -80,12 +80,12 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                 // used.
                 let (used, sugg_mac) = if let Some(macro_name) = calling_macro {
                     (
-                        format!("{}!({}(), ...)", macro_name, dest_name),
+                        format!("{macro_name}!({dest_name}(), ...)"),
                         macro_name.replace("write", "print"),
                     )
                 } else {
                     (
-                        format!("{}().write_fmt(...)", dest_name),
+                        format!("{dest_name}().write_fmt(...)"),
                         "print".into(),
                     )
                 };
@@ -100,9 +100,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                     cx,
                     EXPLICIT_WRITE,
                     expr.span,
-                    &format!("use of `{}.unwrap()`", used),
+                    &format!("use of `{used}.unwrap()`"),
                     "try this",
-                    format!("{}{}!({})", prefix, sugg_mac, inputs_snippet),
+                    format!("{prefix}{sugg_mac}!({inputs_snippet})"),
                     applicability,
                 )
             }
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index f2e07980963..6fee7fb308c 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -173,9 +173,9 @@ impl FloatFormat {
         T: fmt::UpperExp + fmt::LowerExp + fmt::Display,
     {
         match self {
-            Self::LowerExp => format!("{:e}", f),
-            Self::UpperExp => format!("{:E}", f),
-            Self::Normal => format!("{}", f),
+            Self::LowerExp => format!("{f:e}"),
+            Self::UpperExp => format!("{f:E}"),
+            Self::Normal => format!("{f}"),
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index ba53a967880..0ed30196475 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -142,8 +142,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
         if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
         then {
             let op = format!(
-                "{}{}{}",
-                suggestion,
+                "{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('.') {
@@ -172,7 +171,7 @@ fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, ar
             expr.span,
             "logarithm for bases 2, 10 and e can be computed more accurately",
             "consider using",
-            format!("{}.{}()", Sugg::hir(cx, receiver, "..").maybe_par(), method),
+            format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_par()),
             Applicability::MachineApplicable,
         );
     }
@@ -251,7 +250,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
                 expr.span,
                 "exponent for bases 2 and e can be computed more accurately",
                 "consider using",
-                format!("{}.{}()", prepare_receiver_sugg(cx, &args[0]), method),
+                format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])),
                 Applicability::MachineApplicable,
             );
         }
@@ -312,7 +311,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
 
                 if let ExprKind::Binary(
                     Spanned {
-                        node: BinOpKind::Add, ..
+                        node: op @ (BinOpKind::Add | BinOpKind::Sub),
+                        ..
                     },
                     lhs,
                     rhs,
@@ -320,6 +320,16 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
                 {
                     let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
 
+                    // Negate expr if original code has subtraction and expr is on the right side
+                    let maybe_neg_sugg = |expr, hir_id| {
+                        let sugg = Sugg::hir(cx, expr, "..");
+                        if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
+                            format!("-{sugg}")
+                        } else {
+                            sugg.to_string()
+                        }
+                    };
+
                     span_lint_and_sugg(
                         cx,
                         SUBOPTIMAL_FLOPS,
@@ -329,8 +339,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
                         format!(
                             "{}.mul_add({}, {})",
                             Sugg::hir(cx, receiver, "..").maybe_par(),
-                            Sugg::hir(cx, receiver, ".."),
-                            Sugg::hir(cx, other_addend, ".."),
+                            maybe_neg_sugg(receiver, expr.hir_id),
+                            maybe_neg_sugg(other_addend, other_addend.hir_id),
                         ),
                         Applicability::MachineApplicable,
                     );
@@ -444,7 +454,8 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'
 fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if let ExprKind::Binary(
         Spanned {
-            node: BinOpKind::Add, ..
+            node: op @ (BinOpKind::Add | BinOpKind::Sub),
+            ..
         },
         lhs,
         rhs,
@@ -458,10 +469,27 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
             }
         }
 
+        let maybe_neg_sugg = |expr| {
+            let sugg = Sugg::hir(cx, expr, "..");
+            if let BinOpKind::Sub = op {
+                format!("-{sugg}")
+            } else {
+                sugg.to_string()
+            }
+        };
+
         let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
-            (inner_lhs, inner_rhs, rhs)
+            (
+                inner_lhs,
+                Sugg::hir(cx, inner_rhs, "..").to_string(),
+                maybe_neg_sugg(rhs),
+            )
         } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
-            (inner_lhs, inner_rhs, lhs)
+            (
+                inner_lhs,
+                maybe_neg_sugg(inner_rhs),
+                Sugg::hir(cx, lhs, "..").to_string(),
+            )
         } else {
             return;
         };
@@ -472,12 +500,7 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
             expr.span,
             "multiply and add expressions can be calculated more efficiently and accurately",
             "consider using",
-            format!(
-                "{}.mul_add({}, {})",
-                prepare_receiver_sugg(cx, recv),
-                Sugg::hir(cx, arg1, ".."),
-                Sugg::hir(cx, arg2, ".."),
-            ),
+            format!("{}.mul_add({arg1}, {arg2})", prepare_receiver_sugg(cx, recv)),
             Applicability::MachineApplicable,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index f10d8256953..bc0c68f535a 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
                 [_] => {
                     // Simulate macro expansion, converting {{ and }} to { and }.
                     let s_expand = format_args.format_string.snippet.replace("{{", "{").replace("}}", "}");
-                    let sugg = format!("{}.to_string()", s_expand);
+                    let sugg = format!("{s_expand}.to_string()");
                     span_useless_format(cx, call_site, sugg, applicability);
                 },
                 [..] => {},
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 9e1eaf248b7..cefebc2a98a 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -1,16 +1,18 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::is_diag_trait_item;
-use clippy_utils::macros::{is_format_macro, FormatArgsExpn};
+use clippy_utils::macros::FormatParamKind::{Implicit, Named, Numbered, Starred};
+use clippy_utils::macros::{is_format_macro, FormatArgsExpn, FormatParam, FormatParamUsage};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::{is_diag_trait_item, meets_msrv, msrvs};
 use if_chain::if_chain;
 use itertools::Itertools;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId};
+use rustc_hir::{Expr, ExprKind, HirId, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment};
 use rustc_middle::ty::Ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, ExpnData, ExpnKind, Span, Symbol};
 
 declare_clippy_lint! {
@@ -64,7 +66,67 @@ declare_clippy_lint! {
     "`to_string` applied to a type that implements `Display` in format args"
 }
 
-declare_lint_pass!(FormatArgs => [FORMAT_IN_FORMAT_ARGS, TO_STRING_IN_FORMAT_ARGS]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detect when a variable is not inlined in a format string,
+    /// and suggests to inline it.
+    ///
+    /// ### Why is this bad?
+    /// Non-inlined code is slightly more difficult to read and understand,
+    /// as it requires arguments to be matched against the format string.
+    /// The inlined syntax, where allowed, is simpler.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let var = 42;
+    /// # let width = 1;
+    /// # let prec = 2;
+    /// format!("{}", var);
+    /// format!("{v:?}", v = var);
+    /// format!("{0} {0}", var);
+    /// format!("{0:1$}", var, width);
+    /// format!("{:.*}", prec, var);
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let var = 42;
+    /// # let width = 1;
+    /// # let prec = 2;
+    /// format!("{var}");
+    /// format!("{var:?}");
+    /// format!("{var} {var}");
+    /// format!("{var:width$}");
+    /// format!("{var:.prec$}");
+    /// ```
+    ///
+    /// ### Known Problems
+    ///
+    /// There may be a false positive if the format string is expanded from certain proc macros:
+    ///
+    /// ```ignore
+    /// println!(indoc!("{}"), var);
+    /// ```
+    ///
+    /// If a format string contains a numbered argument that cannot be inlined
+    /// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
+    #[clippy::version = "1.65.0"]
+    pub UNINLINED_FORMAT_ARGS,
+    pedantic,
+    "using non-inlined variables in `format!` calls"
+}
+
+impl_lint_pass!(FormatArgs => [FORMAT_IN_FORMAT_ARGS, UNINLINED_FORMAT_ARGS, TO_STRING_IN_FORMAT_ARGS]);
+
+pub struct FormatArgs {
+    msrv: Option<RustcVersion>,
+}
+
+impl FormatArgs {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for FormatArgs {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -86,9 +148,72 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
                     check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value);
                     check_to_string_in_format_args(cx, name, arg.param.value);
                 }
+                if meets_msrv(self.msrv, msrvs::FORMAT_ARGS_CAPTURE) {
+                    check_uninlined_args(cx, &format_args, outermost_expn_data.call_site);
+                }
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
+}
+
+fn check_uninlined_args(cx: &LateContext<'_>, args: &FormatArgsExpn<'_>, call_site: Span) {
+    if args.format_string.span.from_expansion() {
+        return;
+    }
+
+    let mut fixes = Vec::new();
+    // If any of the arguments are referenced by an index number,
+    // and that argument is not a simple variable and cannot be inlined,
+    // we cannot remove any other arguments in the format string,
+    // because the index numbers might be wrong after inlining.
+    // Example of an un-inlinable format:  print!("{}{1}", foo, 2)
+    if !args.params().all(|p| check_one_arg(args, &p, &mut fixes)) || fixes.is_empty() {
+        return;
+    }
+
+    // FIXME: Properly ignore a rare case where the format string is wrapped in a macro.
+    // Example:  `format!(indoc!("{}"), foo);`
+    // If inlined, they will cause a compilation error:
+    //     > to avoid ambiguity, `format_args!` cannot capture variables
+    //     > when the format string is expanded from a macro
+    // @Alexendoo explanation:
+    //     > indoc! is a proc macro that is producing a string literal with its span
+    //     > set to its input it's not marked as from expansion, and since it's compatible
+    //     > tokenization wise clippy_utils::is_from_proc_macro wouldn't catch it either
+    // This might be a relatively expensive test, so do it only we are ready to replace.
+    // See more examples in tests/ui/uninlined_format_args.rs
+
+    span_lint_and_then(
+        cx,
+        UNINLINED_FORMAT_ARGS,
+        call_site,
+        "variables can be used directly in the `format!` string",
+        |diag| {
+            diag.multipart_suggestion("change this to", fixes, Applicability::MachineApplicable);
+        },
+    );
+}
+
+fn check_one_arg(args: &FormatArgsExpn<'_>, param: &FormatParam<'_>, fixes: &mut Vec<(Span, String)>) -> bool {
+    if matches!(param.kind, Implicit | Starred | Named(_) | Numbered)
+        && let ExprKind::Path(QPath::Resolved(None, path)) = param.value.kind
+        && let [segment] = path.segments
+        && let Some(arg_span) = args.value_with_prev_comma_span(param.value.hir_id)
+    {
+        let replacement = match param.usage {
+            FormatParamUsage::Argument => segment.ident.name.to_string(),
+            FormatParamUsage::Width => format!("{}$", segment.ident.name),
+            FormatParamUsage::Precision => format!(".{}$", segment.ident.name),
+        };
+        fixes.push((param.span, replacement));
+        fixes.push((arg_span, String::new()));
+        true  // successful inlining, continue checking
+    } else {
+        // if we can't inline a numbered argument, we can't continue
+        param.kind != Numbered
+    }
 }
 
 fn outermost_expn_data(expn_data: ExpnData) -> ExpnData {
@@ -117,11 +242,10 @@ fn check_format_in_format_args(
         cx,
         FORMAT_IN_FORMAT_ARGS,
         call_site,
-        &format!("`format!` in `{}!` args", name),
+        &format!("`format!` in `{name}!` args"),
         |diag| {
             diag.help(&format!(
-                "combine the `format!(..)` arguments with the outer `{}!(..)` call",
-                name
+                "combine the `format!(..)` arguments with the outer `{name}!(..)` call"
             ));
             diag.help("or consider changing `format!` to `format_args!`");
         },
@@ -149,8 +273,7 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
                     TO_STRING_IN_FORMAT_ARGS,
                     value.span.with_lo(receiver.span.hi()),
                     &format!(
-                        "`to_string` applied to a type that implements `Display` in `{}!` args",
-                        name
+                        "`to_string` applied to a type that implements `Display` in `{name}!` args"
                     ),
                     "remove this",
                     String::new(),
@@ -162,16 +285,13 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
                     TO_STRING_IN_FORMAT_ARGS,
                     value.span,
                     &format!(
-                        "`to_string` applied to a type that implements `Display` in `{}!` args",
-                        name
+                        "`to_string` applied to a type that implements `Display` in `{name}!` args"
                     ),
                     "use this",
                     format!(
-                        "{}{:*>width$}{}",
+                        "{}{:*>n_needed_derefs$}{receiver_snippet}",
                         if needs_ref { "&" } else { "" },
-                        "",
-                        receiver_snippet,
-                        width = n_needed_derefs
+                        ""
                     ),
                     Applicability::MachineApplicable,
                 );
@@ -180,7 +300,7 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
     }
 }
 
-// Returns true if `hir_id` is referred to by multiple format params
+/// Returns true if `hir_id` is referred to by multiple format params
 fn is_aliased(args: &FormatArgsExpn<'_>, hir_id: HirId) -> bool {
     args.params().filter(|param| param.value.hir_id == hir_id).at_most_one().is_err()
 }
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index b628fd9f758..ed1342a5465 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -214,12 +214,12 @@ fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait:
                 cx,
                 PRINT_IN_FORMAT_IMPL,
                 macro_call.span,
-                &format!("use of `{}!` in `{}` impl", name, impl_trait.name),
+                &format!("use of `{name}!` in `{}` impl", impl_trait.name),
                 "replace with",
                 if let Some(formatter_name) = impl_trait.formatter_name {
-                    format!("{}!({}, ..)", replacement, formatter_name)
+                    format!("{replacement}!({formatter_name}, ..)")
                 } else {
-                    format!("{}!(..)", replacement)
+                    format!("{replacement}!(..)")
                 },
                 Applicability::HasPlaceholders,
             );
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index 01cefe4af85..a866a68987d 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -154,11 +154,10 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
                             eqop_span,
                             &format!(
                                 "this looks like you are trying to use `.. {op}= ..`, but you \
-                                 really are doing `.. = ({op} ..)`",
-                                op = op
+                                 really are doing `.. = ({op} ..)`"
                             ),
                             None,
-                            &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op),
+                            &format!("to remove this lint, use either `{op}=` or `= {op}`"),
                         );
                     }
                 }
@@ -191,16 +190,12 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
                 SUSPICIOUS_UNARY_OP_FORMATTING,
                 eqop_span,
                 &format!(
-                    "by not having a space between `{binop}` and `{unop}` it looks like \
-                     `{binop}{unop}` is a single operator",
-                    binop = binop_str,
-                    unop = unop_str
+                    "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}` and `{unop}` and remove the space after `{unop}`",
-                    binop = binop_str,
-                    unop = unop_str
+                    "put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"
                 ),
             );
         }
@@ -246,12 +241,11 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
                 cx,
                 SUSPICIOUS_ELSE_FORMATTING,
                 else_span,
-                &format!("this is an `else {}` but the formatting might hide it", else_desc),
+                &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,
+                     `else` and `{else_desc}`",
                 ),
             );
         }
@@ -320,11 +314,10 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
                 cx,
                 SUSPICIOUS_ELSE_FORMATTING,
                 else_span,
-                &format!("this looks like {} but the `else` is missing", looks_like),
+                &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,
+                    "to remove this lint, add the missing `else` or add a new line before {next_thing}",
                 ),
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
index 74941d817be..cf8b7acd66d 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -1,4 +1,5 @@
 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;
 use if_chain::if_chain;
@@ -60,8 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
             if pathseg.ident.name.as_str() == "from_str_radix";
 
             // check if the second argument is a primitive `10`
-            if let ExprKind::Lit(lit) = &radix.kind;
-            if let rustc_ast::ast::LitKind::Int(10, _) = lit.node;
+            if is_integer_literal(radix, 10);
 
             then {
                 let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
                     exp.span,
                     "this call to `from_str_radix` can be replaced with a call to `str::parse`",
                     "try",
-                    format!("{}.parse::<{}>()", sugg, prim_ty.name_str()),
+                    format!("{sugg}.parse::<{}>()", prim_ty.name_str()),
                     Applicability::MaybeIncorrect
                 );
             }
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index d6d33bda173..d263804f32c 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -1,7 +1,7 @@
 use rustc_ast::ast::Attribute;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::{DefIdSet, LocalDefId};
-use rustc_hir::{self as hir, def::Res, intravisit, QPath};
+use rustc_hir::{self as hir, def::Res, QPath};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::{
     lint::in_external_macro,
@@ -13,8 +13,11 @@ use clippy_utils::attrs::is_proc_macro;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_must_use_ty;
+use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{match_def_path, return_ty, trait_ref_of_method};
 
+use core::ops::ControlFlow;
+
 use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
@@ -47,7 +50,8 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
-        } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id.def_id).is_none() {
+        } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id.def_id).is_none()
+        {
             check_must_use_candidate(
                 cx,
                 sig.decl,
@@ -143,7 +147,7 @@ fn check_must_use_candidate<'tcx>(
             diag.span_suggestion(
                 fn_span,
                 "add the attribute",
-                format!("#[must_use] {}", snippet),
+                format!("#[must_use] {snippet}"),
                 Applicability::MachineApplicable,
             );
         }
@@ -199,79 +203,65 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
     }
 }
 
-struct StaticMutVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    mutates_static: bool,
+fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
+    use hir::ExprKind::{Field, Index, Path};
+
+    match e.kind {
+        Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
+        Path(_) => true,
+        Field(inner, _) | Index(inner, _) => is_mutated_static(inner),
+        _ => false,
+    }
 }
 
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
+    for_each_expr(body.value, |e| {
         use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall};
 
-        if self.mutates_static {
-            return;
-        }
-        match expr.kind {
+        match e.kind {
             Call(_, args) => {
                 let mut tys = DefIdSet::default();
                 for arg in args {
-                    if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                    if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
                         && is_mutable_ty(
-                            self.cx,
-                            self.cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
+                            cx,
+                            cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
                             arg.span,
                             &mut tys,
                         )
                         && is_mutated_static(arg)
                     {
-                        self.mutates_static = true;
-                        return;
+                        return ControlFlow::Break(());
                     }
                     tys.clear();
                 }
+                ControlFlow::Continue(())
             },
             MethodCall(_, receiver, args, _) => {
                 let mut tys = DefIdSet::default();
                 for arg in std::iter::once(receiver).chain(args.iter()) {
-                    if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+                    if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
                         && is_mutable_ty(
-                            self.cx,
-                            self.cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
+                            cx,
+                            cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
                             arg.span,
                             &mut tys,
                         )
                         && is_mutated_static(arg)
                     {
-                        self.mutates_static = true;
-                        return;
+                        return ControlFlow::Break(());
                     }
                     tys.clear();
                 }
+                ControlFlow::Continue(())
             },
-            Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
-                self.mutates_static |= is_mutated_static(target);
+            Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target)
+                if is_mutated_static(target) =>
+            {
+                ControlFlow::Break(())
             },
-            _ => {},
+            _ => ControlFlow::Continue(()),
         }
-    }
-}
-
-fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
-    use hir::ExprKind::{Field, Index, Path};
-
-    match e.kind {
-        Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
-        Path(_) => true,
-        Field(inner, _) | Index(inner, _) => is_mutated_static(inner),
-        _ => false,
-    }
-}
-
-fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
-    let mut v = StaticMutVisitor {
-        cx,
-        mutates_static: false,
-    };
-    intravisit::walk_expr(&mut v, body.value);
-    v.mutates_static
+    })
+    .is_some()
 }
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 0b50431fbaa..b7595d101e0 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -5,8 +5,11 @@ use rustc_span::def_id::LocalDefId;
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::type_is_unsafe_function;
+use clippy_utils::visitors::for_each_expr_with_closures;
 use clippy_utils::{iter_input_pats, path_to_local};
 
+use core::ops::ControlFlow;
+
 use super::NOT_UNSAFE_PTR_ARG_DEREF;
 
 pub(super) fn check_fn<'tcx>(
@@ -39,21 +42,34 @@ fn check_raw_ptr<'tcx>(
     body: &'tcx hir::Body<'tcx>,
     def_id: LocalDefId,
 ) {
-    let expr = &body.value;
     if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(def_id) {
         let raw_ptrs = iter_input_pats(decl, body)
             .filter_map(|arg| raw_ptr_arg(cx, arg))
             .collect::<HirIdSet>();
 
         if !raw_ptrs.is_empty() {
-            let typeck_results = cx.tcx.typeck_body(body.id());
-            let mut v = DerefVisitor {
-                cx,
-                ptrs: raw_ptrs,
-                typeck_results,
-            };
-
-            intravisit::walk_expr(&mut v, expr);
+            let typeck = cx.tcx.typeck_body(body.id());
+            let _: Option<!> = for_each_expr_with_closures(cx, body.value, |e| {
+                match e.kind {
+                    hir::ExprKind::Call(f, args) if type_is_unsafe_function(cx, typeck.expr_ty(f)) => {
+                        for arg in args {
+                            check_arg(cx, &raw_ptrs, arg);
+                        }
+                    },
+                    hir::ExprKind::MethodCall(_, recv, args, _) => {
+                        let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap();
+                        if cx.tcx.fn_sig(def_id).skip_binder().unsafety == hir::Unsafety::Unsafe {
+                            check_arg(cx, &raw_ptrs, recv);
+                            for arg in args {
+                                check_arg(cx, &raw_ptrs, arg);
+                            }
+                        }
+                    },
+                    hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => check_arg(cx, &raw_ptrs, ptr),
+                    _ => (),
+                }
+                ControlFlow::Continue(())
+            });
         }
     }
 }
@@ -70,54 +86,13 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId>
     }
 }
 
-struct DerefVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    ptrs: HirIdSet,
-    typeck_results: &'a ty::TypeckResults<'tcx>,
-}
-
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        match expr.kind {
-            hir::ExprKind::Call(f, args) => {
-                let ty = self.typeck_results.expr_ty(f);
-
-                if type_is_unsafe_function(self.cx, ty) {
-                    for arg in args {
-                        self.check_arg(arg);
-                    }
-                }
-            },
-            hir::ExprKind::MethodCall(_, receiver, args, _) => {
-                let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
-                let base_type = self.cx.tcx.type_of(def_id);
-
-                if type_is_unsafe_function(self.cx, base_type) {
-                    self.check_arg(receiver);
-                    for arg in args {
-                        self.check_arg(arg);
-                    }
-                }
-            },
-            hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => self.check_arg(ptr),
-            _ => (),
-        }
-
-        intravisit::walk_expr(self, expr);
-    }
-}
-
-impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
-    fn check_arg(&self, ptr: &hir::Expr<'_>) {
-        if let Some(id) = path_to_local(ptr) {
-            if self.ptrs.contains(&id) {
-                span_lint(
-                    self.cx,
-                    NOT_UNSAFE_PTR_ARG_DEREF,
-                    ptr.span,
-                    "this public function might dereference a raw pointer but is not marked `unsafe`",
-                );
-            }
-        }
+fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) {
+    if path_to_local(arg).map_or(false, |id| raw_ptrs.contains(&id)) {
+        span_lint(
+            cx,
+            NOT_UNSAFE_PTR_ARG_DEREF,
+            arg.span,
+            "this public function might dereference a raw pointer but is not marked `unsafe`",
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
index 5c8d8b8e755..1e08922a616 100644
--- a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
@@ -59,10 +59,7 @@ fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span,
             cx,
             TOO_MANY_ARGUMENTS,
             fn_span,
-            &format!(
-                "this function has too many arguments ({}/{})",
-                args, too_many_arguments_threshold
-            ),
+            &format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
index 54bdea7ea25..f83f8b40f94 100644
--- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
@@ -78,10 +78,7 @@ pub(super) fn check_fn(
             cx,
             TOO_MANY_LINES,
             span,
-            &format!(
-                "this function has too many lines ({}/{})",
-                line_count, too_many_lines_threshold
-            ),
+            &format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index 11c43247868..0d6718c168a 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -1,7 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::source::snippet_with_macro_callsite;
-use clippy_utils::{contains_return, higher, is_else_clause, is_lang_ctor, meets_msrv, msrvs, peel_blocks};
+use clippy_utils::{
+    contains_return, higher, is_else_clause, is_res_lang_ctor, meets_msrv, msrvs, path_res, peel_blocks,
+};
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -76,15 +78,13 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
             && let ExprKind::Block(then_block, _) = then.kind
             && let Some(then_expr) = then_block.expr
             && let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
-            && let ExprKind::Path(ref then_call_qpath) = then_call.kind
-            && is_lang_ctor(cx, then_call_qpath, OptionSome)
-            && let ExprKind::Path(ref qpath) = peel_blocks(els).kind
-            && is_lang_ctor(cx, qpath, OptionNone)
+            && is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
+            && is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
             && !stmts_contains_early_return(then_block.stmts)
         {
             let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
             let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
-                format!("({})", cond_snip)
+                format!("({cond_snip})")
             } else {
                 cond_snip.into_owned()
             };
@@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
             let mut method_body = if then_block.stmts.is_empty() {
                 arg_snip.into_owned()
             } else {
-                format!("{{ /* snippet */ {} }}", arg_snip)
+                format!("{{ /* snippet */ {arg_snip} }}")
             };
             let method_name = if switch_to_eager_eval(cx, expr) && meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) {
                 "then_some"
@@ -102,14 +102,13 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
             };
 
             let help = format!(
-                "consider using `bool::{}` like: `{}.{}({})`",
-                method_name, cond_snip, method_name, method_body,
+                "consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",
             );
             span_lint_and_help(
                 cx,
                 IF_THEN_SOME_ELSE_NONE,
                 expr.span,
-                &format!("this could be simplified with `bool::{}`", method_name),
+                &format!("this could be simplified with `bool::{method_name}`"),
                 None,
                 &help,
             );
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index a920c3bba2a..93efe957b1d 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -5,6 +5,7 @@ use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
@@ -12,7 +13,6 @@ use rustc_middle::ty::{Ty, TypeckResults};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::sym;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 use if_chain::if_chain;
 
@@ -89,8 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                     (
                         generics_suggestion_span,
                         format!(
-                            "<{}{}S: ::std::hash::BuildHasher{}>",
-                            generics_snip,
+                            "<{generics_snip}{}S: ::std::hash::BuildHasher{}>",
                             if generics_snip.is_empty() { "" } else { ", " },
                             if vis.suggestions.is_empty() {
                                 ""
@@ -263,8 +262,8 @@ impl<'tcx> ImplicitHasherType<'tcx> {
 
     fn type_arguments(&self) -> String {
         match *self {
-            ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v),
-            ImplicitHasherType::HashSet(.., ref t) => format!("{}", t),
+            ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{k}, {v}"),
+            ImplicitHasherType::HashSet(.., ref t) => format!("{t}"),
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index feec8ec2e23..946d04eff6f 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -2,10 +2,11 @@ use clippy_utils::{
     diagnostics::span_lint_hir_and_then,
     get_async_fn_body, is_async_fn,
     source::{snippet_with_applicability, snippet_with_context, walk_span_to_context},
-    visitors::expr_visitor_no_bodies,
+    visitors::for_each_expr,
 };
+use core::ops::ControlFlow;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -53,7 +54,7 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
         span,
         "missing `return` statement",
         |diag| {
-            diag.span_suggestion(span, "add `return` as shown", format!("return {}", snip), app);
+            diag.span_suggestion(span, "add `return` as shown", format!("return {snip}"), app);
         },
     );
 }
@@ -71,7 +72,7 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp
             diag.span_suggestion(
                 break_span,
                 "change `break` to `return` as shown",
-                format!("return {}", snip),
+                format!("return {snip}"),
                 app,
             );
         },
@@ -152,7 +153,7 @@ fn lint_implicit_returns(
 
         ExprKind::Loop(block, ..) => {
             let mut add_return = false;
-            expr_visitor_no_bodies(|e| {
+            let _: Option<!> = for_each_expr(block, |e| {
                 if let ExprKind::Break(dest, sub_expr) = e.kind {
                     if dest.target_id.ok() == Some(expr.hir_id) {
                         if call_site_span.is_none() && e.span.ctxt() == ctxt {
@@ -167,9 +168,8 @@ fn lint_implicit_returns(
                         }
                     }
                 }
-                true
-            })
-            .visit_block(block);
+                ControlFlow::Continue(())
+            });
             if add_return {
                 #[expect(clippy::option_if_let_else)]
                 if let Some(span) = call_site_span {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
new file mode 100644
index 00000000000..bf1351829c6
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -0,0 +1,114 @@
+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_applicability;
+use if_chain::if_chain;
+use rustc_ast::ast::{LitIntType, LitKind};
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{Int, IntTy, Ty, Uint, UintTy};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for implicit saturating addition.
+    ///
+    /// ### Why is this bad?
+    /// The built-in function is more readable and may be faster.
+    ///
+    /// ### Example
+    /// ```rust
+    ///let mut u:u32 = 7000;
+    ///
+    /// if u != u32::MAX {
+    ///     u += 1;
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    ///let mut u:u32 = 7000;
+    ///
+    /// u = u.saturating_add(1);
+    /// ```
+    #[clippy::version = "1.65.0"]
+    pub IMPLICIT_SATURATING_ADD,
+    style,
+    "Perform saturating addition instead of implicitly checking max bound of data type"
+}
+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 {
+                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);
+            if clippy_utils::SpanlessEq::new(cx).eq_expr(l, target);
+            if BinOpKind::Add == op1.node;
+            if let ExprKind::Lit(ref 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_applicability(cx, target.span, "_", &mut app);
+                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);
+            }
+        }
+    }
+}
+
+fn get_int_max(ty: Ty<'_>) -> Option<u128> {
+    match ty.peel_refs().kind() {
+        Int(IntTy::I8) => i8::max_value().try_into().ok(),
+        Int(IntTy::I16) => i16::max_value().try_into().ok(),
+        Int(IntTy::I32) => i32::max_value().try_into().ok(),
+        Int(IntTy::I64) => i64::max_value().try_into().ok(),
+        Int(IntTy::I128) => i128::max_value().try_into().ok(),
+        Int(IntTy::Isize) => isize::max_value().try_into().ok(),
+        Uint(UintTy::U8) => u8::max_value().try_into().ok(),
+        Uint(UintTy::U16) => u16::max_value().try_into().ok(),
+        Uint(UintTy::U32) => u32::max_value().try_into().ok(),
+        Uint(UintTy::U64) => u64::max_value().try_into().ok(),
+        Uint(UintTy::U128) => Some(u128::max_value()),
+        Uint(UintTy::Usize) => usize::max_value().try_into().ok(),
+        _ => None,
+    }
+}
+
+fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
+    if let ExprKind::Binary(op, l, r) = expr.kind {
+        let tr = cx.typeck_results();
+        if let Some((Constant::Int(c), _)) = constant(cx, tr, r) {
+            return Some((c, op.node, l));
+        };
+        if let Some((Constant::Int(c), _)) = constant(cx, tr, l) {
+            return Some((c, invert_op(op.node)?, r));
+        }
+    }
+    None
+}
+
+fn invert_op(op: BinOpKind) -> Option<BinOpKind> {
+    use rustc_hir::BinOpKind::{Ge, Gt, Le, Lt, Ne};
+    match op {
+        Lt => Some(Gt),
+        Le => Some(Ge),
+        Ne => Some(Ne),
+        Ge => Some(Le),
+        Gt => Some(Lt),
+        _ => None,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 46654bc61e0..48edbf6ae57 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{higher, peel_blocks_with_stmt, SpanlessEq};
+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;
@@ -131,17 +131,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
 fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Expr<'a>> {
     match peel_blocks_with_stmt(expr).kind {
         ExprKind::AssignOp(ref op1, target, value) => {
-            if_chain! {
-                if BinOpKind::Sub == op1.node;
-                // Check if literal being subtracted is one
-                if let ExprKind::Lit(ref lit1) = value.kind;
-                if let LitKind::Int(1, _) = lit1.node;
-                then {
-                    Some(target)
-                } else {
-                    None
-                }
-            }
+            // Check if literal being subtracted is one
+            (BinOpKind::Sub == op1.node && is_integer_literal(value, 1)).then_some(target)
         },
         ExprKind::Assign(target, value, _) => {
             if_chain! {
@@ -150,8 +141,7 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp
 
                 if SpanlessEq::new(cx).eq_expr(left1, target);
 
-                if let ExprKind::Lit(ref lit1) = right1.kind;
-                if let LitKind::Int(1, _) = lit1.node;
+                if is_integer_literal(right1, 1);
                 then {
                     Some(target)
                 } else {
@@ -170,7 +160,7 @@ fn print_lint_and_sugg(cx: &LateContext<'_>, var_name: &str, expr: &Expr<'_>) {
         expr.span,
         "implicitly performing saturating subtraction",
         "try",
-        format!("{} = {}.saturating_sub({});", var_name, var_name, '1'),
+        format!("{var_name} = {var_name}.saturating_sub({});", '1'),
         Applicability::MachineApplicable,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index 14b22d2b50d..e2f2d3d42e6 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
                 let mut fields_snippet = String::new();
                 let (last_ident, idents) = ordered_fields.split_last().unwrap();
                 for ident in idents {
-                    let _ = write!(fields_snippet, "{}, ", ident);
+                    let _ = write!(fields_snippet, "{ident}, ");
                 }
                 fields_snippet.push_str(&last_ident.to_string());
 
@@ -100,10 +100,8 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
                         String::new()
                     };
 
-                let sugg = format!("{} {{ {}{} }}",
+                let sugg = format!("{} {{ {fields_snippet}{base_snippet} }}",
                     snippet(cx, qpath.span(), ".."),
-                    fields_snippet,
-                    base_snippet,
                     );
 
                 span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 0dd7f5bf000..c7b5badaae5 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -139,14 +139,14 @@ fn lint_slice(cx: &LateContext<'_>, slice: &SliceLintInformation) {
         .map(|(index, _)| *index)
         .collect::<FxHashSet<_>>();
 
-    let value_name = |index| format!("{}_{}", slice.ident.name, index);
+    let value_name = |index| format!("{}_{index}", slice.ident.name);
 
     if let Some(max_index) = used_indices.iter().max() {
         let opt_ref = if slice.needs_ref { "ref " } else { "" };
         let pat_sugg_idents = (0..=*max_index)
             .map(|index| {
                 if used_indices.contains(&index) {
-                    format!("{}{}", opt_ref, value_name(index))
+                    format!("{opt_ref}{}", value_name(index))
                 } else {
                     "_".to_string()
                 }
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 8c2c96fa105..d1d2db27c6f 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::higher;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{higher, match_def_path, path_def_id, paths};
 use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -168,9 +168,16 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
         },
         ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
         ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
-        ExprKind::Call(path, _) => path_def_id(cx, path)
-            .map_or(false, |id| match_def_path(cx, id, &paths::ITER_REPEAT))
-            .into(),
+        ExprKind::Call(path, _) => {
+            if let ExprKind::Path(ref qpath) = path.kind {
+                cx.qpath_res(qpath, path.hir_id)
+                    .opt_def_id()
+                    .map_or(false, |id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
+                    .into()
+            } else {
+                Finite
+            }
+        },
         ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
         _ => Finite,
     }
diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
index cb6c2ec0fb9..676136df572 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
+use clippy_utils::{return_ty, trait_ref_of_method};
 use if_chain::if_chain;
 use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -118,7 +118,10 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
 }
 
 fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
-    let display_trait_id = get_trait_def_id(cx, &paths::DISPLAY_TRAIT).expect("Failed to get trait ID of `Display`!");
+    let display_trait_id = cx
+        .tcx
+        .get_diagnostic_item(sym::Display)
+        .expect("Failed to get trait ID of `Display`!");
 
     // Get the real type of 'self'
     let self_type = cx.tcx.fn_sig(item.def_id).input(0);
@@ -131,23 +134,19 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
             INHERENT_TO_STRING_SHADOW_DISPLAY,
             item.span,
             &format!(
-                "type `{}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`",
-                self_type
+                "type `{self_type}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`"
             ),
             None,
-            &format!("remove the inherent method from type `{}`", self_type),
+            &format!("remove the inherent method from type `{self_type}`"),
         );
     } else {
         span_lint_and_help(
             cx,
             INHERENT_TO_STRING,
             item.span,
-            &format!(
-                "implementation of inherent method `to_string(&self) -> String` for type `{}`",
-                self_type
-            ),
+            &format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"),
             None,
-            &format!("implement trait `Display` for type `{}` instead", self_type),
+            &format!("implement trait `Display` for type `{self_type}` instead"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index dd7177e0131..d609a5ca4d4 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -51,7 +51,7 @@ fn check_attrs(cx: &LateContext<'_>, name: Symbol, attrs: &[Attribute]) {
             cx,
             INLINE_FN_WITHOUT_BODY,
             attr.span,
-            &format!("use of `#[inline]` on trait method `{}` which has no body", name),
+            &format!("use of `#[inline]` on trait method `{name}` which has no body"),
             |diag| {
                 diag.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable);
             },
diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
index 9a944def3eb..33491da3fc5 100644
--- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs
+++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
@@ -138,8 +138,8 @@ impl IntPlusOne {
         if let Some(snippet) = snippet_opt(cx, node.span) {
             if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) {
                 let rec = match side {
-                    Side::Lhs => Some(format!("{} {} {}", snippet, binop_string, other_side_snippet)),
-                    Side::Rhs => Some(format!("{} {} {}", other_side_snippet, binop_string, snippet)),
+                    Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
+                    Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
                 };
                 return rec;
             }
diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
index 2027c23d328..ea9f046fb97 100644
--- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
@@ -80,10 +80,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI
                 cx,
                 ITER_NOT_RETURNING_ITERATOR,
                 sig.span,
-                &format!(
-                    "this method is named `{}` but its return type does not implement `Iterator`",
-                    name
-                ),
+                &format!("this method is named `{name}` but its return type does not implement `Iterator`"),
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index d6eb53ae29b..76c83ab47d0 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -2,12 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{BytePos, Pos, Span};
-use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 7d15dd4cb21..3a563736fb0 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -210,7 +210,8 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
         }
     }
 
-    if cx.access_levels.is_exported(visited_trait.def_id.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
+    if cx.access_levels.is_exported(visited_trait.def_id.def_id)
+        && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
     {
         let mut current_and_super_traits = DefIdSet::default();
         fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
@@ -278,15 +279,13 @@ impl<'tcx> LenOutput<'tcx> {
             _ => "",
         };
         match self {
-            Self::Integral => format!("expected signature: `({}self) -> bool`", self_ref),
-            Self::Option(_) => format!(
-                "expected signature: `({}self) -> bool` or `({}self) -> Option<bool>",
-                self_ref, self_ref
-            ),
-            Self::Result(..) => format!(
-                "expected signature: `({}self) -> bool` or `({}self) -> Result<bool>",
-                self_ref, self_ref
-            ),
+            Self::Integral => format!("expected signature: `({self_ref}self) -> bool`"),
+            Self::Option(_) => {
+                format!("expected signature: `({self_ref}self) -> bool` or `({self_ref}self) -> Option<bool>")
+            },
+            Self::Result(..) => {
+                format!("expected signature: `({self_ref}self) -> bool` or `({self_ref}self) -> Result<bool>")
+            },
         }
     }
 }
@@ -326,8 +325,7 @@ fn check_for_is_empty<'tcx>(
     let (msg, is_empty_span, self_kind) = match is_empty {
         None => (
             format!(
-                "{} `{}` has a public `len` method, but no `is_empty` method",
-                item_kind,
+                "{item_kind} `{}` has a public `len` method, but no `is_empty` method",
                 item_name.as_str(),
             ),
             None,
@@ -335,8 +333,7 @@ fn check_for_is_empty<'tcx>(
         ),
         Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => (
             format!(
-                "{} `{}` has a public `len` method, but a private `is_empty` method",
-                item_kind,
+                "{item_kind} `{}` has a public `len` method, but a private `is_empty` method",
                 item_name.as_str(),
             ),
             Some(cx.tcx.def_span(is_empty.def_id)),
@@ -348,8 +345,7 @@ fn check_for_is_empty<'tcx>(
         {
             (
                 format!(
-                    "{} `{}` has a public `len` method, but the `is_empty` method has an unexpected signature",
-                    item_kind,
+                    "{item_kind} `{}` has a public `len` method, but the `is_empty` method has an unexpected signature",
                     item_name.as_str(),
                 ),
                 Some(cx.tcx.def_span(is_empty.def_id)),
@@ -419,10 +415,9 @@ fn check_len(
                 LEN_ZERO,
                 span,
                 &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
-                &format!("using `{}is_empty` is clearer and more explicit", op),
+                &format!("using `{op}is_empty` is clearer and more explicit"),
                 format!(
-                    "{}{}.is_empty()",
-                    op,
+                    "{op}{}.is_empty()",
                     snippet_with_applicability(cx, receiver.span, "_", &mut applicability)
                 ),
                 applicability,
@@ -439,10 +434,9 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex
             COMPARISON_TO_EMPTY,
             span,
             "comparison to empty slice",
-            &format!("using `{}is_empty` is clearer and more explicit", op),
+            &format!("using `{op}is_empty` is clearer and more explicit"),
             format!(
-                "{}{}.is_empty()",
-                op,
+                "{op}{}.is_empty()",
                 snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
             ),
             applicability,
diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index 10fc0f4018e..13071d64441 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
@@ -106,8 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
                     // use mutably after the `if`
 
                     let sug = format!(
-                        "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
-                        mut=mutability,
+                        "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 { "" },
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
index 8718d5fa1da..5d26e4b3360 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
@@ -21,6 +21,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(booleans::NONMINIMAL_BOOL),
     LintId::of(booleans::OVERLY_COMPLEX_BOOL_EXPR),
     LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
+    LintId::of(box_default::BOX_DEFAULT),
     LintId::of(casts::CAST_ABS_TO_UNSIGNED),
     LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
     LintId::of(casts::CAST_ENUM_TRUNCATION),
@@ -44,7 +45,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(derivable_impls::DERIVABLE_IMPLS),
     LintId::of(derive::DERIVE_HASH_XOR_EQ),
     LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
-    LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
+    LintId::of(disallowed_macros::DISALLOWED_MACROS),
     LintId::of(disallowed_methods::DISALLOWED_METHODS),
     LintId::of(disallowed_names::DISALLOWED_NAMES),
     LintId::of(disallowed_types::DISALLOWED_TYPES),
@@ -85,6 +86,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(functions::RESULT_UNIT_ERR),
     LintId::of(functions::TOO_MANY_ARGUMENTS),
     LintId::of(if_let_mutex::IF_LET_MUTEX),
+    LintId::of(implicit_saturating_add::IMPLICIT_SATURATING_ADD),
     LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
     LintId::of(infinite_iter::INFINITE_ITER),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
@@ -125,6 +127,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(main_recursion::MAIN_RECURSION),
     LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
     LintId::of(manual_bits::MANUAL_BITS),
+    LintId::of(manual_clamp::MANUAL_CLAMP),
     LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
     LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID),
     LintId::of(manual_retain::MANUAL_RETAIN),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
index 185189a6af5..a58d066fa6b 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
@@ -22,6 +22,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
     LintId::of(loops::MANUAL_FLATTEN),
     LintId::of(loops::SINGLE_ELEMENT_LOOP),
     LintId::of(loops::WHILE_LET_LOOP),
+    LintId::of(manual_clamp::MANUAL_CLAMP),
     LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID),
     LintId::of(manual_strip::MANUAL_STRIP),
     LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
index be63646a12f..71dfdab369b 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
@@ -13,10 +13,10 @@ store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
     LintId::of(utils::internal_lints::INVALID_CLIPPY_VERSION_ATTRIBUTE),
     LintId::of(utils::internal_lints::INVALID_PATHS),
     LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS),
-    LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM),
     LintId::of(utils::internal_lints::MISSING_CLIPPY_VERSION_ATTRIBUTE),
     LintId::of(utils::internal_lints::MISSING_MSRV_ATTR_IMPL),
     LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA),
     LintId::of(utils::internal_lints::PRODUCE_ICE),
+    LintId::of(utils::internal_lints::UNNECESSARY_DEF_PATH),
     LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR),
 ])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
index 02fcc8de507..05d927dbea7 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
@@ -24,8 +24,6 @@ store.register_lints(&[
     #[cfg(feature = "internal")]
     utils::internal_lints::LINT_WITHOUT_LINT_PASS,
     #[cfg(feature = "internal")]
-    utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
-    #[cfg(feature = "internal")]
     utils::internal_lints::MISSING_CLIPPY_VERSION_ATTRIBUTE,
     #[cfg(feature = "internal")]
     utils::internal_lints::MISSING_MSRV_ATTR_IMPL,
@@ -34,6 +32,8 @@ store.register_lints(&[
     #[cfg(feature = "internal")]
     utils::internal_lints::PRODUCE_ICE,
     #[cfg(feature = "internal")]
+    utils::internal_lints::UNNECESSARY_DEF_PATH,
+    #[cfg(feature = "internal")]
     utils::internal_lints::UNNECESSARY_SYMBOL_STR,
     almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE,
     approx_const::APPROX_CONSTANT,
@@ -60,6 +60,7 @@ store.register_lints(&[
     booleans::NONMINIMAL_BOOL,
     booleans::OVERLY_COMPLEX_BOOL_EXPR,
     borrow_deref_ref::BORROW_DEREF_REF,
+    box_default::BOX_DEFAULT,
     cargo::CARGO_COMMON_METADATA,
     cargo::MULTIPLE_CRATE_VERSIONS,
     cargo::NEGATIVE_FEATURE_NAMES,
@@ -113,16 +114,17 @@ store.register_lints(&[
     derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ,
     derive::EXPL_IMPL_CLONE_ON_COPY,
     derive::UNSAFE_DERIVE_DESERIALIZE,
+    disallowed_macros::DISALLOWED_MACROS,
     disallowed_methods::DISALLOWED_METHODS,
     disallowed_names::DISALLOWED_NAMES,
     disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS,
     disallowed_types::DISALLOWED_TYPES,
+    doc::DOC_LINK_WITH_QUOTES,
     doc::DOC_MARKDOWN,
     doc::MISSING_ERRORS_DOC,
     doc::MISSING_PANICS_DOC,
     doc::MISSING_SAFETY_DOC,
     doc::NEEDLESS_DOCTEST_MAIN,
-    doc_link_with_quotes::DOC_LINK_WITH_QUOTES,
     double_parens::DOUBLE_PARENS,
     drop_forget_ref::DROP_COPY,
     drop_forget_ref::DROP_NON_DROP,
@@ -159,6 +161,7 @@ store.register_lints(&[
     format::USELESS_FORMAT,
     format_args::FORMAT_IN_FORMAT_ARGS,
     format_args::TO_STRING_IN_FORMAT_ARGS,
+    format_args::UNINLINED_FORMAT_ARGS,
     format_impl::PRINT_IN_FORMAT_IMPL,
     format_impl::RECURSIVE_FORMAT_IMPL,
     format_push_string::FORMAT_PUSH_STRING,
@@ -182,6 +185,7 @@ store.register_lints(&[
     if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
     implicit_hasher::IMPLICIT_HASHER,
     implicit_return::IMPLICIT_RETURN,
+    implicit_saturating_add::IMPLICIT_SATURATING_ADD,
     implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
     inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
     index_refutable_slice::INDEX_REFUTABLE_SLICE,
@@ -243,6 +247,7 @@ store.register_lints(&[
     manual_assert::MANUAL_ASSERT,
     manual_async_fn::MANUAL_ASYNC_FN,
     manual_bits::MANUAL_BITS,
+    manual_clamp::MANUAL_CLAMP,
     manual_instant_elapsed::MANUAL_INSTANT_ELAPSED,
     manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
     manual_rem_euclid::MANUAL_REM_EUCLID,
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
index f1783dd9dde..e0b4639af53 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
@@ -6,6 +6,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
     LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
     LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
     LintId::of(copies::BRANCHES_SHARING_CODE),
+    LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
     LintId::of(equatable_if_let::EQUATABLE_IF_LET),
     LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
     LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
index 584ccf55e51..bc2f0beb358 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
@@ -20,15 +20,16 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
     LintId::of(dereference::REF_BINDING_TO_REFERENCE),
     LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY),
     LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE),
+    LintId::of(doc::DOC_LINK_WITH_QUOTES),
     LintId::of(doc::DOC_MARKDOWN),
     LintId::of(doc::MISSING_ERRORS_DOC),
     LintId::of(doc::MISSING_PANICS_DOC),
-    LintId::of(doc_link_with_quotes::DOC_LINK_WITH_QUOTES),
     LintId::of(empty_enum::EMPTY_ENUM),
     LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
     LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
     LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
     LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
+    LintId::of(format_args::UNINLINED_FORMAT_ARGS),
     LintId::of(functions::MUST_USE_CANDIDATE),
     LintId::of(functions::TOO_MANY_LINES),
     LintId::of(if_not_else::IF_NOT_ELSE),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
index 195ce41e31e..8e927470e02 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
@@ -3,6 +3,7 @@
 // Manual edits will be overwritten.
 
 store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
+    LintId::of(box_default::BOX_DEFAULT),
     LintId::of(entry::MAP_ENTRY),
     LintId::of(escape::BOXED_LOCAL),
     LintId::of(format_args::FORMAT_IN_FORMAT_ARGS),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
index 05d2ec2e9e1..8e1390167dc 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
@@ -15,7 +15,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
     LintId::of(default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY),
     LintId::of(dereference::NEEDLESS_BORROW),
-    LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
+    LintId::of(disallowed_macros::DISALLOWED_MACROS),
     LintId::of(disallowed_methods::DISALLOWED_METHODS),
     LintId::of(disallowed_names::DISALLOWED_NAMES),
     LintId::of(disallowed_types::DISALLOWED_TYPES),
@@ -30,6 +30,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(functions::DOUBLE_MUST_USE),
     LintId::of(functions::MUST_USE_UNIT),
     LintId::of(functions::RESULT_UNIT_ERR),
+    LintId::of(implicit_saturating_add::IMPLICIT_SATURATING_ADD),
     LintId::of(inherent_to_string::INHERENT_TO_STRING),
     LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
     LintId::of(len_zero::COMPARISON_TO_EMPTY),
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index c3db194c4ad..2dcefd78763 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -31,6 +31,7 @@ extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
 extern crate rustc_hir;
+extern crate rustc_hir_analysis;
 extern crate rustc_hir_pretty;
 extern crate rustc_index;
 extern crate rustc_infer;
@@ -43,7 +44,6 @@ extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
 extern crate rustc_trait_selection;
-extern crate rustc_hir_analysis;
 
 #[macro_use]
 extern crate clippy_utils;
@@ -180,6 +180,7 @@ mod bool_assert_comparison;
 mod bool_to_int_with_if;
 mod booleans;
 mod borrow_deref_ref;
+mod box_default;
 mod cargo;
 mod casts;
 mod checked_conversions;
@@ -198,12 +199,12 @@ mod default_union_representation;
 mod dereference;
 mod derivable_impls;
 mod derive;
+mod disallowed_macros;
 mod disallowed_methods;
 mod disallowed_names;
 mod disallowed_script_idents;
 mod disallowed_types;
 mod doc;
-mod doc_link_with_quotes;
 mod double_parens;
 mod drop_forget_ref;
 mod duplicate_mod;
@@ -238,6 +239,7 @@ mod if_not_else;
 mod if_then_some_else_none;
 mod implicit_hasher;
 mod implicit_return;
+mod implicit_saturating_add;
 mod implicit_saturating_sub;
 mod inconsistent_struct_constructor;
 mod index_refutable_slice;
@@ -267,6 +269,7 @@ mod main_recursion;
 mod manual_assert;
 mod manual_async_fn;
 mod manual_bits;
+mod manual_clamp;
 mod manual_instant_elapsed;
 mod manual_non_exhaustive;
 mod manual_rem_euclid;
@@ -416,8 +419,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
     let msrv = conf.msrv.as_ref().and_then(|s| {
         parse_msrv(s, None, None).or_else(|| {
             sess.err(&format!(
-                "error reading Clippy's configuration file. `{}` is not a valid Rust version",
-                s
+                "error reading Clippy's configuration file. `{s}` is not a valid Rust version"
             ));
             None
         })
@@ -433,8 +435,7 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
     let clippy_msrv = conf.msrv.as_ref().and_then(|s| {
         parse_msrv(s, None, None).or_else(|| {
             sess.err(&format!(
-                "error reading Clippy's configuration file. `{}` is not a valid Rust version",
-                s
+                "error reading Clippy's configuration file. `{s}` is not a valid Rust version"
             ));
             None
         })
@@ -445,8 +446,7 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
             // if both files have an msrv, let's compare them and emit a warning if they differ
             if clippy_msrv != cargo_msrv {
                 sess.warn(&format!(
-                    "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{}` from `clippy.toml`",
-                    clippy_msrv
+                    "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
                 ));
             }
 
@@ -465,7 +465,7 @@ pub fn read_conf(sess: &Session) -> Conf {
         Ok(Some(path)) => path,
         Ok(None) => return Conf::default(),
         Err(error) => {
-            sess.struct_err(&format!("error finding Clippy's configuration file: {}", error))
+            sess.struct_err(&format!("error finding Clippy's configuration file: {error}"))
                 .emit();
             return Conf::default();
         },
@@ -535,9 +535,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         store.register_late_pass(|_| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
         store.register_late_pass(|_| Box::new(utils::internal_lints::IfChainStyle));
         store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths));
-        store.register_late_pass(|_| Box::new(utils::internal_lints::InterningDefinedSymbol::default()));
-        store.register_late_pass(|_| Box::new(utils::internal_lints::LintWithoutLintPass::default()));
-        store.register_late_pass(|_| Box::new(utils::internal_lints::MatchTypeOnDiagItem));
+        store.register_late_pass(|_| Box::<utils::internal_lints::InterningDefinedSymbol>::default());
+        store.register_late_pass(|_| Box::<utils::internal_lints::LintWithoutLintPass>::default());
+        store.register_late_pass(|_| Box::new(utils::internal_lints::UnnecessaryDefPath));
         store.register_late_pass(|_| Box::new(utils::internal_lints::OuterExpnDataPass));
         store.register_late_pass(|_| Box::new(utils::internal_lints::MsrvAttrImpl));
     }
@@ -629,10 +629,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             msrv,
         ))
     });
-    store.register_late_pass(|_| Box::new(shadow::Shadow::default()));
+    store.register_late_pass(|_| Box::<shadow::Shadow>::default());
     store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
     store.register_late_pass(|_| Box::new(loops::Loops));
-    store.register_late_pass(|_| Box::new(main_recursion::MainRecursion::default()));
+    store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
     store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
     store.register_late_pass(|_| Box::new(entry::HashMapPass));
     store.register_late_pass(|_| Box::new(minmax::MinMaxPass));
@@ -666,7 +666,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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(new_without_default::NewWithoutDefault::default()));
+    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;
@@ -705,7 +705,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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));
-    store.register_late_pass(|_| Box::new(useless_conversion::UselessConversion::default()));
+    store.register_late_pass(|_| Box::<useless_conversion::UselessConversion>::default());
     store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher));
     store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom));
     store.register_late_pass(|_| Box::new(question_mark::QuestionMark));
@@ -775,7 +775,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             upper_case_acronyms_aggressive,
         ))
     });
-    store.register_late_pass(|_| Box::new(default::Default::default()));
+    store.register_late_pass(|_| Box::<default::Default>::default());
     store.register_late_pass(move |_| Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api)));
     store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
     store.register_late_pass(|_| Box::new(exit::Exit));
@@ -798,7 +798,7 @@ 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::new(redundant_pub_crate::RedundantPubCrate::default()));
+    store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
     store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
     store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv)));
     store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
@@ -816,11 +816,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     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_late_pass(|_| Box::new(macro_use::MacroUseImports::default()));
+    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));
@@ -829,7 +831,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(strings::StrToString));
     store.register_late_pass(|_| Box::new(strings::StringToString));
     store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues));
-    store.register_late_pass(|_| Box::new(vec_init_then_push::VecInitThenPush::default()));
+    store.register_late_pass(|_| Box::<vec_init_then_push::VecInitThenPush>::default());
     store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing));
     store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10));
     store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv)));
@@ -857,7 +859,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
-    store.register_late_pass(move |_| Box::new(format_args::FormatArgs));
+    store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv)));
     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));
@@ -866,8 +868,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
     store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv)));
     store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
-    store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes));
-    store.register_late_pass(|_| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default()));
+    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 cargo_ignore_publish = conf.cargo_ignore_publish;
@@ -876,7 +877,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             ignore_publish: cargo_ignore_publish,
         })
     });
-    store.register_late_pass(|_| Box::new(write::Write::default()));
+    store.register_late_pass(|_| Box::<write::Write>::default());
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
     store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
     store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
@@ -886,7 +887,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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));
-    store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
+    store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
     store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
     store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
     store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
@@ -898,13 +899,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
-    store.register_late_pass(|_| Box::new(std_instead_of_core::StdReexports::default()));
+    store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
     store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed));
     store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
+    store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv)));
     store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
     store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
     store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
     store.register_late_pass(|_| Box::new(bool_to_int_with_if::BoolToIntWithIf));
+    store.register_late_pass(|_| Box::new(box_default::BoxDefault));
+    store.register_late_pass(|_| Box::new(implicit_saturating_add::ImplicitSaturatingAdd));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 399a03187d9..aef253303a8 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -9,8 +9,8 @@ use rustc_hir::intravisit::{
 use rustc_hir::FnRetTy::Return;
 use rustc_hir::{
     BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
-    ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
-    TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+    ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn,
+    TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter as middle_nested_filter;
@@ -276,7 +276,7 @@ fn could_use_elision<'tcx>(
         let mut checker = BodyLifetimeChecker {
             lifetimes_used_in_body: false,
         };
-        checker.visit_expr(&body.value);
+        checker.visit_expr(body.value);
         if checker.lifetimes_used_in_body {
             return false;
         }
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index fb2104861c8..25f19b9c6e6 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -478,7 +478,7 @@ impl DecimalLiteralRepresentation {
             if num_lit.radix == Radix::Decimal;
             if val >= u128::from(self.threshold);
             then {
-                let hex = format!("{:#X}", val);
+                let hex = format!("{val:#X}");
                 let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
                 let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
                     warning_type.display(num_lit.format(), cx, lit.span);
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
index 8e3ab26a947..14f22348132 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -44,11 +44,10 @@ pub(super) fn check<'tcx>(
                                 cx,
                                 EXPLICIT_COUNTER_LOOP,
                                 span,
-                                &format!("the variable `{}` is used as a loop counter", name),
+                                &format!("the variable `{name}` is used as a loop counter"),
                                 "consider using",
                                 format!(
-                                    "for ({}, {}) in {}.enumerate()",
-                                    name,
+                                    "for ({name}, {}) in {}.enumerate()",
                                     snippet_with_applicability(cx, pat.span, "item", &mut applicability),
                                     make_iterator_snippet(cx, arg, &mut applicability),
                                 ),
@@ -65,24 +64,21 @@ pub(super) fn check<'tcx>(
                         cx,
                         EXPLICIT_COUNTER_LOOP,
                         span,
-                        &format!("the variable `{}` is used as a loop counter", name),
+                        &format!("the variable `{name}` is used as a loop counter"),
                         |diag| {
                             diag.span_suggestion(
                                 span,
                                 "consider using",
                                 format!(
-                                    "for ({}, {}) in (0_{}..).zip({})",
-                                    name,
+                                    "for ({name}, {}) in (0_{int_name}..).zip({})",
                                     snippet_with_applicability(cx, pat.span, "item", &mut applicability),
-                                    int_name,
                                     make_iterator_snippet(cx, arg, &mut applicability),
                                 ),
                                 applicability,
                             );
 
                             diag.note(&format!(
-                                "`{}` is of type `{}`, making it ineligible for `Iterator::enumerate`",
-                                name, int_name
+                                "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
                             ));
                         },
                     );
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 5f5beccd030..b1f2941622a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, m
         "it is more concise to loop over references to containers instead of using explicit \
          iteration methods",
         "to write this more concisely, try",
-        format!("&{}{}", muta, object),
+        format!("&{muta}{object}"),
         applicability,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
index bee0e1d7683..ed620460dbe 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
                     cx,
                     FOR_KV_MAP,
                     arg_span,
-                    &format!("you seem to want to iterate on a map's {}s", kind),
+                    &format!("you seem to want to iterate on a map's {kind}s"),
                     |diag| {
                         let map = sugg::Sugg::hir(cx, arg, "map");
                         multispan_sugg(
@@ -46,7 +46,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
                             "use the corresponding method",
                             vec![
                                 (pat_span, snippet(cx, new_pat_span, kind).into_owned()),
-                                (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl)),
+                                (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_par())),
                             ],
                         );
                     },
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index 09b2376d5c0..4bb9936e9cd 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -1,7 +1,7 @@
 use super::utils::make_iterator_snippet;
 use super::MANUAL_FIND;
 use clippy_utils::{
-    diagnostics::span_lint_and_then, higher, is_lang_ctor, path_res, peel_blocks_with_stmt,
+    diagnostics::span_lint_and_then, higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt,
     source::snippet_with_applicability, ty::implements_trait,
 };
 use if_chain::if_chain;
@@ -30,8 +30,8 @@ pub(super) fn check<'tcx>(
         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(Expr { kind: ExprKind::Path(ctor), .. }, [inner_ret]) = ret_value.kind;
-        if is_lang_ctor(cx, ctor, LangItem::OptionSome);
+        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 {
@@ -143,8 +143,7 @@ fn last_stmt_and_ret<'tcx>(
         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 let ExprKind::Path(path) = &last_ret.kind;
-        if is_lang_ctor(cx, path, LangItem::OptionNone);
+        if is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone);
         if let Some((_, Node::Expr(_block))) = parent_iter.next();
         // This includes the function header
         if let Some((_, func)) = parent_iter.next();
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 1d6ddf4b99f..8c27c09404b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -3,13 +3,13 @@ use super::MANUAL_FLATTEN;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher;
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{is_lang_ctor, path_to_local_id, peel_blocks_with_stmt};
+use clippy_utils::{path_to_local_id, peel_blocks_with_stmt};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionSome, ResultOk};
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, Pat, PatKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, DefIdTree};
 use rustc_span::source_map::Span;
 
 /// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
@@ -30,15 +30,17 @@ pub(super) fn check<'tcx>(
         if 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;
-        let some_ctor = is_lang_ctor(cx, qpath, OptionSome);
-        let ok_ctor = is_lang_ctor(cx, qpath, ResultOk);
+        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;
         // 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 `{}` variant of the iterator element is used", if_let_type);
+            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;
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 3fc569af89e..c87fc4f90e2 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -177,13 +177,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
     let dst = if dst_offset == sugg::EMPTY && dst_limit == sugg::EMPTY {
         dst_base_str
     } else {
-        format!(
-            "{}[{}..{}]",
-            dst_base_str,
-            dst_offset.maybe_par(),
-            dst_limit.maybe_par()
-        )
-        .into()
+        format!("{dst_base_str}[{}..{}]", dst_offset.maybe_par(), dst_limit.maybe_par()).into()
     };
 
     let method_str = if is_copy(cx, elem_ty) {
@@ -193,10 +187,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
     };
 
     format!(
-        "{}.{}(&{}[{}..{}]);",
-        dst,
-        method_str,
-        src_base_str,
+        "{dst}.{method_str}(&{src_base_str}[{}..{}]);",
         src_offset.maybe_par(),
         src_limit.maybe_par()
     )
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 74f3bda9f43..c0a0444485e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -635,7 +635,7 @@ declare_clippy_lint! {
     ///     arr.into_iter().find(|&el| el == 1)
     /// }
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.64.0"]
     pub MANUAL_FIND,
     complexity,
     "manual implementation of `Iterator::find`"
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 6d585c2e45d..0ee42b61c9a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -4,11 +4,11 @@ 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_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::{mir::FakeReadCause, ty};
 use rustc_span::source_map::Span;
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
     if_chain! {
@@ -114,7 +114,13 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(
+        &mut self,
+        _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
+        _: FakeReadCause,
+        _: HirId,
+    ) {
+    }
 }
 
 impl MutatePairDelegate<'_, '_> {
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
index 6e6faa79adc..66f9e28596e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -45,7 +45,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
                         let (arg, pred) = contains_arg
                             .strip_prefix('&')
                             .map_or(("&x", &*contains_arg), |s| ("x", s));
-                        format!("any(|{}| x == {})", arg, pred)
+                        format!("any(|{arg}| x == {pred})")
                     }
                     _ => return,
                 }
@@ -141,9 +141,9 @@ impl IterFunction {
             IterFunctionKind::Contains(span) => {
                 let s = snippet(cx, *span, "..");
                 if let Some(stripped) = s.strip_prefix('&') {
-                    format!(".any(|x| x == {})", stripped)
+                    format!(".any(|x| x == {stripped})")
                 } else {
-                    format!(".any(|x| x == *{})", s)
+                    format!(".any(|x| x == *{s})")
                 }
             },
         }
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 8ab640051b6..00cfc6d49f1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -145,7 +145,7 @@ pub(super) fn check<'tcx>(
                         cx,
                         NEEDLESS_RANGE_LOOP,
                         arg.span,
-                        &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed),
+                        &format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
                         |diag| {
                             multispan_sugg(
                                 diag,
@@ -154,7 +154,7 @@ pub(super) fn check<'tcx>(
                                     (pat.span, format!("({}, <item>)", ident.name)),
                                     (
                                         arg.span,
-                                        format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2),
+                                        format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
                                     ),
                                 ],
                             );
@@ -162,16 +162,16 @@ pub(super) fn check<'tcx>(
                     );
                 } else {
                     let repl = if starts_at_zero && take_is_empty {
-                        format!("&{}{}", ref_mut, indexed)
+                        format!("&{ref_mut}{indexed}")
                     } else {
-                        format!("{}.{}(){}{}", indexed, method, method_1, method_2)
+                        format!("{indexed}.{method}(){method_1}{method_2}")
                     };
 
                     span_lint_and_then(
                         cx,
                         NEEDLESS_RANGE_LOOP,
                         arg.span,
-                        &format!("the loop variable `{}` is only used to index `{}`", ident.name, indexed),
+                        &format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
                         |diag| {
                             multispan_sugg(
                                 diag,
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 116e589cad6..16b00ad6637 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -42,6 +42,7 @@ pub(super) fn check(
     }
 }
 
+#[derive(Copy, Clone)]
 enum NeverLoopResult {
     // A break/return always get triggered but not necessarily for the main loop.
     AlwaysBreak,
@@ -51,8 +52,8 @@ enum NeverLoopResult {
 }
 
 #[must_use]
-fn absorb_break(arg: &NeverLoopResult) -> NeverLoopResult {
-    match *arg {
+fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
+    match arg {
         NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
         NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
     }
@@ -92,19 +93,29 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult
 }
 
 fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
-    let mut iter = block.stmts.iter().filter_map(stmt_to_expr).chain(block.expr);
+    let mut iter = block
+        .stmts
+        .iter()
+        .filter_map(stmt_to_expr)
+        .chain(block.expr.map(|expr| (expr, None)));
     never_loop_expr_seq(&mut iter, main_loop_id)
 }
 
-fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_loop_id: HirId) -> NeverLoopResult {
-    es.map(|e| never_loop_expr(e, main_loop_id))
-        .fold(NeverLoopResult::Otherwise, combine_seq)
+fn never_loop_expr_seq<'a, T: Iterator<Item = (&'a Expr<'a>, Option<&'a Block<'a>>)>>(
+    es: &mut T,
+    main_loop_id: HirId,
+) -> NeverLoopResult {
+    es.map(|(e, els)| {
+        let e = never_loop_expr(e, main_loop_id);
+        els.map_or(e, |els| combine_branches(e, never_loop_block(els, main_loop_id)))
+    })
+    .fold(NeverLoopResult::Otherwise, combine_seq)
 }
 
-fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'tcx Block<'tcx>>)> {
     match stmt.kind {
-        StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some(e),
-        StmtKind::Local(local) => local.init,
+        StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some((e, None)),
+        StmtKind::Local(local) => local.init.map(|init| (init, local.els)),
         StmtKind::Item(..) => None,
     }
 }
@@ -139,7 +150,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), main_loop_id),
         ExprKind::Loop(b, _, _, _) => {
             // Break can come from the inner loop so remove them.
-            absorb_break(&never_loop_block(b, main_loop_id))
+            absorb_break(never_loop_block(b, main_loop_id))
         },
         ExprKind::If(e, e2, e3) => {
             let e1 = never_loop_expr(e, main_loop_id);
@@ -211,9 +222,5 @@ fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>)
     let pat_snippet = snippet(cx, pat.span, "_");
     let iter_snippet = make_iterator_snippet(cx, iterator, &mut Applicability::Unspecified);
 
-    format!(
-        "if let Some({pat}) = {iter}.next()",
-        pat = pat_snippet,
-        iter = iter_snippet
-    )
+    format!("if let Some({pat_snippet}) = {iter_snippet}.next()")
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index aeefe6e33fb..07edee46fa6 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -30,10 +30,7 @@ pub(super) fn check<'tcx>(
             vec.span,
             "it looks like the same item is being pushed into this Vec",
             None,
-            &format!(
-                "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
-                item_str, vec_str, item_str
-            ),
+            &format!("try using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
         );
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index f1f58db80b3..b6f4cf7bbb3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -5,12 +5,12 @@ use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor};
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, Pat, PatKind, Stmt};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_hir_analysis::hir_ty_to_ty;
 use std::iter::Iterator;
 
 #[derive(Debug, PartialEq, Eq)]
@@ -344,9 +344,8 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
                     _ => arg,
                 };
                 format!(
-                    "{}.{}()",
+                    "{}.{method_name}()",
                     sugg::Sugg::hir_with_applicability(cx, caller, "_", applic_ref).maybe_par(),
-                    method_name,
                 )
             },
             _ => format!(
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index deb21894f36..153f97e4e66 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{
-    get_enclosing_loop_or_multi_call_closure, is_refutable, is_trait_method, match_def_path, paths,
-    visitors::is_res_used,
+    get_enclosing_loop_or_multi_call_closure, is_refutable, is_res_lang_ctor, is_trait_method, visitors::is_res_used,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
+use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::ty::adjustment::Adjust;
@@ -19,9 +18,8 @@ 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);
         // check for `Some(..)` pattern
-        if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind;
-        if let Res::Def(_, pat_did) = pat_path.res;
-        if match_def_path(cx, pat_did, &paths::OPTION_SOME);
+        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);
         // check for call to `Iterator::next`
         if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
         if method_name.ident.name == sym::next;
@@ -67,7 +65,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         expr.span.with_hi(scrutinee_expr.span.hi()),
         "this loop could be written as a `for` loop",
         "try",
-        format!("for {} in {}{}", loop_var, iterator, by_ref),
+        format!("for {loop_var} in {iterator}{by_ref}"),
         applicability,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index d573a1b4fbb..594f6af76b3 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -189,9 +189,9 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
         let mut suggestions = vec![];
         for ((root, span, hir_id), path) in used {
             if path.len() == 1 {
-                suggestions.push((span, format!("{}::{}", root, path[0]), hir_id));
+                suggestions.push((span, format!("{root}::{}", path[0]), hir_id));
             } else {
-                suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")), hir_id));
+                suggestions.push((span, format!("{root}::{{{}}}", path.join(", ")), hir_id));
             }
         }
 
@@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
         // such as `std::prelude::v1::foo` or some other macro that expands to an import.
         if self.mac_refs.is_empty() {
             for (span, import, hir_id) in suggestions {
-                let help = format!("use {};", import);
+                let help = format!("use {import};");
                 span_lint_hir_and_then(
                     cx,
                     MACRO_USE_IMPORTS,
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index 26b53ab5d68..825ec84b4a8 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -1,7 +1,8 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use crate::rustc_lint::LintContext;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{peel_blocks_with_stmt, sugg};
+use clippy_utils::{peel_blocks_with_stmt, span_extract_comment, sugg};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -50,20 +51,36 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
                 let mut applicability = Applicability::MachineApplicable;
                 let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
                 let cond = cond.peel_drop_temps();
+                let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
+                if !comments.is_empty() {
+                    comments += "\n";
+                }
                 let (cond, not) = match cond.kind {
                     ExprKind::Unary(UnOp::Not, e) => (e, ""),
                     _ => (cond, "!"),
                 };
                 let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
                 let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
-                span_lint_and_sugg(
+                // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block
+                span_lint_and_then(
                     cx,
                     MANUAL_ASSERT,
                     expr.span,
                     "only a `panic!` in `if`-then statement",
-                    "try",
-                    sugg,
-                    Applicability::MachineApplicable,
+                    |diag| {
+                        // comments can be noisy, do not show them to the user
+                        diag.tool_only_span_suggestion(
+                                    expr.span.shrink_to_lo(),
+                                    "add comments back",
+                                    comments,
+                                    applicability);
+                        diag.span_suggestion(
+                                    expr.span,
+                                    "try instead",
+                                    sugg,
+                                    applicability);
+                                     }
+
                 );
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 754b0e78a14..9a0a26c0991 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -74,11 +74,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                             if let Some(ret_pos) = position_before_rarrow(&header_snip);
                             if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
                             then {
-                                let help = format!("make the function `async` and {}", ret_sugg);
+                                let help = format!("make the function `async` and {ret_sugg}");
                                 diag.span_suggestion(
                                     header_span,
                                     &help,
-                                    format!("async {}{}", &header_snip[..ret_pos], ret_snip),
+                                    format!("async {}{ret_snip}", &header_snip[..ret_pos]),
                                     Applicability::MachineApplicable
                                 );
 
@@ -196,7 +196,7 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str,
         },
         _ => {
             let sugg = "return the output of the future directly";
-            snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {}", snip)))
+            snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
         },
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
new file mode 100644
index 00000000000..ece4df95505
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -0,0 +1,713 @@
+use itertools::Itertools;
+use rustc_errors::Diagnostic;
+use rustc_hir::{
+    def::Res, Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind,
+};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty;
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{symbol::sym, Span};
+use std::ops::Deref;
+
+use clippy_utils::{
+    diagnostics::{span_lint_and_then, span_lint_hir_and_then},
+    eq_expr_value, get_trait_def_id,
+    higher::If,
+    is_diag_trait_item, is_trait_method, meets_msrv, msrvs, path_res, path_to_local_id, paths, peel_blocks,
+    peel_blocks_with_stmt,
+    sugg::Sugg,
+    ty::implements_trait,
+    visitors::is_const_evaluatable,
+    MaybePath,
+};
+use rustc_errors::Applicability;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Identifies good opportunities for a clamp function from std or core, and suggests using it.
+    ///
+    /// ### Why is this bad?
+    /// clamp is much shorter, easier to read, and doesn't use any control flow.
+    ///
+    /// ### Known issue(s)
+    /// If the clamped variable is NaN this suggestion will cause the code to propagate NaN
+    /// rather than returning either `max` or `min`.
+    ///
+    /// `clamp` functions will panic if `max < min`, `max.is_nan()`, or `min.is_nan()`.
+    /// Some may consider panicking in these situations to be desirable, but it also may
+    /// introduce panicking where there wasn't any before.
+    ///
+    /// ### Examples
+    /// ```rust
+    /// # let (input, min, max) = (0, -2, 1);
+    /// if input > max {
+    ///     max
+    /// } else if input < min {
+    ///     min
+    /// } else {
+    ///     input
+    /// }
+    /// # ;
+    /// ```
+    ///
+    /// ```rust
+    /// # let (input, min, max) = (0, -2, 1);
+    /// input.max(min).min(max)
+    /// # ;
+    /// ```
+    ///
+    /// ```rust
+    /// # let (input, min, max) = (0, -2, 1);
+    /// match input {
+    ///     x if x > max => max,
+    ///     x if x < min => min,
+    ///     x => x,
+    /// }
+    /// # ;
+    /// ```
+    ///
+    /// ```rust
+    /// # let (input, min, max) = (0, -2, 1);
+    /// let mut x = input;
+    /// if x < min { x = min; }
+    /// if x > max { x = max; }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let (input, min, max) = (0, -2, 1);
+    /// input.clamp(min, max)
+    /// # ;
+    /// ```
+    #[clippy::version = "1.66.0"]
+    pub MANUAL_CLAMP,
+    complexity,
+    "using a clamp pattern instead of the clamp function"
+}
+impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]);
+
+pub struct ManualClamp {
+    msrv: Option<RustcVersion>,
+}
+
+impl ManualClamp {
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+#[derive(Debug)]
+struct ClampSuggestion<'tcx> {
+    params: InputMinMax<'tcx>,
+    span: Span,
+    make_assignment: Option<&'tcx Expr<'tcx>>,
+    hir_with_ignore_attr: Option<HirId>,
+}
+
+#[derive(Debug)]
+struct InputMinMax<'tcx> {
+    input: &'tcx Expr<'tcx>,
+    min: &'tcx Expr<'tcx>,
+    max: &'tcx Expr<'tcx>,
+    is_float: bool,
+}
+
+impl<'tcx> LateLintPass<'tcx> for ManualClamp {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if !meets_msrv(self.msrv, msrvs::CLAMP) {
+            return;
+        }
+        if !expr.span.from_expansion() {
+            let suggestion = is_if_elseif_else_pattern(cx, expr)
+                .or_else(|| is_max_min_pattern(cx, expr))
+                .or_else(|| is_call_max_min_pattern(cx, expr))
+                .or_else(|| is_match_pattern(cx, expr))
+                .or_else(|| is_if_elseif_pattern(cx, expr));
+            if let Some(suggestion) = suggestion {
+                emit_suggestion(cx, &suggestion);
+            }
+        }
+    }
+
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
+        if !meets_msrv(self.msrv, msrvs::CLAMP) {
+            return;
+        }
+        for suggestion in is_two_if_pattern(cx, block) {
+            emit_suggestion(cx, &suggestion);
+        }
+    }
+    extract_msrv_attr!(LateContext);
+}
+
+fn emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) {
+    let ClampSuggestion {
+        params: InputMinMax {
+            input,
+            min,
+            max,
+            is_float,
+        },
+        span,
+        make_assignment,
+        hir_with_ignore_attr,
+    } = suggestion;
+    let input = Sugg::hir(cx, input, "..").maybe_par();
+    let min = Sugg::hir(cx, min, "..");
+    let max = Sugg::hir(cx, max, "..");
+    let semicolon = if make_assignment.is_some() { ";" } else { "" };
+    let assignment = if let Some(assignment) = make_assignment {
+        let assignment = Sugg::hir(cx, assignment, "..");
+        format!("{assignment} = ")
+    } else {
+        String::new()
+    };
+    let suggestion = format!("{assignment}{input}.clamp({min}, {max}){semicolon}");
+    let msg = "clamp-like pattern without using clamp function";
+    let lint_builder = |d: &mut Diagnostic| {
+        d.span_suggestion(*span, "replace with clamp", suggestion, Applicability::MaybeIncorrect);
+        if *is_float {
+            d.note("clamp will panic if max < min, min.is_nan(), or max.is_nan()")
+                .note("clamp returns NaN if the input is NaN");
+        } else {
+            d.note("clamp will panic if max < min");
+        }
+    };
+    if let Some(hir_id) = hir_with_ignore_attr {
+        span_lint_hir_and_then(cx, MANUAL_CLAMP, *hir_id, *span, msg, lint_builder);
+    } else {
+        span_lint_and_then(cx, MANUAL_CLAMP, *span, msg, lint_builder);
+    }
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+enum TypeClampability {
+    Float,
+    Ord,
+}
+
+impl TypeClampability {
+    fn is_clampable<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<TypeClampability> {
+        if ty.is_floating_point() {
+            Some(TypeClampability::Float)
+        } else if get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])) {
+            Some(TypeClampability::Ord)
+        } else {
+            None
+        }
+    }
+
+    fn is_float(self) -> bool {
+        matches!(self, TypeClampability::Float)
+    }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min, max) = (0, -3, 12);
+///
+/// if input < min {
+///     min
+/// } else if input > max {
+///     max
+/// } else {
+///     input
+/// }
+/// # ;
+/// ```
+fn is_if_elseif_else_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+    if let Some(If {
+        cond,
+        then,
+        r#else: Some(else_if),
+    }) = If::hir(expr)
+    && let Some(If {
+        cond: else_if_cond,
+        then: else_if_then,
+        r#else: Some(else_body),
+    }) = If::hir(peel_blocks(else_if))
+    {
+        let params = is_clamp_meta_pattern(
+            cx,
+            &BinaryOp::new(peel_blocks(cond))?,
+            &BinaryOp::new(peel_blocks(else_if_cond))?,
+            peel_blocks(then),
+            peel_blocks(else_if_then),
+            None,
+        )?;
+        // Contents of the else should be the resolved input.
+        if !eq_expr_value(cx, params.input, peel_blocks(else_body)) {
+            return None;
+        }
+        Some(ClampSuggestion {
+            params,
+            span: expr.span,
+            make_assignment: None,
+            hir_with_ignore_attr: None,
+        })
+    } else {
+        None
+    }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min_value, max_value) = (0, -3, 12);
+///
+/// input.max(min_value).min(max_value)
+/// # ;
+/// ```
+fn is_max_min_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+    if let ExprKind::MethodCall(seg_second, receiver, [arg_second], _) = &expr.kind
+        && (cx.typeck_results().expr_ty_adjusted(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord))
+        && let ExprKind::MethodCall(seg_first, input, [arg_first], _) = &receiver.kind
+        && (cx.typeck_results().expr_ty_adjusted(input).is_floating_point() || is_trait_method(cx, receiver, sym::Ord))
+    {
+        let is_float = cx.typeck_results().expr_ty_adjusted(input).is_floating_point();
+        let (min, max) = match (seg_first.ident.as_str(), seg_second.ident.as_str()) {
+            ("min", "max") => (arg_second, arg_first),
+            ("max", "min") => (arg_first, arg_second),
+            _ => return None,
+        };
+        Some(ClampSuggestion {
+            params: InputMinMax { input, min, max, is_float },
+            span: expr.span,
+            make_assignment: None,
+            hir_with_ignore_attr: None,
+        })
+    } else {
+        None
+    }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min_value, max_value) = (0, -3, 12);
+/// # use std::cmp::{max, min};
+/// min(max(input, min_value), max_value)
+/// # ;
+/// ```
+fn is_call_max_min_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+    fn segment<'tcx>(cx: &LateContext<'_>, func: &Expr<'tcx>) -> Option<FunctionType<'tcx>> {
+        match func.kind {
+            ExprKind::Path(QPath::Resolved(None, path)) => {
+                let id = path.res.opt_def_id()?;
+                match cx.tcx.get_diagnostic_name(id) {
+                    Some(sym::cmp_min) => Some(FunctionType::CmpMin),
+                    Some(sym::cmp_max) => Some(FunctionType::CmpMax),
+                    _ if is_diag_trait_item(cx, id, sym::Ord) => {
+                        Some(FunctionType::OrdOrFloat(path.segments.last().expect("infallible")))
+                    },
+                    _ => None,
+                }
+            },
+            ExprKind::Path(QPath::TypeRelative(ty, seg)) => {
+                matches!(path_res(cx, ty), Res::PrimTy(PrimTy::Float(_))).then(|| FunctionType::OrdOrFloat(seg))
+            },
+            _ => None,
+        }
+    }
+
+    enum FunctionType<'tcx> {
+        CmpMin,
+        CmpMax,
+        OrdOrFloat(&'tcx PathSegment<'tcx>),
+    }
+
+    fn check<'tcx>(
+        cx: &LateContext<'tcx>,
+        outer_fn: &'tcx Expr<'tcx>,
+        inner_call: &'tcx Expr<'tcx>,
+        outer_arg: &'tcx Expr<'tcx>,
+        span: Span,
+    ) -> Option<ClampSuggestion<'tcx>> {
+        if let ExprKind::Call(inner_fn, [first, second]) = &inner_call.kind
+            && let Some(inner_seg) = segment(cx, inner_fn)
+            && let Some(outer_seg) = segment(cx, outer_fn)
+        {
+            let (input, inner_arg) = match (is_const_evaluatable(cx, first), is_const_evaluatable(cx, second)) {
+                (true, false) => (second, first),
+                (false, true) => (first, second),
+                _ => return None,
+            };
+            let is_float = cx.typeck_results().expr_ty_adjusted(input).is_floating_point();
+            let (min, max) = match (inner_seg, outer_seg) {
+                (FunctionType::CmpMin, FunctionType::CmpMax) => (outer_arg, inner_arg),
+                (FunctionType::CmpMax, FunctionType::CmpMin) => (inner_arg, outer_arg),
+                (FunctionType::OrdOrFloat(first_segment), FunctionType::OrdOrFloat(second_segment)) => {
+                    match (first_segment.ident.as_str(), second_segment.ident.as_str()) {
+                        ("min", "max") => (outer_arg, inner_arg),
+                        ("max", "min") => (inner_arg, outer_arg),
+                        _ => return None,
+                    }
+                }
+                _ => return None,
+            };
+            Some(ClampSuggestion {
+                params: InputMinMax { input, min, max, is_float },
+                span,
+                make_assignment: None,
+                hir_with_ignore_attr: None,
+            })
+        } else {
+            None
+        }
+    }
+
+    if let ExprKind::Call(outer_fn, [first, second]) = &expr.kind {
+        check(cx, outer_fn, first, second, expr.span).or_else(|| check(cx, outer_fn, second, first, expr.span))
+    } else {
+        None
+    }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min, max) = (0, -3, 12);
+///
+/// match input {
+///     input if input > max => max,
+///     input if input < min => min,
+///     input => input,
+/// }
+/// # ;
+/// ```
+fn is_match_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+    if let ExprKind::Match(value, [first_arm, second_arm, last_arm], rustc_hir::MatchSource::Normal) = &expr.kind {
+        // Find possible min/max branches
+        let minmax_values = |a: &'tcx Arm<'tcx>| {
+            if let PatKind::Binding(_, var_hir_id, _, None) = &a.pat.kind
+            && let Some(Guard::If(e)) = a.guard {
+                Some((e, var_hir_id, a.body))
+            } else {
+                None
+            }
+        };
+        let (first, first_hir_id, first_expr) = minmax_values(first_arm)?;
+        let (second, second_hir_id, second_expr) = minmax_values(second_arm)?;
+        let first = BinaryOp::new(first)?;
+        let second = BinaryOp::new(second)?;
+        if let PatKind::Binding(_, binding, _, None) = &last_arm.pat.kind
+            && path_to_local_id(peel_blocks_with_stmt(last_arm.body), *binding)
+            && last_arm.guard.is_none()
+        {
+            // Proceed as normal
+        } else {
+            return None;
+        }
+        if let Some(params) = is_clamp_meta_pattern(
+            cx,
+            &first,
+            &second,
+            first_expr,
+            second_expr,
+            Some((*first_hir_id, *second_hir_id)),
+        ) {
+            return Some(ClampSuggestion {
+                params: InputMinMax {
+                    input: value,
+                    min: params.min,
+                    max: params.max,
+                    is_float: params.is_float,
+                },
+                span: expr.span,
+                make_assignment: None,
+                hir_with_ignore_attr: None,
+            });
+        }
+    }
+    None
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min, max) = (0, -3, 12);
+///
+/// let mut x = input;
+/// if x < min { x = min; }
+/// if x > max { x = max; }
+/// ```
+fn is_two_if_pattern<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Vec<ClampSuggestion<'tcx>> {
+    block_stmt_with_last(block)
+        .tuple_windows()
+        .filter_map(|(maybe_set_first, maybe_set_second)| {
+            if let StmtKind::Expr(first_expr) = *maybe_set_first
+                && let StmtKind::Expr(second_expr) = *maybe_set_second
+                && let Some(If { cond: first_cond, then: first_then, r#else: None }) = If::hir(first_expr)
+                && let Some(If { cond: second_cond, then: second_then, r#else: None }) = If::hir(second_expr)
+                && let ExprKind::Assign(
+                    maybe_input_first_path,
+                    maybe_min_max_first,
+                    _
+                ) = peel_blocks_with_stmt(first_then).kind
+                && let ExprKind::Assign(
+                    maybe_input_second_path,
+                    maybe_min_max_second,
+                    _
+                ) = peel_blocks_with_stmt(second_then).kind
+                && eq_expr_value(cx, maybe_input_first_path, maybe_input_second_path)
+                && let Some(first_bin) = BinaryOp::new(first_cond)
+                && let Some(second_bin) = BinaryOp::new(second_cond)
+                && let Some(input_min_max) = is_clamp_meta_pattern(
+                    cx,
+                    &first_bin,
+                    &second_bin,
+                    maybe_min_max_first,
+                    maybe_min_max_second,
+                    None
+                )
+            {
+                Some(ClampSuggestion {
+                    params: InputMinMax {
+                        input: maybe_input_first_path,
+                        min: input_min_max.min,
+                        max: input_min_max.max,
+                        is_float: input_min_max.is_float,
+                    },
+                    span: first_expr.span.to(second_expr.span),
+                    make_assignment: Some(maybe_input_first_path),
+                    hir_with_ignore_attr: Some(first_expr.hir_id()),
+                })
+            } else {
+                None
+            }
+        })
+        .collect()
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (mut input, min, max) = (0, -3, 12);
+///
+/// if input < min {
+///     input = min;
+/// } else if input > max {
+///     input = max;
+/// }
+/// ```
+fn is_if_elseif_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+    if let Some(If {
+        cond,
+        then,
+        r#else: Some(else_if),
+    }) = If::hir(expr)
+        && let Some(If {
+            cond: else_if_cond,
+            then: else_if_then,
+            r#else: None,
+        }) = If::hir(peel_blocks(else_if))
+        && let ExprKind::Assign(
+            maybe_input_first_path,
+            maybe_min_max_first,
+            _
+        ) = peel_blocks_with_stmt(then).kind
+        && let ExprKind::Assign(
+            maybe_input_second_path,
+            maybe_min_max_second,
+            _
+        ) = peel_blocks_with_stmt(else_if_then).kind
+    {
+        let params = is_clamp_meta_pattern(
+            cx,
+            &BinaryOp::new(peel_blocks(cond))?,
+            &BinaryOp::new(peel_blocks(else_if_cond))?,
+            peel_blocks(maybe_min_max_first),
+            peel_blocks(maybe_min_max_second),
+            None,
+        )?;
+        if !eq_expr_value(cx, maybe_input_first_path, maybe_input_second_path) {
+            return None;
+        }
+        Some(ClampSuggestion {
+            params,
+            span: expr.span,
+            make_assignment: Some(maybe_input_first_path),
+            hir_with_ignore_attr: None,
+        })
+    } else {
+        None
+    }
+}
+
+/// `ExprKind::Binary` but more narrowly typed
+#[derive(Debug, Clone, Copy)]
+struct BinaryOp<'tcx> {
+    op: BinOpKind,
+    left: &'tcx Expr<'tcx>,
+    right: &'tcx Expr<'tcx>,
+}
+
+impl<'tcx> BinaryOp<'tcx> {
+    fn new(e: &'tcx Expr<'tcx>) -> Option<BinaryOp<'tcx>> {
+        match &e.kind {
+            ExprKind::Binary(op, left, right) => Some(BinaryOp {
+                op: op.node,
+                left,
+                right,
+            }),
+            _ => None,
+        }
+    }
+
+    fn flip(&self) -> Self {
+        Self {
+            op: match self.op {
+                BinOpKind::Le => BinOpKind::Ge,
+                BinOpKind::Lt => BinOpKind::Gt,
+                BinOpKind::Ge => BinOpKind::Le,
+                BinOpKind::Gt => BinOpKind::Lt,
+                other => other,
+            },
+            left: self.right,
+            right: self.left,
+        }
+    }
+}
+
+/// The clamp meta pattern is a pattern shared between many (but not all) patterns.
+/// In summary, this pattern consists of two if statements that meet many criteria,
+/// - binary operators that are one of [`>`, `<`, `>=`, `<=`].
+/// - Both binary statements must have a shared argument
+///     - Which can appear on the left or right side of either statement
+///     - The binary operators must define a finite range for the shared argument. To put this in
+///       the terms of Rust `std` library, the following ranges are acceptable
+///         - `Range`
+///         - `RangeInclusive`
+///       And all other range types are not accepted. For the purposes of `clamp` it's irrelevant
+///       whether the range is inclusive or not, the output is the same.
+/// - The result of each if statement must be equal to the argument unique to that if statement. The
+///   result can not be the shared argument in either case.
+fn is_clamp_meta_pattern<'tcx>(
+    cx: &LateContext<'tcx>,
+    first_bin: &BinaryOp<'tcx>,
+    second_bin: &BinaryOp<'tcx>,
+    first_expr: &'tcx Expr<'tcx>,
+    second_expr: &'tcx Expr<'tcx>,
+    // This parameters is exclusively for the match pattern.
+    // It exists because the variable bindings used in that pattern
+    // refer to the variable bound in the match arm, not the variable
+    // bound outside of it. Fortunately due to context we know this has to
+    // be the input variable, not the min or max.
+    input_hir_ids: Option<(HirId, HirId)>,
+) -> Option<InputMinMax<'tcx>> {
+    fn check<'tcx>(
+        cx: &LateContext<'tcx>,
+        first_bin: &BinaryOp<'tcx>,
+        second_bin: &BinaryOp<'tcx>,
+        first_expr: &'tcx Expr<'tcx>,
+        second_expr: &'tcx Expr<'tcx>,
+        input_hir_ids: Option<(HirId, HirId)>,
+        is_float: bool,
+    ) -> Option<InputMinMax<'tcx>> {
+        match (&first_bin.op, &second_bin.op) {
+            (BinOpKind::Ge | BinOpKind::Gt, BinOpKind::Le | BinOpKind::Lt) => {
+                let (min, max) = (second_expr, first_expr);
+                let refers_to_input = match input_hir_ids {
+                    Some((first_hir_id, second_hir_id)) => {
+                        path_to_local_id(peel_blocks(first_bin.left), first_hir_id)
+                            && path_to_local_id(peel_blocks(second_bin.left), second_hir_id)
+                    },
+                    None => eq_expr_value(cx, first_bin.left, second_bin.left),
+                };
+                (refers_to_input
+                    && eq_expr_value(cx, first_bin.right, first_expr)
+                    && eq_expr_value(cx, second_bin.right, second_expr))
+                .then_some(InputMinMax {
+                    input: first_bin.left,
+                    min,
+                    max,
+                    is_float,
+                })
+            },
+            _ => None,
+        }
+    }
+    // First filter out any expressions with side effects
+    let exprs = [
+        first_bin.left,
+        first_bin.right,
+        second_bin.left,
+        second_bin.right,
+        first_expr,
+        second_expr,
+    ];
+    let clampability = TypeClampability::is_clampable(cx, cx.typeck_results().expr_ty(first_expr))?;
+    let is_float = clampability.is_float();
+    if exprs.iter().any(|e| peel_blocks(e).can_have_side_effects()) {
+        return None;
+    }
+    if !(is_ord_op(first_bin.op) && is_ord_op(second_bin.op)) {
+        return None;
+    }
+    let cases = [
+        (*first_bin, *second_bin),
+        (first_bin.flip(), second_bin.flip()),
+        (first_bin.flip(), *second_bin),
+        (*first_bin, second_bin.flip()),
+    ];
+
+    cases.into_iter().find_map(|(first, second)| {
+        check(cx, &first, &second, first_expr, second_expr, input_hir_ids, is_float).or_else(|| {
+            check(
+                cx,
+                &second,
+                &first,
+                second_expr,
+                first_expr,
+                input_hir_ids.map(|(l, r)| (r, l)),
+                is_float,
+            )
+        })
+    })
+}
+
+fn block_stmt_with_last<'tcx>(block: &'tcx Block<'tcx>) -> impl Iterator<Item = MaybeBorrowedStmtKind<'tcx>> {
+    block
+        .stmts
+        .iter()
+        .map(|s| MaybeBorrowedStmtKind::Borrowed(&s.kind))
+        .chain(
+            block
+                .expr
+                .as_ref()
+                .map(|e| MaybeBorrowedStmtKind::Owned(StmtKind::Expr(e))),
+        )
+}
+
+fn is_ord_op(op: BinOpKind) -> bool {
+    matches!(op, BinOpKind::Ge | BinOpKind::Gt | BinOpKind::Le | BinOpKind::Lt)
+}
+
+/// Really similar to Cow, but doesn't have a `Clone` requirement.
+#[derive(Debug)]
+enum MaybeBorrowedStmtKind<'a> {
+    Borrowed(&'a StmtKind<'a>),
+    Owned(StmtKind<'a>),
+}
+
+impl<'a> Clone for MaybeBorrowedStmtKind<'a> {
+    fn clone(&self) -> Self {
+        match self {
+            Self::Borrowed(t) => Self::Borrowed(t),
+            Self::Owned(StmtKind::Expr(e)) => Self::Owned(StmtKind::Expr(e)),
+            Self::Owned(_) => unreachable!("Owned should only ever contain a StmtKind::Expr."),
+        }
+    }
+}
+
+impl<'a> Deref for MaybeBorrowedStmtKind<'a> {
+    type Target = StmtKind<'a>;
+
+    fn deref(&self) -> &Self::Target {
+        match self {
+            Self::Borrowed(t) => t,
+            Self::Owned(t) => t,
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 53e7565bd33..6a42275322b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -133,7 +133,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct {
                             diag.span_suggestion(
                                 header_span,
                                 "add the attribute",
-                                format!("#[non_exhaustive] {}", snippet),
+                                format!("#[non_exhaustive] {snippet}"),
                                 Applicability::Unspecified,
                             );
                         }
@@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
                             diag.span_suggestion(
                                 header_span,
                                 "add the attribute",
-                                format!("#[non_exhaustive] {}", snippet),
+                                format!("#[non_exhaustive] {snippet}"),
                                 Applicability::Unspecified,
                             );
                     }
diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
index 95cc6bdbd8b..6f25a2ed8e4 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -27,7 +27,7 @@ declare_clippy_lint! {
     /// let x: i32 = 24;
     /// let rem = x.rem_euclid(4);
     /// ```
-    #[clippy::version = "1.63.0"]
+    #[clippy::version = "1.64.0"]
     pub MANUAL_REM_EUCLID,
     complexity,
     "manually reimplementing `rem_euclid`"
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index f28c37d3dca..3181bc86d17 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -43,7 +43,7 @@ declare_clippy_lint! {
     /// let mut vec = vec![0, 1, 2];
     /// vec.retain(|x| x % 2 == 0);
     /// ```
-    #[clippy::version = "1.63.0"]
+    #[clippy::version = "1.64.0"]
     pub MANUAL_RETAIN,
     perf,
     "`retain()` is simpler and the same functionalitys"
@@ -92,7 +92,7 @@ fn check_into_iter(
         && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
         && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
         && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
-        && match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER)
+        && cx.tcx.lang_items().require(hir::LangItem::IntoIterIntoIter).ok() == Some(into_iter_def_id)
         && match_acceptable_type(cx, left_expr, msrv)
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
         suggest(cx, parent_expr, left_expr, target_expr);
@@ -153,7 +153,7 @@ fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::E
         && let [filter_params] = filter_body.params
         && let Some(sugg) = match filter_params.pat.kind {
             hir::PatKind::Binding(_, _, filter_param_ident, None) => {
-                Some(format!("{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), filter_param_ident, snippet(cx, filter_body.value.span, "..")))
+                Some(format!("{}.retain(|{filter_param_ident}| {})", snippet(cx, left_expr.span, ".."), snippet(cx, filter_body.value.span, "..")))
             },
             hir::PatKind::Tuple([key_pat, value_pat], _) => {
                 make_sugg(cx, key_pat, value_pat, left_expr, filter_body)
@@ -161,7 +161,7 @@ fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::E
             hir::PatKind::Ref(pat, _) => {
                 match pat.kind {
                     hir::PatKind::Binding(_, _, filter_param_ident, None) => {
-                        Some(format!("{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), filter_param_ident, snippet(cx, filter_body.value.span, "..")))
+                        Some(format!("{}.retain(|{filter_param_ident}| {})", snippet(cx, left_expr.span, ".."), snippet(cx, filter_body.value.span, "..")))
                     },
                     _ => None
                 }
@@ -190,23 +190,19 @@ fn make_sugg(
     match (&key_pat.kind, &value_pat.kind) {
         (hir::PatKind::Binding(_, _, key_param_ident, None), hir::PatKind::Binding(_, _, value_param_ident, None)) => {
             Some(format!(
-                "{}.retain(|{}, &mut {}| {})",
+                "{}.retain(|{key_param_ident}, &mut {value_param_ident}| {})",
                 snippet(cx, left_expr.span, ".."),
-                key_param_ident,
-                value_param_ident,
                 snippet(cx, filter_body.value.span, "..")
             ))
         },
         (hir::PatKind::Binding(_, _, key_param_ident, None), hir::PatKind::Wild) => Some(format!(
-            "{}.retain(|{}, _| {})",
+            "{}.retain(|{key_param_ident}, _| {})",
             snippet(cx, left_expr.span, ".."),
-            key_param_ident,
             snippet(cx, filter_body.value.span, "..")
         )),
         (hir::PatKind::Wild, hir::PatKind::Binding(_, _, value_param_ident, None)) => Some(format!(
-            "{}.retain(|_, &mut {}| {})",
+            "{}.retain(|_, &mut {value_param_ident}| {})",
             snippet(cx, left_expr.span, ".."),
-            value_param_ident,
             snippet(cx, filter_body.value.span, "..")
         )),
         _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 7941c8c9c7e..0976940afac 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -108,15 +108,14 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
                     };
 
                     let test_span = expr.span.until(then.span);
-                    span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {} manually", kind_word), |diag| {
-                        diag.span_note(test_span, &format!("the {} was tested here", kind_word));
+                    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_{}` method", kind_word),
+                            &format!("try using the `strip_{kind_word}` method"),
                             vec![(test_span,
-                                  format!("if let Some(<stripped>) = {}.strip_{}({}) ",
+                                  format!("if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
                                           snippet(cx, target_arg.span, ".."),
-                                          kind_word,
                                           snippet(cx, pattern.span, "..")))]
                             .into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
                         );
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index 33d74481529..32da37a862d 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -131,12 +131,12 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) ->
         },
         hir::ExprKind::Block(block, _) => {
             match (block.stmts, block.expr.as_ref()) {
-                (&[], Some(inner_expr)) => {
+                ([], Some(inner_expr)) => {
                     // If block only contains an expression,
                     // reduce `{ X }` to `X`
                     reduce_unit_expression(cx, inner_expr)
                 },
-                (&[ref inner_stmt], None) => {
+                ([inner_stmt], None) => {
                     // If block only contains statements,
                     // reduce `{ X; }` to `X` or `X;`
                     match inner_stmt.kind {
@@ -194,10 +194,7 @@ fn let_binding_name(cx: &LateContext<'_>, var_arg: &hir::Expr<'_>) -> String {
 
 #[must_use]
 fn suggestion_msg(function_type: &str, map_type: &str) -> String {
-    format!(
-        "called `map(f)` on an `{0}` value where `f` is a {1} that returns the unit type `()`",
-        map_type, function_type
-    )
+    format!("called `map(f)` on an `{map_type}` value where `f` is a {function_type} that returns the unit type `()`")
 }
 
 fn lint_map_unit_fn(
diff --git a/src/tools/clippy/clippy_lints/src/match_result_ok.rs b/src/tools/clippy/clippy_lints/src/match_result_ok.rs
index 8588ab1ed8d..a020282d234 100644
--- a/src/tools/clippy/clippy_lints/src/match_result_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/match_result_ok.rs
@@ -70,9 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
                 let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
                 let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_path.ident.span), "", &mut applicability);
                 let sugg = format!(
-                    "{} let Ok({}) = {}",
-                    ifwhile,
-                    some_expr_string,
+                    "{ifwhile} let Ok({some_expr_string}) = {}",
                     trimmed_ok.trim().trim_end_matches('.'),
                 );
                 span_lint_and_sugg(
@@ -80,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
                     MATCH_RESULT_OK,
                     expr.span.with_hi(let_expr.span.hi()),
                     "matching on `Some` with `ok()` is redundant",
-                    &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string),
+                    &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),
                     sugg,
                     applicability,
                 );
diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
index 07021f1bcad..fd14d868df3 100644
--- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
@@ -1,7 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq};
+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;
@@ -110,7 +112,7 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
     }
     match arm.pat.kind {
         PatKind::Binding(..) | PatKind::Wild => true,
-        PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
+        PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_map.rs b/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
index b0198e856d5..76f5e1c941c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
@@ -3,8 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
 use clippy_utils::{
-    can_move_expr_to_closure, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id, peel_blocks,
-    peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
+    can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
+    peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
 };
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::Applicability;
@@ -144,7 +144,7 @@ fn check<'tcx>(
     let scrutinee = peel_hir_expr_refs(scrutinee).0;
     let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
     let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
-        format!("({})", scrutinee_str)
+        format!("({scrutinee_str})")
     } else {
         scrutinee_str.into()
     };
@@ -172,9 +172,9 @@ fn check<'tcx>(
                 };
                 let expr_snip = snippet_with_context(cx, some_expr.expr.span, expr_ctxt, "..", &mut app).0;
                 if some_expr.needs_unsafe_block {
-                    format!("|{}{}| unsafe {{ {} }}", annotation, some_binding, expr_snip)
+                    format!("|{annotation}{some_binding}| unsafe {{ {expr_snip} }}")
                 } else {
-                    format!("|{}{}| {}", annotation, some_binding, expr_snip)
+                    format!("|{annotation}{some_binding}| {expr_snip}")
                 }
             }
         }
@@ -183,9 +183,9 @@ fn check<'tcx>(
         let pat_snip = snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0;
         let expr_snip = snippet_with_context(cx, some_expr.expr.span, expr_ctxt, "..", &mut app).0;
         if some_expr.needs_unsafe_block {
-            format!("|{}| unsafe {{ {} }}", pat_snip, expr_snip)
+            format!("|{pat_snip}| unsafe {{ {expr_snip} }}")
         } else {
-            format!("|{}| {}", pat_snip, expr_snip)
+            format!("|{pat_snip}| {expr_snip}")
         }
     } else {
         // Refutable bindings and mixed reference annotations can't be handled by `map`.
@@ -199,9 +199,9 @@ fn check<'tcx>(
         "manual implementation of `Option::map`",
         "try this",
         if else_pat.is_none() && is_else_clause(cx.tcx, expr) {
-            format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str)
+            format!("{{ {scrutinee_str}{as_ref_str}.map({body_str}) }}")
         } else {
-            format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str)
+            format!("{scrutinee_str}{as_ref_str}.map({body_str})")
         },
         app,
     );
@@ -251,9 +251,11 @@ fn try_parse_pattern<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: Syn
         match pat.kind {
             PatKind::Wild => Some(OptionPat::Wild),
             PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
-            PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None),
+            PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionNone) => {
+                Some(OptionPat::None)
+            },
             PatKind::TupleStruct(ref qpath, [pattern], _)
-                if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt =>
+                if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionSome) && pat.span.ctxt() == ctxt =>
             {
                 Some(OptionPat::Some { pattern, ref_count })
             },
@@ -272,16 +274,14 @@ fn get_some_expr<'tcx>(
 ) -> Option<SomeExpr<'tcx>> {
     // TODO: Allow more complex expressions.
     match expr.kind {
-        ExprKind::Call(
-            Expr {
-                kind: ExprKind::Path(ref qpath),
-                ..
-            },
-            [arg],
-        ) if ctxt == expr.span.ctxt() && is_lang_ctor(cx, qpath, OptionSome) => Some(SomeExpr {
-            expr: arg,
-            needs_unsafe_block,
-        }),
+        ExprKind::Call(callee, [arg])
+            if ctxt == expr.span.ctxt() && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) =>
+        {
+            Some(SomeExpr {
+                expr: arg,
+                needs_unsafe_block,
+            })
+        },
         ExprKind::Block(
             Block {
                 stmts: [],
@@ -302,5 +302,5 @@ fn get_some_expr<'tcx>(
 
 // Checks for the `None` value.
 fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    matches!(peel_blocks(expr).kind, ExprKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
+    is_res_lang_ctor(cx, path_res(cx, peel_blocks(expr)), OptionNone)
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index e1111c80f2f..587c926dc01 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -3,12 +3,14 @@ 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::usage::contains_return_break_continue_macro;
-use clippy_utils::{is_lang_ctor, path_to_local_id, sugg};
+use clippy_utils::{is_res_lang_ctor, path_to_local_id, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::LangItem::{OptionNone, ResultErr};
 use rustc_hir::{Arm, Expr, PatKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::DefIdTree;
 use rustc_span::sym;
 
 use super::MANUAL_UNWRAP_OR;
@@ -42,12 +44,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
             span_lint_and_sugg(
                 cx,
                 MANUAL_UNWRAP_OR, expr.span,
-                &format!("this pattern reimplements `{}::unwrap_or`", ty_name),
+                &format!("this pattern reimplements `{ty_name}::unwrap_or`"),
                 "replace with",
                 format!(
-                    "{}.unwrap_or({})",
-                    suggestion,
-                    reindented_or_body,
+                    "{suggestion}.unwrap_or({reindented_or_body})",
                 ),
                 Applicability::MachineApplicable,
             );
@@ -61,15 +61,19 @@ fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'
         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_lang_ctor(cx, qpath, OptionNone),
+                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_lang_ctor(cx, qpath, ResultErr),
+                    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 is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk);
+        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();
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
index 91d17f481e2..2818f030b7a 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_lang_ctor, peel_blocks};
+use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
 use rustc_lint::LateContext;
@@ -45,13 +45,11 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
                 cx,
                 MATCH_AS_REF,
                 expr.span,
-                &format!("use `{}()` instead", suggestion),
+                &format!("use `{suggestion}()` instead"),
                 "try this",
                 format!(
-                    "{}.{}(){}",
+                    "{}.{suggestion}(){cast}",
                     snippet_with_applicability(cx, ex.span, "_", &mut applicability),
-                    suggestion,
-                    cast,
                 ),
                 applicability,
             );
@@ -61,18 +59,20 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
 
 // Checks if arm has the form `None => None`
 fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
-    matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, LangItem::OptionNone))
+    matches!(
+        arm.pat.kind,
+        PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionNone)
+    )
 }
 
 // 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_lang_ctor(cx, qpath, LangItem::OptionSome);
+        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 let ExprKind::Path(ref some_path) = e.kind;
-        if is_lang_ctor(cx, some_path, LangItem::OptionSome);
+        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 {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 34cc082687e..107fad32393 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -112,7 +112,7 @@ where
                     .join(" | ")
             };
             let pat_and_guard = if let Some(Guard::If(g)) = first_guard {
-                format!("{} if {}", pat, snippet_with_applicability(cx, g.span, "..", &mut applicability))
+                format!("{pat} if {}", snippet_with_applicability(cx, g.span, "..", &mut applicability))
             } else {
                 pat
             };
@@ -131,10 +131,9 @@ where
                 &format!("{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" }),
                 "try this",
                 format!(
-                    "{}matches!({}, {})",
+                    "{}matches!({}, {pat_and_guard})",
                     if b0 { "" } else { "!" },
                     snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
-                    pat_and_guard,
                 ),
                 applicability,
             );
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index d37f44d4a17..37049f83577 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -134,7 +134,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                     diag.span_suggestion(
                         keep_arm.pat.span,
                         "try merging the arm patterns",
-                        format!("{} | {}", keep_pat_snip, move_pat_snip),
+                        format!("{keep_pat_snip} | {move_pat_snip}"),
                         Applicability::MaybeIncorrect,
                     )
                     .help("or try changing either arm body")
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index 5ae4a65acaf..68682cedf1d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -75,12 +75,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
                 Some(AssignmentExpr::Local { span, pat_span }) => (
                     span,
                     format!(
-                        "let {} = {};\n{}let {} = {};",
+                        "let {} = {};\n{}let {} = {snippet_body};",
                         snippet_with_applicability(cx, bind_names, "..", &mut applicability),
                         snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
                         " ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
-                        snippet_with_applicability(cx, pat_span, "..", &mut applicability),
-                        snippet_body
+                        snippet_with_applicability(cx, pat_span, "..", &mut applicability)
                     ),
                 ),
                 None => {
@@ -110,10 +109,8 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
             if ex.can_have_side_effects() {
                 let indent = " ".repeat(indent_of(cx, expr.span).unwrap_or(0));
                 let sugg = format!(
-                    "{};\n{}{}",
-                    snippet_with_applicability(cx, ex.span, "..", &mut applicability),
-                    indent,
-                    snippet_body
+                    "{};\n{indent}{snippet_body}",
+                    snippet_with_applicability(cx, ex.span, "..", &mut applicability)
                 );
 
                 span_lint_and_sugg(
@@ -178,10 +175,10 @@ fn sugg_with_curlies<'a>(
     let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
     if let Some(parent_expr) = get_parent_expr(cx, match_expr) {
         if let ExprKind::Closure { .. } = parent_expr.kind {
-            cbrace_end = format!("\n{}}}", indent);
+            cbrace_end = format!("\n{indent}}}");
             // Fix body indent due to the closure
             indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
-            cbrace_start = format!("{{\n{}", indent);
+            cbrace_start = format!("{{\n{indent}");
         }
     }
 
@@ -190,10 +187,10 @@ fn sugg_with_curlies<'a>(
     let parent_node_id = cx.tcx.hir().get_parent_node(match_expr.hir_id);
     if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) {
         if let ExprKind::Match(..) = arm.body.kind {
-            cbrace_end = format!("\n{}}}", indent);
+            cbrace_end = format!("\n{indent}}}");
             // Fix body indent due to the match
             indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
-            cbrace_start = format!("{{\n{}", indent);
+            cbrace_start = format!("{{\n{indent}");
         }
     }
 
@@ -204,13 +201,8 @@ fn sugg_with_curlies<'a>(
     });
 
     format!(
-        "{}let {} = {};\n{}{}{}{}",
-        cbrace_start,
+        "{cbrace_start}let {} = {};\n{indent}{assignment_str}{snippet_body}{cbrace_end}",
         snippet_with_applicability(cx, bind_names, "..", applicability),
-        snippet_with_applicability(cx, matched_vars, "..", applicability),
-        indent,
-        assignment_str,
-        snippet_body,
-        cbrace_end
+        snippet_with_applicability(cx, matched_vars, "..", applicability)
     )
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
index 1e80b6cf2d8..6647322caa3 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -118,8 +118,8 @@ fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad
         MATCH_STR_CASE_MISMATCH,
         bad_case_span,
         "this `match` arm has a differing case than its expression",
-        &format!("consider changing the case of this arm to respect `{}`", method_str),
-        format!("\"{}\"", suggestion),
+        &format!("consider changing the case of this arm to respect `{method_str}`"),
+        format!("\"{suggestion}\""),
         Applicability::MachineApplicable,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index a3aa2e4b389..42f1e2629d4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -38,7 +38,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
                             span_lint_and_note(cx,
                                 MATCH_WILD_ERR_ARM,
                                 arm.pat.span,
-                                &format!("`Err({})` matches all errors", ident_bind_name),
+                                &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/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
index 58ea43e69d9..c4f6852aedc 100644
--- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
@@ -3,15 +3,15 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{
-    eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_lang_ctor, over,
+    eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_res_lang_ctor, over, path_res,
     peel_blocks_with_stmt,
 };
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
 use rustc_span::sym;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if arms.len() > 1 && expr_ty_matches_p_ty(cx, ex, expr) && check_all_arms(cx, ex, arms) {
@@ -112,10 +112,7 @@ fn check_if_let_inner(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool
             let ret = strip_return(else_expr);
             let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
             if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
-                if let ExprKind::Path(ref qpath) = ret.kind {
-                    return is_lang_ctor(cx, qpath, OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
-                }
-                return false;
+                return is_res_lang_ctor(cx, path_res(cx, ret), OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
             }
             return eq_expr_value(cx, if_let.let_expr, ret);
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index c89784065b8..81bebff34c8 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -4,11 +4,12 @@ use clippy_utils::source::snippet;
 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;
-use clippy_utils::{higher, is_lang_ctor, is_trait_method};
+use clippy_utils::{higher, is_trait_method};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::{self, OptionSome, OptionNone, PollPending, PollReady, ResultOk, ResultErr};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
 use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, subst::GenericArgKind, DefIdTree, Ty};
@@ -87,15 +88,21 @@ fn find_sugg_for_if_let<'tcx>(
             }
         },
         PatKind::Path(ref path) => {
-            let method = if is_lang_ctor(cx, path, OptionNone) {
-                "is_none()"
-            } else if is_lang_ctor(cx, path, PollPending) {
-                "is_pending()"
+            if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, check_pat.hir_id)
+                && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
+            {
+                let method = if cx.tcx.lang_items().option_none_variant() == Some(variant_id) {
+                    "is_none()"
+                } else if cx.tcx.lang_items().poll_pending_variant() == Some(variant_id) {
+                    "is_pending()"
+                } else {
+                    return;
+                };
+                // `None` and `Pending` don't have an inner type.
+                (method, cx.tcx.types.unit)
             } else {
                 return;
-            };
-            // `None` and `Pending` don't have an inner type.
-            (method, cx.tcx.types.unit)
+            }
         },
         _ => return,
     };
@@ -138,7 +145,7 @@ fn find_sugg_for_if_let<'tcx>(
         cx,
         REDUNDANT_PATTERN_MATCHING,
         let_pat.span,
-        &format!("redundant pattern matching, consider using `{}`", good_method),
+        &format!("redundant pattern matching, consider using `{good_method}`"),
         |diag| {
             // if/while let ... = ... { ... }
             // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -162,7 +169,7 @@ fn find_sugg_for_if_let<'tcx>(
                 .maybe_par()
                 .to_string();
 
-            diag.span_suggestion(span, "try this", format!("{} {}.{}", keyword, sugg, good_method), app);
+            diag.span_suggestion(span, "try this", format!("{keyword} {sugg}.{good_method}"), app);
 
             if needs_drop {
                 diag.note("this will change drop order of the result, as well as all temporaries");
@@ -213,7 +220,6 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
                 if patterns.len() == 1 =>
             {
                 if let PatKind::Wild = patterns[0].kind {
-
                     find_good_method_for_match(
                         cx,
                         arms,
@@ -253,12 +259,12 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
                 cx,
                 REDUNDANT_PATTERN_MATCHING,
                 expr.span,
-                &format!("redundant pattern matching, consider using `{}`", good_method),
+                &format!("redundant pattern matching, consider using `{good_method}`"),
                 |diag| {
                     diag.span_suggestion(
                         span,
                         "try this",
-                        format!("{}.{}", snippet(cx, result_expr.span, "_"), good_method),
+                        format!("{}.{good_method}", snippet(cx, result_expr.span, "_")),
                         Applicability::MaybeIncorrect, // snippet
                     );
                 },
@@ -269,8 +275,8 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
 
 #[derive(Clone, Copy)]
 enum Item {
-  Lang(LangItem),
-  Diag(Symbol, Symbol),
+    Lang(LangItem),
+    Diag(Symbol, Symbol),
 }
 
 fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expected_item: Item) -> bool {
@@ -285,15 +291,16 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
             let ty = cx.typeck_results().pat_ty(pat);
 
             if is_type_diagnostic_item(cx, ty, expected_ty) {
-                let variant = ty.ty_adt_def()
+                let variant = ty
+                    .ty_adt_def()
                     .expect("struct pattern type is not an ADT")
                     .variant_of_res(cx.qpath_res(path, pat.hir_id));
 
-                return variant.name == expected_variant
+                return variant.name == expected_variant;
             }
 
             false
-        }
+        },
     }
 }
 
@@ -308,20 +315,16 @@ fn find_good_method_for_match<'a>(
     should_be_left: &'a str,
     should_be_right: &'a str,
 ) -> Option<&'a str> {
-    let pat_left = arms[0].pat;
-    let pat_right = arms[1].pat;
+    let first_pat = arms[0].pat;
+    let second_pat = arms[1].pat;
 
-    let body_node_pair = if (
-        is_pat_variant(cx, pat_left, path_left, expected_item_left)
-    ) && (
-        is_pat_variant(cx, pat_right, path_right, expected_item_right)
-    ) {
+    let body_node_pair = if (is_pat_variant(cx, first_pat, path_left, expected_item_left))
+        && (is_pat_variant(cx, second_pat, path_right, expected_item_right))
+    {
         (&arms[0].body.kind, &arms[1].body.kind)
-    } else if (
-        is_pat_variant(cx, pat_left, path_left, expected_item_right)
-    ) && (
-        is_pat_variant(cx, pat_right, path_right, expected_item_left)
-    ) {
+    } else if (is_pat_variant(cx, first_pat, path_left, expected_item_right))
+        && (is_pat_variant(cx, second_pat, path_right, expected_item_left))
+    {
         (&arms[1].body.kind, &arms[0].body.kind)
     } else {
         return None;
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 86a9df03497..85269e533a0 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -50,13 +50,13 @@ fn set_diagnostic<'tcx>(diag: &mut Diagnostic, cx: &LateContext<'tcx>, expr: &'t
     let trailing_indent = " ".repeat(indent_of(cx, found.found_span).unwrap_or(0));
 
     let replacement = if found.lint_suggestion == LintSuggestion::MoveAndDerefToCopy {
-        format!("let value = *{};\n{}", original, trailing_indent)
+        format!("let value = *{original};\n{trailing_indent}")
     } else if found.is_unit_return_val {
         // If the return value of the expression to be moved is unit, then we don't need to
         // capture the result in a temporary -- we can just replace it completely with `()`.
-        format!("{};\n{}", original, trailing_indent)
+        format!("{original};\n{trailing_indent}")
     } else {
-        format!("let value = {};\n{}", original, trailing_indent)
+        format!("let value = {original};\n{trailing_indent}")
     };
 
     let suggestion_message = if found.lint_suggestion == LintSuggestion::MoveOnly {
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 56bcdc01fe4..d496107ffd6 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -99,23 +99,21 @@ fn report_single_pattern(
 
             let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`";
             let sugg = format!(
-                "if {} == {}{} {}{}",
+                "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, None, "..", Some(expr.span)),
-                els_str,
             );
             (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 {} = {} {}{}",
+                "if let {} = {} {}{els_str}",
                 snippet(cx, arms[0].pat.span, ".."),
                 snippet(cx, ex.span, ".."),
                 expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
-                els_str,
             );
             (msg, sugg)
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
index 663277d1136..c6cba81d871 100644
--- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
@@ -1,7 +1,7 @@
 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_lang_ctor, match_def_path, paths};
+use clippy_utils::{get_parent_expr, is_res_lang_ctor, match_def_path, path_res, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::ResultErr;
@@ -27,8 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
         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 let ExprKind::Path(ref err_fun_path) = err_fun.kind;
-        if is_lang_ctor(cx, err_fun_path, ResultErr);
+        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;
@@ -61,9 +60,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
                 "return "
             };
             let suggestion = if err_ty == expr_err_ty {
-                format!("{}{}{}{}", ret_prefix, prefix, origin_snippet, suffix)
+                format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
             } else {
-                format!("{}{}{}.into(){}", ret_prefix, prefix, origin_snippet, suffix)
+                format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
             };
 
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index cad3ea2a176..0c4d9f100f7 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::is_non_aggregate_primitive_type;
-use clippy_utils::{is_default_equivalent, is_lang_ctor, meets_msrv, msrvs};
+use clippy_utils::{is_default_equivalent, is_res_lang_ctor, meets_msrv, msrvs, path_res};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
@@ -102,40 +102,38 @@ impl_lint_pass!(MemReplace =>
     [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
 
 fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
-    if let ExprKind::Path(ref replacement_qpath) = src.kind {
-        // Check that second argument is `Option::None`
-        if is_lang_ctor(cx, replacement_qpath, OptionNone) {
-            // Since this is a late pass (already type-checked),
-            // and we already know that the second argument is an
-            // `Option`, we do not need to check the first
-            // argument's type. All that's left is to get
-            // replacee's path.
-            let replaced_path = match dest.kind {
-                ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
-                    if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
-                        replaced_path
-                    } else {
-                        return;
-                    }
-                },
-                ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
-                _ => return,
-            };
+    // Check that second argument is `Option::None`
+    if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
+        // Since this is a late pass (already type-checked),
+        // and we already know that the second argument is an
+        // `Option`, we do not need to check the first
+        // argument's type. All that's left is to get
+        // replacee's path.
+        let replaced_path = match dest.kind {
+            ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
+                if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
+                    replaced_path
+                } else {
+                    return;
+                }
+            },
+            ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
+            _ => return,
+        };
 
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                MEM_REPLACE_OPTION_WITH_NONE,
-                expr_span,
-                "replacing an `Option` with `None`",
-                "consider `Option::take()` instead",
-                format!(
-                    "{}.take()",
-                    snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
-                ),
-                applicability,
-            );
-        }
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            MEM_REPLACE_OPTION_WITH_NONE,
+            expr_span,
+            "replacing an `Option` with `None`",
+            "consider `Option::take()` instead",
+            format!(
+                "{}.take()",
+                snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
+            ),
+            applicability,
+        );
     }
 }
 
@@ -203,10 +201,8 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
         return;
     }
     // disable lint for Option since it is covered in another lint
-    if let ExprKind::Path(q) = &src.kind {
-        if is_lang_ctor(cx, q, OptionNone) {
-            return;
-        }
+    if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
+        return;
     }
     if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
         span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 22f5635a5bc..cc26b0f7fa8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -85,7 +85,7 @@ pub(crate) trait BindInsteadOfMap {
 
                 let closure_args_snip = snippet(cx, closure_args_span, "..");
                 let option_snip = snippet(cx, recv.span, "..");
-                let note = format!("{}.{}({} {})", option_snip, Self::GOOD_METHOD_NAME, closure_args_snip, some_inner_snip);
+                let note = format!("{option_snip}.{}({closure_args_snip} {some_inner_snip})", Self::GOOD_METHOD_NAME);
                 span_lint_and_sugg(
                     cx,
                     BIND_INSTEAD_OF_MAP,
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
index 44857d61fef..2e96346be97 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
         cx,
         BYTES_NTH,
         expr.span,
-        &format!("called `.bytes().nth()` on a `{}`", caller_type),
+        &format!("called `.bytes().nth()` on a `{caller_type}`"),
         "try",
         format!(
             "{}.as_bytes().get({})",
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
index b2bc1ad5c9e..56b7fbb9d4b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
@@ -33,12 +33,11 @@ pub(super) fn check(
                 cx,
                 lint,
                 info.expr.span,
-                &format!("you should use the `{}` method", suggest),
+                &format!("you should use the `{suggest}` method"),
                 "like this",
-                format!("{}{}.{}({})",
+                format!("{}{}.{suggest}({})",
                         if info.eq { "" } else { "!" },
                         snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
-                        suggest,
                         snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
                 applicability,
             );
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
index b85bfec2b12..7e808760663 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -26,12 +26,11 @@ pub(super) fn check<'tcx>(
                 cx,
                 lint,
                 info.expr.span,
-                &format!("you should use the `{}` method", suggest),
+                &format!("you should use the `{suggest}` method"),
                 "like this",
-                format!("{}{}.{}('{}')",
+                format!("{}{}.{suggest}('{}')",
                         if info.eq { "" } else { "!" },
                         snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
-                        suggest,
                         c.escape_default()),
                 applicability,
             );
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 7ab6b84c207..7c7938dd2e8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -49,8 +49,7 @@ pub(super) fn check(
                 expr.span,
                 &format!(
                     "using `clone` on a double-reference; \
-                    this will copy the reference of type `{}` instead of cloning the inner type",
-                    ty
+                    this will copy the reference of type `{ty}` instead of cloning the inner type"
                 ),
                 |diag| {
                     if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
@@ -62,11 +61,11 @@ pub(super) fn check(
                         }
                         let refs = "&".repeat(n + 1);
                         let derefs = "*".repeat(n);
-                        let explicit = format!("<{}{}>::clone({})", refs, ty, snip);
+                        let explicit = format!("<{refs}{ty}>::clone({snip})");
                         diag.span_suggestion(
                             expr.span,
                             "try dereferencing it",
-                            format!("{}({}{}).clone()", refs, derefs, snip.deref()),
+                            format!("{refs}({derefs}{}).clone()", snip.deref()),
                             Applicability::MaybeIncorrect,
                         );
                         diag.span_suggestion(
@@ -121,16 +120,16 @@ pub(super) fn check(
         let (help, sugg) = if deref_count == 0 {
             ("try removing the `clone` call", snip.into())
         } else if parent_is_suffix_expr {
-            ("try dereferencing it", format!("({}{})", "*".repeat(deref_count), snip))
+            ("try dereferencing it", format!("({}{snip})", "*".repeat(deref_count)))
         } else {
-            ("try dereferencing it", format!("{}{}", "*".repeat(deref_count), snip))
+            ("try dereferencing it", format!("{}{snip}", "*".repeat(deref_count)))
         };
 
         span_lint_and_sugg(
             cx,
             CLONE_ON_COPY,
             expr.span,
-            &format!("using `clone` on type `{}` which implements the `Copy` trait", ty),
+            &format!("using `clone` on type `{ty}` which implements the `Copy` trait"),
             help,
             sugg,
             app,
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
index f82ca891200..355f53532e2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -41,7 +41,7 @@ pub(super) fn check(
             expr.span,
             "using `.clone()` on a ref-counted pointer",
             "try this",
-            format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet),
+            format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
             Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index bd846d71d46..d0cf411dfd3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -143,9 +143,9 @@ pub(super) fn check<'tcx>(
             cx,
             EXPECT_FUN_CALL,
             span_replace_word,
-            &format!("use of `{}` followed by a function call", name),
+            &format!("use of `{name}` followed by a function call"),
             "try this",
-            format!("unwrap_or_else({} panic!({}))", closure_args, sugg),
+            format!("unwrap_or_else({closure_args} panic!({sugg}))"),
             applicability,
         );
         return;
@@ -160,12 +160,9 @@ pub(super) fn check<'tcx>(
         cx,
         EXPECT_FUN_CALL,
         span_replace_word,
-        &format!("use of `{}` followed by a function call", name),
+        &format!("use of `{name}` followed by a function call"),
         "try this",
-        format!(
-            "unwrap_or_else({} {{ panic!(\"{{}}\", {}) }})",
-            closure_args, arg_root_snippet
-        ),
+        format!("unwrap_or_else({closure_args} {{ panic!(\"{{}}\", {arg_root_snippet}) }})"),
         applicability,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
index 7b2967feb0f..3fef53739fb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
@@ -1,17 +1,18 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::match_type;
-use clippy_utils::{get_parent_expr, paths};
+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;
+use rustc_span::sym;
 
 use super::FILETYPE_IS_FILE;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
     let ty = cx.typeck_results().expr_ty(recv);
 
-    if !match_type(cx, ty, &paths::FILE_TYPE) {
+    if !is_type_diagnostic_item(cx, ty, sym::FileType) {
         return;
     }
 
@@ -35,7 +36,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
             span = expr.span;
         }
     }
-    let lint_msg = format!("`{}FileType::is_file()` only {} regular files", lint_unary, verb);
-    let help_msg = format!("use `{}FileType::is_dir()` instead", help_unary);
+    let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files");
+    let help_msg = format!("use `{help_unary}FileType::is_dir()` instead");
     span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, None, &help_msg);
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
index 38ec4d8e3ab..ddf8a1f09b8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
                 expr.span,
                 msg,
                 "try this",
-                format!("{}.find_map({})", iter_snippet, filter_snippet),
+                format!("{iter_snippet}.find_map({filter_snippet})"),
                 Applicability::MachineApplicable,
             );
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
index bcf8d93b602..edcec0fc101 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
                 expr.span,
                 msg,
                 "try this",
-                format!("{}.find({})", iter_snippet, filter_snippet),
+                format!("{iter_snippet}.find({filter_snippet})"),
                 Applicability::MachineApplicable,
             );
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index 6436e28a63c..66dfce3682b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
             // `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!("{}.collect::<{}>()", iter_expr, turbofish);
+            let sugg = format!("{iter_expr}.collect::<{turbofish}>()");
             span_lint_and_sugg(
                 cx,
                 FROM_ITER_INSTEAD_OF_COLLECT,
@@ -63,7 +63,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
                             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!("{}{}", without_ts.join("::"), type_specifier)
+                        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>`
@@ -72,7 +72,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
                         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!("{}<{}>", elements.join("::"), wildcards)
+                        format!("{}<{wildcards}>", elements.join("::"))
                     }
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_first.rs b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
index 4de77de7404..cb17af608a3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
@@ -29,9 +29,9 @@ pub(super) fn check<'tcx>(
                 cx,
                 GET_FIRST,
                 expr.span,
-                &format!("accessing first element with `{0}.get(0)`", slice_name),
+                &format!("accessing first element with `{slice_name}.get(0)`"),
                 "try",
-                format!("{}.first()", slice_name),
+                format!("{slice_name}.first()"),
                 app,
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
index 02aada87202..3bdc154df04 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::SpanlessEq;
-use rustc_ast::LitKind;
+use clippy_utils::{is_integer_literal, SpanlessEq};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -26,8 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
         && lhs_path.ident.name == sym::len
 
         // RHS of subtraction is 1
-        && let ExprKind::Lit(rhs_lit) = &rhs.kind
-        && let LitKind::Int(1, ..) = rhs_lit.node
+        && is_integer_literal(rhs, 1)
 
         // check that recv == lhs_recv `recv.get(lhs_recv.len() - 1)`
         && SpanlessEq::new(cx).eq_expr(recv, lhs_recv)
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
index 18e08d6ee23..ffc3a4d780e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
@@ -71,16 +71,11 @@ pub(super) fn check<'tcx>(
         cx,
         GET_UNWRAP,
         span,
-        &format!(
-            "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise",
-            mut_str, caller_type
-        ),
+        &format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
         "try this",
         format!(
-            "{}{}[{}]",
-            borrow_str,
-            snippet_with_applicability(cx, recv.span, "..", &mut applicability),
-            get_args_str
+            "{borrow_str}{}[{get_args_str}]",
+            snippet_with_applicability(cx, recv.span, "..", &mut applicability)
         ),
         applicability,
     );
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index 9651a52be4e..429cdc1918d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -26,12 +26,12 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
                 cx,
                 IMPLICIT_CLONE,
                 expr.span,
-                &format!("implicitly cloning a `{}` by calling `{}` on its dereferenced type", ty_name, method_name),
+                &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"),
                 "consider using",
                 if ref_count > 1 {
-                    format!("({}{}).clone()", "*".repeat(ref_count - 1), recv_snip)
+                    format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1))
                 } else {
-                    format!("{}.clone()", recv_snip)
+                    format!("{recv_snip}.clone()")
                 },
                 app,
             );
diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
index e1c9b5248a8..ede3b8bb74e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
@@ -34,18 +34,17 @@ pub fn check<'tcx>(
                 cx,
                 INEFFICIENT_TO_STRING,
                 expr.span,
-                &format!("calling `to_string` on `{}`", arg_ty),
+                &format!("calling `to_string` on `{arg_ty}`"),
                 |diag| {
                     diag.help(&format!(
-                        "`{}` implements `ToString` through a slower blanket impl, but `{}` has a fast specialization of `ToString`",
-                        self_ty, deref_self_ty
+                        "`{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!("({}{}).to_string()", "*".repeat(deref_count), arg_snippet),
+                        format!("({}{arg_snippet}).to_string()", "*".repeat(deref_count)),
                         applicability,
                     );
                 },
@@ -66,7 +65,7 @@ fn specializes_tostring(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
     }
 
     if let ty::Adt(adt, substs) = ty.kind() {
-        match_def_path(cx, adt.did(), &paths::COW) && substs.type_at(1).is_str()
+        cx.tcx.is_diagnostic_item(sym::Cow, adt.did()) && substs.type_at(1).is_str()
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
index 11e76841e9f..be56b63506a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -30,8 +30,7 @@ pub(super) fn check(
                 INTO_ITER_ON_REF,
                 method_span,
                 &format!(
-                    "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`",
-                    method_name, kind,
+                    "this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",
                 ),
                 "call directly",
                 method_name.to_string(),
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
index aa176dcc8b4..304024e8066 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
@@ -37,12 +37,11 @@ pub(super) fn check<'tcx>(
             cx,
             IS_DIGIT_ASCII_RADIX,
             expr.span,
-            &format!("use of `char::is_digit` with literal radix of {}", num),
+            &format!("use of `char::is_digit` with literal radix of {num}"),
             "try",
             format!(
-                "{}.{}()",
-                snippet_with_applicability(cx, self_arg.span, "..", &mut applicability),
-                replacement
+                "{}.{replacement}()",
+                snippet_with_applicability(cx, self_arg.span, "..", &mut applicability)
             ),
             applicability,
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
index 30d56113c6c..bde6f92b076 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -20,8 +20,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir:
                 cx,
                 ITER_CLONED_COLLECT,
                 to_replace,
-                &format!("called `iter().{}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
-                more readable", method_name),
+                &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/src/tools/clippy/clippy_lints/src/methods/iter_count.rs b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
index 052be3d8ee7..bcddc7c786a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
@@ -37,7 +37,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
         cx,
         ITER_COUNT,
         expr.span,
-        &format!("called `.{}().count()` on a `{}`", iter_method, caller_type),
+        &format!("called `.{iter_method}().count()` on a `{caller_type}`"),
         "try",
         format!(
             "{}.len()",
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index a7eecabd684..2244ebfb129 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -54,9 +54,9 @@ pub(super) fn check<'tcx>(
                         cx,
                         ITER_KV_MAP,
                         expr.span,
-                        &format!("iterating on a map's {}s", replacement_kind),
+                        &format!("iterating on a map's {replacement_kind}s"),
                         "try",
-                        format!("{}.{}{}s()", recv_snippet, into_prefix, replacement_kind),
+                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"),
                         applicability,
                     );
                 } else {
@@ -64,9 +64,9 @@ pub(super) fn check<'tcx>(
                         cx,
                         ITER_KV_MAP,
                         expr.span,
-                        &format!("iterating on a map's {}s", replacement_kind),
+                        &format!("iterating on a map's {replacement_kind}s"),
                         "try",
-                        format!("{}.{}{}s().map(|{}| {})", recv_snippet, into_prefix, replacement_kind, binded_ident,
+                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
                             snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
                         applicability,
                     );
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
index b8d1dabe007..83c1bf20346 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
@@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal
                 let suggest = if start_idx == 0 {
                     format!("{}.first()", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability))
                 } else {
-                    format!("{}.get({})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability), start_idx)
+                    format!("{}.get({start_idx})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability))
                 };
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
index 80ca4c94219..ceee12784cb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
@@ -32,8 +32,8 @@ pub(super) fn check<'tcx>(
         cx,
         ITER_NTH,
         expr.span,
-        &format!("called `.iter{0}().nth()` on a {1}", mut_str, caller_type),
+        &format!("called `.iter{mut_str}().nth()` on a {caller_type}"),
         None,
-        &format!("calling `.get{}()` is both faster and more readable", mut_str),
+        &format!("calling `.get{mut_str}()` is both faster and more readable"),
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index cea7b0d82ff..4f73b3ec422 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use clippy_utils::{get_expr_use_or_unification_node, is_lang_ctor, is_no_std_crate};
+use clippy_utils::{get_expr_use_or_unification_node, is_no_std_crate, is_res_lang_ctor, path_res};
 
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
@@ -26,26 +26,11 @@ impl IterType {
 }
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
-    let item = match &recv.kind {
-        ExprKind::Array(v) if v.len() <= 1 => v.first(),
-        ExprKind::Path(p) => {
-            if is_lang_ctor(cx, p, OptionNone) {
-                None
-            } else {
-                return;
-            }
-        },
-        ExprKind::Call(f, some_args) if some_args.len() == 1 => {
-            if let ExprKind::Path(p) = &f.kind {
-                if is_lang_ctor(cx, p, OptionSome) {
-                    Some(&some_args[0])
-                } else {
-                    return;
-                }
-            } else {
-                return;
-            }
-        },
+    let item = match recv.kind {
+        ExprKind::Array([]) => None,
+        ExprKind::Array([e]) => Some(e),
+        ExprKind::Path(ref p) if is_res_lang_ctor(cx, cx.qpath_res(p, recv.hir_id), OptionNone) => None,
+        ExprKind::Call(f, [arg]) if is_res_lang_ctor(cx, path_res(cx, f), OptionSome) => Some(arg),
         _ => return,
     };
     let iter_type = match method_name {
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
index a669cbbbcc6..3da230e12d7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
             cx,
             ITER_WITH_DRAIN,
             span.with_hi(expr.span.hi()),
-            &format!("`drain(..)` used on a `{}`", ty_name),
+            &format!("`drain(..)` used on a `{ty_name}`"),
             "try this",
             "into_iter()".to_string(),
             Applicability::MaybeIncorrect,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
index ffd2f4a38b8..5b758f1e654 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
@@ -1,11 +1,11 @@
 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_lang_ctor, path_to_local_id};
+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::{Closure, Expr, ExprKind, PatKind};
+use rustc_hir::{Expr, ExprKind, PatKind};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
@@ -22,8 +22,8 @@ pub(super) fn check<'tcx>(
         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), sym::Option);
-        if let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, [err_arg]) = or_expr.kind;
-        if is_lang_ctor(cx, err_path, ResultErr);
+        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);
@@ -37,9 +37,7 @@ pub(super) fn check<'tcx>(
                 "this pattern reimplements `Option::ok_or`",
                 "replace with",
                 format!(
-                    "{}.ok_or({})",
-                    recv_snippet,
-                    reindented_err_arg_snippet
+                    "{recv_snippet}.ok_or({reindented_err_arg_snippet})"
                 ),
                 Applicability::MachineApplicable,
             );
@@ -48,17 +46,19 @@ pub(super) fn check<'tcx>(
 }
 
 fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
-    if let ExprKind::Path(ref qpath) = map_expr.kind {
-        if is_lang_ctor(cx, qpath, ResultOk) {
-            return true;
-        }
-    }
-    if_chain! {
-        if let ExprKind::Closure(&Closure { body, .. }) = map_expr.kind;
-        let body = cx.tcx.hir().body(body);
-        if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
-        if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind;
-        if is_lang_ctor(cx, ok_path, ResultOk);
-        then { path_to_local_id(ok_arg, param_id) } else { false }
+    match map_expr.kind {
+        ExprKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, map_expr.hir_id), ResultOk) => true,
+        ExprKind::Closure(closure) => {
+            let body = cx.tcx.hir().body(closure.body);
+            if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind
+                && let ExprKind::Call(callee, [ok_arg]) = body.value.kind
+                && is_res_lang_ctor(cx, path_res(cx, callee), ResultOk)
+            {
+                path_to_local_id(ok_arg, param_id)
+            } else {
+                false
+            }
+        },
+        _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 0fe510beaa0..ec694cf6882 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -57,11 +57,10 @@ pub fn check(
         super::MANUAL_SATURATING_ARITHMETIC,
         expr.span,
         "manual saturating arithmetic",
-        &format!("try using `saturating_{}`", arith),
+        &format!("try using `saturating_{arith}`"),
         format!(
-            "{}.saturating_{}({})",
+            "{}.saturating_{arith}({})",
             snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
-            arith,
             snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
         ),
         applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
index 46d2fc493f8..8b6b8f1bf16 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+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, match_type};
-use clippy_utils::{is_expr_path_def_path, paths};
+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;
@@ -38,7 +38,7 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
         let ty = cx.typeck_results().expr_ty(e);
         if is_type_diagnostic_item(cx, ty, sym::String)
             || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, Ty::is_str))
-            || (match_type(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, Ty::is_str))
+            || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, Ty::is_str))
         {
             Some(RepeatKind::String)
         } else {
@@ -57,7 +57,7 @@ pub(super) fn check(
 ) {
     if_chain! {
         if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
-        if is_expr_path_def_path(cx, repeat_fn, &paths::ITER_REPEAT);
+        if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat);
         if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::String);
         if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id);
         if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
@@ -91,7 +91,7 @@ pub(super) fn check(
                 collect_expr.span,
                 "manual implementation of `str::repeat` using iterators",
                 "try this",
-                format!("{}.repeat({})", val_str, count_snip),
+                format!("{val_str}.repeat({count_snip})"),
                 app
             )
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 8261ef5e1ce..7ce14ec080b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -111,11 +111,10 @@ fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_cop
         MAP_CLONE,
         replace,
         message,
-        &format!("consider calling the dedicated `{}` method", sugg_method),
+        &format!("consider calling the dedicated `{sugg_method}` method"),
         format!(
-            "{}.{}()",
+            "{}.{sugg_method}()",
             snippet_with_applicability(cx, root, "..", &mut applicability),
-            sugg_method,
         ),
         applicability,
     );
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
index 13853dec99d..361ffcb5ef3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
@@ -20,12 +20,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_
             cx,
             MAP_FLATTEN,
             expr.span.with_lo(map_span.lo()),
-            &format!("called `map(..).flatten()` on `{}`", caller_ty_name),
-            &format!(
-                "try replacing `map` with `{}` and remove the `.flatten()`",
-                method_to_use
-            ),
-            format!("{}({})", method_to_use, closure_snippet),
+            &format!("called `map(..).flatten()` on `{caller_ty_name}`"),
+            &format!("try replacing `map` with `{method_to_use}` and remove the `.flatten()`"),
+            format!("{method_to_use}({closure_snippet})"),
             applicability,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
index 862a9578e6f..0f25ef82ed4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
@@ -30,7 +30,7 @@ pub(super) fn check(
                 MAP_IDENTITY,
                 sugg_span,
                 "unnecessary map of the identity function",
-                &format!("remove the call to `{}`", name),
+                &format!("remove the call to `{name}`"),
                 String::new(),
                 Applicability::MachineApplicable,
             )
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
index 4a8e7ce4ddb..74fdead216b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
@@ -65,7 +65,7 @@ pub(super) fn check<'tcx>(
                 expr.span,
                 msg,
                 "try this",
-                format!("{}.map_or_else({}, {})", var_snippet, unwrap_snippet, map_snippet),
+                format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"),
                 Applicability::MachineApplicable,
             );
             return true;
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 428a354ec6b..cfcf9596c50 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -109,13 +109,13 @@ use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TraitItem, TraitItemKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, TraitRef, Ty};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
-use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -3255,65 +3255,59 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         let self_ty = cx.tcx.type_of(item.def_id);
 
         let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
-        if_chain! {
-            if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
-            if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next();
-
-            let method_sig = cx.tcx.fn_sig(impl_item.def_id.def_id);
+        if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind {
+            let method_sig = cx.tcx.fn_sig(impl_item.def_id);
             let method_sig = cx.tcx.erase_late_bound_regions(method_sig);
-
-            let first_arg_ty = method_sig.inputs().iter().next();
-
-            // check conventions w.r.t. conversion method names and predicates
-            if let Some(first_arg_ty) = first_arg_ty;
-
-            then {
-                // if this impl block implements a trait, lint in trait definition instead
-                if !implements_trait && cx.access_levels.is_exported(impl_item.def_id.def_id) {
-                    // check missing trait implementations
-                    for method_config in &TRAIT_METHODS {
-                        if name == method_config.method_name &&
-                            sig.decl.inputs.len() == method_config.param_count &&
-                            method_config.output_type.matches(&sig.decl.output) &&
-                            method_config.self_kind.matches(cx, self_ty, *first_arg_ty) &&
-                            fn_header_equals(method_config.fn_header, sig.header) &&
-                            method_config.lifetime_param_cond(impl_item)
-                        {
-                            span_lint_and_help(
-                                cx,
-                                SHOULD_IMPLEMENT_TRAIT,
-                                impl_item.span,
-                                &format!(
-                                    "method `{}` can be confused for the standard trait method `{}::{}`",
-                                    method_config.method_name,
-                                    method_config.trait_name,
-                                    method_config.method_name
-                                ),
-                                None,
-                                &format!(
-                                    "consider implementing the trait `{}` or choosing a less ambiguous method name",
-                                    method_config.trait_name
-                                )
-                            );
-                        }
+            let first_arg_ty_opt = method_sig.inputs().iter().next().copied();
+            // if this impl block implements a trait, lint in trait definition instead
+            if !implements_trait && cx.access_levels.is_exported(impl_item.def_id.def_id) {
+                // check missing trait implementations
+                for method_config in &TRAIT_METHODS {
+                    if name == method_config.method_name
+                        && sig.decl.inputs.len() == method_config.param_count
+                        && method_config.output_type.matches(&sig.decl.output)
+                        // in case there is no first arg, since we already have checked the number of arguments
+                        // it's should be always true
+                        && first_arg_ty_opt.map_or(true, |first_arg_ty| method_config
+                            .self_kind.matches(cx, self_ty, first_arg_ty)
+                            )
+                        && fn_header_equals(method_config.fn_header, sig.header)
+                        && method_config.lifetime_param_cond(impl_item)
+                    {
+                        span_lint_and_help(
+                            cx,
+                            SHOULD_IMPLEMENT_TRAIT,
+                            impl_item.span,
+                            &format!(
+                                "method `{}` can be confused for the standard trait method `{}::{}`",
+                                method_config.method_name, method_config.trait_name, method_config.method_name
+                            ),
+                            None,
+                            &format!(
+                                "consider implementing the trait `{}` or choosing a less ambiguous method name",
+                                method_config.trait_name
+                            ),
+                        );
                     }
                 }
+            }
 
-                if sig.decl.implicit_self.has_implicit_self()
+            if sig.decl.implicit_self.has_implicit_self()
                     && !(self.avoid_breaking_exported_api
-                        && cx.access_levels.is_exported(impl_item.def_id.def_id))
+                    && cx.access_levels.is_exported(impl_item.def_id.def_id))
+                    && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next()
+                    && let Some(first_arg_ty) = first_arg_ty_opt
                 {
                     wrong_self_convention::check(
                         cx,
                         name,
                         self_ty,
-                        *first_arg_ty,
+                        first_arg_ty,
                         first_arg.pat.span,
                         implements_trait,
                         false
                     );
                 }
-            }
         }
 
         // if this impl block implements a trait, lint in trait definition instead
@@ -3799,7 +3793,6 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
     ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
     ShouldImplTraitCase::new("std::clone::Clone", "clone",  1,  FN_HEADER,  SelfKind::Ref,  OutType::Any, true),
     ShouldImplTraitCase::new("std::cmp::Ord", "cmp",  2,  FN_HEADER,  SelfKind::Ref,  OutType::Any, true),
-    // FIXME: default doesn't work
     ShouldImplTraitCase::new("std::default::Default", "default",  0,  FN_HEADER,  SelfKind::No,  OutType::Any, true),
     ShouldImplTraitCase::new("std::ops::Deref", "deref",  1,  FN_HEADER,  SelfKind::Ref,  OutType::Ref, true),
     ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut",  1,  FN_HEADER,  SelfKind::RefMut,  OutType::Ref, true),
@@ -3827,7 +3820,7 @@ enum SelfKind {
     Value,
     Ref,
     RefMut,
-    No,
+    No, // When we want the first argument type to be different than `Self`
 }
 
 impl SelfKind {
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index c409268de76..6fb92d1c663 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -98,13 +98,12 @@ pub(super) fn check<'tcx>(
             format!(".as_ref().map({})", snippet(cx, map_arg.span, ".."))
         };
         let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" };
-        let hint = format!("{}.{}()", snippet(cx, as_ref_recv.span, ".."), method_hint);
-        let suggestion = format!("try using {} instead", method_hint);
+        let hint = format!("{}.{method_hint}()", snippet(cx, as_ref_recv.span, ".."));
+        let suggestion = format!("try using {method_hint} instead");
 
         let msg = format!(
-            "called `{0}` on an Option value. This can be done more directly \
-            by calling `{1}` instead",
-            current_method, hint
+            "called `{current_method}` on an Option value. This can be done more directly \
+            by calling `{hint}` instead"
         );
         span_lint_and_sugg(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
index 6657cdccd01..3a23ecc50dc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_lang_ctor, path_def_id};
+use clippy_utils::{is_res_lang_ctor, path_def_id, path_res};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
@@ -51,22 +51,12 @@ pub(super) fn check<'tcx>(
         return;
     }
 
-    let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
-        is_lang_ctor(cx, qpath, OptionNone)
-    } else {
-        return;
-    };
-
-    if !default_arg_is_none {
+    if !is_res_lang_ctor(cx, path_res(cx, def_arg), OptionNone) {
         // nothing to lint!
         return;
     }
 
-    let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
-        is_lang_ctor(cx, qpath, OptionSome)
-    } else {
-        false
-    };
+    let f_arg_is_some = is_res_lang_ctor(cx, path_res(cx, map_arg), OptionSome);
 
     if is_option {
         let self_snippet = snippet(cx, recv.span, "..");
@@ -87,7 +77,7 @@ pub(super) fn check<'tcx>(
                     expr.span,
                     msg,
                     "try using `map` instead",
-                    format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
+                    format!("{self_snippet}.map({arg_snippet} {func_snippet})"),
                     Applicability::MachineApplicable,
                 );
             }
@@ -102,7 +92,7 @@ pub(super) fn check<'tcx>(
             expr.span,
             msg,
             "try using `and_then` instead",
-            format!("{0}.and_then({1})", self_snippet, func_snippet),
+            format!("{self_snippet}.and_then({func_snippet})"),
             Applicability::MachineApplicable,
         );
     } else if f_arg_is_some {
@@ -115,7 +105,7 @@ pub(super) fn check<'tcx>(
             expr.span,
             msg,
             "try using `ok` instead",
-            format!("{0}.ok()", self_snippet),
+            format!("{self_snippet}.ok()"),
             Applicability::MachineApplicable,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 3c4002a3aef..30421a6dd5a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -65,9 +65,8 @@ pub(super) fn check<'tcx>(
             "map_or(<a>, <f>)"
         };
         let msg = &format!(
-            "called `map(<f>).unwrap_or({})` on an `Option` value. \
-            This can be done more directly by calling `{}` instead",
-            arg, suggest
+            "called `map(<f>).unwrap_or({arg})` on an `Option` value. \
+            This can be done more directly by calling `{suggest}` instead"
         );
 
         span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| {
@@ -82,10 +81,10 @@ pub(super) fn check<'tcx>(
             ];
 
             if !unwrap_snippet_none {
-                suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{}, ", unwrap_snippet)));
+                suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, ")));
             }
 
-            diag.multipart_suggestion(&format!("use `{}` instead", suggest), suggestion, applicability);
+            diag.multipart_suggestion(&format!("use `{suggest}` instead"), suggestion, applicability);
         });
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index b43b9258c47..6a35024d036 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -62,9 +62,9 @@ pub(super) fn check<'tcx>(
                     cx,
                     OR_FUN_CALL,
                     method_span.with_hi(span.hi()),
-                    &format!("use of `{}` followed by a call to `{}`", name, path),
+                    &format!("use of `{name}` followed by a call to `{path}`"),
                     "try this",
-                    format!("{}()", sugg),
+                    format!("{sugg}()"),
                     Applicability::MachineApplicable,
                 );
 
@@ -131,7 +131,7 @@ pub(super) fn check<'tcx>(
 
                     if use_lambda {
                         let l_arg = if fn_has_arguments { "_" } else { "" };
-                        format!("|{}| {}", l_arg, snippet).into()
+                        format!("|{l_arg}| {snippet}").into()
                     } else {
                         snippet
                     }
@@ -141,9 +141,9 @@ pub(super) fn check<'tcx>(
                     cx,
                     OR_FUN_CALL,
                     span_replace_word,
-                    &format!("use of `{}` followed by a function call", name),
+                    &format!("use of `{name}` followed by a function call"),
                     "try this",
-                    format!("{}_{}({})", name, suffix, sugg),
+                    format!("{name}_{suffix}({sugg})"),
                     Applicability::HasPlaceholders,
                 );
             }
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
index be5768c3545..55ba6e262df 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
@@ -1,6 +1,6 @@
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{diagnostics::span_lint_and_sugg, is_lang_ctor};
+use clippy_utils::{diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res};
 use rustc_errors::Applicability;
 use rustc_hir::{lang_items::LangItem, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -58,8 +58,7 @@ pub(super) fn check<'tcx>(
 
 fn get_content_if_ctor_matches(cx: &LateContext<'_>, expr: &Expr<'_>, item: LangItem) -> Option<Span> {
     if let ExprKind::Call(some_expr, [arg]) = expr.kind
-        && let ExprKind::Path(qpath) = &some_expr.kind
-        && is_lang_ctor(cx, qpath, item)
+        && is_res_lang_ctor(cx, path_res(cx, some_expr), item)
     {
         Some(arg.span)
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index 7572ba3fe9a..324c9c17b5a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -30,10 +30,7 @@ pub(super) fn check<'tcx>(
     let option_check_method = if is_some { "is_some" } else { "is_none" };
     // lint if caller of search is an Iterator
     if is_trait_method(cx, is_some_recv, sym::Iterator) {
-        let msg = format!(
-            "called `{}()` after searching an `Iterator` with `{}`",
-            option_check_method, search_method
-        );
+        let msg = format!("called `{option_check_method}()` after searching an `Iterator` with `{search_method}`");
         let search_snippet = snippet(cx, search_arg.span, "..");
         if search_snippet.lines().count() <= 1 {
             // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
@@ -86,8 +83,7 @@ pub(super) fn check<'tcx>(
                     &msg,
                     "use `!_.any()` instead",
                     format!(
-                        "!{}.any({})",
-                        iter,
+                        "!{iter}.any({})",
                         any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
                     ),
                     applicability,
@@ -119,7 +115,7 @@ pub(super) fn check<'tcx>(
             if is_string_or_str_slice(search_recv);
             if is_string_or_str_slice(search_arg);
             then {
-                let msg = format!("called `{}()` after calling `find()` on a string", option_check_method);
+                let msg = format!("called `{option_check_method}()` after calling `find()` on a string");
                 match option_check_method {
                     "is_some" => {
                         let mut applicability = Applicability::MachineApplicable;
@@ -130,7 +126,7 @@ pub(super) fn check<'tcx>(
                             method_span.with_hi(expr.span.hi()),
                             &msg,
                             "use `contains()` instead",
-                            format!("contains({})", find_arg),
+                            format!("contains({find_arg})"),
                             applicability,
                         );
                     },
@@ -144,7 +140,7 @@ pub(super) fn check<'tcx>(
                             expr.span,
                             &msg,
                             "use `!_.contains()` instead",
-                            format!("!{}.contains({})", string, find_arg),
+                            format!("!{string}.contains({find_arg})"),
                             applicability,
                         );
                     },
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
index 18b6b5be175..44a7ad394fa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
@@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
         let base_string_snippet =
             snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
         let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
-        let sugg = format!("{}.insert({}, {})", base_string_snippet, pos_arg, extension_string);
+        let sugg = format!("{base_string_snippet}.insert({pos_arg}, {extension_string})");
         span_lint_and_sugg(
             cx,
             SINGLE_CHAR_ADD_STR,
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
index 9ea6751956a..0698bd6a0c5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
@@ -13,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
     if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) {
         let base_string_snippet =
             snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
-        let sugg = format!("{}.push({})", base_string_snippet, extension_string);
+        let sugg = format!("{base_string_snippet}.push({extension_string})");
         span_lint_and_sugg(
             cx,
             SINGLE_CHAR_ADD_STR,
diff --git a/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs b/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
index 91951c65bb3..09c8ca4cbe4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
@@ -17,11 +17,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx
             cx,
             STABLE_SORT_PRIMITIVE,
             e.span,
-            &format!("used `sort` on primitive type `{}`", slice_type),
+            &format!("used `sort` on primitive type `{slice_type}`"),
             |diag| {
                 let mut app = Applicability::MachineApplicable;
                 let recv_snip = snippet_with_context(cx, recv.span, e.span.ctxt(), "..", &mut app).0;
-                diag.span_suggestion(e.span, "try", format!("{}.sort_unstable()", recv_snip), app);
+                diag.span_suggestion(e.span, "try", format!("{recv_snip}.sort_unstable()"), app);
                 diag.note(
                     "an unstable sort typically performs faster without any observable difference for this data type",
                 );
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 9ca4d65550d..ae3594bd36c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -2,11 +2,11 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::usage::local_used_after_expr;
-use clippy_utils::visitors::expr_visitor;
+use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
 use clippy_utils::{is_diag_item_method, match_def_path, meets_msrv, msrvs, path_to_local_id, paths};
+use core::ops::ControlFlow;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::Visitor;
 use rustc_hir::{
     BindingAnnotation, Expr, ExprKind, HirId, LangItem, Local, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind,
 };
@@ -211,7 +211,7 @@ fn indirect_usage<'tcx>(
     binding: HirId,
     ctxt: SyntaxContext,
 ) -> Option<IndirectUsage<'tcx>> {
-    if let StmtKind::Local(Local {
+    if let StmtKind::Local(&Local {
         pat: Pat {
             kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None),
             ..
@@ -222,14 +222,12 @@ fn indirect_usage<'tcx>(
     }) = stmt.kind
     {
         let mut path_to_binding = None;
-        expr_visitor(cx, |expr| {
-            if path_to_local_id(expr, binding) {
-                path_to_binding = Some(expr);
+        let _: Option<!> = for_each_expr_with_closures(cx, init_expr, |e| {
+            if path_to_local_id(e, binding) {
+                path_to_binding = Some(e);
             }
-
-            path_to_binding.is_none()
-        })
-        .visit_expr(init_expr);
+            ControlFlow::Continue(Descend::from(path_to_binding.is_none()))
+        });
 
         let mut parents = cx.tcx.hir().parent_iter(path_to_binding?.hir_id);
         let iter_usage = parse_iter_usage(cx, ctxt, &mut parents)?;
@@ -250,7 +248,7 @@ fn indirect_usage<'tcx>(
             ..
         } = iter_usage
         {
-            if parent_id == *local_hir_id {
+            if parent_id == local_hir_id {
                 return Some(IndirectUsage {
                     name: ident.name,
                     span: stmt.span,
diff --git a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
index 143dcee3505..6974260f70d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs
@@ -34,9 +34,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
             "calling `.extend(_.chars())`",
             "try this",
             format!(
-                "{}.push_str({}{})",
+                "{}.push_str({ref_str}{})",
                 snippet_with_applicability(cx, recv.span, "..", &mut applicability),
-                ref_str,
                 snippet_with_applicability(cx, target.span, "..", &mut applicability)
             ),
             applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
index 55567d8625e..219a9edd657 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -24,10 +24,10 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
             }
 
             let (msg, note_msg) = if count == 0 {
-                (format!("`{}` called with `0` splits", method_name),
+                (format!("`{method_name}` called with `0` splits"),
                 "the resulting iterator will always return `None`")
             } else {
-                (format!("`{}` called with `1` split", method_name),
+                (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 {
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
index 6b306fbf008..15c1c618c51 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
@@ -24,9 +24,9 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
                 cx,
                 SUSPICIOUS_TO_OWNED,
                 expr.span,
-                &format!("this `to_owned` call clones the {0} itself and does not cause the {0} contents to become owned", input_type),
+                &format!("this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"),
                 "consider using, depending on intent",
-                format!("{0}.clone()` or `{0}.into_owned()", recv_snip),
+                format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
                 app,
             );
             return true;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index 4e8c201f470..1cef6226ad4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -2,9 +2,10 @@ use super::utils::clone_or_copy_needed;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_copy;
 use clippy_utils::usage::mutated_variables;
-use clippy_utils::{is_lang_ctor, is_trait_method, path_to_local_id};
+use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
+use core::ops::ControlFlow;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -13,7 +14,7 @@ use rustc_span::sym;
 use super::UNNECESSARY_FILTER_MAP;
 use super::UNNECESSARY_FIND_MAP;
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, name: &str) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>, name: &str) {
     if !is_trait_method(cx, expr, sym::Iterator) {
         return;
     }
@@ -26,10 +27,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
 
         let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value);
 
-        let mut return_visitor = ReturnVisitor::new(cx, arg_id);
-        return_visitor.visit_expr(body.value);
-        found_mapping |= return_visitor.found_mapping;
-        found_filtering |= return_visitor.found_filtering;
+        let _: Option<!> = for_each_expr(body.value, |e| {
+            if let hir::ExprKind::Ret(Some(e)) = &e.kind {
+                let (found_mapping_res, found_filtering_res) = check_expression(cx, arg_id, e);
+                found_mapping |= found_mapping_res;
+                found_filtering |= found_filtering_res;
+                ControlFlow::Continue(Descend::No)
+            } else {
+                ControlFlow::Continue(Descend::Yes)
+            }
+        });
 
         let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
         let sugg = if !found_filtering {
@@ -54,22 +61,20 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
                 UNNECESSARY_FIND_MAP
             },
             expr.span,
-            &format!("this `.{}` can be written more simply using `.{}`", name, sugg),
+            &format!("this `.{name}` can be written more simply using `.{sugg}`"),
         );
     }
 }
 
 // returns (found_mapping, found_filtering)
 fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) {
-    match &expr.kind {
+    match expr.kind {
         hir::ExprKind::Call(func, args) => {
-            if let hir::ExprKind::Path(ref path) = func.kind {
-                if is_lang_ctor(cx, path, OptionSome) {
-                    if path_to_local_id(&args[0], arg_id) {
-                        return (false, false);
-                    }
-                    return (true, false);
+            if is_res_lang_ctor(cx, path_res(cx, func), OptionSome) {
+                if path_to_local_id(&args[0], arg_id) {
+                    return (false, false);
                 }
+                return (true, false);
             }
             (true, true)
         },
@@ -80,7 +85,7 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
         hir::ExprKind::Match(_, arms, _) => {
             let mut found_mapping = false;
             let mut found_filtering = false;
-            for arm in *arms {
+            for arm in arms {
                 let (m, f) = check_expression(cx, arg_id, arm.body);
                 found_mapping |= m;
                 found_filtering |= f;
@@ -93,39 +98,9 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
             let else_check = check_expression(cx, arg_id, else_arm);
             (if_check.0 | else_check.0, if_check.1 | else_check.1)
         },
-        hir::ExprKind::Path(path) if is_lang_ctor(cx, path, OptionNone) => (false, true),
+        hir::ExprKind::Path(ref path) if is_res_lang_ctor(cx, cx.qpath_res(path, expr.hir_id), OptionNone) => {
+            (false, true)
+        },
         _ => (true, true),
     }
 }
-
-struct ReturnVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    arg_id: hir::HirId,
-    // Found a non-None return that isn't Some(input)
-    found_mapping: bool,
-    // Found a return that isn't Some
-    found_filtering: bool,
-}
-
-impl<'a, 'tcx> ReturnVisitor<'a, 'tcx> {
-    fn new(cx: &'a LateContext<'tcx>, arg_id: hir::HirId) -> ReturnVisitor<'a, 'tcx> {
-        ReturnVisitor {
-            cx,
-            arg_id,
-            found_mapping: false,
-            found_filtering: false,
-        }
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        if let hir::ExprKind::Ret(Some(expr)) = &expr.kind {
-            let (found_mapping, found_filtering) = check_expression(self.cx, self.arg_id, expr);
-            self.found_mapping |= found_mapping;
-            self.found_filtering |= found_filtering;
-        } else {
-            walk_expr(self, expr);
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index c17ef6809f9..aa87dead38f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -49,15 +49,12 @@ pub(super) fn check(
                 let mut applicability = Applicability::MachineApplicable;
                 let sugg = if replacement_has_args {
                     format!(
-                        "{replacement}(|{s}| {r})",
-                        replacement = replacement_method_name,
-                        s = second_arg_ident,
+                        "{replacement_method_name}(|{second_arg_ident}| {r})",
                         r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
                     )
                 } else {
                     format!(
-                        "{replacement}()",
-                        replacement = replacement_method_name,
+                        "{replacement_method_name}()",
                     )
                 };
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 95138c0e25b..1966a85f7a7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -68,7 +68,7 @@ pub fn check_for_loop_iter(
                 cx,
                 UNNECESSARY_TO_OWNED,
                 expr.span,
-                &format!("unnecessary use of `{}`", method_name),
+                &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
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index a187a8d6016..0e73459ad65 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{eager_or_lazy, usage};
+use clippy_utils::{eager_or_lazy, is_from_proc_macro, usage};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -18,6 +18,10 @@ pub(super) fn check<'tcx>(
     arg: &'tcx hir::Expr<'_>,
     simplify_using: &str,
 ) {
+    if is_from_proc_macro(cx, expr) {
+        return;
+    }
+
     let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
     let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
     let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
@@ -58,8 +62,8 @@ pub(super) fn check<'tcx>(
                     span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
                         diag.span_suggestion(
                             span,
-                            &format!("use `{}(..)` instead", simplify_using),
-                            format!("{}({})", simplify_using, snippet(cx, body_expr.span, "..")),
+                            &format!("use `{simplify_using}(..)` instead"),
+                            format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
                             applicability,
                         );
                     });
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 559f32a563e..9ab0d614114 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -8,6 +8,7 @@ use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trai
 use clippy_utils::{meets_msrv, msrvs};
 use rustc_errors::Applicability;
 use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
+use rustc_hir_analysis::check::{FnCtxt, Inherited};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::Mutability;
@@ -18,7 +19,6 @@ use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitP
 use rustc_semver::RustcVersion;
 use rustc_span::{sym, Symbol};
 use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
-use rustc_hir_analysis::check::{FnCtxt, Inherited};
 use std::cmp::max;
 
 use super::UNNECESSARY_TO_OWNED;
@@ -132,12 +132,11 @@ fn check_addr_of_expr(
                     cx,
                     UNNECESSARY_TO_OWNED,
                     parent.span,
-                    &format!("unnecessary use of `{}`", method_name),
+                    &format!("unnecessary use of `{method_name}`"),
                     "use",
                     format!(
-                        "{:&>width$}{}",
+                        "{:&>width$}{receiver_snippet}",
                         "",
-                        receiver_snippet,
                         width = n_target_refs - n_receiver_refs
                     ),
                     Applicability::MachineApplicable,
@@ -154,7 +153,7 @@ fn check_addr_of_expr(
                             cx,
                             UNNECESSARY_TO_OWNED,
                             parent.span,
-                            &format!("unnecessary use of `{}`", method_name),
+                            &format!("unnecessary use of `{method_name}`"),
                             "use",
                             receiver_snippet,
                             Applicability::MachineApplicable,
@@ -164,7 +163,7 @@ fn check_addr_of_expr(
                             cx,
                             UNNECESSARY_TO_OWNED,
                             expr.span.with_lo(receiver.span.hi()),
-                            &format!("unnecessary use of `{}`", method_name),
+                            &format!("unnecessary use of `{method_name}`"),
                             "remove this",
                             String::new(),
                             Applicability::MachineApplicable,
@@ -181,9 +180,9 @@ fn check_addr_of_expr(
                         cx,
                         UNNECESSARY_TO_OWNED,
                         parent.span,
-                        &format!("unnecessary use of `{}`", method_name),
+                        &format!("unnecessary use of `{method_name}`"),
                         "use",
-                        format!("{}.as_ref()", receiver_snippet),
+                        format!("{receiver_snippet}.as_ref()"),
                         Applicability::MachineApplicable,
                     );
                     return true;
@@ -228,9 +227,9 @@ fn check_into_iter_call_arg(
                 cx,
                 UNNECESSARY_TO_OWNED,
                 parent.span,
-                &format!("unnecessary use of `{}`", method_name),
+                &format!("unnecessary use of `{method_name}`"),
                 "use",
-                format!("{}.iter().{}()", receiver_snippet, cloned_or_copied),
+                format!("{receiver_snippet}.iter().{cloned_or_copied}()"),
                 Applicability::MaybeIncorrect,
             );
             return true;
@@ -275,9 +274,9 @@ fn check_other_call_arg<'tcx>(
                 cx,
                 UNNECESSARY_TO_OWNED,
                 maybe_arg.span,
-                &format!("unnecessary use of `{}`", method_name),
+                &format!("unnecessary use of `{method_name}`"),
                 "use",
-                format!("{:&>width$}{}", "", receiver_snippet, width = n_refs),
+                format!("{:&>n_refs$}{receiver_snippet}", ""),
                 Applicability::MachineApplicable,
             );
             return true;
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index ca5d33ee8b0..c1139d84e2f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -1,11 +1,12 @@
 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, match_trait_method, paths};
+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;
+use rustc_span::sym;
 
 use super::USELESS_ASREF;
 
@@ -13,7 +14,7 @@ use super::USELESS_ASREF;
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, recvr: &hir::Expr<'_>) {
     // when we get here, we've already checked that the call name is "as_ref" or "as_mut"
     // check if the call is to the actual `AsRef` or `AsMut` trait
-    if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) {
+    if is_trait_method(cx, expr, sym::AsRef) || is_trait_method(cx, expr, sym::AsMut) {
         // check if the type after `as_ref` or `as_mut` is the same as before
         let rcv_ty = cx.typeck_results().expr_ty(recvr);
         let res_ty = cx.typeck_results().expr_ty(expr);
@@ -35,7 +36,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
                 cx,
                 USELESS_ASREF,
                 expr.span,
-                &format!("this call to `{}` does nothing", call_name),
+                &format!("this call to `{call_name}` does nothing"),
                 "try this",
                 snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
                 applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
index 4b368d3ffae..1fbf783b886 100644
--- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
@@ -61,20 +61,20 @@ impl Convention {
 impl fmt::Display for Convention {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         match *self {
-            Self::Eq(this) => format!("`{}`", this).fmt(f),
-            Self::StartsWith(this) => format!("`{}*`", this).fmt(f),
-            Self::EndsWith(this) => format!("`*{}`", this).fmt(f),
-            Self::NotEndsWith(this) => format!("`~{}`", this).fmt(f),
+            Self::Eq(this) => format!("`{this}`").fmt(f),
+            Self::StartsWith(this) => format!("`{this}*`").fmt(f),
+            Self::EndsWith(this) => format!("`*{this}`").fmt(f),
+            Self::NotEndsWith(this) => format!("`~{this}`").fmt(f),
             Self::IsSelfTypeCopy(is_true) => {
                 format!("`self` type is{} `Copy`", if is_true { "" } else { " not" }).fmt(f)
             },
             Self::ImplementsTrait(is_true) => {
                 let (negation, s_suffix) = if is_true { ("", "s") } else { (" does not", "") };
-                format!("method{} implement{} a trait", negation, s_suffix).fmt(f)
+                format!("method{negation} implement{s_suffix} a trait").fmt(f)
             },
             Self::IsTraitItem(is_true) => {
                 let suffix = if is_true { " is" } else { " is not" };
-                format!("method{} a trait item", suffix).fmt(f)
+                format!("method{suffix} a trait item").fmt(f)
             },
         }
     }
@@ -138,8 +138,7 @@ pub(super) fn check<'tcx>(
                 WRONG_SELF_CONVENTION,
                 first_arg_span,
                 &format!(
-                    "{} usually take {}",
-                    suggestion,
+                    "{suggestion} usually take {}",
                     &self_kinds
                         .iter()
                         .map(|k| k.description())
diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs
index 4d8579135fc..4f967755bfa 100644
--- a/src/tools/clippy/clippy_lints/src/minmax.rs
+++ b/src/tools/clippy/clippy_lints/src/minmax.rs
@@ -1,6 +1,6 @@
 use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{match_trait_method, paths};
+use clippy_utils::is_trait_method;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -83,7 +83,7 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
             }
         },
         ExprKind::MethodCall(path, receiver, args @ [_], _) => {
-            if cx.typeck_results().expr_ty(receiver).is_floating_point() || match_trait_method(cx, expr, &paths::ORD) {
+            if cx.typeck_results().expr_ty(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord) {
                 if path.ident.name == sym!(max) {
                     fetch_const(cx, Some(receiver), args, MinMax::Max)
                 } else if path.ident.name == sym!(min) {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index ea245edd770..516dee20f8b 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet, snippet_opt};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
@@ -15,7 +14,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{ExpnKind, Span};
 
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_expr, in_constant, iter_input_pats, last_path_segment, SpanlessEq};
+use clippy_utils::{get_parent_expr, in_constant, is_integer_literal, iter_input_pats, last_path_segment, SpanlessEq};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -178,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
                     ("", sugg_init.addr())
                 };
                 let tyopt = if let Some(ty) = local.ty {
-                    format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, ".."))
+                    format!(": &{mutopt}{ty}", ty=snippet(cx, ty.span, ".."))
                 } else {
                     String::new()
                 };
@@ -195,8 +194,6 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
                             format!(
                                 "let {name}{tyopt} = {initref};",
                                 name=snippet(cx, name.span, ".."),
-                                tyopt=tyopt,
-                                initref=initref,
                             ),
                             Applicability::MachineApplicable,
                         );
@@ -222,8 +219,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
                             stmt.span,
                             "replace it with",
                             format!(
-                                "if {} {{ {}; }}",
-                                sugg,
+                                "if {sugg} {{ {}; }}",
                                 &snippet(cx, b.span, ".."),
                             ),
                             Applicability::MachineApplicable, // snippet
@@ -275,9 +271,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
                 USED_UNDERSCORE_BINDING,
                 expr.span,
                 &format!(
-                    "used binding `{}` which is prefixed with an underscore. A leading \
-                     underscore signals that a binding will not be used",
-                    binding
+                    "used binding `{binding}` which is prefixed with an underscore. A leading \
+                     underscore signals that a binding will not be used"
                 ),
             );
         }
@@ -318,8 +313,7 @@ fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool {
 fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
     if_chain! {
         if let TyKind::Ptr(ref mut_ty) = ty.kind;
-        if let ExprKind::Lit(ref lit) = e.kind;
-        if let LitKind::Int(0, _) = lit.node;
+        if is_integer_literal(e, 0);
         if !in_constant(cx, e.hir_id);
         then {
             let (msg, sugg_fn) = match mut_ty.mutbl {
@@ -328,12 +322,12 @@ fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>)
             };
 
             let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
-                (format!("{}()", sugg_fn), Applicability::MachineApplicable)
+                (format!("{sugg_fn}()"), Applicability::MachineApplicable)
             } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
-                (format!("{}::<{}>()", sugg_fn, mut_ty_snip), Applicability::MachineApplicable)
+                (format!("{sugg_fn}::<{mut_ty_snip}>()"), Applicability::MachineApplicable)
             } else {
                 // `MaybeIncorrect` as type inference may not work with the suggested code
-                (format!("{}()", sugg_fn), Applicability::MaybeIncorrect)
+                (format!("{sugg_fn}()"), Applicability::MaybeIncorrect)
             };
             span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
         }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
index 1165c19a0cf..62c6ca32d31 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
@@ -18,9 +18,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &s
                 cx,
                 SEPARATED_LITERAL_SUFFIX,
                 lit.span,
-                &format!("{} type suffix should not be separated by an underscore", sugg_type),
+                &format!("{sugg_type} type suffix should not be separated by an underscore"),
                 "remove the underscore",
-                format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix),
+                format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
                 Applicability::MachineApplicable,
             );
         } else {
@@ -28,9 +28,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &s
                 cx,
                 UNSEPARATED_LITERAL_SUFFIX,
                 lit.span,
-                &format!("{} type suffix should be separated by an underscore", sugg_type),
+                &format!("{sugg_type} type suffix should be separated by an underscore"),
                 "add an underscore",
-                format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
+                format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
                 Applicability::MachineApplicable,
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index 704918c0b97..c8227ca4450 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -357,9 +357,8 @@ impl EarlyLintPass for MiscEarlyLints {
                             DUPLICATE_UNDERSCORE_ARGUMENT,
                             *correspondence,
                             &format!(
-                                "`{}` already exists, having another argument having almost the same \
-                                 name makes code comprehension and documentation more difficult",
-                                arg_name
+                                "`{arg_name}` already exists, having another argument having almost the same \
+                                 name makes code comprehension and documentation more difficult"
                             ),
                         );
                     }
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
index fff533167ed..676e5d40bb7 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
@@ -27,7 +27,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                 pat.span,
                 "all the struct fields are matched to a wildcard pattern, consider using `..`",
                 None,
-                &format!("try with `{} {{ .. }}` instead", type_name),
+                &format!("try with `{type_name} {{ .. }}` instead"),
             );
             return;
         }
@@ -63,7 +63,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                             "you matched a field with a wildcard pattern, consider using `..` \
                              instead",
                             None,
-                            &format!("try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")),
+                            &format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
                         );
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
index 020efeaebf0..6dd76a6531e 100644
--- a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
+++ b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
@@ -91,10 +91,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
                 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!("`{}` has a similarly named generic type parameter `{}` in its declaration, but in a different order",
-                                          type_name, impl_param_name);
-                        let help = format!("try `{}`, or a name that does not conflict with `{}`'s generic params",
-                                           type_param_names[i], type_name);
+                        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,
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 00376f0d790..71cc0d0a81c 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -8,12 +8,12 @@ use rustc_hir as hir;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 47219556676..b3f1553cfea 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -103,7 +103,7 @@ impl MissingDoc {
                 cx,
                 MISSING_DOCS_IN_PRIVATE_ITEMS,
                 sp,
-                &format!("missing documentation for {} {}", article, desc),
+                &format!("missing documentation for {article} {desc}"),
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
index 3d0a2382283..872679f25ab 100644
--- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
@@ -58,7 +58,8 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]);
 impl LateLintPass<'_> for ImportRename {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         for Rename { path, rename } in &self.conf_renames {
-            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &path.split("::").collect::<Vec<_>>()) {
+            let segs = path.split("::").collect::<Vec<_>>();
+            if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, None) {
                 self.renames.insert(id, Symbol::intern(rename));
             }
         }
@@ -90,9 +91,7 @@ impl LateLintPass<'_> for ImportRename {
                     "this import should be renamed",
                     "try",
                     format!(
-                        "{} as {}",
-                        import,
-                        name,
+                        "{import} as {name}",
                     ),
                     Applicability::MachineApplicable,
                 );
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 9d5764ac092..655df5419ac 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -65,7 +65,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp
             cx,
             MISSING_INLINE_IN_PUBLIC_ITEMS,
             sp,
-            &format!("missing `#[inline]` for {}", desc),
+            &format!("missing `#[inline]` for {desc}"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 102b9fbae83..0742943dff2 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -118,13 +118,7 @@ impl EarlyLintPass for ModStyle {
                         SELF_NAMED_MODULE_FILES,
                         Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
                         format!("`mod.rs` files are required, found `{}`", path.display()),
-                        |lint| {
-                            lint.help(format!(
-                                "move `{}` to `{}`",
-                                path.display(),
-                                correct.display(),
-                            ))
-                        },
+                        |lint| lint.help(format!("move `{}` to `{}`", path.display(), correct.display(),)),
                     );
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 084c0d471dd..4547ed7eafc 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -87,7 +87,7 @@ fn check_arguments<'tcx>(
                                 cx,
                                 UNNECESSARY_MUT_PASSED,
                                 argument.span,
-                                &format!("the {} `{}` doesn't need a mutable reference", fn_kind, name),
+                                &format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
                             );
                         }
                     },
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 44fdf84c6df..d8647a99105 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -56,10 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for DebugAssertWithMutCall {
                     cx,
                     DEBUG_ASSERT_WITH_MUT_CALL,
                     span,
-                    &format!(
-                        "do not call a function with mutable arguments inside of `{}!`",
-                        macro_name
-                    ),
+                    &format!("do not call a function with mutable arguments inside of `{macro_name}!`"),
                 );
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index a98577093ed..09cb5333176 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -84,9 +84,8 @@ impl<'tcx> LateLintPass<'tcx> for Mutex {
                 let mutex_param = subst.type_at(0);
                 if let Some(atomic_name) = get_atomic_name(mutex_param) {
                     let msg = format!(
-                        "consider using an `{}` instead of a `Mutex` here; if you just want the locking \
-                         behavior and not the internal type, consider using `Mutex<()>`",
-                        atomic_name
+                        "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \
+                         behavior and not the internal type, consider using `Mutex<()>`"
                     );
                     match *mutex_param.kind() {
                         ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
index b8855e5adbf..10c3ff026b6 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
@@ -1,6 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BindingAnnotation, Mutability, Node, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -8,36 +6,26 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for bindings that destructure a reference and borrow the inner
+    /// Checks for bindings that needlessly destructure a reference and borrow the inner
     /// value with `&ref`.
     ///
     /// ### Why is this bad?
     /// This pattern has no effect in almost all cases.
     ///
-    /// ### Known problems
-    /// In some cases, `&ref` is needed to avoid a lifetime mismatch error.
-    /// Example:
-    /// ```rust
-    /// fn foo(a: &Option<String>, b: &Option<String>) {
-    ///     match (a, b) {
-    ///         (None, &ref c) | (&ref c, None) => (),
-    ///         (&Some(ref c), _) => (),
-    ///     };
-    /// }
-    /// ```
-    ///
     /// ### Example
     /// ```rust
     /// let mut v = Vec::<String>::new();
-    /// # #[allow(unused)]
     /// v.iter_mut().filter(|&ref a| a.is_empty());
+    ///
+    /// if let &[ref first, ref second] = v.as_slice() {}
     /// ```
     ///
     /// Use instead:
     /// ```rust
     /// let mut v = Vec::<String>::new();
-    /// # #[allow(unused)]
     /// v.iter_mut().filter(|a| a.is_empty());
+    ///
+    /// if let [first, second] = v.as_slice() {}
     /// ```
     #[clippy::version = "pre 1.29.0"]
     pub NEEDLESS_BORROWED_REFERENCE,
@@ -54,34 +42,83 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
             return;
         }
 
-        if_chain! {
-            // Only lint immutable refs, because `&mut ref T` may be useful.
-            if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
+        // Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
+        for (_, node) in cx.tcx.hir().parent_iter(pat.hir_id) {
+            let Node::Pat(pat) = node else { break };
+
+            if matches!(pat.kind, PatKind::Or(_)) {
+                return;
+            }
+        }
+
+        // Only lint immutable refs, because `&mut ref T` may be useful.
+        let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind else { return };
 
+        match sub_pat.kind {
             // Check sub_pat got a `ref` keyword (excluding `ref mut`).
-            if let PatKind::Binding(BindingAnnotation::REF, .., spanned_name, _) = sub_pat.kind;
-            let parent_id = cx.tcx.hir().get_parent_node(pat.hir_id);
-            if let Some(parent_node) = cx.tcx.hir().find(parent_id);
-            then {
-                // do not recurse within patterns, as they may have other references
-                // XXXManishearth we can relax this constraint if we only check patterns
-                // with a single ref pattern inside them
-                if let Node::Pat(_) = parent_node {
-                    return;
+            PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
+                span_lint_and_then(
+                    cx,
+                    NEEDLESS_BORROWED_REFERENCE,
+                    pat.span,
+                    "this pattern takes a reference on something that is being dereferenced",
+                    |diag| {
+                        // `&ref ident`
+                        //  ^^^^^
+                        let span = pat.span.until(ident.span);
+                        diag.span_suggestion_verbose(
+                            span,
+                            "try removing the `&ref` part",
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                    },
+                );
+            },
+            // Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
+            PatKind::Slice(
+                before,
+                None
+                | Some(Pat {
+                    kind: PatKind::Wild, ..
+                }),
+                after,
+            ) => {
+                let mut suggestions = Vec::new();
+
+                for element_pat in itertools::chain(before, after) {
+                    if let PatKind::Binding(BindingAnnotation::REF, _, ident, None) = element_pat.kind {
+                        // `&[..., ref ident, ...]`
+                        //         ^^^^
+                        let span = element_pat.span.until(ident.span);
+                        suggestions.push((span, String::new()));
+                    } else {
+                        return;
+                    }
                 }
-                let mut applicability = Applicability::MachineApplicable;
-                span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span,
-                                   "this pattern takes a reference on something that is being de-referenced",
-                                   |diag| {
-                                       let hint = snippet_with_applicability(cx, spanned_name.span, "..", &mut applicability).into_owned();
-                                       diag.span_suggestion(
-                                           pat.span,
-                                           "try removing the `&ref` part and just keep",
-                                           hint,
-                                           applicability,
-                                       );
-                                   });
-            }
+
+                if !suggestions.is_empty() {
+                    span_lint_and_then(
+                        cx,
+                        NEEDLESS_BORROWED_REFERENCE,
+                        pat.span,
+                        "dereferencing a slice pattern where every element takes a reference",
+                        |diag| {
+                            // `&[...]`
+                            //  ^
+                            let span = pat.span.until(sub_pat.span);
+                            suggestions.push((span, String::new()));
+
+                            diag.multipart_suggestion(
+                                "try removing the `&` and `ref` parts",
+                                suggestions,
+                                Applicability::MachineApplicable,
+                            );
+                        },
+                    );
+                }
+            },
+            _ => {},
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index 98a3bce1ff3..6f0e755466e 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -309,7 +309,7 @@ fn emit_warning<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str,
         expr.span,
         message,
         None,
-        &format!("{}\n{}", header, snip),
+        &format!("{header}\n{snip}"),
     );
 }
 
@@ -322,10 +322,7 @@ fn suggestion_snippet_for_continue_inside_if<'a>(cx: &EarlyContext<'_>, data: &'
 
     let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0);
     format!(
-        "{indent}if {} {}\n{indent}{}",
-        cond_code,
-        continue_code,
-        else_code,
+        "{indent}if {cond_code} {continue_code}\n{indent}{else_code}",
         indent = " ".repeat(indent_if),
     )
 }
@@ -349,7 +346,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data:
             let span = cx.sess().source_map().stmt_span(stmt.span, data.loop_block.span);
             let snip = snippet_block(cx, span, "..", None).into_owned();
             snip.lines()
-                .map(|line| format!("{}{}", " ".repeat(indent), line))
+                .map(|line| format!("{}{line}", " ".repeat(indent)))
                 .collect::<Vec<_>>()
                 .join("\n")
         })
@@ -358,10 +355,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data:
 
     let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0);
     format!(
-        "{indent_if}if {} {}\n{indent}// merged code follows:\n{}\n{indent_if}}}",
-        cond_code,
-        block_code,
-        to_annex,
+        "{indent_if}if {cond_code} {block_code}\n{indent}// merged code follows:\n{to_annex}\n{indent_if}}}",
         indent = " ".repeat(indent),
         indent_if = " ".repeat(indent_if),
     )
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index de99f1d7078..9d26e590086 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::path_to_local;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::needs_ordered_drop;
-use clippy_utils::visitors::{expr_visitor, expr_visitor_no_bodies, is_local_used};
+use clippy_utils::visitors::{for_each_expr, for_each_expr_with_closures, is_local_used};
+use core::ops::ControlFlow;
 use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::intravisit::Visitor;
 use rustc_hir::{
     BindingAnnotation, Block, Expr, ExprKind, HirId, Local, LocalSource, MatchSource, Node, Pat, PatKind, Stmt,
     StmtKind,
@@ -64,31 +64,25 @@ declare_clippy_lint! {
 declare_lint_pass!(NeedlessLateInit => [NEEDLESS_LATE_INIT]);
 
 fn contains_assign_expr<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> bool {
-    let mut seen = false;
-    expr_visitor(cx, |expr| {
-        if let ExprKind::Assign(..) = expr.kind {
-            seen = true;
+    for_each_expr_with_closures(cx, stmt, |e| {
+        if matches!(e.kind, ExprKind::Assign(..)) {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
         }
-
-        !seen
     })
-    .visit_stmt(stmt);
-
-    seen
+    .is_some()
 }
 
 fn contains_let(cond: &Expr<'_>) -> bool {
-    let mut seen = false;
-    expr_visitor_no_bodies(|expr| {
-        if let ExprKind::Let(_) = expr.kind {
-            seen = true;
+    for_each_expr(cond, |e| {
+        if matches!(e.kind, ExprKind::Let(_)) {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
         }
-
-        !seen
     })
-    .visit_expr(cond);
-
-    seen
+    .is_some()
 }
 
 fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
@@ -287,7 +281,7 @@ fn check<'tcx>(
 
                     diag.span_suggestion(
                         assign.lhs_span,
-                        &format!("declare `{}` here", binding_name),
+                        &format!("declare `{binding_name}` here"),
                         let_snippet,
                         Applicability::MachineApplicable,
                     );
@@ -307,8 +301,8 @@ fn check<'tcx>(
 
                     diag.span_suggestion_verbose(
                         usage.stmt.span.shrink_to_lo(),
-                        &format!("declare `{}` here", binding_name),
-                        format!("{} = ", let_snippet),
+                        &format!("declare `{binding_name}` here"),
+                        format!("{let_snippet} = "),
                         applicability,
                     );
 
@@ -338,8 +332,8 @@ fn check<'tcx>(
 
                     diag.span_suggestion_verbose(
                         usage.stmt.span.shrink_to_lo(),
-                        &format!("declare `{}` here", binding_name),
-                        format!("{} = ", let_snippet),
+                        &format!("declare `{binding_name}` here"),
+                        format!("{let_snippet} = "),
                         applicability,
                     );
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 4f46872439c..178c973981b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -12,17 +12,17 @@ use rustc_hir::{
     BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind,
 };
 use rustc_hir::{HirIdMap, HirIdSet};
+use rustc_hir_analysis::expr_use_visitor as euv;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, TypeVisitable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::kw;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::misc::can_type_implement_copy;
-use rustc_hir_analysis::expr_use_visitor as euv;
 use std::borrow::Cow;
 
 declare_clippy_lint! {
@@ -186,6 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 if !is_self(arg);
                 if !ty.is_mutable_ptr();
                 if !is_copy(cx, ty);
+                if ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env);
                 if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
                 if !implements_borrow_trait;
                 if !all_borrowable_trait;
@@ -236,7 +237,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                         snippet_opt(cx, span)
                                             .map_or(
                                                 "change the call to".into(),
-                                                |x| Cow::from(format!("change `{}` to", x)),
+                                                |x| Cow::from(format!("change `{x}` to")),
                                             )
                                             .as_ref(),
                                         suggestion,
@@ -266,7 +267,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                         snippet_opt(cx, span)
                                             .map_or(
                                                 "change the call to".into(),
-                                                |x| Cow::from(format!("change `{}` to", x))
+                                                |x| Cow::from(format!("change `{x}` to"))
                                             )
                                             .as_ref(),
                                         suggestion,
@@ -341,5 +342,11 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
 
     fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
 
-    fn fake_read(&mut self, _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(
+        &mut self,
+        _: &rustc_hir_analysis::expr_use_visitor::PlaceWithHirId<'tcx>,
+        _: FakeReadCause,
+        _: HirId,
+    ) {
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
index 8f85b00596c..97c8cfbd3eb 100644
--- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
@@ -1,11 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_lang_ctor;
+use clippy_utils::path_res;
 use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionSome, ResultOk};
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::DefIdTree;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -112,11 +113,12 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
 
 fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
-        if let ExprKind::Call(path, [arg]) = &expr.kind;
-        if let ExprKind::Path(ref qpath) = &path.kind;
-        let sugg_remove = if is_lang_ctor(cx, qpath, OptionSome) {
+        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) {
             "Some()"
-        } else if is_lang_ctor(cx, qpath, ResultOk) {
+        } else if cx.tcx.lang_items().result_ok_variant() == Some(variant_id) {
             "Ok()"
         } else {
             return;
@@ -134,7 +136,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 NEEDLESS_QUESTION_MARK,
                 expr.span,
                 "question mark operator is useless here",
-                &format!("try removing question mark and `{}`", sugg_remove),
+                &format!("try removing question mark and `{sugg_remove}`"),
                 format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
                 Applicability::MachineApplicable,
             );
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index b087cfb36b1..fb9a4abd0b4 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -62,9 +62,9 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
             let mut applicability = Applicability::MachineApplicable;
             let snip = snippet_with_applicability(cx, exp.span, "..", &mut applicability);
             let suggestion = if exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) {
-                format!("-({})", snip)
+                format!("-({snip})")
             } else {
-                format!("-{}", snip)
+                format!("-{snip}")
             };
             span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index 357a71693d2..6017117e1ec 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -136,8 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                     id,
                                     impl_item.span,
                                     &format!(
-                                        "you should consider adding a `Default` implementation for `{}`",
-                                        self_type_snip
+                                        "you should consider adding a `Default` implementation for `{self_type_snip}`"
                                     ),
                                     |diag| {
                                         diag.suggest_prepend_item(
@@ -161,9 +160,9 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
 fn create_new_without_default_suggest_msg(self_type_snip: &str, generics_sugg: &str) -> String {
     #[rustfmt::skip]
     format!(
-"impl{} Default for {} {{
+"impl{generics_sugg} Default for {self_type_snip} {{
     fn default() -> Self {{
         Self::new()
     }}
-}}", generics_sugg, self_type_snip)
+}}")
 }
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 48ff737dae7..2c839d029c6 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -13,6 +13,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{
     BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
 };
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass, Lint};
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
@@ -20,7 +21,6 @@ use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, InnerSpan, Span, DUMMY_SP};
-use rustc_hir_analysis::hir_ty_to_ty;
 
 // FIXME: this is a correctness problem but there's no suitable
 // warn-by-default category.
@@ -149,6 +149,9 @@ fn is_value_unfrozen_raw<'tcx>(
             // the fact that we have to dig into every structs to search enums
             // leads us to the point checking `UnsafeCell` directly is the only option.
             ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true,
+            // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
+            // contained value.
+            ty::Adt(def, ..) if def.is_union() => false,
             ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
                 let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
                 val.fields.iter().any(|field| inner(cx, *field))
diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index a7cd1f6d065..9f6917c146f 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -112,10 +112,7 @@ impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> {
                 self.cx,
                 MANY_SINGLE_CHAR_NAMES,
                 span,
-                &format!(
-                    "{} bindings with single-character names in scope",
-                    num_single_char_names
-                ),
+                &format!("{num_single_char_names} bindings with single-character names in scope"),
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
index 25fb4f0f4cf..1a765b14892 100644
--- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,12 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -49,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
                 if_chain! {
                     if (path.ident.name == sym!(mode)
                         && (match_type(cx, obj_ty, &paths::OPEN_OPTIONS)
-                            || match_type(cx, obj_ty, &paths::DIR_BUILDER)))
+                            || is_type_diagnostic_item(cx, obj_ty, sym::DirBuilder)))
                         || (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS));
                     if let ExprKind::Lit(_) = param.kind;
 
diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
index f86dfb6b8df..0ca0befc135 100644
--- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
@@ -3,16 +3,17 @@ use std::{
     hash::{Hash, Hasher},
 };
 
-use clippy_utils::diagnostics::span_lint_and_help;
+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;
 use rustc_hir::def_id::DefId;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
 use serde::{de, Deserialize};
 
 declare_clippy_lint! {
@@ -39,8 +40,8 @@ declare_clippy_lint! {
 
 const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")];
 
-/// The (name, (open brace, close brace), source snippet)
-type MacroInfo<'a> = (Symbol, &'a (String, String), String);
+/// The (callsite span, (open brace, close brace), source snippet)
+type MacroInfo<'a> = (Span, &'a (String, String), String);
 
 #[derive(Clone, Debug, Default)]
 pub struct MacroBraces {
@@ -62,33 +63,29 @@ impl_lint_pass!(MacroBraces => [NONSTANDARD_MACRO_BRACES]);
 
 impl EarlyLintPass for MacroBraces {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
-        if let Some((name, braces, snip)) = is_offending_macro(cx, item.span, self) {
-            let span = item.span.ctxt().outer_expn_data().call_site;
-            emit_help(cx, snip, braces, name, span);
+        if let Some((span, braces, snip)) = is_offending_macro(cx, item.span, self) {
+            emit_help(cx, &snip, braces, span);
             self.done.insert(span);
         }
     }
 
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
-        if let Some((name, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
-            let span = stmt.span.ctxt().outer_expn_data().call_site;
-            emit_help(cx, snip, braces, name, span);
+        if let Some((span, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
+            emit_help(cx, &snip, braces, span);
             self.done.insert(span);
         }
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        if let Some((name, braces, snip)) = is_offending_macro(cx, expr.span, self) {
-            let span = expr.span.ctxt().outer_expn_data().call_site;
-            emit_help(cx, snip, braces, name, span);
+        if let Some((span, braces, snip)) = is_offending_macro(cx, expr.span, self) {
+            emit_help(cx, &snip, braces, span);
             self.done.insert(span);
         }
     }
 
     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
-        if let Some((name, braces, snip)) = is_offending_macro(cx, ty.span, self) {
-            let span = ty.span.ctxt().outer_expn_data().call_site;
-            emit_help(cx, snip, braces, name, span);
+        if let Some((span, braces, snip)) = is_offending_macro(cx, ty.span, self) {
+            emit_help(cx, &snip, braces, span);
             self.done.insert(span);
         }
     }
@@ -102,48 +99,44 @@ fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a Mac
                 .last()
                 .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.ctxt().outer_expn_data().call_site);
+        if 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 snip.starts_with(&format!("{name}!"));
         if unnested_or_local();
         // make formatting consistent
         let c = snip.replace(' ', "");
-        if !c.starts_with(&format!("{}!{}", name, braces.0));
-        if !mac_braces.done.contains(&span.ctxt().outer_expn_data().call_site);
+        if !c.starts_with(&format!("{name}!{}", braces.0));
+        if !mac_braces.done.contains(&span_call_site);
         then {
-            Some((mac_name, braces, snip))
+            Some((span_call_site, braces, snip))
         } else {
             None
         }
     }
 }
 
-fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: Symbol, span: Span) {
-    let with_space = &format!("! {}", braces.0);
-    let without_space = &format!("!{}", braces.0);
-    let mut help = snip;
-    for b in BRACES.iter().filter(|b| b.0 != braces.0) {
-        help = help.replace(b.0, &braces.0).replace(b.1, &braces.1);
-        // Only `{` traditionally has space before the brace
-        if braces.0 != "{" && help.contains(with_space) {
-            help = help.replace(with_space, without_space);
-        } else if braces.0 == "{" && help.contains(without_space) {
-            help = help.replace(without_space, with_space);
-        }
+fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), 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
+        macro_args.remove(0);
+        macro_args.pop();
+        span_lint_and_sugg(
+            cx,
+            NONSTANDARD_MACRO_BRACES,
+            span,
+            &format!("use of irregular braces for `{macro_name}!` macro"),
+            "consider writing",
+            format!("{macro_name}!{}{macro_args}{}", braces.0, braces.1),
+            Applicability::MachineApplicable,
+        );
     }
-    span_lint_and_help(
-        cx,
-        NONSTANDARD_MACRO_BRACES,
-        span,
-        &format!("use of irregular braces for `{}!` macro", name),
-        Some(span),
-        &format!("consider writing `{}`", help),
-    );
 }
 
 fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> {
@@ -273,9 +266,7 @@ impl<'de> Deserialize<'de> for MacroMatcher {
                         .iter()
                         .find(|b| b.0 == brace)
                         .map(|(o, c)| ((*o).to_owned(), (*c).to_owned()))
-                        .ok_or_else(|| {
-                            de::Error::custom(&format!("expected one of `(`, `{{`, `[` found `{}`", brace))
-                        })?,
+                        .ok_or_else(|| de::Error::custom(&format!("expected one of `(`, `{{`, `[` found `{brace}`")))?,
                 })
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
index bffbf20b4d2..f380a506582 100644
--- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs
+++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
@@ -102,7 +102,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
         // construct a replacement escape
         // the maximum value is \077, or \x3f, so u8 is sufficient here
         if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) {
-            write!(suggest_1, "\\x{:02x}", n).unwrap();
+            write!(suggest_1, "\\x{n:02x}").unwrap();
         }
 
         // append the null byte as \x00 and the following digits literally
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index 1ec4240afef..d29ca37eaeb 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -34,13 +34,12 @@ pub(super) fn check<'tcx>(
         };
 
         let help = format!(
-            "because `{}` is the {} value for this type, {}",
+            "because `{}` is the {} value for this type, {conclusion}",
             snippet(cx, culprit.expr.span, "x"),
             match culprit.which {
                 ExtremeType::Minimum => "minimum",
                 ExtremeType::Maximum => "maximum",
-            },
-            conclusion
+            }
         );
 
         span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help);
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index d24c57c0a4b..8827daaa3ee 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -1,8 +1,3 @@
-#![allow(
-    // False positive
-    clippy::match_same_arms
-)]
-
 use super::ARITHMETIC_SIDE_EFFECTS;
 use clippy_utils::{consts::constant_simple, diagnostics::span_lint};
 use rustc_ast as ast;
@@ -14,11 +9,12 @@ use rustc_session::impl_lint_pass;
 use rustc_span::source_map::{Span, Spanned};
 
 const HARD_CODED_ALLOWED: &[&str] = &[
+    "&str",
     "f32",
     "f64",
     "std::num::Saturating",
-    "std::string::String",
     "std::num::Wrapping",
+    "std::string::String",
 ];
 
 #[derive(Debug)]
@@ -45,61 +41,59 @@ impl ArithmeticSideEffects {
     /// Assuming that `expr` is a literal integer, checks operators (+=, -=, *, /) in a
     /// non-constant environment that won't overflow.
     fn has_valid_op(op: &Spanned<hir::BinOpKind>, expr: &hir::Expr<'_>) -> bool {
-        if let hir::BinOpKind::Add | hir::BinOpKind::Sub = op.node
-            && let hir::ExprKind::Lit(ref lit) = expr.kind
-            && let ast::LitKind::Int(0, _) = lit.node
-        {
-            return true;
-        }
-        if let hir::BinOpKind::Div | hir::BinOpKind::Rem = op.node
-            && let hir::ExprKind::Lit(ref lit) = expr.kind
-            && !matches!(lit.node, ast::LitKind::Int(0, _))
+        if let hir::ExprKind::Lit(ref lit) = expr.kind &&
+            let ast::LitKind::Int(value, _) = lit.node
         {
-            return true;
-        }
-        if let hir::BinOpKind::Mul = op.node
-            && let hir::ExprKind::Lit(ref lit) = expr.kind
-            && let ast::LitKind::Int(0 | 1, _) = lit.node
-        {
-            return true;
+            match (&op.node, value) {
+                (hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
+                (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
+                    | (hir::BinOpKind::Div | hir::BinOpKind::Rem, _)
+                    | (hir::BinOpKind::Mul, 0 | 1) => true,
+                _ => false,
+            }
+        } else {
+            false
         }
-        false
     }
 
     /// Checks if the given `expr` has any of the inner `allowed` elements.
-    fn is_allowed_ty(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
-        self.allowed.contains(
-            cx.typeck_results()
-                .expr_ty(expr)
-                .to_string()
-                .split('<')
-                .next()
-                .unwrap_or_default(),
-        )
+    fn is_allowed_ty(&self, ty: Ty<'_>) -> bool {
+        self.allowed
+            .contains(ty.to_string().split('<').next().unwrap_or_default())
     }
 
-    /// Explicit integers like `1` or `i32::MAX`. Does not take into consideration references.
-    fn is_literal_integer(expr: &hir::Expr<'_>, expr_refs: Ty<'_>) -> bool {
-        let is_integral = expr_refs.is_integral();
-        let is_literal = matches!(expr.kind, hir::ExprKind::Lit(_));
-        is_integral && is_literal
+    // For example, 8i32 or &i64::MAX.
+    fn is_integral(ty: Ty<'_>) -> bool {
+        ty.peel_refs().is_integral()
     }
 
+    // Common entry-point to avoid code duplication.
     fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
         let msg = "arithmetic operation that can potentially result in unexpected side-effects";
         span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
         self.expr_span = Some(expr.span);
     }
 
+    /// If `expr` does not match any variant of `LiteralIntegerTy`, returns `None`.
+    fn literal_integer<'expr, 'tcx>(expr: &'expr hir::Expr<'tcx>) -> Option<LiteralIntegerTy<'expr, 'tcx>> {
+        if matches!(expr.kind, hir::ExprKind::Lit(_)) {
+            return Some(LiteralIntegerTy::Value(expr));
+        }
+        if let hir::ExprKind::AddrOf(.., inn) = expr.kind && let hir::ExprKind::Lit(_) = inn.kind {
+            return Some(LiteralIntegerTy::Ref(inn));
+        }
+        None
+    }
+
     /// Manages when the lint should be triggered. Operations in constant environments, hard coded
     /// types, custom allowed types and non-constant operations that won't overflow are ignored.
-    fn manage_bin_ops(
+    fn manage_bin_ops<'tcx>(
         &mut self,
-        cx: &LateContext<'_>,
-        expr: &hir::Expr<'_>,
+        cx: &LateContext<'tcx>,
+        expr: &hir::Expr<'tcx>,
         op: &Spanned<hir::BinOpKind>,
-        lhs: &hir::Expr<'_>,
-        rhs: &hir::Expr<'_>,
+        lhs: &hir::Expr<'tcx>,
+        rhs: &hir::Expr<'tcx>,
     ) {
         if constant_simple(cx, cx.typeck_results(), expr).is_some() {
             return;
@@ -116,17 +110,20 @@ impl ArithmeticSideEffects {
         ) {
             return;
         };
-        if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
+        let lhs_ty = cx.typeck_results().expr_ty(lhs);
+        let rhs_ty = cx.typeck_results().expr_ty(rhs);
+        let lhs_and_rhs_have_the_same_ty = lhs_ty == rhs_ty;
+        if lhs_and_rhs_have_the_same_ty && self.is_allowed_ty(lhs_ty) && self.is_allowed_ty(rhs_ty) {
             return;
         }
-        let has_valid_op = match (
-            Self::is_literal_integer(lhs, cx.typeck_results().expr_ty(lhs).peel_refs()),
-            Self::is_literal_integer(rhs, cx.typeck_results().expr_ty(rhs).peel_refs()),
-        ) {
-            (true, true) => true,
-            (true, false) => Self::has_valid_op(op, lhs),
-            (false, true) => Self::has_valid_op(op, rhs),
-            (false, false) => false,
+        let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
+            match (Self::literal_integer(lhs), Self::literal_integer(rhs)) {
+                (None, Some(lit_int_ty)) | (Some(lit_int_ty), None) => Self::has_valid_op(op, lit_int_ty.into()),
+                (Some(LiteralIntegerTy::Value(_)), Some(LiteralIntegerTy::Value(_))) => true,
+                (None, None) | (Some(_), Some(_)) => false,
+            }
+        } else {
+            false
         };
         if !has_valid_op {
             self.issue_lint(cx, expr);
@@ -135,7 +132,7 @@ impl ArithmeticSideEffects {
 }
 
 impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
         if self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) {
             return;
         }
@@ -180,3 +177,22 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
         }
     }
 }
+
+/// Tells if an expression is a integer declared by value or by reference.
+///
+/// If `LiteralIntegerTy::Ref`, then the contained value will be `hir::ExprKind::Lit` rather
+/// than `hirExprKind::Addr`.
+enum LiteralIntegerTy<'expr, 'tcx> {
+    /// For example, `&199`
+    Ref(&'expr hir::Expr<'tcx>),
+    /// For example, `1` or `i32::MAX`
+    Value(&'expr hir::Expr<'tcx>),
+}
+
+impl<'expr, 'tcx> From<LiteralIntegerTy<'expr, 'tcx>> for &'expr hir::Expr<'tcx> {
+    fn from(from: LiteralIntegerTy<'expr, 'tcx>) -> Self {
+        match from {
+            LiteralIntegerTy::Ref(elem) | LiteralIntegerTy::Value(elem) => elem,
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index f134c6c4cdb..26bca7c306a 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -2,16 +2,17 @@ use clippy_utils::binop_traits;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{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::intravisit::{walk_expr, Visitor};
+use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::BorrowKind;
 use rustc_trait_selection::infer::TyCtxtInferExt;
-use rustc_hir_analysis::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 use super::ASSIGN_OP_PATTERN;
 
@@ -55,7 +56,7 @@ pub(super) fn check<'tcx>(
                                 diag.span_suggestion(
                                     expr.span,
                                     "replace it with",
-                                    format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
+                                    format!("{snip_a} {}= {snip_r}", op.node.as_str()),
                                     Applicability::MachineApplicable,
                                 );
                             }
@@ -65,15 +66,19 @@ pub(super) fn check<'tcx>(
             }
         };
 
-        let mut visitor = ExprVisitor {
-            assignee,
-            counter: 0,
-            cx,
-        };
-
-        walk_expr(&mut visitor, e);
+        let mut found = false;
+        let found_multiple = for_each_expr(e, |e| {
+            if eq_expr_value(cx, assignee, e) {
+                if found {
+                    return ControlFlow::Break(());
+                }
+                found = true;
+            }
+            ControlFlow::Continue(())
+        })
+        .is_some();
 
-        if visitor.counter == 1 {
+        if found && !found_multiple {
             // a = a op b
             if eq_expr_value(cx, assignee, l) {
                 lint(assignee, r);
@@ -98,22 +103,6 @@ pub(super) fn check<'tcx>(
     }
 }
 
-struct ExprVisitor<'a, 'tcx> {
-    assignee: &'a hir::Expr<'a>,
-    counter: u8,
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        if eq_expr_value(self.cx, self.assignee, expr) {
-            self.counter += 1;
-        }
-
-        walk_expr(self, expr);
-    }
-}
-
 fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
     struct S(hir::HirIdSet);
     impl Delegate<'_> for S {
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 74387fbc87b..1369b3e7462 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -64,10 +64,7 @@ fn check_bit_mask(
                             cx,
                             BAD_BIT_MASK,
                             span,
-                            &format!(
-                                "incompatible bit mask: `_ & {}` can never be equal to `{}`",
-                                mask_value, cmp_value
-                            ),
+                            &format!("incompatible bit mask: `_ & {mask_value}` can never be equal to `{cmp_value}`"),
                         );
                     }
                 } else if mask_value == 0 {
@@ -80,10 +77,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!(
-                            "incompatible bit mask: `_ | {}` can never be equal to `{}`",
-                            mask_value, cmp_value
-                        ),
+                        &format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"),
                     );
                 }
             },
@@ -96,10 +90,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!(
-                            "incompatible bit mask: `_ & {}` will always be lower than `{}`",
-                            mask_value, cmp_value
-                        ),
+                        &format!("incompatible bit mask: `_ & {mask_value}` will always be lower than `{cmp_value}`"),
                     );
                 } else if mask_value == 0 {
                     span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
@@ -111,10 +102,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!(
-                            "incompatible bit mask: `_ | {}` will never be lower than `{}`",
-                            mask_value, cmp_value
-                        ),
+                        &format!("incompatible bit mask: `_ | {mask_value}` will never be lower than `{cmp_value}`"),
                     );
                 } else {
                     check_ineffective_lt(cx, span, mask_value, cmp_value, "|");
@@ -130,10 +118,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!(
-                            "incompatible bit mask: `_ & {}` will never be higher than `{}`",
-                            mask_value, cmp_value
-                        ),
+                        &format!("incompatible bit mask: `_ & {mask_value}` will never be higher than `{cmp_value}`"),
                     );
                 } else if mask_value == 0 {
                     span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
@@ -145,10 +130,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!(
-                            "incompatible bit mask: `_ | {}` will always be higher than `{}`",
-                            mask_value, cmp_value
-                        ),
+                        &format!("incompatible bit mask: `_ | {mask_value}` will always be higher than `{cmp_value}`"),
                     );
                 } else {
                     check_ineffective_gt(cx, span, mask_value, cmp_value, "|");
@@ -167,10 +149,7 @@ fn check_ineffective_lt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
             cx,
             INEFFECTIVE_BIT_MASK,
             span,
-            &format!(
-                "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
-                op, m, c
-            ),
+            &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
         );
     }
 }
@@ -181,10 +160,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
             cx,
             INEFFECTIVE_BIT_MASK,
             span,
-            &format!(
-                "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
-                op, m, c
-            ),
+            &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index 638a514ff9b..c9c777f1bd8 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -99,7 +99,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
             let expr_snip;
             let eq_impl;
             if with_deref.is_implemented() {
-                expr_snip = format!("*{}", arg_snip);
+                expr_snip = format!("*{arg_snip}");
                 eq_impl = with_deref;
             } else {
                 expr_snip = arg_snip.to_string();
@@ -121,17 +121,15 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
                 };
                 if eq_impl.ty_eq_other {
                     hint = format!(
-                        "{}{}{}",
-                        expr_snip,
+                        "{expr_snip}{}{}",
                         snippet(cx, cmp_span, ".."),
                         snippet(cx, other.span, "..")
                     );
                 } else {
                     hint = format!(
-                        "{}{}{}",
+                        "{}{}{expr_snip}",
                         snippet(cx, other.span, ".."),
-                        snippet(cx, cmp_span, ".."),
-                        expr_snip
+                        snippet(cx, cmp_span, "..")
                     );
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index 827a2b26709..49e662cacb0 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -31,12 +31,11 @@ pub(crate) fn check<'tcx>(
             cx,
             DURATION_SUBSEC,
             expr.span,
-            &format!("calling `{}()` is more concise than this calculation", suggested_fn),
+            &format!("calling `{suggested_fn}()` is more concise than this calculation"),
             "try",
             format!(
-                "{}.{}()",
-                snippet_with_applicability(cx, self_arg.span, "_", &mut applicability),
-                suggested_fn
+                "{}.{suggested_fn}()",
+                snippet_with_applicability(cx, self_arg.span, "_", &mut applicability)
             ),
             applicability,
         );
diff --git a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
index 44cf0bb0612..67913f7392c 100644
--- a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
@@ -22,7 +22,7 @@ pub(crate) fn check_assert<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
             cx,
             EQ_OP,
             lhs.span.to(rhs.span),
-            &format!("identical args used in this `{}!` macro call", macro_name),
+            &format!("identical args used in this `{macro_name}!` macro call"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
index 0024384d927..ae805147f07 100644
--- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
@@ -47,18 +47,14 @@ fn lint_misrefactored_assign_op(
             if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
                 let a = &sugg::Sugg::hir(cx, assignee, "..");
                 let r = &sugg::Sugg::hir(cx, rhs, "..");
-                let long = format!("{} = {}", snip_a, sugg::make_binop(op.into(), a, r));
+                let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r));
                 diag.span_suggestion(
                     expr.span,
                     &format!(
-                        "did you mean `{} = {} {} {}` or `{}`? Consider replacing it with",
-                        snip_a,
-                        snip_a,
-                        op.as_str(),
-                        snip_r,
-                        long
+                        "did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with",
+                        op.as_str()
                     ),
-                    format!("{} {}= {}", snip_a, op.as_str(), snip_r),
+                    format!("{snip_a} {}= {snip_r}", op.as_str()),
                     Applicability::MaybeIncorrect,
                 );
                 diag.span_suggestion(
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index c32b4df4f75..b8a20d5ebe9 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -67,7 +67,7 @@ declare_clippy_lint! {
     /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
     /// or can panic (`/`, `%`).
     ///
-    /// Known safe built-in types like `Wrapping` or `Saturing`, floats, operations in constant
+    /// Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant
     /// environments, allowed types and non-constant operations that won't overflow are ignored.
     ///
     /// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs
index e902235a014..ab5fb178700 100644
--- a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs
@@ -27,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp
                 if let Some(lhs_snip) = snippet_opt(cx, lhs.span)
                     && let Some(rhs_snip) = snippet_opt(cx, rhs.span)
                 {
-                    let sugg = format!("{} {} {}", lhs_snip, op_str, rhs_snip);
+                    let sugg = format!("{lhs_snip} {op_str} {rhs_snip}");
                     diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index b6097710dc6..0830a106f55 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,5 +1,6 @@
 use clippy_utils::consts::constant_simple;
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_integer_literal;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
@@ -50,11 +51,9 @@ impl Context {
                 hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
                     hir::ExprKind::Lit(_lit) => (),
                     hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
-                        if let hir::ExprKind::Lit(lit) = &expr.kind {
-                            if let rustc_ast::ast::LitKind::Int(1, _) = lit.node {
-                                span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                                self.expr_id = Some(expr.hir_id);
-                            }
+                        if is_integer_literal(expr, 1) {
+                            span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
+                            self.expr_id = Some(expr.hir_id);
                         }
                     },
                     _ => {
diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
index 1aefc2741c2..1229c202f5a 100644
--- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
                     expr.span,
                     LINT_MSG,
                     "try",
-                    format!("std::ptr::eq({}, {})", left_snip, right_snip),
+                    format!("std::ptr::eq({left_snip}, {right_snip})"),
                     Applicability::MachineApplicable,
                     );
             }
diff --git a/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs b/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs
index 9d6bec05bf0..7c9d5320a3a 100644
--- a/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, lhs: &'tcx
             cx,
             SELF_ASSIGNMENT,
             e.span,
-            &format!("self-assignment of `{}` to `{}`", rhs, lhs),
+            &format!("self-assignment of `{rhs}` to `{lhs}`"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
index ff85fd55429..fbf65e92b32 100644
--- a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
                 diag.span_suggestion(
                     e.span,
                     "try",
-                    format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()),
+                    format!("{sugg}.trailing_zeros() >= {}", n.count_ones()),
                     Applicability::MaybeIncorrect,
                 );
             },
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index 0315678bf97..4eb42da1fed 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_lang_ctor, peel_blocks,
+    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;
@@ -88,7 +88,7 @@ declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);
 ///     None/_ => {..}
 /// }
 /// ```
-struct OptionOccurence {
+struct OptionOccurrence {
     option: String,
     method_sugg: String,
     some_expr: String,
@@ -109,13 +109,13 @@ fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: boo
     )
 }
 
-fn try_get_option_occurence<'tcx>(
+fn try_get_option_occurrence<'tcx>(
     cx: &LateContext<'tcx>,
     pat: &Pat<'tcx>,
     expr: &Expr<'_>,
     if_then: &'tcx Expr<'_>,
     if_else: &'tcx Expr<'_>,
-) -> Option<OptionOccurence> {
+) -> Option<OptionOccurrence> {
     let cond_expr = match expr.kind {
         ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
         _ => expr,
@@ -160,10 +160,10 @@ fn try_get_option_occurence<'tcx>(
                 }
             }
 
-            return Some(OptionOccurence {
+            return Some(OptionOccurrence {
                 option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                 method_sugg: method_sugg.to_string(),
-                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir_with_macro_callsite(cx, some_body, "..")),
+                some_expr: format!("|{capture_mut}{capture_name}| {}", Sugg::hir_with_macro_callsite(cx, some_body, "..")),
                 none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir_with_macro_callsite(cx, none_body, "..")),
             });
         }
@@ -174,7 +174,8 @@ fn try_get_option_occurence<'tcx>(
 
 fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
     if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
-        if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk) {
+        let res = cx.qpath_res(qpath, pat.hir_id);
+        if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
             return Some(inner_pat);
         }
     }
@@ -182,9 +183,9 @@ fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'
 }
 
 /// If this expression is the option if let/else construct we're detecting, then
-/// this function returns an `OptionOccurence` struct with details if
+/// this function returns an `OptionOccurrence` struct with details if
 /// this construct is found, or None if this construct is not found.
-fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurence> {
+fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurrence> {
     if let Some(higher::IfLet {
         let_pat,
         let_expr,
@@ -193,16 +194,16 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) ->
     }) = higher::IfLet::hir(cx, expr)
     {
         if !is_else_clause(cx.tcx, expr) {
-            return try_get_option_occurence(cx, let_pat, let_expr, if_then, if_else);
+            return try_get_option_occurrence(cx, let_pat, let_expr, if_then, if_else);
         }
     }
     None
 }
 
-fn detect_option_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurence> {
+fn detect_option_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurrence> {
     if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind {
         if let Some((let_pat, if_then, if_else)) = try_convert_match(cx, arms) {
-            return try_get_option_occurence(cx, let_pat, ex, if_then, if_else);
+            return try_get_option_occurrence(cx, let_pat, ex, if_then, if_else);
         }
     }
     None
@@ -226,9 +227,10 @@ fn try_convert_match<'tcx>(
 
 fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
     match arm.pat.kind {
-        PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
+        PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
         PatKind::TupleStruct(ref qpath, [first_pat], _) => {
-            is_lang_ctor(cx, qpath, ResultErr) && matches!(first_pat.kind, PatKind::Wild)
+            is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
+                && matches!(first_pat.kind, PatKind::Wild)
         },
         PatKind::Wild => true,
         _ => false,
diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
index 4aa0d9227ab..efec12489a9 100644
--- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
@@ -2,9 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::return_ty;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::expr_visitor_no_bodies;
+use clippy_utils::visitors::{for_each_expr, Descend};
+use core::ops::ControlFlow;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
@@ -58,18 +59,20 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn {
 
 fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) {
     let mut panics = Vec::new();
-    expr_visitor_no_bodies(|expr| {
-        let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return true };
+    let _: Option<!> = for_each_expr(body.value, |e| {
+        let Some(macro_call) = root_macro_call_first_node(cx, e) else {
+            return ControlFlow::Continue(Descend::Yes);
+        };
         if matches!(
             cx.tcx.item_name(macro_call.def_id).as_str(),
             "unimplemented" | "unreachable" | "panic" | "todo" | "assert" | "assert_eq" | "assert_ne"
         ) {
             panics.push(macro_call.span);
-            return false;
+            ControlFlow::Continue(Descend::No)
+        } else {
+            ControlFlow::Continue(Descend::Yes)
         }
-        true
-    })
-    .visit_expr(body.value);
+    });
     if !panics.is_empty() {
         span_lint_and_then(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
index 000b0ba7a14..6810a243175 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
@@ -1,5 +1,5 @@
 use clippy_utils::{
-    diagnostics::span_lint_and_sugg, is_lang_ctor, peel_hir_expr_refs, peel_ref_operators, sugg,
+    diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res, peel_hir_expr_refs, peel_ref_operators, sugg,
     ty::is_type_diagnostic_item,
 };
 use rustc_errors::Applicability;
@@ -54,8 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialeqToNone {
         // If the expression is a literal `Option::None`
         let is_none_ctor = |expr: &Expr<'_>| {
             !expr.span.from_expansion()
-                && matches!(&peel_hir_expr_refs(expr).0.kind,
-            ExprKind::Path(p) if is_lang_ctor(cx, p, LangItem::OptionNone))
+                && is_res_lang_ctor(cx, path_res(cx, peel_hir_expr_refs(expr).0), LangItem::OptionNone)
         };
 
         let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 6b2eea48932..45e98de10ac 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -209,7 +209,7 @@ impl<'tcx> PassByRefOrValue {
                             cx,
                             TRIVIALLY_COPY_PASS_BY_REF,
                             input.span,
-                            &format!("this argument ({} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", size, self.ref_min_size),
+                            &format!("this argument ({size} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", self.ref_min_size),
                             "consider passing by value instead",
                             value_type,
                             Applicability::Unspecified,
@@ -237,7 +237,7 @@ impl<'tcx> PassByRefOrValue {
                                 cx,
                                 LARGE_TYPES_PASSED_BY_VALUE,
                                 input.span,
-                                &format!("this argument ({} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", size, self.value_max_size),
+                                &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/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 41d1baba64f..d296a150b46 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -463,7 +463,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                                     diag.span_suggestion(
                                         hir_ty.span,
                                         "change this to",
-                                        format!("&{}{}", mutability.prefix_str(), ty_name),
+                                        format!("&{}{ty_name}", mutability.prefix_str()),
                                         Applicability::Unspecified,
                                     );
                                 }
@@ -669,7 +669,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
 }
 
 fn get_rptr_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
-    if let TyKind::Rptr(ref lt, ref m) = ty.kind {
+    if let TyKind::Rptr(lt, ref m) = ty.kind {
         Some((lt, m.mutbl, ty.span))
     } else {
         None
diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
index 4dc65da3ea1..b0a5d1a6758 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast {
             None => return,
         };
 
-        let msg = format!("use of `{}` with a `usize` casted to an `isize`", method);
+        let msg = format!("use of `{method}` with a `usize` casted to an `isize`");
         if let Some(sugg) = build_suggestion(cx, method, receiver_expr, cast_lhs_expr) {
             span_lint_and_sugg(
                 cx,
@@ -124,7 +124,7 @@ fn build_suggestion<'tcx>(
 ) -> Option<String> {
     let receiver = snippet_opt(cx, receiver_expr.span)?;
     let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?;
-    Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs))
+    Some(format!("{receiver}.{}({cast_lhs})", method.suggestion()))
 }
 
 #[derive(Copy, Clone)]
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 569870ab2b7..328371fd602 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -3,11 +3,12 @@ use clippy_utils::higher;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{
-    eq_expr_value, get_parent_node, is_else_clause, is_lang_ctor, path_to_local, path_to_local_id, peel_blocks,
-    peel_blocks_with_stmt,
+    eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, 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::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
 use rustc_lint::{LateContext, LateLintPass};
@@ -58,7 +59,7 @@ enum IfBlockType<'hir> {
     /// Contains: let_pat_qpath (Xxx), let_pat_type, let_pat_sym (a), let_expr (b), if_then (c),
     /// if_else (d)
     IfLet(
-        &'hir QPath<'hir>,
+        Res,
         Ty<'hir>,
         Symbol,
         &'hir Expr<'hir>,
@@ -97,12 +98,12 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
                 !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)
+                    format!("Some({receiver_str}?)")
                 } else {
                     return;
                 }
             } else {
-                format!("{}{}?;", receiver_str, if by_ref { ".as_ref()" } else { "" })
+                format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
             };
 
             span_lint_and_sugg(
@@ -126,7 +127,14 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
         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(path1, caller_ty, ident.name, let_expr, if_then, if_else);
+        let if_block = IfBlockType::IfLet(
+            cx.qpath_res(path1, let_pat.hir_id),
+            caller_ty,
+            ident.name,
+            let_expr,
+            if_then,
+            if_else
+        );
         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();
@@ -135,8 +143,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
             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,
+                "{receiver_str}{}?{}",
                 if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
                 if requires_semi { ";" } else { "" }
             );
@@ -166,21 +173,21 @@ fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_
                     _ => false,
                 }
         },
-        IfBlockType::IfLet(qpath, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
+        IfBlockType::IfLet(res, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
             is_type_diagnostic_item(cx, let_expr_ty, smbl)
                 && match smbl {
                     sym::Option => {
                         // We only need to check `if let Some(x) = option` not `if let None = option`,
                         // because the later one will be suggested as `if option.is_none()` thus causing conflict.
-                        is_lang_ctor(cx, qpath, OptionSome)
+                        is_res_lang_ctor(cx, res, OptionSome)
                             && if_else.is_some()
                             && expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, None)
                     },
                     sym::Result => {
-                        (is_lang_ctor(cx, qpath, ResultOk)
+                        (is_res_lang_ctor(cx, res, ResultOk)
                             && if_else.is_some()
                             && expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, Some(let_pat_sym)))
-                            || is_lang_ctor(cx, qpath, ResultErr)
+                            || is_res_lang_ctor(cx, res, ResultErr)
                                 && expr_return_none_or_err(smbl, cx, if_then, let_expr, Some(let_pat_sym))
                     },
                     _ => false,
@@ -199,7 +206,7 @@ fn expr_return_none_or_err(
     match peel_blocks_with_stmt(expr).kind {
         ExprKind::Ret(Some(ret_expr)) => expr_return_none_or_err(smbl, cx, ret_expr, cond_expr, err_sym),
         ExprKind::Path(ref qpath) => match smbl {
-            sym::Option => is_lang_ctor(cx, qpath, OptionNone),
+            sym::Option => is_res_lang_ctor(cx, cx.qpath_res(qpath, expr.hir_id), OptionNone),
             sym::Result => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
             _ => false,
         },
@@ -224,7 +231,9 @@ fn expr_return_none_or_err(
 
 impl<'tcx> LateLintPass<'tcx> for QuestionMark {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        check_is_none_or_err_and_early_return(cx, expr);
-        check_if_let_some_or_err_and_early_return(cx, expr);
+        if !in_constant(cx, expr.hir_id) {
+            check_is_none_or_err_and_early_return(cx, expr);
+            check_if_let_some_or_err_and_early_return(cx, expr);
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 918d624eec6..c6fbb5e805a 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -243,9 +243,9 @@ fn check_possible_range_contains(
                 cx,
                 MANUAL_RANGE_CONTAINS,
                 span,
-                &format!("manual `{}::contains` implementation", range_type),
+                &format!("manual `{range_type}::contains` implementation"),
                 "use",
-                format!("({}{}{}{}).contains(&{})", lo, space, range_op, hi, name),
+                format!("({lo}{space}{range_op}{hi}).contains(&{name})"),
                 applicability,
             );
         } else if !combine_and && ord == Some(l.ord) {
@@ -273,9 +273,9 @@ fn check_possible_range_contains(
                 cx,
                 MANUAL_RANGE_CONTAINS,
                 span,
-                &format!("manual `!{}::contains` implementation", range_type),
+                &format!("manual `!{range_type}::contains` implementation"),
                 "use",
-                format!("!({}{}{}{}).contains(&{})", lo, space, range_op, hi, name),
+                format!("!({lo}{space}{range_op}{hi}).contains(&{name})"),
                 applicability,
             );
         }
@@ -372,14 +372,14 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
                             diag.span_suggestion(
                                 span,
                                 "use",
-                                format!("({}..={})", start, end),
+                                format!("({start}..={end})"),
                                 Applicability::MaybeIncorrect,
                             );
                         } else {
                             diag.span_suggestion(
                                 span,
                                 "use",
-                                format!("{}..={}", start, end),
+                                format!("{start}..={end}"),
                                 Applicability::MachineApplicable, // snippet
                             );
                         }
@@ -408,7 +408,7 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
                     diag.span_suggestion(
                         expr.span,
                         "use",
-                        format!("{}..{}", start, end),
+                        format!("{start}..{end}"),
                         Applicability::MachineApplicable, // snippet
                     );
                 },
@@ -486,7 +486,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
                                 expr.span,
                                 "consider using the following if you are attempting to iterate over this \
                                  range in reverse",
-                                format!("({}{}{}).rev()", end_snippet, dots, start_snippet),
+                                format!("({end_snippet}{dots}{start_snippet}).rev()"),
                                 Applicability::MaybeIncorrect,
                             );
                         }
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index 94dec191103..fa107858863 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -2,9 +2,10 @@ use clippy_utils::{
     diagnostics::{span_lint, span_lint_and_sugg},
     higher::{get_vec_init_kind, VecInitKind},
     source::snippet,
-    visitors::expr_visitor_no_bodies,
+    visitors::for_each_expr,
 };
-use hir::{intravisit::Visitor, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind};
+use core::ops::ControlFlow;
+use hir::{Expr, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
@@ -58,10 +59,8 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                 && let PatKind::Binding(_, _, ident, _) = pat.kind
                 && let Some(vec_init_kind) = get_vec_init_kind(cx, init)
             {
-                // finds use of `_.read(&mut v)`
-                let mut read_found = false;
-                let mut visitor = expr_visitor_no_bodies(|expr| {
-                    if let ExprKind::MethodCall(path, _self, [arg], _) = expr.kind
+                let visitor = |expr: &Expr<'_>| {
+                    if let ExprKind::MethodCall(path, _, [arg], _) = expr.kind
                         && let PathSegment { ident: read_or_read_exact, .. } = *path
                         && matches!(read_or_read_exact.as_str(), "read" | "read_exact")
                         && let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind
@@ -69,27 +68,22 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                         && let [inner_seg] = inner_path.segments
                         && ident.name == inner_seg.ident.name
                     {
-                        read_found = true;
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(())
                     }
-                    !read_found
-                });
+                };
 
-                let next_stmt_span;
-                if idx == block.stmts.len() - 1 {
+                let (read_found, next_stmt_span) =
+                if let Some(next_stmt) = block.stmts.get(idx + 1) {
+                    // case { .. stmt; stmt; .. }
+                    (for_each_expr(next_stmt, visitor).is_some(), next_stmt.span)
+                } else if let Some(e) = block.expr {
                     // case { .. stmt; expr }
-                    if let Some(e) = block.expr {
-                        visitor.visit_expr(e);
-                        next_stmt_span = e.span;
-                    } else {
-                        return;
-                    }
+                    (for_each_expr(e, visitor).is_some(), e.span)
                 } else {
-                    // case { .. stmt; stmt; .. }
-                    let next_stmt = &block.stmts[idx + 1];
-                    visitor.visit_stmt(next_stmt);
-                    next_stmt_span = next_stmt.span;
-                }
-                drop(visitor);
+                    return
+                };
 
                 if read_found && !next_stmt_span.from_expansion() {
                     let applicability = Applicability::MaybeIncorrect;
@@ -101,9 +95,8 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                                 next_stmt_span,
                                 "reading zero byte data to `Vec`",
                                 "try",
-                                format!("{}.resize({}, 0); {}",
+                                format!("{}.resize({len}, 0); {}",
                                     ident.as_str(),
-                                    len,
                                     snippet(cx, next_stmt_span, "..")
                                 ),
                                 applicability,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index 3c6ca9d9897..464f6827e1d 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
                     cx,
                     REDUNDANT_PUB_CRATE,
                     span,
-                    &format!("pub(crate) {} inside private module", descr),
+                    &format!("pub(crate) {descr} inside private module"),
                     |diag| {
                         diag.span_suggestion(
                             item.vis_span,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 8693ca9af83..245a02ea26e 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -127,9 +127,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
 
                     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, "*".repeat(deref_count), snip)
+                        format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
                     } else {
-                        format!("{}{}{}", reborrow_str, "*".repeat(deref_count), snip)
+                        format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
                     };
 
                     (lint, help_str, sugg)
@@ -141,9 +141,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
                         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!("(&{}{}*{})", mutability.prefix_str(), "*".repeat(indexed_ref_count), snip)
+                                format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
                             } else {
-                                format!("&{}{}*{}", mutability.prefix_str(), "*".repeat(indexed_ref_count), snip)
+                                format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
                             };
                             (DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg)
                         } else {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
index 2d751c27467..60ba62c4a43 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -67,7 +67,7 @@ impl RedundantStaticLifetimes {
                         TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
                             if lifetime.ident.name == rustc_span::symbol::kw::StaticLifetime {
                                 let snip = snippet(cx, borrow_type.ty.span, "<type>");
-                                let sugg = format!("&{}", snip);
+                                let sugg = format!("&{snip}");
                                 span_lint_and_then(
                                     cx,
                                     REDUNDANT_STATIC_LIFETIMES,
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 6bcae0da8f4..1fda58fa54d 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -172,7 +172,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
                     );
                 },
                 Err(e) => {
-                    span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e));
+                    span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
                 },
             }
         }
@@ -200,7 +200,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
                 );
             },
             Err(e) => {
-                span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e));
+                span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
             },
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 91553240e3c..2b2a41d1601 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,9 +1,11 @@
-use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_context};
+use clippy_utils::visitors::{for_each_expr, Descend};
 use clippy_utils::{fn_def_id, path_to_local_id};
+use core::ops::ControlFlow;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -72,6 +74,27 @@ enum RetReplacement {
     Unit,
 }
 
+impl RetReplacement {
+    fn sugg_help(self) -> &'static str {
+        match self {
+            Self::Empty => "remove `return`",
+            Self::Block => "replace `return` with an empty block",
+            Self::Unit => "replace `return` with a unit value",
+        }
+    }
+}
+
+impl ToString for RetReplacement {
+    fn to_string(&self) -> String {
+        match *self {
+            Self::Empty => "",
+            Self::Block => "{}",
+            Self::Unit => "()",
+        }
+        .to_string()
+    }
+}
+
 declare_lint_pass!(Return => [LET_AND_RETURN, NEEDLESS_RETURN]);
 
 impl<'tcx> LateLintPass<'tcx> for Return {
@@ -139,26 +162,35 @@ impl<'tcx> LateLintPass<'tcx> for Return {
                 } else {
                     RetReplacement::Empty
                 };
-                check_final_expr(cx, body.value, Some(body.value.span), replacement);
+                check_final_expr(cx, body.value, vec![], replacement);
             },
             FnKind::ItemFn(..) | FnKind::Method(..) => {
-                if let ExprKind::Block(block, _) = body.value.kind {
-                    check_block_return(cx, block);
-                }
+                check_block_return(cx, &body.value.kind, vec![]);
             },
         }
     }
 }
 
-fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) {
-    if let Some(expr) = block.expr {
-        check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty);
-    } else if let Some(stmt) = block.stmts.iter().last() {
-        match stmt.kind {
-            StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
-                check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty);
-            },
-            _ => (),
+// if `expr` is a block, check if there are needless returns in it
+fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, semi_spans: Vec<Span>) {
+    if let ExprKind::Block(block, _) = expr_kind {
+        if let Some(block_expr) = block.expr {
+            check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
+        } else if let Some(stmt) = block.stmts.iter().last() {
+            match stmt.kind {
+                StmtKind::Expr(expr) => {
+                    check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
+                },
+                StmtKind::Semi(semi_expr) => {
+                    let mut semi_spans_and_this_one = semi_spans;
+                    // we only want the span containing the semicolon so we can remove it later. From `entry.rs:382`
+                    if let Some(semicolon_span) = stmt.span.trim_start(semi_expr.span) {
+                        semi_spans_and_this_one.push(semicolon_span);
+                        check_final_expr(cx, semi_expr, semi_spans_and_this_one, RetReplacement::Empty);
+                    }
+                },
+                _ => (),
+            }
         }
     }
 }
@@ -166,10 +198,12 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) {
 fn check_final_expr<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'tcx>,
-    span: Option<Span>,
+    semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
+                            * needless return */
     replacement: RetReplacement,
 ) {
-    match expr.kind {
+    let peeled_drop_expr = expr.peel_drop_temps();
+    match &peeled_drop_expr.kind {
         // simple return is always "bad"
         ExprKind::Ret(ref inner) => {
             if cx.tcx.hir().attrs(expr.hir_id).is_empty() {
@@ -177,24 +211,18 @@ fn check_final_expr<'tcx>(
                 if !borrows {
                     emit_return_lint(
                         cx,
-                        inner.map_or(expr.hir_id, |inner| inner.hir_id),
-                        span.expect("`else return` is not possible"),
+                        peeled_drop_expr.span,
+                        semi_spans,
                         inner.as_ref().map(|i| i.span),
                         replacement,
                     );
                 }
             }
         },
-        // a whole block? check it!
-        ExprKind::Block(block, _) => {
-            check_block_return(cx, block);
-        },
         ExprKind::If(_, then, else_clause_opt) => {
-            if let ExprKind::Block(ifblock, _) = then.kind {
-                check_block_return(cx, ifblock);
-            }
+            check_block_return(cx, &then.kind, semi_spans.clone());
             if let Some(else_clause) = else_clause_opt {
-                check_final_expr(cx, else_clause, None, RetReplacement::Empty);
+                check_block_return(cx, &else_clause.kind, semi_spans);
             }
         },
         // a match expr, check all arms
@@ -203,123 +231,61 @@ fn check_final_expr<'tcx>(
         // (except for unit type functions) so we don't match it
         ExprKind::Match(_, arms, MatchSource::Normal) => {
             for arm in arms.iter() {
-                check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Unit);
+                check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit);
             }
         },
-        ExprKind::DropTemps(expr) => check_final_expr(cx, expr, None, RetReplacement::Empty),
-        _ => (),
+        // if it's a whole block, check it
+        other_expr_kind => check_block_return(cx, other_expr_kind, semi_spans),
     }
 }
 
 fn emit_return_lint(
     cx: &LateContext<'_>,
-    emission_place: HirId,
     ret_span: Span,
+    semi_spans: Vec<Span>,
     inner_span: Option<Span>,
     replacement: RetReplacement,
 ) {
     if ret_span.from_expansion() {
         return;
     }
-    match inner_span {
-        Some(inner_span) => {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_hir_and_then(
-                cx,
-                NEEDLESS_RETURN,
-                emission_place,
-                ret_span,
-                "unneeded `return` statement",
-                |diag| {
-                    let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
-                    diag.span_suggestion(ret_span, "remove `return`", snippet, applicability);
-                },
-            );
-        },
-        None => match replacement {
-            RetReplacement::Empty => {
-                span_lint_hir_and_then(
-                    cx,
-                    NEEDLESS_RETURN,
-                    emission_place,
-                    ret_span,
-                    "unneeded `return` statement",
-                    |diag| {
-                        diag.span_suggestion(
-                            ret_span,
-                            "remove `return`",
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                );
-            },
-            RetReplacement::Block => {
-                span_lint_hir_and_then(
-                    cx,
-                    NEEDLESS_RETURN,
-                    emission_place,
-                    ret_span,
-                    "unneeded `return` statement",
-                    |diag| {
-                        diag.span_suggestion(
-                            ret_span,
-                            "replace `return` with an empty block",
-                            "{}".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                );
-            },
-            RetReplacement::Unit => {
-                span_lint_hir_and_then(
-                    cx,
-                    NEEDLESS_RETURN,
-                    emission_place,
-                    ret_span,
-                    "unneeded `return` statement",
-                    |diag| {
-                        diag.span_suggestion(
-                            ret_span,
-                            "replace `return` with a unit value",
-                            "()".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    },
-                );
-            },
+    let mut applicability = Applicability::MachineApplicable;
+    let return_replacement = inner_span.map_or_else(
+        || replacement.to_string(),
+        |inner_span| {
+            let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
+            snippet.to_string()
         },
-    }
+    );
+    let sugg_help = if inner_span.is_some() {
+        "remove `return`"
+    } else {
+        replacement.sugg_help()
+    };
+    span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| {
+        diag.span_suggestion_hidden(ret_span, sugg_help, return_replacement, applicability);
+        // for each parent statement, we need to remove the semicolon
+        for semi_stmt_span in semi_spans {
+            diag.tool_only_span_suggestion(semi_stmt_span, "remove this semicolon", "", applicability);
+        }
+    });
 }
 
 fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
-    let mut visitor = BorrowVisitor { cx, borrows: false };
-    walk_expr(&mut visitor, expr);
-    visitor.borrows
-}
-
-struct BorrowVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    borrows: bool,
-}
-
-impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if self.borrows || expr.span.from_expansion() {
-            return;
-        }
-
-        if let Some(def_id) = fn_def_id(self.cx, expr) {
-            self.borrows = self
-                .cx
+    for_each_expr(expr, |e| {
+        if let Some(def_id) = fn_def_id(cx, e)
+            && cx
                 .tcx
                 .fn_sig(def_id)
-                .output()
                 .skip_binder()
+                .output()
                 .walk()
-                .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
+                .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+        {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(Descend::from(!expr.span.from_expansion()))
         }
-
-        walk_expr(self, expr);
-    }
+    })
+    .is_some()
 }
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 20184d54b76..4249063d2d4 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
                                     |diag| {
                                         diag.span_note(
                                             trait_method_span,
-                                            &format!("existing `{}` defined here", method_name),
+                                            &format!("existing `{method_name}` defined here"),
                                         );
                                     },
                                 );
@@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
                                         // iterate on trait_spans?
                                         diag.span_note(
                                             trait_spans[0],
-                                            &format!("existing `{}` defined here", method_name),
+                                            &format!("existing `{method_name}` defined here"),
                                         );
                                     },
                                 );
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
index 729694da46d..66638eed998 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
                 }
 
                 let sugg = sugg::Sugg::hir_with_macro_callsite(cx, expr, "..");
-                let suggestion = format!("{0};", sugg);
+                let suggestion = format!("{sugg};");
                 span_lint_and_sugg(
                     cx,
                     SEMICOLON_IF_NOTHING_RETURNED,
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index c07aa00a127..76039923151 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -1,9 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{get_enclosing_block, is_expr_path_def_path, path_to_local, path_to_local_id, paths, SpanlessEq};
+use clippy_utils::{
+    get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local, path_to_local_id, SpanlessEq,
+};
 use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
 use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind};
@@ -174,7 +175,7 @@ impl SlowVectorInit {
             diag.span_suggestion(
                 vec_alloc.allocation_expr.span,
                 "consider replace allocation with",
-                format!("vec![0; {}]", len_expr),
+                format!("vec![0; {len_expr}]"),
                 Applicability::Unspecified,
             );
         });
@@ -219,8 +220,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
             && path_to_local_id(self_arg, self.vec_alloc.local_id)
             && path.ident.name == sym!(resize)
             // Check that is filled with 0
-            && let ExprKind::Lit(ref lit) = fill_arg.kind
-            && let LitKind::Int(0, _) = lit.node {
+            && is_integer_literal(fill_arg, 0) {
                 // Check that len expression is equals to `with_capacity` expression
                 if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) {
                     self.slow_expression = Some(InitializationType::Resize(expr));
@@ -254,10 +254,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool {
         if_chain! {
             if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind;
-            if is_expr_path_def_path(self.cx, fn_expr, &paths::ITER_REPEAT);
-            if let ExprKind::Lit(ref lit) = repeat_arg.kind;
-            if let LitKind::Int(0, _) = lit.node;
-
+            if is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat);
+            if is_integer_literal(repeat_arg, 0);
             then {
                 true
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index ffd63cc687a..d6b336bef94 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -1,6 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_hir::def_id::DefId;
 use rustc_hir::{def::Res, HirId, Path, PathSegment};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::DefIdTree;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, symbol::kw, Span};
 
@@ -94,6 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
     fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
         if let Res::Def(_, def_id) = path.res
             && let Some(first_segment) = get_first_segment(path)
+            && is_stable(cx, def_id)
         {
             let (lint, msg, help) = match first_segment.ident.name {
                 sym::std => match cx.tcx.crate_name(def_id.krate) {
@@ -146,3 +149,22 @@ fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>>
         _ => None,
     }
 }
+
+/// Checks if all ancestors of `def_id` are stable, to avoid linting
+/// [unstable moves](https://github.com/rust-lang/rust/pull/95956)
+fn is_stable(cx: &LateContext<'_>, mut def_id: DefId) -> bool {
+    loop {
+        if cx
+            .tcx
+            .lookup_stability(def_id)
+            .map_or(false, |stability| stability.is_unstable())
+        {
+            return false;
+        }
+
+        match cx.tcx.opt_parent(def_id) {
+            Some(parent) => def_id = parent,
+            None => return true,
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 662d399ca53..d356c99c8fc 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -284,7 +284,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
                     e.span,
                     "calling a slice of `as_bytes()` with `from_utf8` should be not necessary",
                     "try",
-                    format!("Some(&{}[{}])", snippet_app, snippet(cx, right.span, "..")),
+                    format!("Some(&{snippet_app}[{}])", snippet(cx, right.span, "..")),
                     applicability
                 )
             }
@@ -500,8 +500,8 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace {
                     cx,
                     TRIM_SPLIT_WHITESPACE,
                     trim_span.with_hi(split_ws_span.lo()),
-                    &format!("found call to `str::{}` before `str::split_whitespace`", trim_fn_name),
-                    &format!("remove `{}()`", trim_fn_name),
+                    &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"),
+                    &format!("remove `{trim_fn_name}()`"),
                     String::new(),
                     Applicability::MachineApplicable,
                 );
diff --git a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
index 78403d9fdb7..03324c66e8e 100644
--- a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
@@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings {
                     span,
                     "using `libc::strlen` on a `CString` or `CStr` value",
                     "try this",
-                    format!("{}.{}().len()", val_name, method_name),
+                    format!("{val_name}.{method_name}().len()"),
                     app,
                 );
             }
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index 5d36f0f5ff8..eef9bdc7849 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -326,8 +326,7 @@ fn replace_left_sugg(
     applicability: &mut Applicability,
 ) -> String {
     format!(
-        "{} {} {}",
-        left_suggestion,
+        "{left_suggestion} {} {}",
         binop.op.to_string(),
         snippet_with_applicability(cx, binop.right.span, "..", applicability),
     )
@@ -340,10 +339,9 @@ fn replace_right_sugg(
     applicability: &mut Applicability,
 ) -> String {
     format!(
-        "{} {} {}",
+        "{} {} {right_suggestion}",
         snippet_with_applicability(cx, binop.left.span, "..", applicability),
         binop.op.to_string(),
-        right_suggestion,
     )
 }
 
@@ -676,9 +674,8 @@ fn suggestion_with_swapped_ident(
         }
 
         Some(format!(
-            "{}{}{}",
+            "{}{new_ident}{}",
             snippet_with_applicability(cx, expr.span.with_hi(current_ident.span.lo()), "..", applicability),
-            new_ident,
             snippet_with_applicability(cx, expr.span.with_lo(current_ident.span.hi()), "..", applicability),
         ))
     })
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index d47ed459387..b57b484bdc8 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -1,8 +1,9 @@
 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_hir::intravisit::{walk_expr, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -92,25 +93,17 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
 }
 
 fn count_binops(expr: &hir::Expr<'_>) -> u32 {
-    let mut visitor = BinaryExprVisitor::default();
-    visitor.visit_expr(expr);
-    visitor.nb_binops
-}
-
-#[derive(Default)]
-struct BinaryExprVisitor {
-    nb_binops: u32,
-}
-
-impl<'tcx> Visitor<'tcx> for BinaryExprVisitor {
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        match expr.kind {
+    let mut count = 0u32;
+    let _: Option<!> = for_each_expr(expr, |e| {
+        if matches!(
+            e.kind,
             hir::ExprKind::Binary(..)
-            | hir::ExprKind::Unary(hir::UnOp::Not | hir::UnOp::Neg, _)
-            | hir::ExprKind::AssignOp(..) => self.nb_binops += 1,
-            _ => {},
+                | hir::ExprKind::Unary(hir::UnOp::Not | hir::UnOp::Neg, _)
+                | hir::ExprKind::AssignOp(..)
+        ) {
+            count += 1;
         }
-
-        walk_expr(self, expr);
-    }
+        ControlFlow::Continue(())
+    });
+    count
 }
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 1885f3ca414..f46c21e1265 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -96,7 +96,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
                             cx,
                             MANUAL_SWAP,
                             span,
-                            &format!("this looks like you are swapping elements of `{}` manually", slice),
+                            &format!("this looks like you are swapping elements of `{slice}` manually"),
                             "try",
                             format!(
                                 "{}.swap({}, {})",
@@ -121,16 +121,16 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
         cx,
         MANUAL_SWAP,
         span,
-        &format!("this looks like you are swapping `{}` and `{}` manually", first, second),
+        &format!("this looks like you are swapping `{first}` and `{second}` manually"),
         |diag| {
             diag.span_suggestion(
                 span,
                 "try",
-                format!("{}::mem::swap({}, {})", sugg, first.mut_addr(), second.mut_addr()),
+                format!("{sugg}::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
                 applicability,
             );
             if !is_xor_based {
-                diag.note(&format!("or maybe you should use `{}::mem::replace`?", sugg));
+                diag.note(&format!("or maybe you should use `{sugg}::mem::replace`?"));
             }
         },
     );
@@ -182,7 +182,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
                 let rhs0 = Sugg::hir_opt(cx, rhs0);
                 let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) {
                     (
-                        format!(" `{}` and `{}`", first, second),
+                        format!(" `{first}` and `{second}`"),
                         first.mut_addr().to_string(),
                         second.mut_addr().to_string(),
                     )
@@ -196,22 +196,19 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
                 span_lint_and_then(cx,
                     ALMOST_SWAPPED,
                     span,
-                    &format!("this looks like you are trying to swap{}", what),
+                    &format!("this looks like you are trying to swap{what}"),
                     |diag| {
                         if !what.is_empty() {
                             diag.span_suggestion(
                                 span,
                                 "try",
                                 format!(
-                                    "{}::mem::swap({}, {})",
-                                    sugg,
-                                    lhs,
-                                    rhs,
+                                    "{sugg}::mem::swap({lhs}, {rhs})",
                                 ),
                                 Applicability::MaybeIncorrect,
                             );
                             diag.note(
-                                &format!("or maybe you should use `{}::mem::replace`?", sugg)
+                                &format!("or maybe you should use `{sugg}::mem::replace`?")
                             );
                         }
                     });
diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
index 3cbbda80f3a..d085dda3582 100644
--- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
@@ -58,7 +58,7 @@ impl LateLintPass<'_> for SwapPtrToRef {
                         let mut app = Applicability::MachineApplicable;
                         let snip1 = snippet_with_context(cx, arg1_span.unwrap_or(arg1.span), ctxt, "..", &mut app).0;
                         let snip2 = snippet_with_context(cx, arg2_span.unwrap_or(arg2.span), ctxt, "..", &mut app).0;
-                        diag.span_suggestion(e.span, "use ptr::swap", format!("core::ptr::swap({}, {})", snip1, snip2), app);
+                        diag.span_suggestion(e.span, "use ptr::swap", format!("core::ptr::swap({snip1}, {snip2})"), app);
                     }
                 }
             );
diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
index 651201f34ed..2512500a6be 100644
--- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
@@ -84,9 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
                         "use of `.to_digit(..).is_some()`",
                         "try this",
                         if is_method_call {
-                            format!("{}.is_digit({})", char_arg_snip, radix_snip)
+                            format!("{char_arg_snip}.is_digit({radix_snip})")
                         } else {
-                            format!("char::is_digit({}, {})", char_arg_snip, radix_snip)
+                            format!("char::is_digit({char_arg_snip}, {radix_snip})")
                         },
                         applicability,
                     );
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index 2be22884027..b5f11b4acae 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -215,9 +215,8 @@ impl TraitBounds {
                         .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability))
                         .join(" + ");
                     let hint_string = format!(
-                        "consider combining the bounds: `{}: {}`",
+                        "consider combining the bounds: `{}: {trait_bounds}`",
                         snippet(cx, p.bounded_ty.span, "_"),
-                        trait_bounds,
                     );
                     span_lint_and_help(
                         cx,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
index 25d0543c861..c4b9d82fc73 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
@@ -13,10 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                 cx,
                 CROSSPOINTER_TRANSMUTE,
                 e.span,
-                &format!(
-                    "transmute from a type (`{}`) to the type that it points to (`{}`)",
-                    from_ty, to_ty
-                ),
+                &format!("transmute from a type (`{from_ty}`) to the type that it points to (`{to_ty}`)"),
             );
             true
         },
@@ -25,10 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                 cx,
                 CROSSPOINTER_TRANSMUTE,
                 e.span,
-                &format!(
-                    "transmute from a type (`{}`) to a pointer to that type (`{}`)",
-                    from_ty, to_ty
-                ),
+                &format!("transmute from a type (`{from_ty}`) to a pointer to that type (`{to_ty}`)"),
             );
             true
         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index 1bde977cfa2..5ecba512b0f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_FLOAT_TO_INT,
                 e.span,
-                &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 |diag| {
                     let mut sugg = sugg::Sugg::hir(cx, arg, "..");
 
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(
                         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();
+                            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/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
index 8c50b58ca4b..58227c53de2 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_INT_TO_BOOL,
                 e.span,
-                &format!("transmute from a `{}` to a `bool`", from_ty),
+                &format!("transmute from a `{from_ty}` to a `bool`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let zero = sugg::Sugg::NonParen(Cow::from("0"));
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
index 9e1823c373b..7d31c375f8c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_INT_TO_CHAR,
                 e.span,
-                &format!("transmute from a `{}` to a `char`", from_ty),
+                &format!("transmute from a `{from_ty}` to a `char`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let arg = if let ty::Int(_) = from_ty.kind() {
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
                     diag.span_suggestion(
                         e.span,
                         "consider using",
-                        format!("std::char::from_u32({}).unwrap()", arg),
+                        format!("std::char::from_u32({arg}).unwrap()"),
                         Applicability::Unspecified,
                     );
                 },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
index b8703052e6c..cc3422edbbf 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_INT_TO_FLOAT,
                 e.span,
-                &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let arg = if let ty::Int(int_ty) = from_ty.kind() {
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
                     diag.span_suggestion(
                         e.span,
                         "consider using",
-                        format!("{}::from_bits({})", to_ty, arg),
+                        format!("{to_ty}::from_bits({arg})"),
                         Applicability::Unspecified,
                     );
                 },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 52d193d11e1..009d5a7c8ae 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -31,13 +31,13 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_NUM_TO_BYTES,
                 e.span,
-                &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     diag.span_suggestion(
                         e.span,
                         "consider using `to_ne_bytes()`",
-                        format!("{}.to_ne_bytes()", arg),
+                        format!("{arg}.to_ne_bytes()"),
                         Applicability::Unspecified,
                     );
                 },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index 5eb03275b8e..12d0b866e1c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -25,10 +25,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_PTR_TO_REF,
                 e.span,
-                &format!(
-                    "transmute from a pointer type (`{}`) to a reference type (`{}`)",
-                    from_ty, to_ty
-                ),
+                &format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let (deref, cast) = if *mutbl == Mutability::Mut {
@@ -41,26 +38,25 @@ pub(super) fn check<'tcx>(
                     let sugg = if let Some(ty) = get_explicit_type(path) {
                         let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app);
                         if meets_msrv(msrv, msrvs::POINTER_CAST) {
-                            format!("{}{}.cast::<{}>()", deref, arg.maybe_par(), ty_snip)
+                            format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par())
                         } else if from_ptr_ty.has_erased_regions() {
-                            sugg::make_unop(deref, arg.as_ty(format!("{} () as {} {}", cast, cast, ty_snip)))
-                                .to_string()
+                            sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string()
                         } else {
-                            sugg::make_unop(deref, arg.as_ty(format!("{} {}", cast, ty_snip))).to_string()
+                            sugg::make_unop(deref, arg.as_ty(format!("{cast} {ty_snip}"))).to_string()
                         }
                     } else if from_ptr_ty.ty == *to_ref_ty {
                         if from_ptr_ty.has_erased_regions() {
                             if meets_msrv(msrv, msrvs::POINTER_CAST) {
-                                format!("{}{}.cast::<{}>()", deref, arg.maybe_par(), to_ref_ty)
+                                format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par())
                             } else {
-                                sugg::make_unop(deref, arg.as_ty(format!("{} () as {} {}", cast, cast, to_ref_ty)))
+                                sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}")))
                                     .to_string()
                             }
                         } else {
                             sugg::make_unop(deref, arg).to_string()
                         }
                     } else {
-                        sugg::make_unop(deref, arg.as_ty(format!("{} {}", cast, to_ref_ty))).to_string()
+                        sugg::make_unop(deref, arg.as_ty(format!("{cast} {to_ref_ty}"))).to_string()
                     };
 
                     diag.span_suggestion(e.span, "try", sugg, app);
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index 707a11d361c..afb7f2e1326 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_BYTES_TO_STR,
                     e.span,
-                    &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+                    &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                     "consider using",
                     if const_context {
                         format!("std::str::from_utf8_unchecked{postfix}({snippet})")
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index ae55a6bf558..1c99a02e6c7 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -75,10 +75,10 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
+                    &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if from_ty_orig.peel_refs() != from_ty.peel_refs() {
-                            diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+                            diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
                         }
                     },
                 );
@@ -89,10 +89,10 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute to `{}` which has an undefined layout", to_ty_orig),
+                    &format!("transmute to `{to_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if to_ty_orig.peel_refs() != to_ty.peel_refs() {
-                            diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+                            diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
                         }
                     },
                 );
@@ -116,8 +116,7 @@ pub(super) fn check<'tcx>(
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
                     &format!(
-                        "transmute from `{}` to `{}`, both of which have an undefined layout",
-                        from_ty_orig, to_ty_orig
+                        "transmute from `{from_ty_orig}` to `{to_ty_orig}`, both of which have an undefined layout"
                     ),
                     |diag| {
                         if let Some(same_adt_did) = same_adt_did {
@@ -127,10 +126,10 @@ pub(super) fn check<'tcx>(
                             ));
                         } else {
                             if from_ty_orig.peel_refs() != from_ty {
-                                diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+                                diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
                             }
                             if to_ty_orig.peel_refs() != to_ty {
-                                diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+                                diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
                             }
                         }
                     },
@@ -145,10 +144,10 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
+                    &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if from_ty_orig.peel_refs() != from_ty {
-                            diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+                            diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
                         }
                     },
                 );
@@ -162,10 +161,10 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute into `{}` which has an undefined layout", to_ty_orig),
+                    &format!("transmute into `{to_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if to_ty_orig.peel_refs() != to_ty {
-                            diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+                            diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
                         }
                     },
                 );
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 626d7cd46fc..6b444922a7c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -21,10 +21,7 @@ pub(super) fn check<'tcx>(
             cx,
             TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
             e.span,
-            &format!(
-                "transmute from `{}` to `{}` which could be expressed as a pointer cast instead",
-                from_ty, to_ty
-            ),
+            &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
             |diag| {
                 if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
                     let sugg = arg.as_ty(&to_ty.to_string()).to_string();
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index d8e349af7af..19ce5ae72c2 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,8 +1,6 @@
 use clippy_utils::consts::{constant_context, Constant};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_path_diagnostic_item;
-use if_chain::if_chain;
-use rustc_ast::LitKind;
+use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
@@ -19,37 +17,28 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
 
     // Catching transmute over constants that resolve to `null`.
     let mut const_eval_context = constant_context(cx, cx.typeck_results());
-    if_chain! {
-        if let ExprKind::Path(ref _qpath) = arg.kind;
-        if let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg);
-        if x == 0;
-        then {
-            span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
-            return true;
-        }
+    if let ExprKind::Path(ref _qpath) = arg.kind &&
+        let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg) &&
+        x == 0
+    {
+        span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
+        return true;
     }
 
     // Catching:
     // `std::mem::transmute(0 as *const i32)`
-    if_chain! {
-        if let ExprKind::Cast(inner_expr, _cast_ty) = arg.kind;
-        if let ExprKind::Lit(ref lit) = inner_expr.kind;
-        if let LitKind::Int(0, _) = lit.node;
-        then {
-            span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
-            return true;
-        }
+    if let ExprKind::Cast(inner_expr, _cast_ty) = arg.kind && is_integer_literal(inner_expr, 0) {
+        span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
+        return true;
     }
 
     // Catching:
     // `std::mem::transmute(std::ptr::null::<i32>())`
-    if_chain! {
-        if let ExprKind::Call(func1, []) = arg.kind;
-        if is_path_diagnostic_item(cx, func1, sym::ptr_null);
-        then {
-            span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
-            return true;
-        }
+    if let ExprKind::Call(func1, []) = arg.kind &&
+        is_path_diagnostic_item(cx, func1, sym::ptr_null)
+    {
+        span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
+        return true;
     }
 
     // FIXME:
diff --git a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
index 831b0d450d2..b1445311b71 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
@@ -37,10 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                     cx,
                     UNSOUND_COLLECTION_TRANSMUTE,
                     e.span,
-                    &format!(
-                        "transmute from `{}` to `{}` with mismatched layout is unsound",
-                        from_ty, to_ty
-                    ),
+                    &format!("transmute from `{from_ty}` to `{to_ty}` with mismatched layout is unsound"),
                 );
                 true
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index 8122cd716e0..f919bbd5afc 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 USELESS_TRANSMUTE,
                 e.span,
-                &format!("transmute from a type (`{}`) to itself", from_ty),
+                &format!("transmute from a type (`{from_ty}`) to itself"),
             );
             true
         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index fdf847bf445..b567d92230b 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -1,8 +1,11 @@
 use rustc_hir::Expr;
+use rustc_hir_analysis::check::{
+    cast::{self, CastCheckResult},
+    FnCtxt, Inherited,
+};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{cast::CastKind, Ty};
 use rustc_span::DUMMY_SP;
-use rustc_hir_analysis::check::{cast::{self, CastCheckResult}, FnCtxt, Inherited};
 
 // check if the component types of the transmuted collection and the result have different ABI,
 // size or alignment
diff --git a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
index 2118f3d6950..d1965565b92 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
@@ -13,7 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                 cx,
                 WRONG_TRANSMUTE,
                 e.span,
-                &format!("transmute from a `{}` to a pointer", from_ty),
+                &format!("transmute from a `{from_ty}` to a pointer"),
             );
             true
         },
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 1268c23206a..9c662995840 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -49,15 +49,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
                     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)
+                            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)
                         },
-                        _ => format!("&{}{}", ltopt, &inner_snippet),
+                        _ => format!("&{ltopt}{}", &inner_snippet),
                     };
                     span_lint_and_sugg(
                         cx,
diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
index ba51404d214..08020ce6638 100644
--- a/src/tools/clippy/clippy_lints/src/types/box_collection.rs
+++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
                 _ => "<..>",
             };
 
-            let box_content = format!("{outer}{generic}", outer = item_type);
+            let box_content = format!("{item_type}{generic}");
             span_lint_and_help(
                 cx,
                 BOX_COLLECTION,
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index aca55817c52..79c31efb9fc 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -352,8 +352,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
         match item.kind {
             ImplItemKind::Const(ty, _) => {
-                let is_in_trait_impl = if let Some(hir::Node::Item(item)) =
-                    cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id)
+                let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx
+                    .tcx
+                    .hir()
+                    .find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id)
                 {
                     matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
                 } else {
@@ -535,7 +537,7 @@ impl Types {
                     QPath::LangItem(..) => {},
                 }
             },
-            TyKind::Rptr(ref lt, ref mut_ty) => {
+            TyKind::Rptr(lt, ref mut_ty) => {
                 context.is_nested_call = true;
                 if !borrowed_box::check(cx, hir_ty, lt, mut_ty) {
                     self.check_ty(cx, mut_ty.ty, context);
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
index 4d72a29e8c7..6b9de64e24c 100644
--- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
+++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
                 hir_ty.span,
                 "usage of `Rc<T>` when T is a buffer type",
                 "try",
-                format!("Rc<{}>", alternate),
+                format!("Rc<{alternate}>"),
                 Applicability::MachineApplicable,
             );
         } else {
@@ -57,7 +57,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
                 hir_ty.span,
                 "usage of `Arc<T>` when T is a buffer type",
                 "try",
-                format!("Arc<{}>", alternate),
+                format!("Arc<{alternate}>"),
                 Applicability::MachineApplicable,
             );
         } else if let Some(ty) = qpath_generic_tys(qpath).next() {
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index d81c5c83845..ecb67200539 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -3,9 +3,9 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::{path_def_id, qpath_generic_tys};
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 use super::{utils, REDUNDANT_ALLOCATION};
 
@@ -27,13 +27,11 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
             cx,
             REDUNDANT_ALLOCATION,
             hir_ty.span,
-            &format!("usage of `{}<{}>`", outer_sym, generic_snippet),
+            &format!("usage of `{outer_sym}<{generic_snippet}>`"),
             |diag| {
-                diag.span_suggestion(hir_ty.span, "try", format!("{}", generic_snippet), applicability);
+                diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability);
                 diag.note(&format!(
-                    "`{generic}` is already a pointer, `{outer}<{generic}>` allocates a pointer on the heap",
-                    outer = outer_sym,
-                    generic = generic_snippet
+                    "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap"
                 ));
             },
         );
@@ -72,19 +70,16 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
             cx,
             REDUNDANT_ALLOCATION,
             hir_ty.span,
-            &format!("usage of `{}<{}<{}>>`", outer_sym, inner_sym, generic_snippet),
+            &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
             |diag| {
                 diag.span_suggestion(
                     hir_ty.span,
                     "try",
-                    format!("{}<{}>", outer_sym, generic_snippet),
+                    format!("{outer_sym}<{generic_snippet}>"),
                     applicability,
                 );
                 diag.note(&format!(
-                    "`{inner}<{generic}>` is already on the heap, `{outer}<{inner}<{generic}>>` makes an extra allocation",
-                    outer = outer_sym,
-                    inner = inner_sym,
-                    generic = generic_snippet
+                    "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
                 ));
             },
         );
@@ -94,19 +89,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
             cx,
             REDUNDANT_ALLOCATION,
             hir_ty.span,
-            &format!("usage of `{}<{}<{}>>`", outer_sym, inner_sym, generic_snippet),
+            &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
             |diag| {
                 diag.note(&format!(
-                    "`{inner}<{generic}>` is already on the heap, `{outer}<{inner}<{generic}>>` makes an extra allocation",
-                    outer = outer_sym,
-                    inner = inner_sym,
-                    generic = generic_snippet
+                    "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
                 ));
                 diag.help(&format!(
-                    "consider using just `{outer}<{generic}>` or `{inner}<{generic}>`",
-                    outer = outer_sym,
-                    inner = inner_sym,
-                    generic = generic_snippet
+                    "consider using just `{outer_sym}<{generic_snippet}>` or `{inner_sym}<{generic_snippet}>`"
                 ));
             },
         );
diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
index 236f9955722..6c329d8cdf1 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -4,11 +4,11 @@ use clippy_utils::source::snippet;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::TypeVisitable;
 use rustc_span::symbol::sym;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 use super::VEC_BOX;
 
diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
index 3f99bd3f315..1ab0162a881 100644
--- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
 use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty};
-use clippy_utils::{is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
+use clippy_utils::{is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
 use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
@@ -211,9 +211,12 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
         }
     });
     match expr.kind {
-        ExprKind::MethodCall(path, self_expr, [_], _) => {
+        ExprKind::MethodCall(path, self_expr, [arg], _) => {
             let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
-            if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" {
+            if is_type_diagnostic_item(cx, self_type, sym::Vec)
+                && path.ident.name.as_str() == "set_len"
+                && !is_integer_literal(arg, 0)
+            {
                 Some((self_expr, expr.span))
             } else {
                 None
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index c0a4f3fbacd..57aff5367dd 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -157,8 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
                                 span,
                                 &format!(
                                     "this closure returns \
-                                   the unit type which also implements {}",
-                                    trait_name
+                                   the unit type which also implements {trait_name}"
                                 ),
                             );
                         },
@@ -169,8 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
                                 span,
                                 &format!(
                                     "this closure returns \
-                                   the unit type which also implements {}",
-                                    trait_name
+                                   the unit type which also implements {trait_name}"
                                 ),
                                 Some(last_semi),
                                 "probably caused by this trailing semicolon",
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
index a6f777abc6e..f6d3fb00f4e 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
@@ -74,7 +74,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
         cx,
         UNIT_ARG,
         expr.span,
-        &format!("passing {}unit value{} to a function", singular, plural),
+        &format!("passing {singular}unit value{plural} to a function"),
         |db| {
             let mut or = "";
             args_to_recover
@@ -129,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
 
                 if arg_snippets_without_empty_blocks.is_empty() {
                     db.multipart_suggestion(
-                        &format!("use {}unit literal{} instead", singular, plural),
+                        &format!("use {singular}unit literal{plural} instead"),
                         args_to_recover
                             .iter()
                             .map(|arg| (arg.span, "()".to_string()))
@@ -143,8 +143,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
                     db.span_suggestion(
                         expr.span,
                         &format!(
-                            "{}move the expression{} in front of the call and replace {} with the unit literal `()`",
-                            or, empty_or_s, it_or_them
+                            "{or}move the expression{empty_or_s} in front of the call and replace {it_or_them} with the unit literal `()`"
                         ),
                         sugg,
                         applicability,
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
index 1dd8895ebd0..226495dcbda 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 cx,
                 UNIT_CMP,
                 macro_call.span,
-                &format!("`{}` of unit values detected. This will always {}", macro_name, result),
+                &format!("`{macro_name}` of unit values detected. This will always {result}"),
             );
         }
         return;
@@ -40,9 +40,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 UNIT_CMP,
                 expr.span,
                 &format!(
-                    "{}-comparison of unit values detected. This will always be {}",
-                    op.as_str(),
-                    result
+                    "{}-comparison of unit values detected. This will always be {result}",
+                    op.as_str()
                 ),
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 8a4f4c0ad97..016aacbf9da 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -3,7 +3,7 @@ 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, Mutability};
+use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
                         );
                 } else {
                     if_chain! {
-                        if match_def_path(cx, fun_def_id, &paths::FROM_FROM);
+                        if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(fun_def_id);
                         if let [.., last_arg] = args;
                         if let ExprKind::Lit(spanned) = &last_arg.kind;
                         if let LitKind::Str(symbol, _) = spanned.node;
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
index 839a4bdab09..bc0dd263d88 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
@@ -57,7 +57,7 @@ impl EarlyLintPass for UnnecessarySelfImports {
                             format!(
                                 "{}{};",
                                 last_segment.ident,
-                                if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {}", alias) } else { String::new() },
+                                if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {alias}") } else { String::new() },
                             ),
                             Applicability::MaybeIncorrect,
                         );
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 2c40827db0e..7211e6864f3 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{contains_return, is_lang_ctor, return_ty, visitors::find_all_ret_expressions};
+use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty, visitors::find_all_ret_expressions};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
@@ -120,9 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
                 if !ret_expr.span.from_expansion();
                 // Check if a function call.
                 if let ExprKind::Call(func, [arg]) = ret_expr.kind;
-                // Check if OPTION_SOME or RESULT_OK, depending on return type.
-                if let ExprKind::Path(qpath) = &func.kind;
-                if is_lang_ctor(cx, qpath, lang_item);
+                if 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 {
@@ -153,11 +151,8 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
                 )
             } else {
                 (
-                    format!(
-                        "this function's return value is unnecessarily wrapped by `{}`",
-                        return_type_label
-                    ),
-                    format!("remove `{}` from the return type...", return_type_label),
+                    format!("this function's return value is unnecessarily wrapped by `{return_type_label}`"),
+                    format!("remove `{return_type_label}` from the return type..."),
                     inner_type.to_string(),
                     "...and then change returning expressions",
                 )
diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
index 64f7a055cd9..32cd4681201 100644
--- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
@@ -65,10 +65,7 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>,
             cx,
             UNSAFE_REMOVED_FROM_NAME,
             span,
-            &format!(
-                "removed `unsafe` from the name of `{}` in use as `{}`",
-                old_str, new_str
-            ),
+            &format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"),
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index b38d71784fc..8bcdff66331 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -1,8 +1,9 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::{is_try, match_trait_method, paths};
+use clippy_utils::{is_trait_method, is_try, match_trait_method, paths};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -116,13 +117,13 @@ fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Exp
             match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
                 || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT)
         } else {
-            match_trait_method(cx, call, &paths::IO_READ)
+            is_trait_method(cx, call, sym::IoRead)
         };
         let write_trait = if is_await {
             match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT)
                 || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT)
         } else {
-            match_trait_method(cx, call, &paths::IO_WRITE)
+            is_trait_method(cx, call, sym::IoWrite)
         };
 
         match (read_trait, write_trait, symbol, is_await) {
diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
index b8a5d4ea8c9..3164937293b 100644
--- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
@@ -58,8 +58,8 @@ impl EarlyLintPass for UnusedRounding {
                 cx,
                 UNUSED_ROUNDING,
                 expr.span,
-                &format!("used the `{}` method with a whole number float", method_name),
-                &format!("remove the `{}` method call", method_name),
+                &format!("used the `{method_name}` method with a whole number float"),
+                &format!("remove the `{method_name}` method call"),
                 float,
                 Applicability::MachineApplicable,
             );
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 3ef26558079..ea878043c04 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -257,9 +257,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
                             expr.hir_id,
                             expr.span,
                             &format!(
-                                "called `{}` on `{}` after checking its variant with `{}`",
+                                "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`",
                                 method_name.ident.name,
-                                unwrappable_variable_name,
                                 unwrappable.check_name.ident.as_str(),
                             ),
                             |diag| {
@@ -268,9 +267,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
                                         unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()),
                                         "try",
                                         format!(
-                                            "if let {} = {}",
-                                            suggested_pattern,
-                                            unwrappable_variable_name,
+                                            "if let {suggested_pattern} = {unwrappable_variable_name}",
                                         ),
                                         // We don't track how the unwrapped value is used inside the
                                         // block or suggest deleting the unwrap, so we can't offer a
diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
index baa53ba664f..a69719b127b 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 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::intravisit::{self, Visitor};
-use rustc_hir::{Expr, ImplItemKind};
+use rustc_hir::ImplItemKind;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 
@@ -73,51 +73,37 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult {
     }
 }
 
-struct FindExpectUnwrap<'a, 'tcx> {
-    lcx: &'a LateContext<'tcx>,
-    typeck_results: &'tcx ty::TypeckResults<'tcx>,
-    result: Vec<Span>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        // check for `expect`
-        if let Some(arglists) = method_chain_args(expr, &["expect"]) {
-            let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
-            if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
-                || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
-            {
-                self.result.push(expr.span);
+fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
+    if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
+        let body = cx.tcx.hir().body(body_id);
+        let typeck = cx.tcx.typeck(impl_item.def_id.def_id);
+        let mut result = Vec::new();
+        let _: Option<!> = for_each_expr(body.value, |e| {
+            // check for `expect`
+            if let Some(arglists) = method_chain_args(e, &["expect"]) {
+                let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs();
+                if is_type_diagnostic_item(cx, receiver_ty, sym::Option)
+                    || is_type_diagnostic_item(cx, receiver_ty, sym::Result)
+                {
+                    result.push(e.span);
+                }
             }
-        }
 
-        // check for `unwrap`
-        if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
-            let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
-            if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
-                || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
-            {
-                self.result.push(expr.span);
+            // check for `unwrap`
+            if let Some(arglists) = method_chain_args(e, &["unwrap"]) {
+                let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs();
+                if is_type_diagnostic_item(cx, receiver_ty, sym::Option)
+                    || is_type_diagnostic_item(cx, receiver_ty, sym::Result)
+                {
+                    result.push(e.span);
+                }
             }
-        }
 
-        // and check sub-expressions
-        intravisit::walk_expr(self, expr);
-    }
-}
-
-fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
-    if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
-        let body = cx.tcx.hir().body(body_id);
-        let mut fpu = FindExpectUnwrap {
-            lcx: cx,
-            typeck_results: cx.tcx.typeck(impl_item.def_id.def_id),
-            result: Vec::new(),
-        };
-        fpu.visit_expr(body.value);
+            ControlFlow::Continue(())
+        });
 
         // if we've found one, lint
-        if !fpu.result.is_empty() {
+        if !result.is_empty() {
             span_lint_and_then(
                 cx,
                 UNWRAP_IN_RESULT,
@@ -125,7 +111,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tc
                 "used unwrap or expect in a function that returns result or option",
                 move |diag| {
                     diag.help("unwrap and expect should not be used in a function that returns result or option");
-                    diag.span_note(fpu.result, "potential non-recoverable error(s)");
+                    diag.span_note(result, "potential non-recoverable error(s)");
                 },
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 2c71f35d490..654ea306793 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -93,7 +93,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) {
             cx,
             UPPER_CASE_ACRONYMS,
             span,
-            &format!("name `{}` contains a capitalized acronym", ident),
+            &format!("name `{ident}` contains a capitalized acronym"),
             "consider making the acronym lowercase, except the initial letter",
             corrected,
             Applicability::MaybeIncorrect,
@@ -114,6 +114,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
                 check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
             },
             ItemKind::Enum(ref enumdef, _) => {
+                check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
                 // check enum variants separately because again we only want to lint on private enums and
                 // the fn check_variant does not know about the vis of the enum of its variants
                 enumdef
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 2c4f5075e98..65f1b546208 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -12,11 +12,11 @@ use rustc_hir::{
     Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath,
     TyKind,
 };
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index f1b6463ad0f..a82643a59f9 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -5,7 +5,7 @@ use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
+use rustc_hir::{Expr, ExprKind, HirId, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{}`", b),
+                            &format!("useless conversion to the same type: `{b}`"),
                             "consider removing `.into()`",
                             sugg,
                             Applicability::MachineApplicable, // snippet
@@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{}`", b),
+                            &format!("useless conversion to the same type: `{b}`"),
                             "consider removing `.into_iter()`",
                             sugg,
                             Applicability::MachineApplicable, // snippet
@@ -118,7 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{}`", b),
+                            &format!("useless conversion to the same type: `{b}`"),
                             None,
                             "consider removing `.try_into()`",
                         );
@@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                                     cx,
                                     USELESS_CONVERSION,
                                     e.span,
-                                    &format!("useless conversion to the same type: `{}`", b),
+                                    &format!("useless conversion to the same type: `{b}`"),
                                     None,
                                     &hint,
                                 );
@@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         }
 
                         if_chain! {
-                            if match_def_path(cx, def_id, &paths::FROM_FROM);
+                            if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(def_id);
                             if same_type_and_consts(a, b);
 
                             then {
@@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                                     cx,
                                     USELESS_CONVERSION,
                                     e.span,
-                                    &format!("useless conversion to the same type: `{}`", b),
+                                    &format!("useless conversion to the same type: `{b}`"),
                                     &sugg_msg,
                                     sugg.to_string(),
                                     Applicability::MachineApplicable, // snippet
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 1df3135c962..e069de8cb5c 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -739,7 +739,7 @@ fn path_to_string(path: &QPath<'_>) -> String {
                     *s += ", ";
                     write!(s, "{:?}", segment.ident.as_str()).unwrap();
                 },
-                other => write!(s, "/* unimplemented: {:?}*/", other).unwrap(),
+                other => write!(s, "/* unimplemented: {other:?}*/").unwrap(),
             },
             QPath::LangItem(..) => panic!("path_to_string: called for lang item qpath"),
         }
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 2be3fa99c81..668123e4d6e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -39,28 +39,28 @@ pub struct Rename {
     pub rename: String,
 }
 
-/// A single disallowed method, used by the `DISALLOWED_METHODS` lint.
 #[derive(Clone, Debug, Deserialize)]
 #[serde(untagged)]
-pub enum DisallowedMethod {
+pub enum DisallowedPath {
     Simple(String),
     WithReason { path: String, reason: Option<String> },
 }
 
-impl DisallowedMethod {
+impl DisallowedPath {
     pub fn path(&self) -> &str {
         let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
 
         path
     }
-}
 
-/// A single disallowed type, used by the `DISALLOWED_TYPES` lint.
-#[derive(Clone, Debug, Deserialize)]
-#[serde(untagged)]
-pub enum DisallowedType {
-    Simple(String),
-    WithReason { path: String, reason: Option<String> },
+    pub fn reason(&self) -> Option<&str> {
+        match self {
+            Self::WithReason {
+                reason: Some(reason), ..
+            } => Some(reason),
+            _ => None,
+        }
+    }
 }
 
 /// Conf with parse errors
@@ -213,7 +213,7 @@ define_Conf! {
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP.
     ///
     /// The minimum rust version that the project supports
     (msrv: Option<String> = None),
@@ -315,14 +315,18 @@ define_Conf! {
     ///
     /// Whether to allow certain wildcard imports (prelude, super in tests).
     (warn_on_all_wildcard_imports: bool = false),
+    /// Lint: DISALLOWED_MACROS.
+    ///
+    /// The list of disallowed macros, written as fully qualified paths.
+    (disallowed_macros: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
     /// Lint: DISALLOWED_METHODS.
     ///
     /// The list of disallowed methods, written as fully qualified paths.
-    (disallowed_methods: Vec<crate::utils::conf::DisallowedMethod> = Vec::new()),
+    (disallowed_methods: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
     /// Lint: DISALLOWED_TYPES.
     ///
     /// The list of disallowed types, written as fully qualified paths.
-    (disallowed_types: Vec<crate::utils::conf::DisallowedType> = Vec::new()),
+    (disallowed_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
     /// Lint: UNREADABLE_LITERAL.
     ///
     /// Should the fraction of a decimal be linted to include separators.
@@ -362,7 +366,7 @@ define_Conf! {
     /// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
     (max_suggested_slice_pattern_length: u64 = 3),
     /// Lint: AWAIT_HOLDING_INVALID_TYPE
-    (await_holding_invalid_types: Vec<crate::utils::conf::DisallowedType> = Vec::new()),
+    (await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
     /// Lint: LARGE_INCLUDE_FILE.
     ///
     /// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
@@ -482,16 +486,13 @@ pub fn format_error(error: Box<dyn Error>) -> String {
                     let field = fields.get(index).copied().unwrap_or_default();
                     write!(
                         msg,
-                        "{:separator_width$}{:field_width$}",
-                        " ",
-                        field,
-                        separator_width = SEPARATOR_WIDTH,
-                        field_width = column_width
+                        "{:SEPARATOR_WIDTH$}{field:column_width$}",
+                        " "
                     )
                     .unwrap();
                 }
             }
-            write!(msg, "\n{}", suffix).unwrap();
+            write!(msg, "\n{suffix}").unwrap();
             msg
         } else {
             s
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 78c036186f5..85bcbc7ad23 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -2,11 +2,11 @@ use crate::utils::internal_lints::metadata_collector::is_deprecated_lint;
 use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::macros::root_macro_call_first_node;
-use clippy_utils::source::snippet;
+use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::match_type;
 use clippy_utils::{
-    def_path_res, higher, is_else_clause, is_expn_of, is_expr_path_def_path, is_lint_allowed, match_def_path,
-    method_calls, paths, peel_blocks_with_stmt, SpanlessEq,
+    def_path_res, higher, is_else_clause, is_expn_of, is_expr_path_def_path, is_lint_allowed, match_any_def_paths,
+    match_def_path, method_calls, paths, peel_blocks_with_stmt, peel_hir_expr_refs, SpanlessEq,
 };
 use if_chain::if_chain;
 use rustc_ast as ast;
@@ -15,26 +15,29 @@ use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{DefKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{
-    BinOpKind, Block, Closure, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty,
+    BinOpKind, Block, Closure, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind,
     TyKind, UnOp,
 };
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::mir::interpret::ConstValue;
-use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, subst::GenericArgKind, FloatTy};
+use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc};
+use rustc_middle::ty::{
+    self, fast_reject::SimplifiedTypeGen, subst::GenericArgKind, AssocKind, DefIdTree, FloatTy, Ty,
+};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{sym, BytePos, Span};
-use rustc_hir_analysis::hir_ty_to_ty;
 
 use std::borrow::{Borrow, Cow};
+use std::str;
 
 #[cfg(feature = "internal")]
 pub mod metadata_collector;
@@ -226,11 +229,11 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for calls to `utils::match_type()` on a type diagnostic item
-    /// and suggests to use `utils::is_type_diagnostic_item()` instead.
+    /// Checks for usages of def paths when a diagnostic item or a `LangItem` could be used.
     ///
     /// ### Why is this bad?
-    /// `utils::is_type_diagnostic_item()` does not require hardcoded paths.
+    /// The path for an item is subject to change and is less efficient to look up than a
+    /// diagnostic item or a `LangItem`.
     ///
     /// ### Example
     /// ```rust,ignore
@@ -241,9 +244,9 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// utils::is_type_diagnostic_item(cx, ty, sym::Vec)
     /// ```
-    pub MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
+    pub UNNECESSARY_DEF_PATH,
     internal,
-    "using `utils::match_type()` instead of `utils::is_type_diagnostic_item()`"
+    "using a def path when a diagnostic item or a `LangItem` is available"
 }
 
 declare_clippy_lint! {
@@ -530,14 +533,14 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                     cx,
                     LINT_WITHOUT_LINT_PASS,
                     lint_span,
-                    &format!("the lint `{}` is not added to any `LintPass`", lint_name),
+                    &format!("the lint `{lint_name}` is not added to any `LintPass`"),
                 );
             }
         }
     }
 }
 
-fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &Ty<'_>) -> bool {
+fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &hir::Ty<'_>) -> bool {
     if let TyKind::Rptr(
         _,
         MutTy {
@@ -666,7 +669,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
                     path.ident.span,
                     "usage of a compiler lint function",
                     None,
-                    &format!("please use the Clippy variant of this function: `{}`", sugg),
+                    &format!("please use the Clippy variant of this function: `{sugg}`"),
                 );
             }
         }
@@ -854,13 +857,8 @@ fn suggest_help(
         "this call is collapsible",
         "collapse into",
         format!(
-            "span_lint_and_help({}, {}, {}, {}, {}, {})",
-            and_then_snippets.cx,
-            and_then_snippets.lint,
-            and_then_snippets.span,
-            and_then_snippets.msg,
-            &option_span,
-            help
+            "span_lint_and_help({}, {}, {}, {}, {}, {help})",
+            and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span,
         ),
         Applicability::MachineApplicable,
     );
@@ -886,107 +884,238 @@ fn suggest_note(
         "this call is collapsible",
         "collapse into",
         format!(
-            "span_lint_and_note({}, {}, {}, {}, {}, {})",
-            and_then_snippets.cx,
-            and_then_snippets.lint,
-            and_then_snippets.span,
-            and_then_snippets.msg,
-            note_span,
-            note
+            "span_lint_and_note({}, {}, {}, {}, {note_span}, {note})",
+            and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg,
         ),
         Applicability::MachineApplicable,
     );
 }
 
-declare_lint_pass!(MatchTypeOnDiagItem => [MATCH_TYPE_ON_DIAGNOSTIC_ITEM]);
+declare_lint_pass!(UnnecessaryDefPath => [UNNECESSARY_DEF_PATH]);
 
-impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem {
+#[allow(clippy::too_many_lines)]
+impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if is_lint_allowed(cx, MATCH_TYPE_ON_DIAGNOSTIC_ITEM, expr.hir_id) {
+        enum Item {
+            LangItem(Symbol),
+            DiagnosticItem(Symbol),
+        }
+        static PATHS: &[&[&str]] = &[
+            &["clippy_utils", "match_def_path"],
+            &["clippy_utils", "match_trait_method"],
+            &["clippy_utils", "ty", "match_type"],
+            &["clippy_utils", "is_expr_path_def_path"],
+        ];
+
+        if is_lint_allowed(cx, UNNECESSARY_DEF_PATH, expr.hir_id) {
             return;
         }
 
         if_chain! {
-            // Check if this is a call to utils::match_type()
-            if let ExprKind::Call(fn_path, [context, ty, ty_path]) = expr.kind;
-            if is_expr_path_def_path(cx, fn_path, &["clippy_utils", "ty", "match_type"]);
+            if let ExprKind::Call(func, [cx_arg, def_arg, args@..]) = expr.kind;
+            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] };
             // Extract the path to the matched type
-            if let Some(segments) = path_to_matched_type(cx, ty_path);
-            let segments: Vec<&str> = segments.iter().map(Symbol::as_str).collect();
-            if let Some(ty_did) = def_path_res(cx, &segments[..]).opt_def_id();
-            // Check if the matched type is a diagnostic item
-            if let Some(item_name) = cx.tcx.get_diagnostic_name(ty_did);
+            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_res(cx, &segments[..], None).opt_def_id();
             then {
-                // TODO: check paths constants from external crates.
-                let cx_snippet = snippet(cx, context.span, "_");
-                let ty_snippet = snippet(cx, ty.span, "_");
+                // def_path_res will match field names before anything else, but for this we want to match
+                // inherent functions first.
+                let def_id = if cx.tcx.def_kind(def_id) == DefKind::Field {
+                    let method_name = *segments.last().unwrap();
+                    cx.tcx.def_key(def_id).parent
+                        .and_then(|parent_idx|
+                            cx.tcx.inherent_impls(DefId { index: parent_idx, krate: def_id.krate }).iter()
+                                .find_map(|impl_id| cx.tcx.associated_items(*impl_id)
+                                    .find_by_name_and_kind(
+                                        cx.tcx,
+                                        Ident::from_str(method_name),
+                                        AssocKind::Fn,
+                                        *impl_id,
+                                    )
+                                )
+                        )
+                        .map_or(def_id, |item| item.def_id)
+                } else {
+                    def_id
+                };
 
-                span_lint_and_sugg(
+                // Check if the target item is a diagnostic item or LangItem.
+                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(lang_item) = cx.tcx.lang_items().items().iter().position(|id| *id == Some(def_id)) {
+                    let lang_items = def_path_res(cx, &["rustc_hir", "lang_items", "LangItem"], Some(Namespace::TypeNS)).def_id();
+                    let item_name = cx.tcx.adt_def(lang_items).variants().iter().nth(lang_item).unwrap().name;
+                    (
+                        "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_def_id.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_def_id.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().require(LangItem::{item}).ok() == 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().require(LangItem::{item}).ok() == Some(id))",
+                        ),
+                        false,
+                    ),
+                    _ => return,
+                };
+
+                span_lint_and_then(
                     cx,
-                    MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
+                    UNNECESSARY_DEF_PATH,
                     expr.span,
-                    "usage of `clippy_utils::ty::match_type()` on a type diagnostic item",
-                    "try",
-                    format!("clippy_utils::ty::is_type_diagnostic_item({}, {}, sym::{})", cx_snippet, ty_snippet, item_name),
-                    Applicability::MaybeIncorrect,
+                    msg,
+                    |diag| {
+                        diag.span_suggestion(expr.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"
+                            );
+                        }
+                    },
                 );
             }
         }
     }
 }
 
-fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Vec<Symbol>> {
-    use rustc_hir::ItemKind;
-
-    match &expr.kind {
-        ExprKind::AddrOf(.., expr) => return path_to_matched_type(cx, expr),
-        ExprKind::Path(qpath) => match cx.qpath_res(qpath, expr.hir_id) {
+fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Vec<String>> {
+    match peel_hir_expr_refs(expr).0.kind {
+        ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
             Res::Local(hir_id) => {
                 let parent_id = cx.tcx.hir().get_parent_node(hir_id);
-                if let Some(Node::Local(local)) = cx.tcx.hir().find(parent_id) {
-                    if let Some(init) = local.init {
-                        return path_to_matched_type(cx, init);
-                    }
+                if let Some(Node::Local(Local { init: Some(init), .. })) = cx.tcx.hir().find(parent_id) {
+                    path_to_matched_type(cx, init)
+                } else {
+                    None
                 }
             },
-            Res::Def(DefKind::Const | DefKind::Static(..), def_id) => {
-                if let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(def_id) {
-                    if let ItemKind::Const(.., body_id) | ItemKind::Static(.., body_id) = item.kind {
-                        let body = cx.tcx.hir().body(body_id);
-                        return path_to_matched_type(cx, body.value);
-                    }
-                }
+            Res::Def(DefKind::Static(_), def_id) => read_mir_alloc_def_path(
+                cx,
+                cx.tcx.eval_static_initializer(def_id).ok()?.inner(),
+                cx.tcx.type_of(def_id),
+            ),
+            Res::Def(DefKind::Const, def_id) => match cx.tcx.const_eval_poly(def_id).ok()? {
+                ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => {
+                    read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id))
+                },
+                _ => None,
             },
-            _ => {},
+            _ => None,
         },
-        ExprKind::Array(exprs) => {
-            let segments: Vec<Symbol> = exprs
-                .iter()
-                .filter_map(|expr| {
-                    if let ExprKind::Lit(lit) = &expr.kind {
-                        if let LitKind::Str(sym, _) = lit.node {
-                            return Some(sym);
-                        }
+        ExprKind::Array(exprs) => exprs
+            .iter()
+            .map(|expr| {
+                if let ExprKind::Lit(lit) = &expr.kind {
+                    if let LitKind::Str(sym, _) = lit.node {
+                        return Some((*sym.as_str()).to_owned());
                     }
+                }
 
-                    None
-                })
-                .collect();
-
-            if segments.len() == exprs.len() {
-                return Some(segments);
-            }
-        },
-        _ => {},
+                None
+            })
+            .collect(),
+        _ => None,
     }
+}
+
+fn read_mir_alloc_def_path<'tcx>(cx: &LateContext<'tcx>, alloc: &'tcx Allocation, ty: Ty<'_>) -> Option<Vec<String>> {
+    let (alloc, ty) = if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() {
+        let &alloc = alloc.provenance().values().next()?;
+        if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
+            (alloc.inner(), ty)
+        } else {
+            return None;
+        }
+    } else {
+        (alloc, ty)
+    };
 
-    None
+    if let ty::Array(ty, _) | ty::Slice(ty) = *ty.kind()
+        && let ty::Ref(_, ty, Mutability::Not) = *ty.kind()
+        && ty.is_str()
+    {
+        alloc
+            .provenance()
+            .values()
+            .map(|&alloc| {
+                if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
+                    let alloc = alloc.inner();
+                    str::from_utf8(alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()))
+                        .ok().map(ToOwned::to_owned)
+                } else {
+                    None
+                }
+            })
+            .collect()
+    } else {
+        None
+    }
 }
 
 // This is not a complete resolver for paths. It works on all the paths currently used in the paths
 // module.  That's all it does and all it needs to do.
 pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
-    if def_path_res(cx, path) != Res::Err {
+    if def_path_res(cx, path, None) != Res::Err {
         return true;
     }
 
@@ -1077,7 +1206,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
         }
 
         for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
-            if let Some(def_id) = def_path_res(cx, module).opt_def_id() {
+            if let Some(def_id) = def_path_res(cx, module, None).opt_def_id() {
                 for item in cx.tcx.module_children(def_id).iter() {
                     if_chain! {
                         if let Res::Def(DefKind::Const, item_def_id) = item.res;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 342f627e382..c84191bb010 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -64,46 +64,6 @@ const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[
 /// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed
 /// to only keep the actual lint group in the output.
 const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::";
-
-/// This template will be used to format the configuration section in the lint documentation.
-/// The `configurations` parameter will be replaced with one or multiple formatted
-/// `ClippyConfiguration` instances. See `CONFIGURATION_VALUE_TEMPLATE` for further customizations
-macro_rules! CONFIGURATION_SECTION_TEMPLATE {
-    () => {
-        r#"
-### Configuration
-This lint has the following configuration variables:
-
-{configurations}
-"#
-    };
-}
-/// This template will be used to format an individual `ClippyConfiguration` instance in the
-/// lint documentation.
-///
-/// The format function will provide strings for the following parameters: `name`, `ty`, `doc` and
-/// `default`
-macro_rules! CONFIGURATION_VALUE_TEMPLATE {
-    () => {
-        "* `{name}`: `{ty}`: {doc} (defaults to `{default}`)\n"
-    };
-}
-
-macro_rules! RENAMES_SECTION_TEMPLATE {
-    () => {
-        r#"
-### Past names
-
-{names}
-"#
-    };
-}
-macro_rules! RENAME_VALUE_TEMPLATE {
-    () => {
-        "* `{name}`\n"
-    };
-}
-
 const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
     &["clippy_utils", "diagnostics", "span_lint"],
     &["clippy_utils", "diagnostics", "span_lint_and_help"],
@@ -205,7 +165,16 @@ impl MetadataCollector {
             .filter(|config| config.lints.iter().any(|lint| lint == lint_name))
             .map(ToString::to_string)
             .reduce(|acc, x| acc + &x)
-            .map(|configurations| format!(CONFIGURATION_SECTION_TEMPLATE!(), configurations = configurations))
+            .map(|configurations| {
+                format!(
+                    r#"
+### Configuration
+This lint has the following configuration variables:
+
+{configurations}
+"#
+                )
+            })
     }
 }
 
@@ -291,16 +260,13 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
                             continue;
                         }
 
-                        panic!("lint `{}` has an unterminated code block", lint_name)
+                        panic!("lint `{lint_name}` has an unterminated code block")
                     }
 
                     break;
                 },
                 Some(line) if line.trim_start() == "{{produces}}" => {
-                    panic!(
-                        "lint `{}` has marker {{{{produces}}}} with an ignored or missing code block",
-                        lint_name
-                    )
+                    panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block")
                 },
                 Some(line) => {
                     let line = line.trim();
@@ -319,7 +285,7 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
             match lines.next() {
                 Some(line) if line.trim_start() == "```" => break,
                 Some(line) => example.push(line),
-                None => panic!("lint `{}` has an unterminated code block", lint_name),
+                None => panic!("lint `{lint_name}` has an unterminated code block"),
             }
         }
 
@@ -336,10 +302,9 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
                             <summary>Produces</summary>\n\
                             \n\
                             ```text\n\
-                            {}\n\
+                            {output}\n\
                             ```\n\
-                        </details>",
-                            output
+                        </details>"
                         ),
                     );
 
@@ -394,7 +359,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
         panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy());
     }
 
-    let prefixed_name = format!("{}{lint_name}", CLIPPY_LINT_GROUP_PREFIX);
+    let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}");
 
     let mut cmd = Command::new("cargo");
 
@@ -417,7 +382,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
     let output = cmd
         .arg(file.as_path())
         .output()
-        .unwrap_or_else(|e| panic!("failed to run `{:?}`: {e}", cmd));
+        .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
 
     let tmp_file_path = file.to_string_lossy();
     let stderr = std::str::from_utf8(&output.stderr).unwrap();
@@ -441,8 +406,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
         let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
         let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
         panic!(
-            "did not find lint `{}` in output of example, got:\n{}\n{}",
-            lint_name,
+            "did not find lint `{lint_name}` in output of example, got:\n{}\n{}",
             non_json.join("\n"),
             rendered.join("\n")
         );
@@ -588,13 +552,10 @@ fn to_kebab(config_name: &str) -> String {
 
 impl fmt::Display for ClippyConfiguration {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
-        write!(
+        writeln!(
             f,
-            CONFIGURATION_VALUE_TEMPLATE!(),
-            name = self.name,
-            ty = self.config_type,
-            doc = self.doc,
-            default = self.default
+            "* `{}`: `{}`: {} (defaults to `{}`)",
+            self.name, self.config_type, self.doc, self.default
         )
     }
 }
@@ -811,7 +772,7 @@ fn get_lint_group_and_level_or_lint(
                 lint_collection_error_item(
                     cx,
                     item,
-                    &format!("Unable to determine lint level for found group `{}`", group),
+                    &format!("Unable to determine lint level for found group `{group}`"),
                 );
                 None
             }
@@ -869,7 +830,7 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
                         if name == lint_name;
                         if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
                         then {
-                            write!(collected, RENAME_VALUE_TEMPLATE!(), name = past_name).unwrap();
+                            writeln!(collected, "* `{past_name}`").unwrap();
                             names.push(past_name.to_string());
                         }
                     }
@@ -882,7 +843,15 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
         }
 
         if !collected.is_empty() {
-            write!(&mut lint.docs, RENAMES_SECTION_TEMPLATE!(), names = collected).unwrap();
+            write!(
+                &mut lint.docs,
+                r#"
+### Past names
+
+{collected}
+"#
+            )
+            .unwrap();
         }
     }
 }
@@ -895,7 +864,7 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s
         cx,
         INTERNAL_METADATA_COLLECTOR,
         item.ident.span,
-        &format!("metadata collection error for `{}`: {}", item.ident.name, message),
+        &format!("metadata collection error for `{}`: {message}", item.ident.name),
     );
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 2604b1ee7c5..301eed9a1fb 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -173,7 +173,7 @@ impl LateLintPass<'_> for WildcardImports {
                 let sugg = if braced_glob {
                     imports_string
                 } else {
-                    format!("{}::{}", import_source_snippet, imports_string)
+                    format!("{import_source_snippet}::{imports_string}")
                 };
 
                 let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res {
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 06e7d701701..36574198f91 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn, MacroCall};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, HirIdMap, Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{sym, BytePos};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -475,11 +475,11 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, name: &
                 value.span,
                 "literal with an empty format string",
                 |diag| {
-                    if let Some(replacement) = replacement {
+                    if let Some(replacement) = replacement
                         // `format!("{}", "a")`, `format!("{named}", named = "b")
                         //              ~~~~~                      ~~~~~~~~~~~~~
-                        let value_span = expand_past_previous_comma(cx, value.span);
-
+                        && let Some(value_span) = format_args.value_with_prev_comma_span(value.hir_id)
+                    {
                         let replacement = replacement.replace('{', "{{").replace('}', "}}");
                         diag.multipart_suggestion(
                             "try this",
@@ -542,10 +542,3 @@ fn conservative_unescape(literal: &str) -> Result<String, UnescapeErr> {
 
     if err { Err(UnescapeErr::Lint) } else { Ok(unescaped) }
 }
-
-// Expand from `writeln!(o, "")` to `writeln!(o, "")`
-//                          ^^                 ^^^^
-fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
-    let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true);
-    extended.with_lo(extended.lo() - BytePos(1))
-}
diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
index 50d3c079fe6..9b3de35dbd3 100644
--- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
@@ -57,8 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
                     "constant division of `0.0` with `0.0` will always result in NaN",
                     None,
                     &format!(
-                        "consider using `{}::NAN` if you would like a constant representing NaN",
-                        float_type,
+                        "consider using `{float_type}::NAN` if you would like a constant representing NaN",
                     ),
                 );
             }
diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
index 703ba2ef4b0..6cf2a955fd5 100644
--- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
@@ -2,12 +2,12 @@ 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};
 use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::{Adt, Ty, TypeVisitable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_hir_analysis::hir_ty_to_ty;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -69,10 +69,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
 
 fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(hir_id);
-    let second_parent_id = cx
-        .tcx
-        .hir()
-        .get_parent_item(parent_id.into()).def_id;
+    let second_parent_id = cx.tcx.hir().get_parent_item(parent_id.into()).def_id;
     if let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(second_parent_id) {
         if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
             return true;