about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs8
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/ci/docker/host-x86_64/arm-android/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/arm-android/android-sdk.lock6
-rw-r--r--src/ci/docker/host-x86_64/dist-android/Dockerfile2
-rwxr-xr-xsrc/ci/docker/scripts/android-start-emulator.sh2
-rwxr-xr-xsrc/ci/github-actions/calculate-job-matrix.py10
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/html/static/js/search.js2
-rw-r--r--src/tools/clippy/.cargo/config.toml2
-rw-r--r--src/tools/clippy/.github/workflows/lintcheck.yml28
-rw-r--r--src/tools/clippy/CHANGELOG.md47
-rw-r--r--src/tools/clippy/Cargo.toml9
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md14
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md3
-rw-r--r--src/tools/clippy/clippy.toml1
-rw-r--r--src/tools/clippy/clippy_config/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs29
-rw-r--r--src/tools/clippy/clippy_config/src/types.rs14
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs8
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/absolute_paths.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/almost_complete_range.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/assigning_clones.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/mod.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs111
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs141
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_if.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/collection_is_never_read.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_methods.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_names.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_types.rs91
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/double_parens.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/else_if_without_else.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_enum.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/endian_bytes.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/equatable_if_let.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/error_impl_error.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs103
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/exit.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_mutex.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/if_not_else.rs63
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/incompatible_msrv.rs5
-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.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/large_futures.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/large_include_file.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_frames.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs463
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_bits.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_hash_one.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs109
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs133
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/min_ident_chars.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mut.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs142
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_for_each.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/non_expressive_names.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/option_env_unwrap.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_unimplemented.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs193
-rw-r--r--src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/raw_strings.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_field_names.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_block.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/serde_api.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/single_call_fn.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/string_patterns.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/types/type_complexity.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs187
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_peekable.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs28
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs29
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs29
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/lintcheck/Cargo.toml2
-rw-r--r--src/tools/clippy/lintcheck/ci_crates.toml208
-rw-r--r--src/tools/clippy/lintcheck/lintcheck_crates.toml74
-rw-r--r--src/tools/clippy/lintcheck/src/config.rs8
-rw-r--r--src/tools/clippy/lintcheck/src/driver.rs1
-rw-r--r--src/tools/clippy/lintcheck/src/input.rs128
-rw-r--r--src/tools/clippy/lintcheck/src/json.rs216
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs63
-rw-r--r--src/tools/clippy/lintcheck/src/output.rs33
-rw-r--r--src/tools/clippy/lintcheck/src/recursive.rs10
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/compile-test.rs14
-rw-r--r--src/tools/clippy/tests/dogfood.rs47
-rw-r--r--src/tools/clippy/tests/integration.rs6
-rw-r--r--src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr10
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed24
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr44
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_bool.stderr149
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_float.stderr129
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.fixed129
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.rs129
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.stderr523
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3717.fixed11
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3717.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3717.stderr2
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.fixed2
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.rs2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed295
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr16
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed13
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs13
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.stderr44
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.fixed4
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.rs4
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.stderr8
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.fixed8
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.rs8
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.stderr32
-rw-r--r--src/tools/clippy/tests/ui/from_str_radix_10.fixed4
-rw-r--r--src/tools/clippy/tests/ui/from_str_radix_10.rs4
-rw-r--r--src/tools/clippy/tests/ui/from_str_radix_10.stderr16
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.fixed177
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs2
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr20
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed29
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr2
-rw-r--r--src/tools/clippy/tests/ui/let_unit.fixed196
-rw-r--r--src/tools/clippy/tests/ui/let_unit.rs2
-rw-r--r--src/tools/clippy/tests/ui/let_unit.stderr8
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed76
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.stderr20
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.fixed76
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.stderr20
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.fixed115
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.stderr26
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.fixed144
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.stderr38
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.fixed16
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.rs16
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.fixed258
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs3
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr30
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.stderr8
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed2
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.fixed18
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.rs18
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed47
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs47
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr50
-rw-r--r--src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed3
-rw-r--r--src/tools/clippy/tests/ui/path_buf_push_overwrite.rs3
-rw-r--r--src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr2
-rw-r--r--src/tools/clippy/tests/ui/pathbuf_init_then_push.fixed22
-rw-r--r--src/tools/clippy/tests/ui/pathbuf_init_then_push.rs26
-rw-r--r--src/tools/clippy/tests/ui/pathbuf_init_then_push.stderr33
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.fixed4
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.rs4
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.stderr4
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed1
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.stderr60
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.fixed144
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.rs2
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.stderr8
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.fixed8
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.rs7
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.stderr18
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.fixed2
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed79
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs87
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr152
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr13
-rw-r--r--src/tools/clippy/tests/ui/types.fixed13
-rw-r--r--src/tools/clippy/tests/ui/types.rs13
-rw-r--r--src/tools/clippy/tests/ui/types.stderr11
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed201
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed70
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs70
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.stderr44
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.fixed587
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.stderr186
-rw-r--r--src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed20
-rw-r--r--src/tools/clippy/tests/ui/zero_repeat_side_effects.rs20
-rw-r--r--src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr36
-rw-r--r--src/tools/clippy/triagebot.toml2
-rw-r--r--src/tools/clippy/util/gh-pages/index.html40
-rw-r--r--src/tools/clippy/util/gh-pages/script.js6
-rw-r--r--src/tools/compiletest/src/command-list.rs1
-rw-r--r--src/tools/run-make-support/src/external_deps/cc.rs23
-rw-r--r--src/tools/run-make-support/src/lib.rs2
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt9
309 files changed, 4923 insertions, 5210 deletions
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 20d79e490ec..e947e3735db 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -247,10 +247,8 @@ pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> Path
         triple.to_string()
     };
 
-    // API 19 is the earliest API level supported by NDK r25b but AArch64 and x86_64 support
-    // begins at API level 21.
-    let api_level =
-        if triple.contains("aarch64") || triple.contains("x86_64") { "21" } else { "19" };
+    // The earliest API supported by NDK r26d is 21.
+    let api_level = "21";
     let compiler = format!("{}{}-{}", triple_translated, api_level, compiler.clang());
     let host_tag = if cfg!(target_os = "macos") {
         // The NDK uses universal binaries, so this is correct even on ARM.
@@ -258,7 +256,7 @@ pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> Path
     } else if cfg!(target_os = "windows") {
         "windows-x86_64"
     } else {
-        // NDK r25b only has official releases for macOS, Windows and Linux.
+        // NDK r26d only has official releases for macOS, Windows and Linux.
         // Try the Linux directory everywhere else, on the assumption that the OS has an
         // emulation layer that can cope (e.g. BSDs).
         "linux-x86_64"
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 083418ed066..879cc079c6b 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -210,4 +210,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "the `wasm-component-ld` tool is now built as part of `build.extended` and can be a member of `build.tools`",
     },
+    ChangeInfo {
+        change_id: 120593,
+        severity: ChangeSeverity::Info,
+        summary: "Removed android-ndk r25b support in favor of android-ndk r26d.",
+    },
 ];
diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile
index abca06fb9fb..222fa8a7355 100644
--- a/src/ci/docker/host-x86_64/arm-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile
@@ -6,7 +6,7 @@ RUN sh /scripts/android-base-apt-get.sh
 
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
-    download_ndk android-ndk-r25b-linux.zip
+    download_ndk android-ndk-r26d-linux.zip
 
 RUN dpkg --add-architecture i386 && \
     apt-get update && \
diff --git a/src/ci/docker/host-x86_64/arm-android/android-sdk.lock b/src/ci/docker/host-x86_64/arm-android/android-sdk.lock
index a1be8a4346b..33b0c66ae09 100644
--- a/src/ci/docker/host-x86_64/arm-android/android-sdk.lock
+++ b/src/ci/docker/host-x86_64/arm-android/android-sdk.lock
@@ -1,6 +1,6 @@
 emulator emulator-linux-5264690.zip 48c1cda2bdf3095d9d9d5c010fbfb3d6d673e3ea
 patcher;v4 3534162-studio.sdk-patcher.zip 046699c5e2716ae11d77e0bad814f7f33fab261e
-platform-tools platform-tools_r28.0.2-linux.zip 46a4c02a9b8e4e2121eddf6025da3c979bf02e28
-platforms;android-18 android-18_r03.zip e6b09b3505754cbbeb4a5622008b907262ee91cb
-system-images;android-18;default;armeabi-v7a sys-img/android/armeabi-v7a-18_r05.zip 580b583720f7de671040d5917c8c9db0c7aa03fd
+platform-tools platform-tools_r34.0.5-linux.zip 96097475cf7b279fdd8f218f5d043ffe94104ec3
+platforms;android-21 android-21_r02.zip 53536556059bb29ae82f414fd2e14bc335a4eb4c
+system-images;android-21;default;armeabi-v7a sys-img/android/armeabi-v7a-21_r04.zip 8c606f81306564b65e41303d2603e4c42ded0d10
 tools sdk-tools-linux-4333796.zip 8c7c28554a32318461802c1291d76fccfafde054
diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile
index 20b72b377ca..54649e0d22b 100644
--- a/src/ci/docker/host-x86_64/dist-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile
@@ -6,7 +6,7 @@ RUN sh /scripts/android-base-apt-get.sh
 # ndk
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
-    download_ndk android-ndk-r25b-linux.zip
+    download_ndk android-ndk-r26d-linux.zip
 
 # env
 ENV TARGETS=arm-linux-androideabi
diff --git a/src/ci/docker/scripts/android-start-emulator.sh b/src/ci/docker/scripts/android-start-emulator.sh
index 09f0d13759c..5ffb72eddb1 100755
--- a/src/ci/docker/scripts/android-start-emulator.sh
+++ b/src/ci/docker/scripts/android-start-emulator.sh
@@ -10,7 +10,7 @@ export SHELL=/bin/bash
 # the emulator date is set to unix epoch (in armeabi-v7a-18 image). Using
 # classic engine the emulator starts with the current date and the tests run
 # fine. If another image is used, this need to be evaluated again.
-nohup nohup emulator @armeabi-v7a-18 \
+nohup nohup emulator @armeabi-v7a-21 \
     -engine classic -no-window -partition-size 2047 0<&- &>/dev/null &
 
 exec "$@"
diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py
index d03bbda1008..7de6d5fcd5f 100755
--- a/src/ci/github-actions/calculate-job-matrix.py
+++ b/src/ci/github-actions/calculate-job-matrix.py
@@ -97,9 +97,15 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
             "refs/heads/automation/bors/try"
         )
 
+        # Unrolled branch from a rollup for testing perf
+        # This should **not** allow custom try jobs
+        is_unrolled_perf_build = ctx.ref == "refs/heads/try-perf"
+
         if try_build:
-            jobs = get_custom_jobs(ctx)
-            return TryRunType(custom_jobs=jobs)
+            custom_jobs = []
+            if not is_unrolled_perf_build:
+                custom_jobs = get_custom_jobs(ctx)
+            return TryRunType(custom_jobs=custom_jobs)
 
         if ctx.ref == "refs/heads/auto":
             return AutoRunType()
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2cd9b6fcd38..26011926cdd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1858,7 +1858,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
         }
         TyKind::Path(_) => clean_qpath(ty, cx),
         TyKind::TraitObject(bounds, ref lifetime, _) => {
-            let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
+            let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect();
             let lifetime =
                 if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
             DynTrait(bounds, lifetime)
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 86af38f3ee7..3eb27ea087c 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2932,7 +2932,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
 
         // Update document title to maintain a meaningful browser history
-        searchState.title = "Results for " + query.original + " - Rust";
+        searchState.title = "\"" + query.original + "\" Search - Rust";
 
         // Because searching is incremental by character, only the most
         // recent search query is added to the browser history.
diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml
index 48a63e48568..7afdd068a99 100644
--- a/src/tools/clippy/.cargo/config.toml
+++ b/src/tools/clippy/.cargo/config.toml
@@ -4,7 +4,7 @@ uibless = "test --test compile-test -- -- --bless"
 bless = "test -- -- --bless"
 dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
 lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml  -- "
-collect-metadata = "test --test dogfood --features internal -- run_metadata_collection_lint --ignored"
+collect-metadata = "test --test dogfood --features internal -- collect_metadata"
 
 [build]
 # -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
diff --git a/src/tools/clippy/.github/workflows/lintcheck.yml b/src/tools/clippy/.github/workflows/lintcheck.yml
index f016a770059..6a5139b6dc0 100644
--- a/src/tools/clippy/.github/workflows/lintcheck.yml
+++ b/src/tools/clippy/.github/workflows/lintcheck.yml
@@ -53,18 +53,18 @@ jobs:
       id: cache-json
       uses: actions/cache@v4
       with:
-        path: lintcheck-logs/lintcheck_crates_logs.json
+        path: lintcheck-logs/ci_crates_logs.json
         key: ${{ steps.key.outputs.key }}
 
     - name: Run lintcheck
       if: steps.cache-json.outputs.cache-hit != 'true'
-      run: ./target/debug/lintcheck --format json --warn-all
+      run: ./target/debug/lintcheck --format json --warn-all --crates-toml ./lintcheck/ci_crates.toml
 
     - name: Upload base JSON
       uses: actions/upload-artifact@v4
       with:
         name: base
-        path: lintcheck-logs/lintcheck_crates_logs.json
+        path: lintcheck-logs/ci_crates_logs.json
 
   # Runs lintcheck on the PR and stores the results as an artifact
   head:
@@ -86,13 +86,13 @@ jobs:
       run: cargo build --manifest-path=lintcheck/Cargo.toml
 
     - name: Run lintcheck
-      run: ./target/debug/lintcheck --format json --warn-all
+      run: ./target/debug/lintcheck --format json --warn-all --crates-toml ./lintcheck/ci_crates.toml
 
     - name: Upload head JSON
       uses: actions/upload-artifact@v4
       with:
         name: head
-        path: lintcheck-logs/lintcheck_crates_logs.json
+        path: lintcheck-logs/ci_crates_logs.json
 
   # Retrieves the head and base JSON results and prints the diff to the GH actions step summary
   diff:
@@ -115,4 +115,20 @@ jobs:
       uses: actions/download-artifact@v4
 
     - name: Diff results
-      run: ./target/debug/lintcheck diff {base,head}/lintcheck_crates_logs.json >> $GITHUB_STEP_SUMMARY
+      # GH's summery has a maximum size of 1024k:
+      # https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary
+      # That's why we first log to file and then to the summary and logs
+      run: |
+        ./target/debug/lintcheck diff {base,head}/ci_crates_logs.json --truncate >> truncated_diff.md
+        head -c 1024000 truncated_diff.md >> $GITHUB_STEP_SUMMARY
+        cat truncated_diff.md
+        ./target/debug/lintcheck diff {base,head}/ci_crates_logs.json >> full_diff.md
+
+    - name: Upload full diff
+      uses: actions/upload-artifact@v4
+      with:
+        name: diff
+        if-no-files-found: ignore
+        path: |
+          full_diff.md
+          truncated_diff.md
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 55281f3cbec..60c03b03d9b 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,53 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[ca3b3937...master](https://github.com/rust-lang/rust-clippy/compare/ca3b3937...master)
+[c9139bd5...master](https://github.com/rust-lang/rust-clippy/compare/c9139bd5...master)
+
+## Rust 1.80
+
+Current stable, released 2024-07-25
+
+[View all 68 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-04-18T22%3A50%3A22Z..2024-05-30T08%3A26%3A18Z+base%3Amaster)
+
+### New Lints
+
+* Added [`while_float`] to `nursery`
+  [#12765](https://github.com/rust-lang/rust-clippy/pull/12765)
+* Added [`macro_metavars_in_unsafe`] to `suspicious`
+  [#12107](https://github.com/rust-lang/rust-clippy/pull/12107)
+* Added [`renamed_function_params`] to `restriction`
+  [#11540](https://github.com/rust-lang/rust-clippy/pull/11540)
+* Added [`doc_lazy_continuation`] to `style`
+  [#12770](https://github.com/rust-lang/rust-clippy/pull/12770)
+
+### Moves and Deprecations
+
+* Moved [`assigning_clones`] to `pedantic` (From `perf` now allow-by-default)
+  [#12779](https://github.com/rust-lang/rust-clippy/pull/12779)
+* Moved [`single_char_pattern`] to `pedantic` (From `perf` now allow-by-default)
+  [#11852](https://github.com/rust-lang/rust-clippy/pull/11852)
+
+### Enhancements
+
+* [`panic`]: Added [`allow-panic-in-tests`] configuration to allow the lint in tests
+  [#12803](https://github.com/rust-lang/rust-clippy/pull/12803)
+* [`missing_const_for_fn`]: Now respects the [`msrv`] configuration
+  [#12713](https://github.com/rust-lang/rust-clippy/pull/12713)
+* [`missing_panics_doc`]: No longer lints on compile-time panics
+  [#12790](https://github.com/rust-lang/rust-clippy/pull/12790)
+* [`collapsible_match`]: Now considers the [`msrv`] configuration for the suggestion
+  [#12745](https://github.com/rust-lang/rust-clippy/pull/12745)
+* [`useless_vec`]: Added [`allow-useless-vec-in-tests`] configuration to allow the lint in tests
+  [#12725](https://github.com/rust-lang/rust-clippy/pull/12725)
+
+### Suggestion Fixes/Improvements
+
+* [`single_match`], [`single_match_else`]: Suggestions are now machine-applicable
+  [#12726](https://github.com/rust-lang/rust-clippy/pull/12726)
 
 ## Rust 1.79
 
-Current stable, released 2024-06-13
+Released 2024-06-13
 
 [View all 102 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-03-08T11%3A13%3A58Z..2024-04-18T15%3A50%3A50Z+base%3Amaster)
 
@@ -5712,6 +5754,7 @@ Released 2018-09-13
 [`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
 [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
 [`path_ends_with_ext`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext
+[`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push
 [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
 [`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
 [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 43788499055..bb4dc97e748 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.81"
+version = "0.1.82"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -30,11 +30,10 @@ color-print = "0.3.4"
 anstream = "0.6.0"
 
 [dev-dependencies]
-ui_test = "0.23"
+ui_test = "0.24"
 regex = "1.5.5"
 toml = "0.7.3"
 walkdir = "2.3"
-# This is used by the `collect-metadata` alias.
 filetime = "0.2.9"
 itertools = "0.12"
 
@@ -63,3 +62,7 @@ rustc_private = true
 [[test]]
 name = "compile-test"
 harness = false
+
+[[test]]
+name = "dogfood"
+harness = false
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index 48c00bcbf34..a71d94daca7 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -458,9 +458,8 @@ pub struct ManualStrip {
 }
 
 impl ManualStrip {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self { msrv: conf.msrv.clone() }
     }
 }
 ```
@@ -689,7 +688,6 @@ for some users. Adding a configuration is done in the following steps:
        ]);
 
        // New manual definition struct
-       #[derive(Copy, Clone)]
        pub struct StructName {}
 
        impl_lint_pass!(StructName => [
@@ -700,7 +698,6 @@ for some users. Adding a configuration is done in the following steps:
     2. Next add the configuration value and a corresponding creation method like
        this:
        ```rust
-       #[derive(Copy, Clone)]
        pub struct StructName {
            configuration_ident: Type,
        }
@@ -708,9 +705,9 @@ for some users. Adding a configuration is done in the following steps:
        // ...
 
        impl StructName {
-           pub fn new(configuration_ident: Type) -> Self {
+           pub fn new(conf: &'static Conf) -> Self {
                Self {
-                   configuration_ident,
+                   configuration_ident: conf.configuration_ident,
                }
            }
        }
@@ -726,8 +723,7 @@ for some users. Adding a configuration is done in the following steps:
    store.register_*_pass(|| box module::StructName);
 
    // New registration with configuration value
-   let configuration_ident = conf.configuration_ident.clone();
-   store.register_*_pass(move || box module::StructName::new(configuration_ident));
+   store.register_*_pass(move || box module::StructName::new(conf));
    ```
 
    Congratulations the work is almost done. The configuration value can now be
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index ad29339a84a..fb717a2c166 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -455,7 +455,7 @@ default configuration of Clippy. By default, any configuration will replace the
 * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
 * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
 
-**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DevOps", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
+**Default Value:** `["TiB", "CoreGraphics", "CoffeeScript", "TeX", "Direct2D", "PiB", "DirectX", "NetBSD", "OAuth", "NaN", "OpenType", "WebGL2", "WebTransport", "JavaScript", "OpenSSL", "OpenSSH", "EiB", "PureScript", "OpenAL", "MiB", "WebAssembly", "MinGW", "CoreFoundation", "WebGPU", "ClojureScript", "CamelCase", "OpenDNS", "NaNs", "OpenMP", "GitLab", "KiB", "sRGB", "CoreText", "macOS", "TypeScript", "GiB", "OpenExr", "YCbCr", "OpenTelemetry", "OpenBSD", "FreeBSD", "GPLv2", "PostScript", "WebP", "LaTeX", "TensorFlow", "AccessKit", "TrueType", "OpenStreetMap", "OpenGL", "DevOps", "OCaml", "WebRTC", "WebGL", "BibLaTeX", "GitHub", "GraphQL", "iOS", "Direct3D", "BibTeX", "DirectWrite", "GPLv3", "IPv6", "WebSocket", "IPv4", "ECMAScript"]`
 
 ---
 **Affected lints:**
@@ -679,6 +679,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 * [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
 * [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
 * [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
+* [`collapsible_match`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match)
 * [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
 * [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
 * [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml
index 319b72e8c5d..a7b0cc56ea1 100644
--- a/src/tools/clippy/clippy.toml
+++ b/src/tools/clippy/clippy.toml
@@ -8,7 +8,6 @@ reason = "this function does not add a link to our documentation, please use the
 path = "rustc_lint::context::LintContext::span_lint"
 reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
 
-
 [[disallowed-methods]]
 path = "rustc_middle::ty::context::TyCtxt::node_span_lint"
 reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead"
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index be0b048ac0c..e1b2edc8a6f 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.81"
+version = "0.1.82"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 7f53aad6793..63140a36875 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -18,23 +18,26 @@ use std::{cmp, env, fmt, fs, io};
 #[rustfmt::skip]
 const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
     "KiB", "MiB", "GiB", "TiB", "PiB", "EiB",
+    "AccessKit",
+    "CoreFoundation", "CoreGraphics", "CoreText",
     "DevOps",
-    "DirectX",
+    "Direct2D", "Direct3D", "DirectWrite", "DirectX",
     "ECMAScript",
     "GPLv2", "GPLv3",
     "GitHub", "GitLab",
     "IPv4", "IPv6",
-    "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript",
+    "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript",
     "WebAssembly",
     "NaN", "NaNs",
     "OAuth", "GraphQL",
     "OCaml",
-    "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry",
-    "WebGL", "WebGL2", "WebGPU",
+    "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry",
+    "OpenType",
+    "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport",
     "WebP", "OpenExr", "YCbCr", "sRGB",
     "TensorFlow",
     "TrueType",
-    "iOS", "macOS", "FreeBSD",
+    "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD",
     "TeX", "LaTeX", "BibTeX", "BibLaTeX",
     "MinGW",
     "CamelCase",
@@ -235,7 +238,7 @@ define_Conf! {
     ///
     /// A type, say `SomeType`, listed in this configuration has the same behavior of
     /// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
-    (arithmetic_side_effects_allowed: FxHashSet<String> = <_>::default()),
+    (arithmetic_side_effects_allowed: Vec<String> = <_>::default()),
     /// Lint: ARITHMETIC_SIDE_EFFECTS.
     ///
     /// Suppress checking of the passed type pair names in binary operations like addition or
@@ -262,12 +265,12 @@ define_Conf! {
     /// ```toml
     /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
     /// ```
-    (arithmetic_side_effects_allowed_unary: FxHashSet<String> = <_>::default()),
+    (arithmetic_side_effects_allowed_unary: Vec<String> = <_>::default()),
     /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN, NEEDLESS_PASS_BY_REF_MUT.
     ///
     /// 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, OPTION_MAP_UNWRAP_OR, 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, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, MANUAL_PATTERN_CHAR_COMPARISON, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, 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, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, MANUAL_PATTERN_CHAR_COMPARISON, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON, COLLAPSIBLE_MATCH.
     ///
     /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
     #[default_text = ""]
@@ -311,7 +314,7 @@ define_Conf! {
     /// default configuration of Clippy. By default, any configuration will replace the default value. For example:
     /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
     /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
-    (doc_valid_idents: Vec<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
+    (doc_valid_idents: FxHashSet<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
     /// Lint: TOO_MANY_ARGUMENTS.
     ///
     /// The maximum number of argument a function or method can have
@@ -547,7 +550,7 @@ define_Conf! {
     /// Lint: PATH_ENDS_WITH_EXT.
     ///
     /// Additional dotfiles (files or directories starting with a dot) to allow
-    (allowed_dotfiles: FxHashSet<String> = FxHashSet::default()),
+    (allowed_dotfiles: Vec<String> = Vec::default()),
     /// Lint: MULTIPLE_CRATE_VERSIONS.
     ///
     /// A list of crate names to allow duplicates of
@@ -700,7 +703,6 @@ pub fn lookup_conf_file() -> io::Result<(Option<PathBuf>, Vec<String>)> {
 fn deserialize(file: &SourceFile) -> TryConf {
     match toml::de::Deserializer::new(file.src.as_ref().unwrap()).deserialize_map(ConfVisitor(file)) {
         Ok(mut conf) => {
-            extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
             extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
             extend_vec_if_indicator_present(&mut conf.conf.allowed_prefixes, DEFAULT_ALLOWED_PREFIXES);
             extend_vec_if_indicator_present(
@@ -713,6 +715,11 @@ fn deserialize(file: &SourceFile) -> TryConf {
                     .allowed_idents_below_min_chars
                     .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string));
             }
+            if conf.conf.doc_valid_idents.contains("..") {
+                conf.conf
+                    .doc_valid_idents
+                    .extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string));
+            }
 
             conf
         },
diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs
index 435aa9244c5..d47e34bb5bc 100644
--- a/src/tools/clippy/clippy_config/src/types.rs
+++ b/src/tools/clippy/clippy_config/src/types.rs
@@ -2,13 +2,13 @@ use serde::de::{self, Deserializer, Visitor};
 use serde::{ser, Deserialize, Serialize};
 use std::fmt;
 
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Debug, Deserialize)]
 pub struct Rename {
     pub path: String,
     pub rename: String,
 }
 
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Debug, Deserialize)]
 #[serde(untagged)]
 pub enum DisallowedPath {
     Simple(String),
@@ -22,12 +22,10 @@ impl DisallowedPath {
         path
     }
 
-    pub fn reason(&self) -> Option<String> {
-        match self {
-            Self::WithReason {
-                reason: Some(reason), ..
-            } => Some(format!("{reason} (from clippy.toml)")),
-            _ => None,
+    pub fn reason(&self) -> Option<&str> {
+        match &self {
+            Self::WithReason { reason, .. } => reason.as_deref(),
+            Self::Simple(_) => None,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index d762e30ef02..de91233d196 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -140,7 +140,7 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
 
     let new_lint = if enable_msrv {
         format!(
-            "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv())));\n    ",
+            "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf)));\n    ",
             lint_pass = lint.pass,
             ctor_arg = if lint.pass == "late" { "_" } else { "" },
             module_name = lint.name,
@@ -274,6 +274,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
         formatdoc!(
             r#"
             use clippy_config::msrvs::{{self, Msrv}};
+            use clippy_config::Conf;
             {pass_import}
             use rustc_lint::{{{context_import}, {pass_type}, LintContext}};
             use rustc_session::impl_lint_pass;
@@ -301,9 +302,8 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
             }}
 
             impl {name_camel} {{
-                #[must_use]
-                pub fn new(msrv: Msrv) -> Self {{
-                    Self {{ msrv }}
+                pub fn new(conf: &'static Conf) -> Self {{
+                    Self {{ msrv: conf.msrv.clone() }}
                 }}
             }}
 
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 5708ffba08f..eb04c006f89 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.81"
+version = "0.1.82"
 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/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs
index 461117cf965..c0a9d888e0b 100644
--- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet_opt;
 use rustc_data_structures::fx::FxHashSet;
@@ -47,7 +48,16 @@ impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]);
 
 pub struct AbsolutePaths {
     pub absolute_paths_max_segments: u64,
-    pub absolute_paths_allowed_crates: FxHashSet<String>,
+    pub absolute_paths_allowed_crates: &'static FxHashSet<String>,
+}
+
+impl AbsolutePaths {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            absolute_paths_max_segments: conf.absolute_paths_max_segments,
+            absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates,
+        }
+    }
 }
 
 impl LateLintPass<'_> for AbsolutePaths {
diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
index 96e9c949b75..451bae95987 100644
--- a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
+++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{trim_span, walk_span_to_context};
 use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
@@ -34,8 +35,10 @@ pub struct AlmostCompleteRange {
     msrv: Msrv,
 }
 impl AlmostCompleteRange {
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 impl EarlyLintPass for AlmostCompleteRange {
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index ec28fd46111..e6d52bcef71 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
@@ -67,9 +68,10 @@ pub struct ApproxConstant {
 }
 
 impl ApproxConstant {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 
     fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
index d57ab539fff..4eafa330faf 100644
--- a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{is_from_proc_macro, last_path_segment};
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
@@ -42,12 +42,11 @@ declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]);
 
 impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if !expr.span.from_expansion()
-            && let ty = cx.typeck_results().expr_ty(expr)
-            && is_type_diagnostic_item(cx, ty, sym::Arc)
-            && let ExprKind::Call(func, [arg]) = expr.kind
-            && let ExprKind::Path(func_path) = func.kind
-            && last_path_segment(&func_path).ident.name == sym::new
+        if let ExprKind::Call(func, [arg]) = expr.kind
+            && let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind
+            && func_name.ident.name == sym::new
+            && !expr.span.from_expansion()
+            && is_type_diagnostic_item(cx, cx.typeck_results().node_type(func_ty.hir_id), sym::Arc)
             && let arg_ty = cx.typeck_results().expr_ty(arg)
             // make sure that the type is not and does not contain any type parameters
             && arg_ty.walk().all(|arg| {
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index 0de0031ed24..03f777600f0 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
 use clippy_utils::sugg::Sugg;
@@ -57,9 +58,10 @@ pub struct AssigningClones {
 }
 
 impl AssigningClones {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index 8ec60314cc9..8f430ae601a 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -16,6 +16,7 @@ mod useless_attribute;
 mod utils;
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
 use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
@@ -499,7 +500,6 @@ declare_clippy_lint! {
     "duplicated attribute"
 }
 
-#[derive(Clone)]
 pub struct Attributes {
     msrv: Msrv,
 }
@@ -517,9 +517,10 @@ impl_lint_pass!(Attributes => [
 ]);
 
 impl Attributes {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -589,7 +590,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
 }
 
 pub struct EarlyAttributes {
-    pub msrv: Msrv,
+    msrv: Msrv,
+}
+
+impl EarlyAttributes {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
 }
 
 impl_lint_pass!(EarlyAttributes => [
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 d4a1e2780d0..d5f017b2650 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -1,11 +1,11 @@
-use clippy_config::types::DisallowedPath;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{match_def_path, paths};
-use rustc_data_structures::fx::FxHashMap;
+use clippy_utils::{create_disallowed_map, match_def_path, paths};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::CoroutineLayout;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::{sym, Span};
 
@@ -172,31 +172,19 @@ declare_clippy_lint! {
 
 impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF, AWAIT_HOLDING_INVALID_TYPE]);
 
-#[derive(Debug)]
 pub struct AwaitHolding {
-    conf_invalid_types: Vec<DisallowedPath>,
-    def_ids: FxHashMap<DefId, DisallowedPath>,
+    def_ids: DefIdMap<(&'static str, Option<&'static str>)>,
 }
 
 impl AwaitHolding {
-    pub(crate) fn new(conf_invalid_types: Vec<DisallowedPath>) -> Self {
+    pub(crate) fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         Self {
-            conf_invalid_types,
-            def_ids: FxHashMap::default(),
+            def_ids: create_disallowed_map(tcx, &conf.await_holding_invalid_types),
         }
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for AwaitHolding {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        for conf in &self.conf_invalid_types {
-            let segs: Vec<_> = conf.path().split("::").collect();
-            for id in clippy_utils::def_path_def_ids(cx, &segs) {
-                self.def_ids.insert(id, conf.clone());
-            }
-        }
-    }
-
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         if let hir::ExprKind::Closure(hir::Closure {
             kind: hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)),
@@ -258,25 +246,22 @@ impl AwaitHolding {
                             );
                         },
                     );
-                } else if let Some(disallowed) = self.def_ids.get(&adt.did()) {
-                    emit_invalid_type(cx, ty_cause.source_info.span, disallowed);
+                } else if let Some(&(path, reason)) = self.def_ids.get(&adt.did()) {
+                    emit_invalid_type(cx, ty_cause.source_info.span, path, reason);
                 }
             }
         }
     }
 }
 
-fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPath) {
+fn emit_invalid_type(cx: &LateContext<'_>, span: Span, path: &'static str, reason: Option<&'static str>) {
     span_lint_and_then(
         cx,
         AWAIT_HOLDING_INVALID_TYPE,
         span,
-        format!(
-            "`{}` may not be held across an await point per `clippy.toml`",
-            disallowed.path()
-        ),
+        format!("holding a disallowed type across an await point `{path}`"),
         |diag| {
-            if let Some(reason) = disallowed.reason() {
+            if let Some(reason) = reason {
                 diag.note(reason);
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index 0ca4a0e067d..bd123a725a7 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -49,35 +49,31 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
 
 impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
-        if !e.span.from_expansion()
-            && let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind
-            && !addrof_target.span.from_expansion()
+        if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind
             && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind
-            && !deref_target.span.from_expansion()
             && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..))
+            && !e.span.from_expansion()
+            && !deref_target.span.from_expansion()
+            && !addrof_target.span.from_expansion()
             && let ref_ty = cx.typeck_results().expr_ty(deref_target)
             && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind()
-        {
-            if let Some(parent_expr) = get_parent_expr(cx, e) {
-                if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..))
-                    && !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id)
-                {
-                    return;
+            && get_parent_expr(cx, e).map_or(true, |parent| {
+                match parent.kind {
+                    // `*&*foo` should lint `deref_addrof` instead.
+                    ExprKind::Unary(UnOp::Deref, _) => is_lint_allowed(cx, DEREF_ADDROF, parent.hir_id),
+                    // `&*foo` creates a distinct temporary from `foo`
+                    ExprKind::AddrOf(_, Mutability::Mut, _) => !matches!(
+                        deref_target.kind,
+                        ExprKind::Path(..)
+                            | ExprKind::Field(..)
+                            | ExprKind::Index(..)
+                            | ExprKind::Unary(UnOp::Deref, ..)
+                    ),
+                    _ => true,
                 }
-
-                // modification to `&mut &*x` is different from `&mut x`
-                if matches!(
-                    deref_target.kind,
-                    ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..)
-                ) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _))
-                {
-                    return;
-                }
-            }
-            if is_from_proc_macro(cx, e) {
-                return;
-            }
-
+            })
+            && !is_from_proc_macro(cx, e)
+        {
             span_lint_and_then(
                 cx,
                 BORROW_DEREF_REF,
diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
index 593bc6c81ee..312ad4c2990 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
@@ -5,6 +5,7 @@ mod multiple_crate_versions;
 mod wildcard_dependencies;
 
 use cargo_metadata::MetadataCommand;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_lint_allowed;
 use rustc_data_structures::fx::FxHashSet;
@@ -204,8 +205,8 @@ declare_clippy_lint! {
 }
 
 pub struct Cargo {
-    pub allowed_duplicate_crates: FxHashSet<String>,
-    pub ignore_publish: bool,
+    allowed_duplicate_crates: &'static FxHashSet<String>,
+    ignore_publish: bool,
 }
 
 impl_lint_pass!(Cargo => [
@@ -217,6 +218,15 @@ impl_lint_pass!(Cargo => [
     LINT_GROUPS_PRIORITY,
 ]);
 
+impl Cargo {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            allowed_duplicate_crates: &conf.allowed_duplicate_crates,
+            ignore_publish: conf.cargo_ignore_publish,
+        }
+    }
+}
+
 impl LateLintPass<'_> for Cargo {
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         static NO_DEPS_LINTS: &[&Lint] = &[
@@ -253,7 +263,7 @@ impl LateLintPass<'_> for Cargo {
         {
             match MetadataCommand::new().exec() {
                 Ok(metadata) => {
-                    multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates);
+                    multiple_crate_versions::check(cx, &metadata, self.allowed_duplicate_crates);
                 },
                 Err(e) => {
                     for lint in WITH_DEPS_LINTS {
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 d52ad1c6f23..ff460a3fd8e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -1,19 +1,21 @@
 use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::in_constant;
-use clippy_utils::source::{snippet_opt, snippet_with_applicability};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_isize_or_usize;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, QPath, TyKind};
+use rustc_hir::{Expr, QPath, TyKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, FloatTy, Ty, UintTy};
+use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_span::hygiene;
 
 use super::{utils, CAST_LOSSLESS};
 
 pub(super) fn check(
     cx: &LateContext<'_>,
     expr: &Expr<'_>,
-    cast_op: &Expr<'_>,
+    cast_from_expr: &Expr<'_>,
     cast_from: Ty<'_>,
     cast_to: Ty<'_>,
     cast_to_hir: &rustc_hir::Ty<'_>,
@@ -23,64 +25,54 @@ pub(super) fn check(
         return;
     }
 
-    // The suggestion is to use a function call, so if the original expression
-    // has parens on the outside, they are no longer needed.
-    let mut app = Applicability::MachineApplicable;
-    let opt = snippet_opt(cx, cast_op.span.source_callsite());
-    let sugg = opt.as_ref().map_or_else(
-        || {
-            app = Applicability::HasPlaceholders;
-            ".."
-        },
-        |snip| {
-            if should_strip_parens(cast_op, snip) {
-                &snip[1..snip.len() - 1]
-            } else {
-                snip.as_str()
-            }
-        },
-    );
-
-    // Display the type alias instead of the aliased type. Fixes #11285
-    //
-    // FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead,
-    // this will allow us to display the right type with `cast_from` as well.
-    let cast_to_fmt = if let TyKind::Path(QPath::Resolved(None, path)) = cast_to_hir.kind
-        // It's a bit annoying but the turbofish is optional for types. A type in an `as` cast
-        // shouldn't have these if they're primitives, which are the only things we deal with.
-        //
-        // This could be removed for performance if this check is determined to have a pretty major
-        // effect.
-        && path.segments.iter().all(|segment| segment.args.is_none())
-    {
-        snippet_with_applicability(cx, cast_to_hir.span, "..", &mut app)
-    } else {
-        cast_to.to_string().into()
-    };
-
-    let message = if cast_from.is_bool() {
-        format!("casting `{cast_from}` to `{cast_to_fmt}` is more cleanly stated with `{cast_to_fmt}::from(_)`")
-    } else {
-        format!("casting `{cast_from}` to `{cast_to_fmt}` may become silently lossy if you later change the type")
-    };
-
-    span_lint_and_sugg(
+    span_lint_and_then(
         cx,
         CAST_LOSSLESS,
         expr.span,
-        message,
-        "try",
-        format!("{cast_to_fmt}::from({sugg})"),
-        app,
+        format!("casts from `{cast_from}` to `{cast_to}` can be expressed infallibly using `From`"),
+        |diag| {
+            diag.help("an `as` cast can become silently lossy if the types change in the future");
+            let mut applicability = Applicability::MachineApplicable;
+            let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &mut applicability);
+            let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else {
+                return;
+            };
+            match cast_to_hir.kind {
+                TyKind::Infer => {
+                    diag.span_suggestion_verbose(
+                        expr.span,
+                        "use `Into::into` instead",
+                        format!("{}.into()", from_sugg.maybe_par()),
+                        applicability,
+                    );
+                },
+                // Don't suggest `A<_>::B::From(x)` or `macro!()::from(x)`
+                kind if matches!(kind, TyKind::Path(QPath::Resolved(_, path)) if path.segments.iter().any(|s| s.args.is_some()))
+                    || !cast_to_hir.span.eq_ctxt(expr.span) =>
+                {
+                    diag.span_suggestion_verbose(
+                        expr.span,
+                        format!("use `<{ty}>::from` instead"),
+                        format!("<{ty}>::from({from_sugg})"),
+                        applicability,
+                    );
+                },
+                _ => {
+                    diag.span_suggestion_verbose(
+                        expr.span,
+                        format!("use `{ty}::from` instead"),
+                        format!("{ty}::from({from_sugg})"),
+                        applicability,
+                    );
+                },
+            }
+        },
     );
 }
 
 fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool {
     // Do not suggest using From in consts/statics until it is valid to do so (see #2267).
-    //
-    // If destination is u128, do not lint because source type cannot be larger
-    // If source is bool, still lint due to the lint message differing (refers to style)
-    if in_constant(cx, expr.hir_id) || (!cast_from.is_bool() && matches!(cast_to.kind(), ty::Uint(UintTy::U128))) {
+    if in_constant(cx, expr.hir_id) {
         return false;
     }
 
@@ -110,12 +102,3 @@ fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to
         },
     }
 }
-
-fn should_strip_parens(cast_expr: &Expr<'_>, snip: &str) -> bool {
-    if let ExprKind::Binary(_, _, _) = cast_expr.kind {
-        if snip.starts_with('(') && snip.ends_with(')') {
-            return true;
-        }
-    }
-    false
-}
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 54f0c7c4687..c31716fbcee 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -24,6 +24,7 @@ mod utils;
 mod zero_ptr;
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::is_hir_ty_cfg_dependant;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -658,11 +659,11 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```rust,ignore
-    /// let _: (0.0_f32 / 0.0) as u64;
+    /// let _ = (0.0_f32 / 0.0) as u64;
     /// ```
     /// Use instead:
     /// ```rust,ignore
-    /// let _: = 0_u64;
+    /// let _ = 0_u64;
     /// ```
     #[clippy::version = "1.66.0"]
     pub CAST_NAN_TO_INT,
@@ -722,9 +723,10 @@ pub struct Casts {
 }
 
 impl Casts {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -761,45 +763,45 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             return;
         }
 
-        if let ExprKind::Cast(cast_expr, cast_to_hir) = expr.kind {
+        if let ExprKind::Cast(cast_from_expr, cast_to_hir) = expr.kind {
             if is_hir_ty_cfg_dependant(cx, cast_to_hir) {
                 return;
             }
             let (cast_from, cast_to) = (
-                cx.typeck_results().expr_ty(cast_expr),
+                cx.typeck_results().expr_ty(cast_from_expr),
                 cx.typeck_results().expr_ty(expr),
             );
 
-            if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) {
+            if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_from_expr, cast_from, cast_to) {
                 return;
             }
-            cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv);
-            ptr_cast_constness::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
-            as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to);
-            fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
-            fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
-            fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
-            zero_ptr::check(cx, expr, cast_expr, cast_to_hir);
+            cast_slice_from_raw_parts::check(cx, expr, cast_from_expr, cast_to, &self.msrv);
+            ptr_cast_constness::check(cx, expr, cast_from_expr, cast_from, cast_to, &self.msrv);
+            as_ptr_cast_mut::check(cx, expr, cast_from_expr, cast_to);
+            fn_to_numeric_cast_any::check(cx, expr, cast_from_expr, cast_from, cast_to);
+            fn_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to);
+            fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to);
+            zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
 
             if cast_to.is_numeric() {
-                cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
+                cast_possible_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir.span);
                 if cast_from.is_numeric() {
                     cast_possible_wrap::check(cx, expr, cast_from, cast_to);
                     cast_precision_loss::check(cx, expr, cast_from, cast_to);
-                    cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
-                    cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
-                    cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to);
+                    cast_sign_loss::check(cx, expr, cast_from_expr, cast_from, cast_to);
+                    cast_abs_to_unsigned::check(cx, expr, cast_from_expr, cast_from, cast_to, &self.msrv);
+                    cast_nan_to_int::check(cx, expr, cast_from_expr, cast_from, cast_to);
                 }
-                cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir, &self.msrv);
-                cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
+                cast_lossless::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir, &self.msrv);
+                cast_enum_constructor::check(cx, expr, cast_from_expr, cast_from);
             }
 
             as_underscore::check(cx, expr, cast_to_hir);
 
             if self.msrv.meets(msrvs::PTR_FROM_REF) {
-                ref_as_ptr::check(cx, expr, cast_expr, cast_to_hir);
+                ref_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
             } else if self.msrv.meets(msrvs::BORROW_AS_PTR) {
-                borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir);
+                borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
             }
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
index 921693567fc..7513e18d408 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -4,7 +4,7 @@ use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 use super::PTR_CAST_CONSTNESS;
 
@@ -24,6 +24,7 @@ pub(super) fn check<'tcx>(
             (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)
         )
         && from_ty == to_ty
+        && !from_ty.has_erased_regions()
     {
         let sugg = Sugg::hir(cx, cast_expr, "_");
         let constness = match *to_mutbl {
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index 92810ea2aa0..0b1ab5411bf 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -1,11 +1,12 @@
 //! lint on manually implemented checked conversions that could be transformed into `try_from`
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
 use rustc_errors::Applicability;
-use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
+use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
@@ -40,9 +41,10 @@ pub struct CheckedConversions {
 }
 
 impl CheckedConversions {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -50,61 +52,54 @@ impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
     fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
-        if !self.msrv.meets(msrvs::TRY_FROM) {
-            return;
-        }
-
-        let result = if !in_constant(cx, item.hir_id)
-            && !in_external_macro(cx.sess(), item.span)
-            && let ExprKind::Binary(op, left, right) = &item.kind
-        {
-            match op.node {
-                BinOpKind::Ge | BinOpKind::Le => single_check(item),
-                BinOpKind::And => double_check(cx, left, right),
-                _ => None,
+        if let ExprKind::Binary(op, lhs, rhs) = item.kind
+            && let (lt1, gt1, op2) = match op.node {
+                BinOpKind::Le => (lhs, rhs, None),
+                BinOpKind::Ge => (rhs, lhs, None),
+                BinOpKind::And
+                    if let ExprKind::Binary(op1, lhs1, rhs1) = lhs.kind
+                        && let ExprKind::Binary(op2, lhs2, rhs2) = rhs.kind
+                        && let Some((lt1, gt1)) = read_le_ge(op1.node, lhs1, rhs1)
+                        && let Some((lt2, gt2)) = read_le_ge(op2.node, lhs2, rhs2) =>
+                {
+                    (lt1, gt1, Some((lt2, gt2)))
+                },
+                _ => return,
             }
-        } else {
-            None
-        };
-
-        if let Some(cv) = result {
-            if let Some(to_type) = cv.to_type {
-                let mut applicability = Applicability::MachineApplicable;
-                let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut applicability);
-                span_lint_and_sugg(
-                    cx,
-                    CHECKED_CONVERSIONS,
-                    item.span,
-                    "checked cast can be simplified",
-                    "try",
-                    format!("{to_type}::try_from({snippet}).is_ok()"),
-                    applicability,
-                );
+            && !in_external_macro(cx.sess(), item.span)
+            && !in_constant(cx, item.hir_id)
+            && self.msrv.meets(msrvs::TRY_FROM)
+            && let Some(cv) = match op2 {
+                // todo: check for case signed -> larger unsigned == only x >= 0
+                None => check_upper_bound(lt1, gt1).filter(|cv| cv.cvt == ConversionType::FromUnsigned),
+                Some((lt2, gt2)) => {
+                    let upper_lower = |lt1, gt1, lt2, gt2| {
+                        check_upper_bound(lt1, gt1)
+                            .zip(check_lower_bound(lt2, gt2))
+                            .and_then(|(l, r)| l.combine(r, cx))
+                    };
+                    upper_lower(lt1, gt1, lt2, gt2).or_else(|| upper_lower(lt2, gt2, lt1, gt1))
+                },
             }
+            && let Some(to_type) = cv.to_type
+        {
+            let mut applicability = Applicability::MachineApplicable;
+            let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut applicability);
+            span_lint_and_sugg(
+                cx,
+                CHECKED_CONVERSIONS,
+                item.span,
+                "checked cast can be simplified",
+                "try",
+                format!("{to_type}::try_from({snippet}).is_ok()"),
+                applicability,
+            );
         }
     }
 
     extract_msrv_attr!(LateContext);
 }
 
-/// Searches for a single check from unsigned to _ is done
-/// todo: check for case signed -> larger unsigned == only x >= 0
-fn single_check<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
-    check_upper_bound(expr).filter(|cv| cv.cvt == ConversionType::FromUnsigned)
-}
-
-/// Searches for a combination of upper & lower bound checks
-fn double_check<'a>(cx: &LateContext<'_>, left: &'a Expr<'_>, right: &'a Expr<'_>) -> Option<Conversion<'a>> {
-    let upper_lower = |l, r| {
-        let upper = check_upper_bound(l);
-        let lower = check_lower_bound(r);
-
-        upper.zip(lower).and_then(|(l, r)| l.combine(r, cx))
-    };
-
-    upper_lower(left, right).or_else(|| upper_lower(right, left))
-}
-
 /// Contains the result of a tried conversion check
 #[derive(Clone, Debug)]
 struct Conversion<'a> {
@@ -121,6 +116,19 @@ enum ConversionType {
     FromUnsigned,
 }
 
+/// Attempts to read either `<=` or `>=` with a normalized operand order.
+fn read_le_ge<'tcx>(
+    op: BinOpKind,
+    lhs: &'tcx Expr<'tcx>,
+    rhs: &'tcx Expr<'tcx>,
+) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> {
+    match op {
+        BinOpKind::Le => Some((lhs, rhs)),
+        BinOpKind::Ge => Some((rhs, lhs)),
+        _ => None,
+    }
+}
+
 impl<'a> Conversion<'a> {
     /// Combine multiple conversions if the are compatible
     pub fn combine(self, other: Self, cx: &LateContext<'_>) -> Option<Conversion<'a>> {
@@ -188,29 +196,17 @@ impl ConversionType {
 }
 
 /// Check for `expr <= (to_type::MAX as from_type)`
-fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
-    if let ExprKind::Binary(ref op, left, right) = &expr.kind
-        && let Some((candidate, check)) = normalize_le_ge(op, left, right)
-        && let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX")
-    {
-        Conversion::try_new(candidate, from, to)
+fn check_upper_bound<'tcx>(lt: &'tcx Expr<'tcx>, gt: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
+    if let Some((from, to)) = get_types_from_cast(gt, INTS, "max_value", "MAX") {
+        Conversion::try_new(lt, from, to)
     } else {
         None
     }
 }
 
 /// Check for `expr >= 0|(to_type::MIN as from_type)`
-fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
-    fn check_function<'a>(candidate: &'a Expr<'a>, check: &'a Expr<'a>) -> Option<Conversion<'a>> {
-        (check_lower_bound_zero(candidate, check)).or_else(|| (check_lower_bound_min(candidate, check)))
-    }
-
-    // First of we need a binary containing the expression & the cast
-    if let ExprKind::Binary(ref op, left, right) = &expr.kind {
-        normalize_le_ge(op, right, left).and_then(|(l, r)| check_function(l, r))
-    } else {
-        None
-    }
+fn check_lower_bound<'tcx>(lt: &'tcx Expr<'tcx>, gt: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
+    check_lower_bound_zero(gt, lt).or_else(|| check_lower_bound_min(gt, lt))
 }
 
 /// Check for `expr >= 0`
@@ -309,15 +305,6 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
     }
 }
 
-/// Will return the expressions as if they were expr1 <= expr2
-fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
-    match op.node {
-        BinOpKind::Le => Some((left, right)),
-        BinOpKind::Ge => Some((right, left)),
-        _ => None,
-    }
-}
-
 // Constants
 const UINTS: &[&str] = &["u8", "u16", "u32", "u64", "usize"];
 const SINTS: &[&str] = &["i8", "i16", "i32", "i64", "isize"];
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 60815f4f2af..5fa0522e4e5 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -1,5 +1,6 @@
 //! calculate cognitive complexity and warn about overly complex functions
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
@@ -39,10 +40,9 @@ pub struct CognitiveComplexity {
 }
 
 impl CognitiveComplexity {
-    #[must_use]
-    pub fn new(limit: u64) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            limit: LimitStack::new(limit),
+            limit: LimitStack::new(conf.cognitive_complexity_threshold),
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
index 07b02c98df1..f311c052ad6 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
@@ -93,20 +93,14 @@ declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
 
 impl EarlyLintPass for CollapsibleIf {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        if !expr.span.from_expansion() {
-            check_if(cx, expr);
-        }
-    }
-}
-
-fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
-    if let ast::ExprKind::If(check, then, else_) = &expr.kind {
-        if let Some(else_) = else_ {
-            check_collapsible_maybe_if_let(cx, then.span, else_);
-        } else if let ast::ExprKind::Let(..) = check.kind {
-            // Prevent triggering on `if let a = b { if c { .. } }`.
-        } else {
-            check_collapsible_no_if_let(cx, expr, check, then);
+        if let ast::ExprKind::If(cond, then, else_) = &expr.kind
+            && !expr.span.from_expansion()
+        {
+            if let Some(else_) = else_ {
+                check_collapsible_maybe_if_let(cx, then.span, else_);
+            } else if !matches!(cond.kind, ast::ExprKind::Let(..)) {
+                check_collapsible_no_if_let(cx, expr, cond, then);
+            }
         }
     }
 }
@@ -189,13 +183,10 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
 
 /// If the block contains only one expression, return it.
 fn expr_block(block: &ast::Block) -> Option<&ast::Expr> {
-    let mut it = block.stmts.iter();
-
-    if let (Some(stmt), None) = (it.next(), it.next()) {
-        match stmt.kind {
-            ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr),
-            _ => None,
-        }
+    if let [stmt] = &*block.stmts
+        && let ast::StmtKind::Expr(expr) | ast::StmtKind::Semi(expr) = &stmt.kind
+    {
+        Some(expr)
     } else {
         None
     }
diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
index 28d9f68d504..eebda3ff76f 100644
--- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
+++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
@@ -59,9 +59,9 @@ static COLLECTIONS: [Symbol; 9] = [
 
 impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
-        // Look for local variables whose type is a container. Search surrounding bock for read access.
-        if match_acceptable_type(cx, local, &COLLECTIONS)
-            && let PatKind::Binding(_, local_id, _, _) = local.pat.kind
+        // Look for local variables whose type is a container. Search surrounding block for read access.
+        if let PatKind::Binding(_, local_id, _, _) = local.pat.kind
+            && match_acceptable_type(cx, local, &COLLECTIONS)
             && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
             && has_no_read_access(cx, local_id, enclosing_block)
         {
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index d896452be92..86e0368c4e4 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
 use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, IntoSpan, SpanRangeExt};
 use clippy_utils::ty::{needs_ordered_drop, InteriorMut};
@@ -11,6 +12,7 @@ use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::hygiene::walk_chain;
 use rustc_span::source_map::SourceMap;
@@ -159,15 +161,13 @@ declare_clippy_lint! {
 }
 
 pub struct CopyAndPaste<'tcx> {
-    ignore_interior_mutability: Vec<String>,
     interior_mut: InteriorMut<'tcx>,
 }
 
-impl CopyAndPaste<'_> {
-    pub fn new(ignore_interior_mutability: Vec<String>) -> Self {
+impl<'tcx> CopyAndPaste<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self {
         Self {
-            ignore_interior_mutability,
-            interior_mut: InteriorMut::default(),
+            interior_mut: InteriorMut::new(tcx, &conf.ignore_interior_mutability),
         }
     }
 }
@@ -180,10 +180,6 @@ impl_lint_pass!(CopyAndPaste<'_> => [
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for CopyAndPaste<'tcx> {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        self.interior_mut = InteriorMut::new(cx, &self.ignore_interior_mutability);
-    }
-
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if !expr.span.from_expansion() && matches!(expr.kind, ExprKind::If(..)) && !is_else_clause(cx.tcx, expr) {
             let (conds, blocks) = if_sequence(expr);
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index adf6f7c4737..678bdbc0ffb 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -53,10 +53,9 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]);
 
 impl EarlyLintPass for CrateInMacroDef {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if item.attrs.iter().any(is_macro_export)
-            && let ItemKind::MacroDef(macro_def) = &item.kind
-            && let tts = macro_def.body.tokens.clone()
-            && let Some(span) = contains_unhygienic_crate_reference(&tts)
+        if let ItemKind::MacroDef(macro_def) = &item.kind
+            && item.attrs.iter().any(is_macro_export)
+            && let Some(span) = contains_unhygienic_crate_reference(&macro_def.body.tokens)
         {
             span_lint_and_sugg(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index b0590b0a71c..788c6f3ada2 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_in_test;
 use clippy_utils::macros::{macro_backtrace, MacroCall};
@@ -33,7 +34,6 @@ declare_clippy_lint! {
     "`dbg!` macro is intended as a debugging tool"
 }
 
-#[derive(Clone)]
 pub struct DbgMacro {
     allow_dbg_in_tests: bool,
     /// Tracks the `dbg!` macro callsites that are already checked.
@@ -45,9 +45,9 @@ pub struct DbgMacro {
 impl_lint_pass!(DbgMacro => [DBG_MACRO]);
 
 impl DbgMacro {
-    pub fn new(allow_dbg_in_tests: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         DbgMacro {
-            allow_dbg_in_tests,
+            allow_dbg_in_tests: conf.allow_dbg_in_tests,
             checked_dbg_call_site: FxHashSet::default(),
             prev_ctxt: SyntaxContext::root(),
         }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index eabc67601a2..69f9eb6842b 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -598,6 +598,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::partialeq_to_none::PARTIALEQ_TO_NONE_INFO,
     crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO,
     crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO,
+    crate::pathbuf_init_then_push::PATHBUF_INIT_THEN_PUSH_INFO,
     crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
     crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
     crate::precedence::PRECEDENCE_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 0c9ad5e8d00..f27f68e2cbc 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::indent_of;
 use clippy_utils::{is_default_equivalent, peel_blocks};
@@ -60,9 +61,10 @@ pub struct DerivableImpls {
 }
 
 impl DerivableImpls {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        DerivableImpls { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        DerivableImpls {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
index 871f529da6c..b51d343132b 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -1,4 +1,5 @@
-use clippy_config::types::DisallowedPath;
+use clippy_config::Conf;
+use clippy_utils::create_disallowed_map;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::macros::macro_backtrace;
 use rustc_ast::Attribute;
@@ -9,6 +10,7 @@ use rustc_hir::{
     Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
 };
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::{ExpnId, MacroKind, Span};
 
@@ -57,27 +59,24 @@ declare_clippy_lint! {
 }
 
 pub struct DisallowedMacros {
-    conf_disallowed: Vec<DisallowedPath>,
-    disallowed: DefIdMap<usize>,
+    disallowed: DefIdMap<(&'static str, Option<&'static str>)>,
     seen: FxHashSet<ExpnId>,
-
     // Track the most recently seen node that can have a `derive` attribute.
     // Needed to use the correct lint level.
     derive_src: Option<OwnerId>,
 }
 
 impl DisallowedMacros {
-    pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         Self {
-            conf_disallowed,
-            disallowed: DefIdMap::default(),
+            disallowed: create_disallowed_map(tcx, &conf.disallowed_macros),
             seen: FxHashSet::default(),
             derive_src: None,
         }
     }
 
     fn check(&mut self, cx: &LateContext<'_>, span: Span, derive_src: Option<OwnerId>) {
-        if self.conf_disallowed.is_empty() {
+        if self.disallowed.is_empty() {
             return;
         }
 
@@ -86,11 +85,10 @@ impl DisallowedMacros {
                 return;
             }
 
-            if let Some(&index) = self.disallowed.get(&mac.def_id) {
-                let conf = &self.conf_disallowed[index];
-                let msg = format!("use of a disallowed macro `{}`", conf.path());
+            if let Some(&(path, reason)) = self.disallowed.get(&mac.def_id) {
+                let msg = format!("use of a disallowed macro `{path}`");
                 let add_note = |diag: &mut Diag<'_, _>| {
-                    if let Some(reason) = conf.reason() {
+                    if let Some(reason) = reason {
                         diag.note(reason);
                     }
                 };
@@ -116,15 +114,6 @@ impl DisallowedMacros {
 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();
-            for id in clippy_utils::def_path_def_ids(cx, &segs) {
-                self.disallowed.insert(id, index);
-            }
-        }
-    }
-
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         self.check(cx, expr.span, None);
         // `$t + $t` can have the context of $t, check also the span of the binary operator
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
index 38fe687f7cc..5a01d76a2a6 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
@@ -1,9 +1,11 @@
-use clippy_config::types::DisallowedPath;
+use clippy_config::Conf;
+use clippy_utils::create_disallowed_map;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 
 declare_clippy_lint! {
@@ -55,17 +57,14 @@ declare_clippy_lint! {
     "use of a disallowed method call"
 }
 
-#[derive(Clone, Debug)]
 pub struct DisallowedMethods {
-    conf_disallowed: Vec<DisallowedPath>,
-    disallowed: DefIdMap<usize>,
+    disallowed: DefIdMap<(&'static str, Option<&'static str>)>,
 }
 
 impl DisallowedMethods {
-    pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         Self {
-            conf_disallowed,
-            disallowed: DefIdMap::default(),
+            disallowed: create_disallowed_map(tcx, &conf.disallowed_methods),
         }
     }
 }
@@ -73,15 +72,6 @@ impl DisallowedMethods {
 impl_lint_pass!(DisallowedMethods => [DISALLOWED_METHODS]);
 
 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();
-            for id in clippy_utils::def_path_def_ids(cx, &segs) {
-                self.disallowed.insert(id, index);
-            }
-        }
-    }
-
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let (id, span) = match &expr.kind {
             ExprKind::Path(path)
@@ -95,14 +85,18 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
             },
             _ => return,
         };
-        if let Some(&index) = self.disallowed.get(&id) {
-            let conf = &self.conf_disallowed[index];
-            let msg = format!("use of a disallowed method `{}`", conf.path());
-            span_lint_and_then(cx, DISALLOWED_METHODS, span, msg, |diag| {
-                if let Some(reason) = conf.reason() {
-                    diag.note(reason);
-                }
-            });
+        if let Some(&(path, reason)) = self.disallowed.get(&id) {
+            span_lint_and_then(
+                cx,
+                DISALLOWED_METHODS,
+                span,
+                format!("use of a disallowed method `{path}`"),
+                |diag| {
+                    if let Some(reason) = reason {
+                        diag.note(reason);
+                    }
+                },
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_names.rs b/src/tools/clippy/clippy_lints/src/disallowed_names.rs
index 58809604c37..f55b0cf1c50 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_names.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_names.rs
@@ -1,9 +1,11 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_in_test;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::{Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
+use rustc_span::Symbol;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -24,15 +26,14 @@ declare_clippy_lint! {
     "usage of a disallowed/placeholder name"
 }
 
-#[derive(Clone, Debug)]
 pub struct DisallowedNames {
-    disallow: FxHashSet<String>,
+    disallow: FxHashSet<Symbol>,
 }
 
 impl DisallowedNames {
-    pub fn new(disallowed_names: &[String]) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            disallow: disallowed_names.iter().cloned().collect(),
+            disallow: conf.disallowed_names.iter().map(|x| Symbol::intern(x)).collect(),
         }
     }
 }
@@ -42,7 +43,7 @@ impl_lint_pass!(DisallowedNames => [DISALLOWED_NAMES]);
 impl<'tcx> LateLintPass<'tcx> for DisallowedNames {
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
         if let PatKind::Binding(.., ident, _) = pat.kind
-            && self.disallow.contains(&ident.name.to_string())
+            && self.disallow.contains(&ident.name)
             && !is_in_test(cx.tcx, pat.hir_id)
         {
             span_lint(
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 5ce11900adf..f79264e6b04 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast;
 use rustc_data_structures::fx::FxHashSet;
@@ -44,19 +45,20 @@ declare_clippy_lint! {
     "usage of non-allowed Unicode scripts"
 }
 
-#[derive(Clone, Debug)]
 pub struct DisallowedScriptIdents {
     whitelist: FxHashSet<Script>,
 }
 
 impl DisallowedScriptIdents {
-    pub fn new(whitelist: &[String]) -> Self {
-        let whitelist = whitelist
-            .iter()
-            .map(String::as_str)
-            .filter_map(Script::from_full_name)
-            .collect();
-        Self { whitelist }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            whitelist: conf
+                .allowed_scripts
+                .iter()
+                .map(String::as_str)
+                .filter_map(Script::from_full_name)
+                .collect(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
index 4196309a22a..3265404f2b2 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
@@ -1,10 +1,11 @@
-use clippy_config::types::DisallowedPath;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::Res;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
@@ -49,60 +50,56 @@ declare_clippy_lint! {
     "use of disallowed types"
 }
 
-#[derive(Clone, Debug)]
 pub struct DisallowedTypes {
-    conf_disallowed: Vec<DisallowedPath>,
-    def_ids: FxHashMap<DefId, usize>,
-    prim_tys: FxHashMap<PrimTy, usize>,
+    def_ids: DefIdMap<(&'static str, Option<&'static str>)>,
+    prim_tys: FxHashMap<PrimTy, (&'static str, Option<&'static str>)>,
 }
 
 impl DisallowedTypes {
-    pub fn new(conf_disallowed: Vec<DisallowedPath>) -> Self {
-        Self {
-            conf_disallowed,
-            def_ids: FxHashMap::default(),
-            prim_tys: FxHashMap::default(),
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
+        let mut def_ids = DefIdMap::default();
+        let mut prim_tys = FxHashMap::default();
+        for x in &conf.disallowed_types {
+            let path: Vec<_> = x.path().split("::").collect::<Vec<_>>();
+            let reason = x.reason();
+            for res in clippy_utils::def_path_res(tcx, &path) {
+                match res {
+                    Res::Def(_, id) => {
+                        def_ids.insert(id, (x.path(), reason));
+                    },
+                    Res::PrimTy(ty) => {
+                        prim_tys.insert(ty, (x.path(), reason));
+                    },
+                    _ => {},
+                }
+            }
         }
+        Self { def_ids, prim_tys }
     }
 
     fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
-        match res {
-            Res::Def(_, did) => {
-                if let Some(&index) = self.def_ids.get(did) {
-                    emit(cx, &cx.tcx.def_path_str(*did), span, &self.conf_disallowed[index]);
-                }
-            },
-            Res::PrimTy(prim) => {
-                if let Some(&index) = self.prim_tys.get(prim) {
-                    emit(cx, prim.name_str(), span, &self.conf_disallowed[index]);
+        let (path, reason) = match res {
+            Res::Def(_, did) if let Some(&x) = self.def_ids.get(did) => x,
+            Res::PrimTy(prim) if let Some(&x) = self.prim_tys.get(prim) => x,
+            _ => return,
+        };
+        span_lint_and_then(
+            cx,
+            DISALLOWED_TYPES,
+            span,
+            format!("use of a disallowed type `{path}`"),
+            |diag| {
+                if let Some(reason) = reason {
+                    diag.note(reason);
                 }
             },
-            _ => {},
-        }
+        );
     }
 }
 
 impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
 
 impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
-    fn check_crate(&mut self, cx: &LateContext<'_>) {
-        for (index, conf) in self.conf_disallowed.iter().enumerate() {
-            let segs: Vec<_> = conf.path().split("::").collect();
-
-            for res in clippy_utils::def_path_res(cx, &segs) {
-                match res {
-                    Res::Def(_, id) => {
-                        self.def_ids.insert(id, index);
-                    },
-                    Res::PrimTy(ty) => {
-                        self.prim_tys.insert(ty, index);
-                    },
-                    _ => {},
-                }
-            }
-        }
-    }
-
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let ItemKind::Use(path, UseKind::Single) = &item.kind {
             for res in &path.res {
@@ -121,17 +118,3 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
         self.check_res_emit(cx, &poly.trait_ref.path.res, poly.trait_ref.path.span);
     }
 }
-
-fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) {
-    span_lint_and_then(
-        cx,
-        DISALLOWED_TYPES,
-        span,
-        format!("`{name}` is not allowed according to config"),
-        |diag| {
-            if let Some(reason) = conf.reason() {
-                diag.note(reason);
-            }
-        },
-    );
-}
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index a2a1a51920f..5b6a5b08aa9 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -1,4 +1,5 @@
 mod lazy_continuation;
+use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
@@ -421,17 +422,16 @@ declare_clippy_lint! {
     "require every line of a paragraph to be indented and marked"
 }
 
-#[derive(Clone)]
 pub struct Documentation {
-    valid_idents: FxHashSet<String>,
+    valid_idents: &'static FxHashSet<String>,
     check_private_items: bool,
 }
 
 impl Documentation {
-    pub fn new(valid_idents: &[String], check_private_items: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            valid_idents: valid_idents.iter().cloned().collect(),
-            check_private_items,
+            valid_idents: &conf.doc_valid_idents,
+            check_private_items: conf.check_private_items,
         }
     }
 }
@@ -452,7 +452,7 @@ impl_lint_pass!(Documentation => [
 
 impl<'tcx> LateLintPass<'tcx> for Documentation {
     fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
-        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
+        let Some(headers) = check_attrs(cx, self.valid_idents, attrs) else {
             return;
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs
index b51bb7951b7..4dd8f01ee70 100644
--- a/src/tools/clippy/clippy_lints/src/double_parens.rs
+++ b/src/tools/clippy/clippy_lints/src/double_parens.rs
@@ -40,35 +40,29 @@ declare_lint_pass!(DoubleParens => [DOUBLE_PARENS]);
 
 impl EarlyLintPass for DoubleParens {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if expr.span.from_expansion() {
-            return;
-        }
-
-        let msg: &str = "consider removing unnecessary double parentheses";
-
-        match expr.kind {
-            ExprKind::Paren(ref in_paren) => match in_paren.kind {
-                ExprKind::Paren(_) | ExprKind::Tup(_) => {
-                    span_lint(cx, DOUBLE_PARENS, expr.span, msg);
-                },
-                _ => {},
-            },
-            ExprKind::Call(_, ref params) => {
-                if params.len() == 1 {
-                    let param = &params[0];
-                    if let ExprKind::Paren(_) = param.kind {
-                        span_lint(cx, DOUBLE_PARENS, param.span, msg);
-                    }
-                }
+        let span = match &expr.kind {
+            ExprKind::Paren(in_paren) if matches!(in_paren.kind, ExprKind::Paren(_) | ExprKind::Tup(_)) => expr.span,
+            ExprKind::Call(_, params)
+                if let [param] = &**params
+                    && let ExprKind::Paren(_) = param.kind =>
+            {
+                param.span
             },
-            ExprKind::MethodCall(ref call) => {
-                if let [ref arg] = call.args[..] {
-                    if let ExprKind::Paren(_) = arg.kind {
-                        span_lint(cx, DOUBLE_PARENS, arg.span, msg);
-                    }
-                }
+            ExprKind::MethodCall(call)
+                if let [arg] = &*call.args
+                    && let ExprKind::Paren(_) = arg.kind =>
+            {
+                arg.span
             },
-            _ => {},
+            _ => return,
+        };
+        if !expr.span.from_expansion() {
+            span_lint(
+                cx,
+                DOUBLE_PARENS,
+                span,
+                "consider removing unnecessary double parentheses",
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
index bb6f9aac223..7a6dc469727 100644
--- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
+++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
@@ -50,12 +50,9 @@ declare_lint_pass!(ElseIfWithoutElse => [ELSE_IF_WITHOUT_ELSE]);
 
 impl EarlyLintPass for ElseIfWithoutElse {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
-        if in_external_macro(cx.sess(), item.span) {
-            return;
-        }
-
         if let ExprKind::If(_, _, Some(ref els)) = item.kind
             && let ExprKind::If(_, _, None) = els.kind
+            && !in_external_macro(cx.sess(), item.span)
         {
             span_lint_and_help(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs
index d16714695cb..1869faab1d3 100644
--- a/src/tools/clippy/clippy_lints/src/empty_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs
@@ -64,25 +64,21 @@ declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]);
 
 impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        // Only suggest the `never_type` if the feature is enabled
-        if !cx.tcx.features().never_type {
-            return;
-        }
-
-        if let ItemKind::Enum(..) = item.kind {
-            let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
-            if adt.variants().is_empty() {
-                span_lint_and_help(
-                    cx,
-                    EMPTY_ENUM,
-                    item.span,
-                    "enum with no variants",
-                    None,
-                    "consider using the uninhabited type `!` (never type) or a wrapper \
-                    around it to introduce a type which can't be instantiated",
-                );
-            }
+        if let ItemKind::Enum(..) = item.kind
+            // Only suggest the `never_type` if the feature is enabled
+            && cx.tcx.features().never_type
+            && let Some(adt) = cx.tcx.type_of(item.owner_id).instantiate_identity().ty_adt_def()
+            && adt.variants().is_empty()
+        {
+            span_lint_and_help(
+                cx,
+                EMPTY_ENUM,
+                item.span,
+                "enum with no variants",
+                None,
+                "consider using the uninhabited type `!` (never type) or a wrapper \
+                around it to introduce a type which can't be instantiated",
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/endian_bytes.rs b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
index 99328e3e643..5bba9c562b9 100644
--- a/src/tools/clippy/clippy_lints/src/endian_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
@@ -109,32 +109,27 @@ impl LintKind {
 
 impl LateLintPass<'_> for EndianBytes {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if in_external_macro(cx.sess(), expr.span) {
-            return;
-        }
-
-        if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind
-            && args.is_empty()
-            && let ty = cx.typeck_results().expr_ty(receiver)
+        let (prefix, name, ty_expr) = match expr.kind {
+            ExprKind::MethodCall(method_name, receiver, [], ..) => (Prefix::To, method_name.ident.name, receiver),
+            ExprKind::Call(function, ..)
+                if let ExprKind::Path(qpath) = function.kind
+                    && let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id()
+                    && let Some(function_name) = cx.get_def_path(def_id).last() =>
+            {
+                (Prefix::From, *function_name, expr)
+            },
+            _ => return,
+        };
+        if !in_external_macro(cx.sess(), expr.span)
+            && let ty = cx.typeck_results().expr_ty(ty_expr)
             && ty.is_primitive_ty()
-            && maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty)
         {
-            return;
-        }
-
-        if let ExprKind::Call(function, ..) = expr.kind
-            && let ExprKind::Path(qpath) = function.kind
-            && let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id()
-            && let Some(function_name) = cx.get_def_path(def_id).last()
-            && let ty = cx.typeck_results().expr_ty(expr)
-            && ty.is_primitive_ty()
-        {
-            maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty);
+            maybe_lint_endian_bytes(cx, expr, prefix, name, ty);
         }
     }
 }
 
-fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix, name: Symbol, ty: Ty<'_>) -> bool {
+fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix, name: Symbol, ty: Ty<'_>) {
     let ne = LintKind::Host.as_name(prefix);
     let le = LintKind::Little.as_name(prefix);
     let be = LintKind::Big.as_name(prefix);
@@ -143,7 +138,7 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
         name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]),
         name if name == le => ((&LintKind::Little), [(&LintKind::Host), (&LintKind::Big)]),
         name if name == be => ((&LintKind::Big), [(&LintKind::Host), (&LintKind::Little)]),
-        _ => return false,
+        _ => return,
     };
 
     let mut help = None;
@@ -208,6 +203,4 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
             }
         },
     );
-
-    true
 }
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 37442bf3e28..fb9f2b1526e 100644
--- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
+++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
@@ -70,9 +70,9 @@ fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: T
 
 impl<'tcx> LateLintPass<'tcx> for PatternEquality {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if !in_external_macro(cx.sess(), expr.span)
-            && let ExprKind::Let(let_expr) = expr.kind
+        if let ExprKind::Let(let_expr) = expr.kind
             && unary_pattern(let_expr.pat)
+            && !in_external_macro(cx.sess(), expr.span)
         {
             let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
             let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);
diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs
index 8e49138cd26..1e6447dc253 100644
--- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs
+++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs
@@ -36,15 +36,12 @@ declare_lint_pass!(ErrorImplError => [ERROR_IMPL_ERROR]);
 
 impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error) else {
-            return;
-        };
-
         match item.kind {
             ItemKind::TyAlias(..)
                 if item.ident.name == sym::Error
                     && is_visible_outside_module(cx, item.owner_id.def_id)
                     && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
+                    && let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
                     && implements_trait(cx, ty, error_def_id, &[]) =>
             {
                 span_lint(
@@ -56,9 +53,9 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
             },
             ItemKind::Impl(imp)
                 if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
+                    && let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
                     && error_def_id == trait_def_id
                     && let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
-                    && let hir_id = cx.tcx.local_def_id_to_hir_id(def_id)
                     && let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id())
                     && ident.name == sym::Error
                     && is_visible_outside_module(cx, def_id) =>
@@ -66,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
                 span_lint_hir_and_then(
                     cx,
                     ERROR_IMPL_ERROR,
-                    hir_id,
+                    cx.tcx.local_def_id_to_hir_id(def_id),
                     ident.span,
                     "exported type named `Error` that implements `Error`",
                     |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 8d6e27700d8..a5da52b0be5 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir;
 use rustc_hir::{intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
@@ -11,9 +12,16 @@ use rustc_span::symbol::kw;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
-#[derive(Copy, Clone)]
 pub struct BoxedLocal {
-    pub too_large_for_stack: u64,
+    too_large_for_stack: u64,
+}
+
+impl BoxedLocal {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            too_large_for_stack: conf.too_large_for_stack,
+        }
+    }
 }
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index 62d5ce24d40..8f469efb1b5 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::{get_parent_as_impl, has_repr_attr, is_bool};
 use rustc_hir::intravisit::FnKind;
@@ -87,69 +88,57 @@ pub struct ExcessiveBools {
     max_fn_params_bools: u64,
 }
 
-#[derive(Eq, PartialEq, Debug, Copy, Clone)]
-enum Kind {
-    Struct,
-    Fn,
-}
-
 impl ExcessiveBools {
-    #[must_use]
-    pub fn new(max_struct_bools: u64, max_fn_params_bools: u64) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            max_struct_bools,
-            max_fn_params_bools,
+            max_struct_bools: conf.max_struct_bools,
+            max_fn_params_bools: conf.max_fn_params_bools,
         }
     }
+}
 
-    fn too_many_bools<'tcx>(&self, tys: impl Iterator<Item = &'tcx Ty<'tcx>>, kind: Kind) -> bool {
-        if let Ok(bools) = tys.filter(|ty| is_bool(ty)).count().try_into() {
-            (if Kind::Fn == kind {
-                self.max_fn_params_bools
-            } else {
-                self.max_struct_bools
-            }) < bools
-        } else {
-            false
-        }
-    }
+impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_BOOLS]);
 
-    fn check_fn_sig(&self, cx: &LateContext<'_>, fn_decl: &FnDecl<'_>, span: Span) {
-        if !span.from_expansion() && self.too_many_bools(fn_decl.inputs.iter(), Kind::Fn) {
-            span_lint_and_help(
-                cx,
-                FN_PARAMS_EXCESSIVE_BOOLS,
-                span,
-                format!("more than {} bools in function parameters", self.max_fn_params_bools),
-                None,
-                "consider refactoring bools into two-variant enums",
-            );
-        }
-    }
+fn has_n_bools<'tcx>(iter: impl Iterator<Item = &'tcx Ty<'tcx>>, mut count: u64) -> bool {
+    iter.filter(|ty| is_bool(ty)).any(|_| {
+        let (x, overflow) = count.overflowing_sub(1);
+        count = x;
+        overflow
+    })
 }
 
-impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_BOOLS]);
+fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) {
+    if has_n_bools(decl.inputs.iter(), max) && !sp.from_expansion() {
+        span_lint_and_help(
+            cx,
+            FN_PARAMS_EXCESSIVE_BOOLS,
+            sp,
+            format!("more than {max} bools in function parameters"),
+            None,
+            "consider refactoring bools into two-variant enums",
+        );
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if item.span.from_expansion() {
-            return;
-        }
-        if let ItemKind::Struct(variant_data, _) = &item.kind {
-            if has_repr_attr(cx, item.hir_id()) {
-                return;
-            }
-
-            if self.too_many_bools(variant_data.fields().iter().map(|field| field.ty), Kind::Struct) {
-                span_lint_and_help(
-                    cx,
-                    STRUCT_EXCESSIVE_BOOLS,
-                    item.span,
-                    format!("more than {} bools in a struct", self.max_struct_bools),
-                    None,
-                    "consider using a state machine or refactoring bools into two-variant enums",
-                );
-            }
+        if let ItemKind::Struct(variant_data, _) = &item.kind
+            && variant_data.fields().len() as u64 > self.max_struct_bools
+            && has_n_bools(
+                variant_data.fields().iter().map(|field| field.ty),
+                self.max_struct_bools,
+            )
+            && !has_repr_attr(cx, item.hir_id())
+            && !item.span.from_expansion()
+        {
+            span_lint_and_help(
+                cx,
+                STRUCT_EXCESSIVE_BOOLS,
+                item.span,
+                format!("more than {} bools in a struct", self.max_struct_bools),
+                None,
+                "consider using a state machine or refactoring bools into two-variant enums",
+            );
         }
     }
 
@@ -157,8 +146,9 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
         // functions with a body are already checked by `check_fn`
         if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind
             && fn_sig.header.abi == Abi::Rust
+            && fn_sig.decl.inputs.len() as u64 > self.max_fn_params_bools
         {
-            self.check_fn_sig(cx, fn_sig.decl, fn_sig.span);
+            check_fn_decl(cx, fn_sig.decl, fn_sig.span, self.max_fn_params_bools);
         }
     }
 
@@ -171,12 +161,13 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
         span: Span,
         def_id: LocalDefId,
     ) {
-        let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
         if let Some(fn_header) = fn_kind.header()
             && fn_header.abi == Abi::Rust
-            && get_parent_as_impl(cx.tcx, hir_id).map_or(true, |impl_item| impl_item.of_trait.is_none())
+            && fn_decl.inputs.len() as u64 > self.max_fn_params_bools
+            && get_parent_as_impl(cx.tcx, cx.tcx.local_def_id_to_hir_id(def_id))
+                .map_or(true, |impl_item| impl_item.of_trait.is_none())
         {
-            self.check_fn_sig(cx, fn_decl, span);
+            check_fn_decl(cx, fn_decl, span, self.max_fn_params_bools);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index 4b0d11c5d1b..5154edd4399 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet;
 use rustc_ast::node_id::NodeSet;
@@ -63,13 +64,19 @@ declare_clippy_lint! {
 }
 impl_lint_pass!(ExcessiveNesting => [EXCESSIVE_NESTING]);
 
-#[derive(Clone)]
 pub struct ExcessiveNesting {
     pub excessive_nesting_threshold: u64,
     pub nodes: NodeSet,
 }
 
 impl ExcessiveNesting {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            excessive_nesting_threshold: conf.excessive_nesting_threshold,
+            nodes: NodeSet::default(),
+        }
+    }
+
     pub fn check_node_id(&self, cx: &EarlyContext<'_>, span: Span, node_id: NodeId) {
         if self.nodes.contains(&node_id) {
             span_lint_and_help(
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 436dc8611bd..0f4176ec73b 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -70,20 +70,24 @@ declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS, EXHAUSTIVE_STRUCTS]);
 
 impl LateLintPass<'_> for ExhaustiveItems {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind
-            && cx.effective_visibilities.is_exported(item.owner_id.def_id)
+        let (lint, msg, fields) = match item.kind {
+            ItemKind::Enum(..) => (
+                EXHAUSTIVE_ENUMS,
+                "exported enums should not be exhaustive",
+                [].as_slice(),
+            ),
+            ItemKind::Struct(v, ..) => (
+                EXHAUSTIVE_STRUCTS,
+                "exported structs should not be exhaustive",
+                v.fields(),
+            ),
+            _ => return,
+        };
+        if cx.effective_visibilities.is_exported(item.owner_id.def_id)
             && let attrs = cx.tcx.hir().attrs(item.hir_id())
             && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
+            && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
         {
-            let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
-                if v.fields().iter().any(|f| !cx.tcx.visibility(f.def_id).is_public()) {
-                    // skip structs with private fields
-                    return;
-                }
-                (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive")
-            } else {
-                (EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive")
-            };
             let suggestion_span = item.span.shrink_to_lo();
             let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
             span_lint_and_then(cx, lint, item.span, msg, |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs
index 91c94d66458..f37d11f7eb9 100644
--- a/src/tools/clippy/clippy_lints/src/exit.rs
+++ b/src/tools/clippy/clippy_lints/src/exit.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_entrypoint_fn;
-use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
+use rustc_hir::{Expr, ExprKind, Item, ItemKind, OwnerNode};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
@@ -47,8 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
             && let ExprKind::Path(ref path) = path_expr.kind
             && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
             && cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
-            && let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id
-            && let Node::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_node_by_def_id(parent)
+            && let parent = cx.tcx.hir().get_parent_item(e.hir_id)
+            && let OwnerNode::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_owner_node(parent)
             // If the next item up is a function we check if it is an entry point
             // and only then emit a linter warning
             && !is_entrypoint_fn(cx, parent.to_def_id())
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 7484f772e08..bfe4e253ae4 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::{is_from_proc_macro, trait_ref_of_method};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -45,26 +46,11 @@ pub struct ExtraUnusedTypeParameters {
 }
 
 impl ExtraUnusedTypeParameters {
-    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            avoid_breaking_exported_api,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
         }
     }
-
-    /// Don't lint external macros or functions with empty bodies. Also, don't lint exported items
-    /// if the `avoid_breaking_exported_api` config option is set.
-    fn is_empty_exported_or_macro(
-        &self,
-        cx: &LateContext<'_>,
-        span: Span,
-        def_id: LocalDefId,
-        body_id: BodyId,
-    ) -> bool {
-        let body = cx.tcx.hir().body(body_id).value;
-        let fn_empty = matches!(&body.kind, ExprKind::Block(blk, None) if blk.stmts.is_empty() && blk.expr.is_none());
-        let is_exported = cx.effective_visibilities.is_exported(def_id);
-        in_external_macro(cx.sess(), span) || fn_empty || (is_exported && self.avoid_breaking_exported_api)
-    }
 }
 
 impl_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]);
@@ -266,10 +252,17 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
     }
 }
 
+fn is_empty_body(cx: &LateContext<'_>, body: BodyId) -> bool {
+    matches!(cx.tcx.hir().body(body).value.kind, ExprKind::Block(b, _) if b.stmts.is_empty() && b.expr.is_none())
+}
+
 impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let ItemKind::Fn(_, generics, body_id) = item.kind
-            && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id)
+            && !generics.params.is_empty()
+            && !is_empty_body(cx, body_id)
+            && (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id))
+            && !in_external_macro(cx.sess(), item.span)
             && !is_from_proc_macro(cx, item)
         {
             let mut walker = TypeWalker::new(cx, generics);
@@ -281,8 +274,12 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
         // Only lint on inherent methods, not trait methods.
         if let ImplItemKind::Fn(.., body_id) = item.kind
+            && !item.generics.params.is_empty()
             && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
-            && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id)
+            && !is_empty_body(cx, body_id)
+            && (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id))
+            && !in_external_macro(cx.sess(), item.span)
+            && !is_from_proc_macro(cx, item)
         {
             let mut walker = TypeWalker::new(cx, item.generics);
             walk_impl_item(&mut walker, item);
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 2261fcdbdab..6adcd2235dc 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -62,10 +62,9 @@ declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]);
 
 impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        let ty = cx.typeck_results().expr_ty(expr);
-        if let ty::Float(fty) = *ty.kind()
-            && let hir::ExprKind::Lit(lit) = expr.kind
+        if let hir::ExprKind::Lit(lit) = expr.kind
             && let LitKind::Float(sym, lit_float_ty) = lit.node
+            && let ty::Float(fty) = *cx.typeck_results().expr_ty(expr).kind()
         {
             let sym_str = sym.as_str();
             let formatter = FloatFormat::new(sym_str);
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 99def199af0..a31d5cb6ec7 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -1,5 +1,6 @@
 use arrayvec::ArrayVec;
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::is_diag_trait_item;
 use clippy_utils::macros::{
@@ -175,12 +176,11 @@ pub struct FormatArgs {
 }
 
 impl FormatArgs {
-    #[must_use]
-    pub fn new(format_args: FormatArgsStorage, msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self {
+    pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self {
         Self {
             format_args,
-            msrv,
-            ignore_mixed: allow_mixed_uninlined_format_args,
+            msrv: conf.msrv.clone(),
+            ignore_mixed: conf.allow_mixed_uninlined_format_args,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index 09be7237b5c..e6f27cb82d1 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -97,7 +97,6 @@ struct FormatTraitNames {
     formatter_name: Option<Symbol>,
 }
 
-#[derive(Default)]
 pub struct FormatImpl {
     format_args: FormatArgsStorage,
     // Whether we are inside Display or Debug trait impl - None for neither
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 1933a00891b..1c1d8b57bc4 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::span_is_local;
 use clippy_utils::path_def_id;
@@ -54,9 +55,10 @@ pub struct FromOverInto {
 }
 
 impl FromOverInto {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        FromOverInto { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        FromOverInto {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -64,10 +66,6 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
 
 impl<'tcx> LateLintPass<'tcx> for FromOverInto {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if !self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) {
-            return;
-        }
-
         if let ItemKind::Impl(Impl {
             of_trait: Some(hir_trait_ref),
             self_ty,
@@ -77,6 +75,8 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
             && let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
             // `impl Into<target_ty> for self_ty`
             && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
+            && self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE)
+            && span_is_local(item.span)
             && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
                                                   .map(ty::EarlyBinder::instantiate_identity)
             && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
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 82ce501bac5..9acb72b2e37 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
@@ -47,9 +47,13 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) {
         if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind
             && let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind
-            // do not lint in constant context, because the suggestion won't work.
-            // NB: keep this check until a new `const_trait_impl` is available and stablized.
-            && !in_constant(cx, exp.hir_id)
+
+            // check if the second argument is a primitive `10`
+            && is_integer_literal(radix, 10)
+
+            // check if the second part of the path indeed calls the associated
+            // function `from_str_radix`
+            && pathseg.ident.name.as_str() == "from_str_radix"
 
             // check if the first part of the path is some integer primitive
             && let TyKind::Path(ty_qpath) = &ty.kind
@@ -57,12 +61,9 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
             && let def::Res::PrimTy(prim_ty) = ty_res
             && matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_))
 
-            // check if the second part of the path indeed calls the associated
-            // function `from_str_radix`
-            && pathseg.ident.name.as_str() == "from_str_radix"
-
-            // check if the second argument is a primitive `10`
-            && is_integer_literal(radix, 10)
+            // do not lint in constant context, because the suggestion won't work.
+            // NB: keep this check until a new `const_trait_impl` is available and stablized.
+            && !in_constant(cx, exp.hir_id)
         {
             let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
                 let ty = cx.typeck_results().expr_ty(expr);
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 26534492ddd..0f48941783b 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -7,10 +7,12 @@ mod result;
 mod too_many_arguments;
 mod too_many_lines;
 
+use clippy_config::Conf;
 use clippy_utils::def_path_def_ids;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::{DefIdSet, LocalDefId};
 use rustc_span::Span;
@@ -391,39 +393,34 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
-    #[clippy::version = "1.74.0"]
+    #[clippy::version = "1.80.0"]
     pub RENAMED_FUNCTION_PARAMS,
     restriction,
     "renamed function parameters in trait implementation"
 }
 
-#[derive(Clone)]
 pub struct Functions {
     too_many_arguments_threshold: u64,
     too_many_lines_threshold: u64,
     large_error_threshold: u64,
     avoid_breaking_exported_api: bool,
-    allow_renamed_params_for: Vec<String>,
     /// A set of resolved `def_id` of traits that are configured to allow
     /// function params renaming.
     trait_ids: DefIdSet,
 }
 
 impl Functions {
-    pub fn new(
-        too_many_arguments_threshold: u64,
-        too_many_lines_threshold: u64,
-        large_error_threshold: u64,
-        avoid_breaking_exported_api: bool,
-        allow_renamed_params_for: Vec<String>,
-    ) -> Self {
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         Self {
-            too_many_arguments_threshold,
-            too_many_lines_threshold,
-            large_error_threshold,
-            avoid_breaking_exported_api,
-            allow_renamed_params_for,
-            trait_ids: DefIdSet::default(),
+            too_many_arguments_threshold: conf.too_many_arguments_threshold,
+            too_many_lines_threshold: conf.too_many_lines_threshold,
+            large_error_threshold: conf.large_error_threshold,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
+            trait_ids: conf
+                .allow_renamed_params_for
+                .iter()
+                .flat_map(|p| def_path_def_ids(tcx, &p.split("::").collect::<Vec<_>>()))
+                .collect(),
         }
     }
 }
@@ -479,12 +476,4 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
         result::check_trait_item(cx, item, self.large_error_threshold);
         impl_trait_in_params::check_trait_item(cx, item, self.avoid_breaking_exported_api);
     }
-
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        for path in &self.allow_renamed_params_for {
-            let path_segments: Vec<&str> = path.split("::").collect();
-            let ids = def_path_def_ids(cx, &path_segments);
-            self.trait_ids.extend(ids);
-        }
-    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index e6506709774..9488ba75686 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -66,15 +66,11 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
         let ret_ty = return_ty(cx, cx.tcx.local_def_id_to_hir_id(fn_def_id).expect_owner());
         if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() {
             let preds = cx.tcx.explicit_item_super_predicates(def_id);
-            let mut is_future = false;
-            for (p, _span) in preds.iter_instantiated_copied(cx.tcx, args) {
-                if let Some(trait_pred) = p.as_trait_clause() {
-                    if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
-                        is_future = true;
-                        break;
-                    }
-                }
-            }
+            let is_future = preds.iter_instantiated_copied(cx.tcx, args).any(|(p, _)| {
+                p.as_trait_clause().is_some_and(|trait_pred| {
+                    Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait()
+                })
+            });
             if is_future {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
index a55836a972f..b38cc7b36a1 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
@@ -1,8 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{higher, SpanlessEq};
+use core::ops::ControlFlow;
 use rustc_errors::Diag;
-use rustc_hir::intravisit::{self as visit, Visitor};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -44,8 +45,6 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]);
 
 impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        let mut arm_visit = ArmVisitor { found_mutex: None, cx };
-        let mut op_visit = OppVisitor { found_mutex: None, cx };
         if let Some(higher::IfLet {
             let_expr,
             if_then,
@@ -53,12 +52,20 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
             ..
         }) = higher::IfLet::hir(cx, expr)
         {
-            op_visit.visit_expr(let_expr);
-            if let Some(op_mutex) = op_visit.found_mutex {
-                arm_visit.visit_expr(if_then);
-                arm_visit.visit_expr(if_else);
+            let is_mutex_lock = |e: &'tcx Expr<'tcx>| {
+                if let Some(mutex) = is_mutex_lock_call(cx, e) {
+                    ControlFlow::Break(mutex)
+                } else {
+                    ControlFlow::Continue(())
+                }
+            };
 
-                if let Some(arm_mutex) = arm_visit.found_mutex_if_same_as(op_mutex) {
+            let op_mutex = for_each_expr_without_closures(let_expr, is_mutex_lock);
+            if let Some(op_mutex) = op_mutex {
+                let arm_mutex = for_each_expr_without_closures((if_then, if_else), is_mutex_lock);
+                if let Some(arm_mutex) = arm_mutex
+                    && SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex)
+                {
                     let diag = |diag: &mut Diag<'_, ()>| {
                         diag.span_label(
                             op_mutex.span,
@@ -83,48 +90,6 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
     }
 }
 
-/// Checks if `Mutex::lock` is called in the `if let` expr.
-pub struct OppVisitor<'a, 'tcx> {
-    found_mutex: Option<&'tcx Expr<'tcx>>,
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'tcx> Visitor<'tcx> for OppVisitor<'_, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if let Some(mutex) = is_mutex_lock_call(self.cx, expr) {
-            self.found_mutex = Some(mutex);
-            return;
-        }
-        visit::walk_expr(self, expr);
-    }
-}
-
-/// Checks if `Mutex::lock` is called in any of the branches.
-pub struct ArmVisitor<'a, 'tcx> {
-    found_mutex: Option<&'tcx Expr<'tcx>>,
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'tcx> Visitor<'tcx> for ArmVisitor<'_, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if let Some(mutex) = is_mutex_lock_call(self.cx, expr) {
-            self.found_mutex = Some(mutex);
-            return;
-        }
-        visit::walk_expr(self, expr);
-    }
-}
-
-impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
-    fn found_mutex_if_same_as(&self, op_mutex: &Expr<'_>) -> Option<&Expr<'_>> {
-        self.found_mutex.and_then(|arm_mutex| {
-            SpanlessEq::new(self.cx)
-                .eq_expr(op_mutex, arm_mutex)
-                .then_some(arm_mutex)
-        })
-    }
-}
-
 fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
         && path.ident.as_str() == "lock"
diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs
index 4dc1ff83771..2f6daeeb90d 100644
--- a/src/tools/clippy/clippy_lints/src/if_not_else.rs
+++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs
@@ -56,44 +56,33 @@ fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
 }
 
 impl LateLintPass<'_> for IfNotElse {
-    fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
-        // While loops will be desugared to ExprKind::If. This will cause the lint to fire.
-        // To fix this, return early if this span comes from a macro or desugaring.
-        if item.span.from_expansion() {
-            return;
-        }
-        if let ExprKind::If(cond, _, Some(els)) = item.kind {
-            if let ExprKind::Block(..) = els.kind {
-                // Disable firing the lint in "else if" expressions.
-                if is_else_clause(cx.tcx, item) {
-                    return;
-                }
+    fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
+        if let ExprKind::If(cond, _, Some(els)) = e.kind
+            && let ExprKind::DropTemps(cond) = cond.kind
+            && let ExprKind::Block(..) = els.kind
+        {
+            let (msg, help) = match cond.kind {
+                ExprKind::Unary(UnOp::Not, _) => (
+                    "unnecessary boolean `not` operation",
+                    "remove the `!` and swap the blocks of the `if`/`else`",
+                ),
+                // Don't lint on `… != 0`, as these are likely to be bit tests.
+                // For example, `if foo & 0x0F00 != 0 { … } else { … }` is already in the "proper" order.
+                ExprKind::Binary(op, _, rhs) if op.node == BinOpKind::Ne && !is_zero_const(rhs, cx) => (
+                    "unnecessary `!=` operation",
+                    "change to `==` and swap the blocks of the `if`/`else`",
+                ),
+                _ => return,
+            };
 
-                match cond.peel_drop_temps().kind {
-                    ExprKind::Unary(UnOp::Not, _) => {
-                        span_lint_and_help(
-                            cx,
-                            IF_NOT_ELSE,
-                            item.span,
-                            "unnecessary boolean `not` operation",
-                            None,
-                            "remove the `!` and swap the blocks of the `if`/`else`",
-                        );
-                    },
-                    ExprKind::Binary(ref kind, _, lhs) if kind.node == BinOpKind::Ne && !is_zero_const(lhs, cx) => {
-                        // Disable firing the lint on `… != 0`, as these are likely to be bit tests.
-                        // For example, `if foo & 0x0F00 != 0 { … } else { … }` already is in the "proper" order.
-                        span_lint_and_help(
-                            cx,
-                            IF_NOT_ELSE,
-                            item.span,
-                            "unnecessary `!=` operation",
-                            None,
-                            "change to `==` and swap the blocks of the `if`/`else`",
-                        );
-                    },
-                    _ => (),
-                }
+            // `from_expansion` will also catch `while` loops which appear in the HIR as:
+            // ```rust
+            // loop {
+            //     if cond { ... } else { break; }
+            // }
+            // ```
+            if !e.span.from_expansion() && !is_else_clause(cx.tcx, e) {
+                span_lint_and_help(cx, IF_NOT_ELSE, e.span, msg, None, help);
             }
         }
     }
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 0b200815219..39ea16b05d1 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,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::source::snippet_with_context;
@@ -51,9 +52,10 @@ pub struct IfThenSomeElseNone {
 }
 
 impl IfThenSomeElseNone {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -61,26 +63,6 @@ impl_lint_pass!(IfThenSomeElseNone => [IF_THEN_SOME_ELSE_NONE]);
 
 impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if !self.msrv.meets(msrvs::BOOL_THEN) {
-            return;
-        }
-
-        if in_external_macro(cx.sess(), expr.span) {
-            return;
-        }
-
-        // We only care about the top-most `if` in the chain
-        if is_else_clause(cx.tcx, expr) {
-            return;
-        }
-
-        // `bool::then()` and `bool::then_some()` are not const
-        if in_constant(cx, expr.hir_id) {
-            return;
-        }
-
-        let ctxt = expr.span.ctxt();
-
         if let Some(higher::If {
             cond,
             then,
@@ -89,9 +71,14 @@ 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 ctxt = expr.span.ctxt()
             && then_expr.span.ctxt() == ctxt
             && is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
             && is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
+            && !is_else_clause(cx.tcx, expr)
+            && !in_constant(cx, expr.hir_id)
+            && !in_external_macro(cx.sess(), expr.span)
+            && self.msrv.meets(msrvs::BOOL_THEN)
             && !contains_return(then_block.stmts)
         {
             let mut app = Applicability::Unspecified;
diff --git a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
index a32201d8079..54b8adbc8ac 100644
--- a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
@@ -37,22 +37,21 @@ declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]);
 
 impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
-        if pat.span.from_expansion() {
-            return;
-        }
-
-        match cx.tcx.parent_hir_node(pat.hir_id) {
-            Node::Param(param) if matches!(cx.tcx.parent_hir_node(param.hir_id), Node::Item(_)) => {
-                // Ignore function parameters
-                return;
-            },
-            Node::LetStmt(local) if local.ty.is_some() => {
-                // Ignore let bindings with explicit type
-                return;
-            },
-            _ => {},
-        }
-        if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).peel_refs().is_unit() {
+        if matches!(pat.kind, PatKind::Wild)
+            && !pat.span.from_expansion()
+            && cx.typeck_results().pat_ty(pat).peel_refs().is_unit()
+        {
+            match cx.tcx.parent_hir_node(pat.hir_id) {
+                Node::Param(param) if matches!(cx.tcx.parent_hir_node(param.hir_id), Node::Item(_)) => {
+                    // Ignore function parameters
+                    return;
+                },
+                Node::LetStmt(local) if local.ty.is_some() => {
+                    // Ignore let bindings with explicit type
+                    return;
+                },
+                _ => {},
+            }
             span_lint_and_sugg(
                 cx,
                 IGNORED_UNIT_PATTERNS,
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index 5c63d48adaf..12ca6d43b27 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::Msrv;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_in_test;
 use rustc_attr::{StabilityLevel, StableSince};
@@ -47,9 +48,9 @@ pub struct IncompatibleMsrv {
 impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]);
 
 impl IncompatibleMsrv {
-    pub fn new(msrv: Msrv) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            msrv,
+            msrv: conf.msrv.clone(),
             is_above_msrv: FxHashMap::default(),
         }
     }
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 1075975f0a2..5b0aadf35c6 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -65,13 +65,13 @@ declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRU
 
 impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if !expr.span.from_expansion()
-            && let ExprKind::Struct(qpath, fields, base) = expr.kind
+        if let ExprKind::Struct(qpath, fields, base) = expr.kind
+            && fields.iter().all(|f| f.is_shorthand)
+            && !expr.span.from_expansion()
             && let ty = cx.typeck_results().expr_ty(expr)
             && let Some(adt_def) = ty.ty_adt_def()
             && adt_def.is_struct()
             && let Some(variant) = adt_def.variants().iter().next()
-            && fields.iter().all(|f| f.is_shorthand)
         {
             let mut def_order_map = FxHashMap::default();
             for (idx, field) in variant.fields.iter().enumerate() {
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 128461ce7bc..526b4e1fba0 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLet;
@@ -58,10 +59,10 @@ pub struct IndexRefutableSlice {
 }
 
 impl IndexRefutableSlice {
-    pub fn new(max_suggested_slice_pattern_length: u64, msrv: Msrv) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            max_suggested_slice: max_suggested_slice_pattern_length,
-            msrv,
+            max_suggested_slice: conf.max_suggested_slice_pattern_length,
+            msrv: conf.msrv.clone(),
         }
     }
 }
@@ -70,8 +71,8 @@ impl_lint_pass!(IndexRefutableSlice => [INDEX_REFUTABLE_SLICE]);
 
 impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if (!expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some())
-            && let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr)
+        if let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr)
+            && (!expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some())
             && !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id)
             && self.msrv.meets(msrvs::SLICE_PATTERNS)
             && let found_slices = find_slice_values(cx, let_pat)
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index d54f2af65cd..6729c7c8d10 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -1,5 +1,6 @@
 //! lint on indexing and slicing operations
 
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::ty::{deref_chain, get_adt_inherent_method};
@@ -87,28 +88,22 @@ declare_clippy_lint! {
 
 impl_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
 
-#[derive(Copy, Clone)]
 pub struct IndexingSlicing {
     suppress_restriction_lint_in_const: bool,
 }
 
 impl IndexingSlicing {
-    pub fn new(suppress_restriction_lint_in_const: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            suppress_restriction_lint_in_const,
+            suppress_restriction_lint_in_const: conf.suppress_restriction_lint_in_const,
         }
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if (self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id))
-            || is_from_proc_macro(cx, expr)
-        {
-            return;
-        }
-
         if let ExprKind::Index(array, index, _) = &expr.kind
+            && (!self.suppress_restriction_lint_in_const || !cx.tcx.hir().is_inside_const_context(expr.hir_id))
             && let expr_ty = cx.typeck_results().expr_ty(array)
             && let mut deref = deref_chain(cx, expr_ty)
             && deref.any(|l| {
@@ -116,6 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
                     || l.peel_refs().is_array()
                     || ty_has_applicable_get_function(cx, l.peel_refs(), expr_ty, expr)
             })
+            && !is_from_proc_macro(cx, expr)
         {
             let note = "the suggestion might not be applicable in constant blocks";
             let ty = cx.typeck_results().expr_ty(array).peel_refs();
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 9ad02735878..fa7e7f6b76d 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -226,13 +226,14 @@ const INFINITE_COLLECTORS: &[Symbol] = &[
 fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
         ExprKind::MethodCall(method, receiver, args, _) => {
+            let method_str = method.ident.name.as_str();
             for &(name, len) in &COMPLETING_METHODS {
-                if method.ident.name.as_str() == name && args.len() == len {
+                if method_str == name && args.len() == len {
                     return is_infinite(cx, receiver);
                 }
             }
             for &(name, len) in &POSSIBLY_COMPLETING_METHODS {
-                if method.ident.name.as_str() == name && args.len() == len {
+                if method_str == name && args.len() == len {
                     return MaybeInfinite.and(is_infinite(cx, receiver));
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 5fe152d1e30..f41fdf3203c 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
@@ -68,9 +69,10 @@ pub struct InstantSubtraction {
 }
 
 impl InstantSubtraction {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index 33764d3eb09..4d44bae02b8 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -1,5 +1,6 @@
 //! lint on enum variants that are prefixed or suffixed by the same characters
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
 use clippy_utils::is_bool;
 use clippy_utils::macros::span_is_local;
@@ -152,21 +153,14 @@ pub struct ItemNameRepetitions {
 }
 
 impl ItemNameRepetitions {
-    #[must_use]
-    pub fn new(
-        enum_threshold: u64,
-        struct_threshold: u64,
-        avoid_breaking_exported_api: bool,
-        allow_private_module_inception: bool,
-        allowed_prefixes: &[String],
-    ) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
             modules: Vec::new(),
-            enum_threshold,
-            struct_threshold,
-            avoid_breaking_exported_api,
-            allow_private_module_inception,
-            allowed_prefixes: allowed_prefixes.iter().map(|s| to_camel_case(s)).collect(),
+            enum_threshold: conf.enum_variant_name_threshold,
+            struct_threshold: conf.struct_field_name_threshold,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
+            allow_private_module_inception: conf.allow_private_module_inception,
+            allowed_prefixes: conf.allowed_prefixes.iter().map(|s| to_camel_case(s)).collect(),
         }
     }
 
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 b18ab625e60..5d2b521b250 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
@@ -32,13 +33,14 @@ declare_clippy_lint! {
 }
 
 pub struct LargeConstArrays {
-    maximum_allowed_size: u128,
+    maximum_allowed_size: u64,
 }
 
 impl LargeConstArrays {
-    #[must_use]
-    pub fn new(maximum_allowed_size: u128) -> Self {
-        Self { maximum_allowed_size }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            maximum_allowed_size: conf.array_size_threshold,
+        }
     }
 }
 
@@ -57,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
             && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
             && let element_count = element_count.to_target_usize(cx.tcx)
             && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
-            && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size)
+            && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
         {
             let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
             let sugg_span = Span::new(
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index 85daadcc537..225d79aa71d 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -1,5 +1,6 @@
 //! lint when there is a large size difference between variants on an enum
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{approx_ty_size, is_copy, AdtVariantInfo};
@@ -59,16 +60,14 @@ declare_clippy_lint! {
     "large size difference between variants on an enum"
 }
 
-#[derive(Copy, Clone)]
 pub struct LargeEnumVariant {
     maximum_size_difference_allowed: u64,
 }
 
 impl LargeEnumVariant {
-    #[must_use]
-    pub fn new(maximum_size_difference_allowed: u64) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            maximum_size_difference_allowed,
+            maximum_size_difference_allowed: conf.enum_variant_size_threshold,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs
index 602227e4249..6f5065e4936 100644
--- a/src/tools/clippy/clippy_lints/src/large_futures.rs
+++ b/src/tools/clippy/clippy_lints/src/large_futures.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::implements_trait;
@@ -39,14 +40,15 @@ declare_clippy_lint! {
     "large future may lead to unexpected stack overflows"
 }
 
-#[derive(Copy, Clone)]
 pub struct LargeFuture {
     future_size_threshold: u64,
 }
 
 impl LargeFuture {
-    pub fn new(future_size_threshold: u64) -> Self {
-        Self { future_size_threshold }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            future_size_threshold: conf.future_size_threshold,
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index 2688283a6ce..c67da689aae 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_note;
 use clippy_utils::macros::root_macro_call_first_node;
 use rustc_ast::LitKind;
@@ -41,9 +42,10 @@ pub struct LargeIncludeFile {
 }
 
 impl LargeIncludeFile {
-    #[must_use]
-    pub fn new(max_file_size: u64) -> Self {
-        Self { max_file_size }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            max_file_size: conf.max_include_file_size,
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index d94b0cce948..15a75b06089 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::macros::macro_backtrace;
@@ -27,15 +28,14 @@ declare_clippy_lint! {
 }
 
 pub struct LargeStackArrays {
-    maximum_allowed_size: u128,
+    maximum_allowed_size: u64,
     prev_vec_macro_callsite: Option<Span>,
 }
 
 impl LargeStackArrays {
-    #[must_use]
-    pub fn new(maximum_allowed_size: u128) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            maximum_allowed_size,
+            maximum_allowed_size: conf.array_size_threshold,
             prev_vec_macro_callsite: None,
         }
     }
@@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
                     })
                 )
             })
-            && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size)
+            && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
         {
             span_lint_and_then(
                 cx,
@@ -106,7 +106,7 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
     ///
     /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
     /// correct result.
-    fn repeat_expr_might_be_expanded<'tcx>(expr: &Expr<'tcx>) -> bool {
+    fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool {
         let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
             return false;
         };
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
index 49408d7e243..4abf7edc9b4 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
@@ -1,5 +1,6 @@
 use std::{fmt, ops};
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::fn_has_unsatisfiable_preds;
 use clippy_utils::source::snippet_opt;
@@ -85,10 +86,9 @@ pub struct LargeStackFrames {
 }
 
 impl LargeStackFrames {
-    #[must_use]
-    pub fn new(size: u64) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            maximum_allowed_size: size,
+            maximum_allowed_size: conf.stack_size_threshold,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
index a08b40bef37..752e1326e3e 100644
--- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::{get_parent_expr, is_from_proc_macro};
 use hir::def_id::DefId;
@@ -38,9 +39,10 @@ pub struct LegacyNumericConstants {
 }
 
 impl LegacyNumericConstants {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index c2dc26d6605..917d9d36076 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -1,6 +1,7 @@
 #![feature(array_windows)]
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(box_patterns)]
+#![feature(control_flow_enum)]
 #![feature(f128)]
 #![feature(f16)]
 #![feature(if_let_guard)]
@@ -288,6 +289,7 @@ mod partial_pub_fields;
 mod partialeq_ne_impl;
 mod partialeq_to_none;
 mod pass_by_ref_or_value;
+mod pathbuf_init_then_push;
 mod pattern_type_mismatch;
 mod permissions_set_readonly_false;
 mod precedence;
@@ -394,7 +396,6 @@ use clippy_config::{get_configuration_metadata, Conf};
 use clippy_utils::macros::FormatArgsStorage;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::{Lint, LintId};
-use std::collections::BTreeMap;
 
 /// Register all pre expansion lints
 ///
@@ -406,9 +407,7 @@ use std::collections::BTreeMap;
 /// Used in `./src/driver.rs`.
 pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
-    let msrv = || conf.msrv.clone();
-
-    store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv: msrv() }));
+    store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
 }
 
 #[derive(Default)]
@@ -534,88 +533,6 @@ fn register_categories(store: &mut rustc_lint::LintStore) {
 /// Used in `./src/driver.rs`.
 #[expect(clippy::too_many_lines)]
 pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
-    let Conf {
-        ref absolute_paths_allowed_crates,
-        absolute_paths_max_segments,
-        accept_comment_above_attributes,
-        accept_comment_above_statement,
-        allow_dbg_in_tests,
-        allow_expect_in_tests,
-        allow_mixed_uninlined_format_args,
-        allow_one_hash_in_raw_strings,
-        allow_panic_in_tests,
-        allow_print_in_tests,
-        allow_private_module_inception,
-        allow_unwrap_in_tests,
-        allow_useless_vec_in_tests,
-        ref allowed_dotfiles,
-        ref allowed_idents_below_min_chars,
-        ref allowed_scripts,
-        ref allowed_wildcard_imports,
-        ref arithmetic_side_effects_allowed_binary,
-        ref arithmetic_side_effects_allowed_unary,
-        ref arithmetic_side_effects_allowed,
-        array_size_threshold,
-        avoid_breaking_exported_api,
-        ref await_holding_invalid_types,
-        cargo_ignore_publish,
-        cognitive_complexity_threshold,
-        ref disallowed_macros,
-        ref disallowed_methods,
-        ref disallowed_names,
-        ref disallowed_types,
-        ref doc_valid_idents,
-        enable_raw_pointer_heuristic_for_send,
-        enforce_iter_loop_reborrow,
-        ref enforced_import_renames,
-        enum_variant_name_threshold,
-        enum_variant_size_threshold,
-        excessive_nesting_threshold,
-        future_size_threshold,
-        ref ignore_interior_mutability,
-        large_error_threshold,
-        literal_representation_threshold,
-        matches_for_let_else,
-        max_fn_params_bools,
-        max_include_file_size,
-        max_struct_bools,
-        max_suggested_slice_pattern_length,
-        max_trait_bounds,
-        min_ident_chars_threshold,
-        missing_docs_in_crate_items,
-        ref msrv,
-        pass_by_value_size_limit,
-        semicolon_inside_block_ignore_singleline,
-        semicolon_outside_block_ignore_multiline,
-        single_char_binding_names_threshold,
-        stack_size_threshold,
-        ref standard_macro_braces,
-        struct_field_name_threshold,
-        suppress_restriction_lint_in_const,
-        too_large_for_stack,
-        too_many_arguments_threshold,
-        too_many_lines_threshold,
-        trivial_copy_size_limit,
-        type_complexity_threshold,
-        unnecessary_box_size,
-        unreadable_literal_lint_fractions,
-        upper_case_acronyms_aggressive,
-        vec_box_size_threshold,
-        verbose_bit_mask_threshold,
-        warn_on_all_wildcard_imports,
-        check_private_items,
-        pub_underscore_fields_behavior,
-        ref allowed_duplicate_crates,
-        allow_comparison_to_zero,
-        ref allowed_prefixes,
-        ref allow_renamed_params_for,
-
-        blacklisted_names: _,
-        cyclomatic_complexity_threshold: _,
-        warn_unsafe_macro_metavars_in_private_macros,
-    } = *conf;
-    let msrv = || msrv.clone();
-
     register_removed_non_tool_lints(store);
     register_categories(store);
 
@@ -660,35 +577,12 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         });
     }
 
-    store.register_late_pass(move |_| {
-        Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(
-            arithmetic_side_effects_allowed
-                .iter()
-                .flat_map(|el| [[el.clone(), "*".to_string()], ["*".to_string(), el.clone()]])
-                .chain(arithmetic_side_effects_allowed_binary.clone())
-                .collect(),
-            arithmetic_side_effects_allowed
-                .iter()
-                .chain(arithmetic_side_effects_allowed_unary.iter())
-                .cloned()
-                .collect(),
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));
     store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
     store.register_late_pass(|_| Box::new(utils::author::Author));
-    store.register_late_pass(move |_| {
-        Box::new(await_holding_invalid::AwaitHolding::new(
-            await_holding_invalid_types.clone(),
-        ))
-    });
+    store.register_late_pass(move |tcx| Box::new(await_holding_invalid::AwaitHolding::new(tcx, conf)));
     store.register_late_pass(|_| Box::new(serde_api::SerdeApi));
-    store.register_late_pass(move |_| {
-        Box::new(types::Types::new(
-            vec_box_size_threshold,
-            type_complexity_threshold,
-            avoid_breaking_exported_api,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(types::Types::new(conf)));
     store.register_late_pass(|_| Box::new(booleans::NonminimalBool));
     store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant));
     store.register_late_pass(|_| Box::new(float_literal::FloatLiteral));
@@ -702,7 +596,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
     store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
     store.register_late_pass(|_| Box::new(len_zero::LenZero));
-    store.register_late_pass(move |_| Box::new(attrs::Attributes::new(msrv())));
+    store.register_late_pass(move |_| Box::new(attrs::Attributes::new(conf)));
     store.register_late_pass(|_| Box::new(blocks_in_conditions::BlocksInConditions));
     store.register_late_pass(|_| Box::new(unicode::Unicode));
     store.register_late_pass(|_| Box::new(uninit_vec::UninitVec));
@@ -714,44 +608,30 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
     store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
     store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
-    store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
+    store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(conf)));
     let format_args = format_args_storage.clone();
-    store.register_late_pass(move |_| {
-        Box::new(methods::Methods::new(
-            avoid_breaking_exported_api,
-            msrv(),
-            allow_expect_in_tests,
-            allow_unwrap_in_tests,
-            allowed_dotfiles.clone(),
-            format_args.clone(),
-        ))
-    });
-    store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv())));
-    store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv())));
-    store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv())));
-    store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv())));
-    store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv())));
-    store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv())));
-    store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv())));
-    store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv())));
-    store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv())));
-    store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv())));
-    store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv())));
-    store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv())));
+    store.register_late_pass(move |_| Box::new(methods::Methods::new(conf, format_args.clone())));
+    store.register_late_pass(move |_| Box::new(matches::Matches::new(conf)));
+    store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(conf)));
+    store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(conf)));
+    store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(conf)));
+    store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(conf)));
+    store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(conf)));
+    store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(conf)));
+    store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(conf)));
+    store.register_late_pass(move |_| Box::new(ranges::Ranges::new(conf)));
+    store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(conf)));
+    store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(conf)));
+    store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(conf)));
     store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark));
-    store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv())));
-    store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv())));
+    store.register_late_pass(move |_| Box::new(casts::Casts::new(conf)));
+    store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(conf)));
     store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount));
     store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod));
-    store.register_late_pass(move |_| {
-        Box::new(index_refutable_slice::IndexRefutableSlice::new(
-            max_suggested_slice_pattern_length,
-            msrv(),
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(index_refutable_slice::IndexRefutableSlice::new(conf)));
     store.register_late_pass(|_| Box::<shadow::Shadow>::default());
     store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
-    store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv(), enforce_iter_loop_reborrow)));
+    store.register_late_pass(move |_| Box::new(loops::Loops::new(conf)));
     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));
@@ -763,75 +643,49 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef));
     store.register_late_pass(|_| Box::<no_effect::NoEffect>::default());
     store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment));
-    store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv())));
-    store.register_late_pass(move |_| {
-        Box::new(cognitive_complexity::CognitiveComplexity::new(
-            cognitive_complexity_threshold,
-        ))
-    });
-    store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack }));
-    store.register_late_pass(move |_| {
-        Box::new(vec::UselessVec {
-            too_large_for_stack,
-            msrv: msrv(),
-            span_to_lint_map: BTreeMap::new(),
-            allow_in_test: allow_useless_vec_in_tests,
-        })
-    });
-    store.register_late_pass(move |_| Box::new(panic_unimplemented::PanicUnimplemented { allow_panic_in_tests }));
+    store.register_late_pass(move |_| Box::new(transmute::Transmute::new(conf)));
+    store.register_late_pass(move |_| Box::new(cognitive_complexity::CognitiveComplexity::new(conf)));
+    store.register_late_pass(move |_| Box::new(escape::BoxedLocal::new(conf)));
+    store.register_late_pass(move |_| Box::new(vec::UselessVec::new(conf)));
+    store.register_late_pass(move |_| Box::new(panic_unimplemented::PanicUnimplemented::new(conf)));
     store.register_late_pass(|_| Box::new(strings::StringLitAsBytes));
     store.register_late_pass(|_| Box::new(derive::Derive));
-    store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(msrv())));
+    store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(conf)));
     store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
     store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
     store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
     store.register_late_pass(|_| Box::<regex::Regex>::default());
-    store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone())));
+    store.register_late_pass(move |tcx| Box::new(copies::CopyAndPaste::new(tcx, conf)));
     store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));
     let format_args = format_args_storage.clone();
     store.register_late_pass(move |_| Box::new(format::UselessFormat::new(format_args.clone())));
     store.register_late_pass(|_| Box::new(swap::Swap));
     store.register_late_pass(|_| Box::new(panicking_overflow_checks::PanickingOverflowChecks));
     store.register_late_pass(|_| Box::<new_without_default::NewWithoutDefault>::default());
-    store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names)));
-    store.register_late_pass(move |_| {
-        Box::new(functions::Functions::new(
-            too_many_arguments_threshold,
-            too_many_lines_threshold,
-            large_error_threshold,
-            avoid_breaking_exported_api,
-            allow_renamed_params_for.clone(),
-        ))
-    });
-    store.register_late_pass(move |_| Box::new(doc::Documentation::new(doc_valid_idents, check_private_items)));
+    store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(conf)));
+    store.register_late_pass(move |tcx| Box::new(functions::Functions::new(tcx, conf)));
+    store.register_late_pass(move |_| Box::new(doc::Documentation::new(conf)));
     store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply));
     store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
     store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
-    store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(missing_docs_in_crate_items)));
+    store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(conf)));
     store.register_late_pass(|_| Box::new(missing_inline::MissingInline));
     store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems));
     store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk));
     store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl));
     store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount));
-    store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)));
+    store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(conf)));
     let format_args = format_args_storage.clone();
     store.register_late_pass(move |_| Box::new(explicit_write::ExplicitWrite::new(format_args.clone())));
     store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue));
-    store.register_late_pass(move |tcx| {
-        Box::new(pass_by_ref_or_value::PassByRefOrValue::new(
-            trivial_copy_size_limit,
-            pass_by_value_size_limit,
-            avoid_breaking_exported_api,
-            tcx.sess.target.pointer_width,
-        ))
-    });
+    store.register_late_pass(move |tcx| Box::new(pass_by_ref_or_value::PassByRefOrValue::new(tcx, 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::<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(move |_| Box::new(question_mark::QuestionMark::new(msrv(), matches_for_let_else)));
+    store.register_late_pass(move |_| Box::new(question_mark::QuestionMark::new(conf)));
     store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed));
     store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings));
     store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl));
@@ -839,22 +693,18 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl));
     store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
     store.register_late_pass(|_| Box::new(unwrap::Unwrap));
-    store.register_late_pass(move |_| {
-        Box::new(indexing_slicing::IndexingSlicing::new(
-            suppress_restriction_lint_in_const,
-        ))
-    });
-    store.register_late_pass(move |_| Box::new(non_copy_const::NonCopyConst::new(ignore_interior_mutability.clone())));
+    store.register_late_pass(move |_| Box::new(indexing_slicing::IndexingSlicing::new(conf)));
+    store.register_late_pass(move |tcx| Box::new(non_copy_const::NonCopyConst::new(tcx, conf)));
     store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
     store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
     store.register_late_pass(|_| Box::new(slow_vector_initialization::SlowVectorInit));
-    store.register_late_pass(move |_| Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api)));
+    store.register_late_pass(move |_| Box::new(unnecessary_wraps::UnnecessaryWraps::new(conf)));
     store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants));
     store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates));
     store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString));
-    store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv())));
+    store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(conf)));
     store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
-    store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
+    store.register_late_pass(move |tcx| Box::new(mut_key::MutableKeyType::new(tcx, conf)));
     store.register_early_pass(|| Box::new(reference::DerefAddrOf));
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
     let format_args = format_args_storage.clone();
@@ -875,80 +725,45 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_early_pass(|| Box::new(redundant_else::RedundantElse));
     store.register_late_pass(|_| Box::new(create_dir::CreateDir));
     store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType));
-    store.register_early_pass(move || {
-        Box::new(literal_representation::LiteralDigitGrouping::new(
-            unreadable_literal_lint_fractions,
-        ))
-    });
-    store.register_early_pass(move || {
-        Box::new(literal_representation::DecimalLiteralRepresentation::new(
-            literal_representation_threshold,
-        ))
-    });
-    store.register_late_pass(move |_| {
-        Box::new(item_name_repetitions::ItemNameRepetitions::new(
-            enum_variant_name_threshold,
-            struct_field_name_threshold,
-            avoid_breaking_exported_api,
-            allow_private_module_inception,
-            allowed_prefixes,
-        ))
-    });
+    store.register_early_pass(move || Box::new(literal_representation::LiteralDigitGrouping::new(conf)));
+    store.register_early_pass(move || Box::new(literal_representation::DecimalLiteralRepresentation::new(conf)));
+    store.register_late_pass(move |_| Box::new(item_name_repetitions::ItemNameRepetitions::new(conf)));
     store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
-    store.register_late_pass(move |_| {
-        Box::new(upper_case_acronyms::UpperCaseAcronyms::new(
-            avoid_breaking_exported_api,
-            upper_case_acronyms_aggressive,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(upper_case_acronyms::UpperCaseAcronyms::new(conf)));
     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(move |_| Box::new(unused_self::UnusedSelf::new(conf)));
     store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
     store.register_late_pass(|_| Box::new(exit::Exit));
     store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome));
-    store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold.into())));
-    store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold.into())));
+    store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(conf)));
+    store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(conf)));
     store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
     store.register_late_pass(|_| Box::new(as_conversions::AsConversions));
     store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
     store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default());
-    store.register_late_pass(move |_| {
-        Box::new(excessive_bools::ExcessiveBools::new(
-            max_struct_bools,
-            max_fn_params_bools,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(excessive_bools::ExcessiveBools::new(conf)));
     store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
-    store.register_late_pass(move |_| {
-        Box::new(wildcard_imports::WildcardImports::new(
-            warn_on_all_wildcard_imports,
-            allowed_wildcard_imports.clone(),
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf)));
     store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
     store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
     store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
     store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
-    store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(future_size_threshold)));
+    store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(conf)));
     store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex));
     store.register_late_pass(|_| Box::new(if_not_else::IfNotElse));
     store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality));
     store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn));
     store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn));
-    store.register_early_pass(move || {
-        Box::new(non_expressive_names::NonExpressiveNames {
-            single_char_binding_names_threshold,
-        })
-    });
-    store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(standard_macro_braces)));
+    store.register_early_pass(move || Box::new(non_expressive_names::NonExpressiveNames::new(conf)));
+    store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(conf)));
     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));
-    store.register_late_pass(move |_| Box::new(disallowed_macros::DisallowedMacros::new(disallowed_macros.clone())));
-    store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
+    store.register_late_pass(move |tcx| Box::new(disallowed_macros::DisallowedMacros::new(tcx, conf)));
+    store.register_late_pass(move |tcx| Box::new(disallowed_methods::DisallowedMethods::new(tcx, conf)));
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
     store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
     store.register_late_pass(|_| Box::new(empty_drop::EmptyDrop));
@@ -958,86 +773,57 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     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())));
+    store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(conf)));
     store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison));
     store.register_early_pass(move || Box::new(module_style::ModStyle));
     store.register_late_pass(|_| Box::<unused_async::UnusedAsync>::default());
-    store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone())));
-    store.register_late_pass(move |_| {
-        Box::new(missing_enforced_import_rename::ImportRename::new(
-            enforced_import_renames.clone(),
-        ))
-    });
-    store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(allowed_scripts)));
+    store.register_late_pass(move |tcx| Box::new(disallowed_types::DisallowedTypes::new(tcx, conf)));
+    store.register_late_pass(move |tcx| Box::new(missing_enforced_import_rename::ImportRename::new(tcx, conf)));
+    store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(conf)));
     store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings));
     store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors));
     store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator));
     store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert));
-    store.register_late_pass(move |_| {
-        Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(
-            enable_raw_pointer_heuristic_for_send,
-        ))
-    });
-    store.register_late_pass(move |_| {
-        Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(
-            accept_comment_above_statement,
-            accept_comment_above_attributes,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(conf)));
+    store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(conf)));
     let format_args = format_args_storage.clone();
-    store.register_late_pass(move |_| {
-        Box::new(format_args::FormatArgs::new(
-            format_args.clone(),
-            msrv(),
-            allow_mixed_uninlined_format_args,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(conf, format_args.clone())));
     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));
     store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse));
     store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields));
     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(move |_| Box::new(manual_bits::ManualBits::new(conf)));
     store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
     store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
-    store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
+    store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(conf)));
     let format_args = format_args_storage.clone();
-    store.register_late_pass(move |_| Box::new(write::Write::new(format_args.clone(), allow_print_in_tests)));
-    store.register_late_pass(move |_| {
-        Box::new(cargo::Cargo {
-            ignore_publish: cargo_ignore_publish,
-            allowed_duplicate_crates: allowed_duplicate_crates.clone(),
-        })
-    });
+    store.register_late_pass(move |_| Box::new(write::Write::new(conf, format_args.clone())));
+    store.register_late_pass(move |_| Box::new(cargo::Cargo::new(conf)));
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
     store.register_early_pass(|| Box::new(empty_with_brackets::EmptyWithBrackets));
     store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
     store.register_early_pass(|| Box::new(pub_use::PubUse));
     store.register_late_pass(|_| Box::new(format_push_string::FormatPushString));
-    store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size)));
+    store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(conf)));
     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::<duplicate_mod::DuplicateMod>::default());
     store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
-    store.register_early_pass(move || Box::new(almost_complete_range::AlmostCompleteRange::new(msrv())));
+    store.register_early_pass(move || Box::new(almost_complete_range::AlmostCompleteRange::new(conf)));
     store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
     store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
     store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
     store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
-    store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv())));
-    store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv())));
+    store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(conf)));
+    store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(conf)));
     store.register_late_pass(move |_| Box::new(manual_rotate::ManualRotate));
-    store.register_late_pass(move |_| {
-        Box::new(operators::Operators::new(
-            verbose_bit_mask_threshold,
-            allow_comparison_to_zero,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(operators::Operators::new(conf)));
     store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
-    store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
+    store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(conf)));
     store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
-    store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv())));
+    store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(conf)));
     store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
     store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
     store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
@@ -1048,44 +834,25 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods));
     store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
     store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
-    store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
-    store.register_late_pass(move |_| {
-        Box::new(semicolon_block::SemicolonBlock::new(
-            semicolon_inside_block_ignore_singleline,
-            semicolon_outside_block_ignore_multiline,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(conf)));
+    store.register_late_pass(move |_| Box::new(semicolon_block::SemicolonBlock::new(conf)));
     store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
     store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
     store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
-    store.register_late_pass(move |_| {
-        Box::new(extra_unused_type_parameters::ExtraUnusedTypeParameters::new(
-            avoid_breaking_exported_api,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(extra_unused_type_parameters::ExtraUnusedTypeParameters::new(conf)));
     store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
     store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead));
     store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage));
     store.register_late_pass(|_| Box::new(needless_maybe_sized::NeedlessMaybeSized));
     store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock));
     store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
-    store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
+    store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(conf)));
     store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
-    store.register_late_pass(move |_| {
-        Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(
-            avoid_breaking_exported_api,
-            unnecessary_box_size,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(conf)));
     store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk));
     store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
     store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
-    store.register_early_pass(move || {
-        Box::new(excessive_nesting::ExcessiveNesting {
-            excessive_nesting_threshold,
-            nodes: rustc_ast::node_id::NodeSet::new(),
-        })
-    });
+    store.register_early_pass(move || Box::new(excessive_nesting::ExcessiveNesting::new(conf)));
     store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
     store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
     store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
@@ -1095,44 +862,21 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations));
     store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync));
     store.register_late_pass(|_| Box::new(needless_if::NeedlessIf));
-    store.register_late_pass(move |_| {
-        Box::new(min_ident_chars::MinIdentChars {
-            allowed_idents_below_min_chars: allowed_idents_below_min_chars.clone(),
-            min_ident_chars_threshold,
-        })
-    });
-    store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold)));
+    store.register_late_pass(move |_| Box::new(min_ident_chars::MinIdentChars::new(conf)));
+    store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(conf)));
     store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit));
-    store.register_late_pass(move |_| {
-        Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut::new(
-            avoid_breaking_exported_api,
-        ))
-    });
+    store.register_late_pass(move |_| Box::new(needless_pass_by_ref_mut::NeedlessPassByRefMut::new(conf)));
     store.register_late_pass(|_| Box::new(non_canonical_impls::NonCanonicalImpls));
-    store.register_late_pass(move |_| {
-        Box::new(single_call_fn::SingleCallFn {
-            avoid_breaking_exported_api,
-            def_id_to_usage: rustc_data_structures::fx::FxIndexMap::default(),
-        })
-    });
-    store.register_early_pass(move || {
-        Box::new(raw_strings::RawStrings {
-            allow_one_hash_in_raw_strings,
-        })
-    });
-    store.register_late_pass(move |_| Box::new(legacy_numeric_constants::LegacyNumericConstants::new(msrv())));
+    store.register_late_pass(move |_| Box::new(single_call_fn::SingleCallFn::new(conf)));
+    store.register_early_pass(move || Box::new(raw_strings::RawStrings::new(conf)));
+    store.register_late_pass(move |_| Box::new(legacy_numeric_constants::LegacyNumericConstants::new(conf)));
     store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns));
     store.register_early_pass(|| Box::new(visibility::Visibility));
-    store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() }));
+    store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions::new(conf)));
     store.register_late_pass(|_| Box::new(manual_float_methods::ManualFloatMethods));
     store.register_late_pass(|_| Box::new(four_forward_slashes::FourForwardSlashes));
     store.register_late_pass(|_| Box::new(error_impl_error::ErrorImplError));
-    store.register_late_pass(move |_| {
-        Box::new(absolute_paths::AbsolutePaths {
-            absolute_paths_max_segments,
-            absolute_paths_allowed_crates: absolute_paths_allowed_crates.clone(),
-        })
-    });
+    store.register_late_pass(move |_| Box::new(absolute_paths::AbsolutePaths::new(conf)));
     store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
     store.register_late_pass(|_| Box::new(ignored_unit_patterns::IgnoredUnitPatterns));
     store.register_late_pass(|_| Box::<reserve_after_initialization::ReserveAfterInitialization>::default());
@@ -1141,38 +885,29 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(unnecessary_map_on_constructor::UnnecessaryMapOnConstructor));
     store.register_late_pass(move |_| {
         Box::new(needless_borrows_for_generic_args::NeedlessBorrowsForGenericArgs::new(
-            msrv(),
+            conf,
         ))
     });
-    store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv())));
+    store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(conf)));
     store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter));
+    store.register_late_pass(|_| Box::<pathbuf_init_then_push::PathbufThenPush<'_>>::default());
     store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType));
     store.register_late_pass(|_| Box::new(impl_hash_with_borrow_str_and_bytes::ImplHashWithBorrowStrBytes));
     store.register_late_pass(|_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity));
     store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences));
     store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions));
     store.register_late_pass(|_| Box::<unconditional_recursion::UnconditionalRecursion>::default());
-    store.register_late_pass(move |_| {
-        Box::new(pub_underscore_fields::PubUnderscoreFields {
-            behavior: pub_underscore_fields_behavior,
-        })
-    });
-    store
-        .register_late_pass(move |_| Box::new(missing_const_for_thread_local::MissingConstForThreadLocal::new(msrv())));
-    store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv())));
+    store.register_late_pass(move |_| Box::new(pub_underscore_fields::PubUnderscoreFields::new(conf)));
+    store.register_late_pass(move |_| Box::new(missing_const_for_thread_local::MissingConstForThreadLocal::new(conf)));
+    store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(conf)));
     store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl));
     store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations));
-    store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(msrv())));
+    store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(conf)));
     store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects));
     store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault));
     store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed));
-    store.register_late_pass(move |_| {
-        Box::new(macro_metavars_in_unsafe::ExprMetavarsInUnsafe {
-            warn_unsafe_macro_metavars_in_private_macros,
-            ..Default::default()
-        })
-    });
-    store.register_late_pass(move |_| Box::new(string_patterns::StringPatterns::new(msrv())));
+    store.register_late_pass(move |_| Box::new(macro_metavars_in_unsafe::ExprMetavarsInUnsafe::new(conf)));
+    store.register_late_pass(move |_| Box::new(string_patterns::StringPatterns::new(conf)));
     store.register_early_pass(|| Box::new(field_scoped_visibility_modifiers::FieldScopedVisibilityModifiers));
     store.register_late_pass(|_| Box::new(set_contains_or_insert::HashsetInsertAfterContains));
     store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice));
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 443d6189c1f..ba34af9c100 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -22,6 +22,7 @@ use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
+use std::ops::ControlFlow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -380,11 +381,8 @@ fn could_use_elision<'tcx>(
             return None;
         }
 
-        let mut checker = BodyLifetimeChecker {
-            lifetimes_used_in_body: false,
-        };
-        checker.visit_expr(body.value);
-        if checker.lifetimes_used_in_body {
+        let mut checker = BodyLifetimeChecker;
+        if checker.visit_expr(body.value).is_break() {
             return None;
         }
     }
@@ -545,7 +543,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
                 if !lt.is_elided() {
                     self.unelided_trait_object_lifetime = true;
                 }
-                for bound in bounds {
+                for (bound, _) in bounds {
                     self.visit_poly_trait_ref(bound);
                 }
             },
@@ -694,15 +692,15 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
     }
 }
 
-struct BodyLifetimeChecker {
-    lifetimes_used_in_body: bool,
-}
+struct BodyLifetimeChecker;
 
 impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
+    type Result = ControlFlow<()>;
     // for lifetimes as parameters of generics
-    fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
+    fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) -> ControlFlow<()> {
         if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
-            self.lifetimes_used_in_body = true;
+            return ControlFlow::Break(());
         }
+        ControlFlow::Continue(())
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index 7481543941a..b685d1dad1a 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -1,6 +1,7 @@
 //! Lints concerned with the grouping of digits with underscores in integral or
 //! floating-point literal expressions.
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::{NumericLiteral, Radix};
 use clippy_utils::source::snippet_opt;
@@ -218,7 +219,6 @@ impl WarningType {
     }
 }
 
-#[derive(Copy, Clone)]
 pub struct LiteralDigitGrouping {
     lint_fraction_readability: bool,
 }
@@ -245,13 +245,13 @@ impl EarlyLintPass for LiteralDigitGrouping {
 const UUID_GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12];
 
 impl LiteralDigitGrouping {
-    pub fn new(lint_fraction_readability: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            lint_fraction_readability,
+            lint_fraction_readability: conf.unreadable_literal_lint_fractions,
         }
     }
 
-    fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
+    fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
         if let Some(src) = snippet_opt(cx, span)
             && let Ok(lit_kind) = LitKind::from_token_lit(lit)
             && let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
@@ -437,7 +437,6 @@ impl LiteralDigitGrouping {
 }
 
 #[expect(clippy::module_name_repetitions)]
-#[derive(Copy, Clone)]
 pub struct DecimalLiteralRepresentation {
     threshold: u64,
 }
@@ -455,11 +454,12 @@ impl EarlyLintPass for DecimalLiteralRepresentation {
 }
 
 impl DecimalLiteralRepresentation {
-    #[must_use]
-    pub fn new(threshold: u64) -> Self {
-        Self { threshold }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            threshold: conf.literal_representation_threshold,
+        }
     }
-    fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
+    fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
         // Lint integral literals.
         if let Ok(lit_kind) = LitKind::from_token_lit(lit)
             && let LitKind::Int(val, _) = lit_kind
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 64ea591993d..7c2a8098af2 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -23,6 +23,7 @@ mod while_let_loop;
 mod while_let_on_iterator;
 
 use clippy_config::msrvs::Msrv;
+use clippy_config::Conf;
 use clippy_utils::higher;
 use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
 use rustc_lint::{LateContext, LateLintPass};
@@ -717,10 +718,10 @@ pub struct Loops {
     enforce_iter_loop_reborrow: bool,
 }
 impl Loops {
-    pub fn new(msrv: Msrv, enforce_iter_loop_reborrow: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            msrv,
-            enforce_iter_loop_reborrow,
+            msrv: conf.msrv.clone(),
+            enforce_iter_loop_reborrow: conf.enforce_iter_loop_reborrow,
         }
     }
 }
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 6c6a9a1a2e0..21f9a71f2c5 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
@@ -8,6 +8,7 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty;
 use rustc_span::Span;
+use std::ops::ControlFlow;
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
     if let Some(higher::Range {
@@ -114,7 +115,6 @@ impl MutatePairDelegate<'_, '_> {
 struct BreakAfterExprVisitor {
     hir_id: HirId,
     past_expr: bool,
-    past_candidate: bool,
     break_after_expr: bool,
 }
 
@@ -123,7 +123,6 @@ impl BreakAfterExprVisitor {
         let mut visitor = BreakAfterExprVisitor {
             hir_id,
             past_expr: false,
-            past_candidate: false,
             break_after_expr: false,
         };
 
@@ -135,21 +134,19 @@ impl BreakAfterExprVisitor {
 }
 
 impl<'tcx> Visitor<'tcx> for BreakAfterExprVisitor {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if self.past_candidate {
-            return;
-        }
-
+    type Result = ControlFlow<()>;
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> {
         if expr.hir_id == self.hir_id {
             self.past_expr = true;
+            ControlFlow::Continue(())
         } else if self.past_expr {
             if matches!(&expr.kind, ExprKind::Break(..)) {
                 self.break_after_expr = true;
             }
 
-            self.past_candidate = true;
+            ControlFlow::Break(())
         } else {
-            intravisit::walk_expr(self, expr);
+            intravisit::walk_expr(self, expr)
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index 108fdb69775..2b41911e8ec 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -5,7 +5,7 @@ use clippy_utils::visitors::contains_break_or_continue;
 use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_ast::Mutability;
 use rustc_errors::Applicability;
-use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat};
+use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_span::edition::Edition;
 use rustc_span::sym;
@@ -70,7 +70,10 @@ pub(super) fn check<'tcx>(
         && !contains_break_or_continue(body)
     {
         let mut applicability = Applicability::MachineApplicable;
-        let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
+        let mut pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
+        if matches!(pat.kind, PatKind::Or(..)) {
+            pat_snip = format!("({pat_snip})").into();
+        }
         let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);
         let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned();
         block_str.remove(0);
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
index 3dff826cb85..e7b3a2c4973 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
@@ -7,6 +7,7 @@ use rustc_hir::def_id::DefIdMap;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Expr, ExprKind, HirIdSet, QPath};
 use rustc_lint::LateContext;
+use std::ops::ControlFlow;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
     if constant(cx, cx.typeck_results(), cond).is_some() {
@@ -35,11 +36,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'
         };
     let mutable_static_in_cond = var_visitor.def_ids.items().any(|(_, v)| *v);
 
-    let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
-        has_break_or_return: false,
-    };
-    has_break_or_return_visitor.visit_expr(expr);
-    let has_break_or_return = has_break_or_return_visitor.has_break_or_return;
+    let mut has_break_or_return_visitor = HasBreakOrReturnVisitor;
+    let has_break_or_return = has_break_or_return_visitor.visit_expr(expr).is_break();
 
     if no_cond_variable_mutated && !mutable_static_in_cond {
         span_lint_and_then(
@@ -59,25 +57,19 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'
     }
 }
 
-struct HasBreakOrReturnVisitor {
-    has_break_or_return: bool,
-}
+struct HasBreakOrReturnVisitor;
 
 impl<'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if self.has_break_or_return {
-            return;
-        }
-
+    type Result = ControlFlow<()>;
+    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> ControlFlow<()> {
         match expr.kind {
             ExprKind::Ret(_) | ExprKind::Break(_, _) => {
-                self.has_break_or_return = true;
-                return;
+                return ControlFlow::Break(());
             },
             _ => {},
         }
 
-        walk_expr(self, expr);
+        walk_expr(self, expr)
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
index d1ae243877d..fed58f7ff14 100644
--- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -1,6 +1,4 @@
-use std::collections::btree_map::Entry;
-use std::collections::BTreeMap;
-
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::is_lint_allowed;
 use itertools::Itertools;
@@ -10,6 +8,8 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::{sym, Span, SyntaxContext};
+use std::collections::btree_map::Entry;
+use std::collections::BTreeMap;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -90,9 +90,8 @@ pub enum MetavarState {
     ReferencedInSafe,
 }
 
-#[derive(Default)]
 pub struct ExprMetavarsInUnsafe {
-    pub warn_unsafe_macro_metavars_in_private_macros: bool,
+    warn_unsafe_macro_metavars_in_private_macros: bool,
     /// A metavariable can be expanded more than once, potentially across multiple bodies, so it
     /// requires some state kept across HIR nodes to make it possible to delay a warning
     /// and later undo:
@@ -106,7 +105,16 @@ pub struct ExprMetavarsInUnsafe {
     ///     }
     /// }
     /// ```
-    pub metavar_expns: BTreeMap<Span, MetavarState>,
+    metavar_expns: BTreeMap<Span, MetavarState>,
+}
+
+impl ExprMetavarsInUnsafe {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            warn_unsafe_macro_metavars_in_private_macros: conf.warn_unsafe_macro_metavars_in_private_macros,
+            metavar_expns: BTreeMap::new(),
+        }
+    }
 }
 
 struct BodyVisitor<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs
index d9f6be6dc2b..5cbdc7f864a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_bits.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
 use clippy_utils::source::snippet_with_context;
@@ -34,15 +35,15 @@ declare_clippy_lint! {
     "manual implementation of `size_of::<T>() * 8` can be simplified with `T::BITS`"
 }
 
-#[derive(Clone)]
 pub struct ManualBits {
     msrv: Msrv,
 }
 
 impl ManualBits {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index e2ab4415518..a79ad018a04 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::higher::If;
@@ -97,8 +98,10 @@ pub struct ManualClamp {
 }
 
 impl ManualClamp {
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
index daa8101aa5f..1c568b1b74f 100644
--- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::visitors::{is_local_used, local_used_once};
@@ -51,9 +52,10 @@ pub struct ManualHashOne {
 }
 
 impl ManualHashOne {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index 6f6ba1852a6..a9f21d34e4c 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::sugg::Sugg;
@@ -62,9 +63,10 @@ pub struct ManualIsAsciiCheck {
 }
 
 impl ManualIsAsciiCheck {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
index 8e8cdc3fb07..db491a8c8f6 100644
--- a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{is_trait_method, match_def_path, paths, peel_hir_expr_refs};
 use rustc_errors::Applicability;
@@ -37,9 +38,10 @@ pub struct ManualMainSeparatorStr {
 }
 
 impl ManualMainSeparatorStr {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
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 73a505fd73f..28cfe22835a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::is_doc_hidden;
 use clippy_utils::source::snippet_opt;
@@ -67,9 +68,10 @@ pub struct ManualNonExhaustiveStruct {
 }
 
 impl ManualNonExhaustiveStruct {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -83,10 +85,9 @@ pub struct ManualNonExhaustiveEnum {
 }
 
 impl ManualNonExhaustiveEnum {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            msrv,
+            msrv: conf.msrv.clone(),
             constructed_enum_variants: FxHashSet::default(),
             potential_enums: Vec::new(),
         }
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 b518dc26937..78a750f0dcd 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant_full_int, FullInt};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
@@ -38,9 +39,10 @@ pub struct ManualRemEuclid {
 }
 
 impl ManualRemEuclid {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 8f7b8abd0c3..09f6362b4dd 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
@@ -59,9 +60,10 @@ pub struct ManualRetain {
 }
 
 impl ManualRetain {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 6a523ad1564..686ecccf829 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
@@ -50,9 +51,10 @@ pub struct ManualStrip {
 }
 
 impl ManualStrip {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
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 0940fc3219b..85a08f81c2f 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
@@ -35,6 +35,17 @@ pub(super) fn check_if_let<'tcx>(
     else_expr: &'tcx Expr<'_>,
 ) {
     let ty = cx.typeck_results().expr_ty(let_expr);
+    let then_ty = cx.typeck_results().expr_ty(then_expr);
+    // The signature is `fn unwrap_or<T>(self: Option<T>, default: T) -> T`.
+    // When `expr_adjustments(then_expr).is_empty()`, `T` should equate to `default`'s type.
+    // Otherwise, type error will occur.
+    if cx.typeck_results().expr_adjustments(then_expr).is_empty()
+        && let rustc_middle::ty::Adt(_did, args) = ty.kind()
+        && let Some(some_ty) = args.first().and_then(|arg| arg.as_type())
+        && some_ty != then_ty
+    {
+        return;
+    }
     check_and_lint(cx, expr, let_pat, let_expr, then_expr, peel_blocks(else_expr), ty);
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 22a299ae3d8..cec3504ed8d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -25,6 +25,7 @@ mod try_err;
 mod wild_in_or_pats;
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::source::walk_span_to_context;
 use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, span_contains_cfg};
 use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind};
@@ -980,10 +981,9 @@ pub struct Matches {
 }
 
 impl Matches {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            msrv,
+            msrv: conf.msrv.clone(),
             infallible_destructuring_match_linted: false,
         }
     }
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 9047c9627d9..9c2f42d2187 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
@@ -232,7 +232,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
 enum SigDropHolder {
     /// No values with significant drop present in this expression.
     ///
-    /// Expressions that we've emited lints do not count.
+    /// Expressions that we've emitted lints do not count.
     None,
     /// Some field in this expression references to values with significant drop.
     ///
@@ -426,7 +426,7 @@ fn ty_has_erased_regions(ty: Ty<'_>) -> bool {
 
 impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
-        // We've emited a lint on some neighborhood expression. That lint will suggest to move out the
+        // We've emitted a lint on some neighborhood expression. That lint will suggest to move out the
         // _parent_ expression (not the expression itself). Since we decide to move out the parent
         // expression, it is pointless to continue to process the current expression.
         if self.sig_drop_holder == SigDropHolder::Moved {
@@ -450,7 +450,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
                 ExprKind::Assign(lhs, _, _) | ExprKind::AssignOp(_, lhs, _)
                     if lhs.hir_id == ex.hir_id && self.sig_drop_holder == SigDropHolder::Moved =>
                 {
-                    // Never move out only the assignee. Instead, we should always move out the whole assigment.
+                    // Never move out only the assignee. Instead, we should always move out the whole assignment.
                     self.replace_current_sig_drop(parent_ex.span, true, 0);
                 },
                 _ => {
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index 578aa7989e7..72a5945ad9b 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 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::sugg::Sugg;
@@ -217,9 +218,10 @@ pub struct MemReplace {
 }
 
 impl MemReplace {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
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 fb440ce656e..20f3722e173 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
@@ -10,59 +10,80 @@ use rustc_hir::{LangItem, QPath};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 
-pub(crate) struct OptionAndThenSome;
-
-impl BindInsteadOfMap for OptionAndThenSome {
-    const VARIANT_LANG_ITEM: LangItem = LangItem::OptionSome;
-    const BAD_METHOD_NAME: &'static str = "and_then";
-    const GOOD_METHOD_NAME: &'static str = "map";
+pub(super) fn check_and_then_some(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    recv: &hir::Expr<'_>,
+    arg: &hir::Expr<'_>,
+) -> bool {
+    BindInsteadOfMap {
+        variant_lang_item: LangItem::OptionSome,
+        bad_method_name: "and_then",
+        good_method_name: "map",
+    }
+    .check(cx, expr, recv, arg)
 }
 
-pub(crate) struct ResultAndThenOk;
-
-impl BindInsteadOfMap for ResultAndThenOk {
-    const VARIANT_LANG_ITEM: LangItem = LangItem::ResultOk;
-    const BAD_METHOD_NAME: &'static str = "and_then";
-    const GOOD_METHOD_NAME: &'static str = "map";
+pub(super) fn check_and_then_ok(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    recv: &hir::Expr<'_>,
+    arg: &hir::Expr<'_>,
+) -> bool {
+    BindInsteadOfMap {
+        variant_lang_item: LangItem::ResultOk,
+        bad_method_name: "and_then",
+        good_method_name: "map",
+    }
+    .check(cx, expr, recv, arg)
 }
 
-pub(crate) struct ResultOrElseErrInfo;
-
-impl BindInsteadOfMap for ResultOrElseErrInfo {
-    const VARIANT_LANG_ITEM: LangItem = LangItem::ResultErr;
-    const BAD_METHOD_NAME: &'static str = "or_else";
-    const GOOD_METHOD_NAME: &'static str = "map_err";
+pub(super) fn check_or_else_err(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    recv: &hir::Expr<'_>,
+    arg: &hir::Expr<'_>,
+) -> bool {
+    BindInsteadOfMap {
+        variant_lang_item: LangItem::ResultErr,
+        bad_method_name: "or_else",
+        good_method_name: "map_err",
+    }
+    .check(cx, expr, recv, arg)
 }
 
-pub(crate) trait BindInsteadOfMap {
-    const VARIANT_LANG_ITEM: LangItem;
-    const BAD_METHOD_NAME: &'static str;
-    const GOOD_METHOD_NAME: &'static str;
+struct BindInsteadOfMap {
+    variant_lang_item: LangItem,
+    bad_method_name: &'static str,
+    good_method_name: &'static str,
+}
 
-    fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
-        let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
+impl BindInsteadOfMap {
+    fn no_op_msg(&self, cx: &LateContext<'_>) -> Option<String> {
+        let variant_id = cx.tcx.lang_items().get(self.variant_lang_item)?;
         let item_id = cx.tcx.parent(variant_id);
         Some(format!(
             "using `{}.{}({})`, which is a no-op",
             cx.tcx.item_name(item_id),
-            Self::BAD_METHOD_NAME,
+            self.bad_method_name,
             cx.tcx.item_name(variant_id),
         ))
     }
 
-    fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
-        let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
+    fn lint_msg(&self, cx: &LateContext<'_>) -> Option<String> {
+        let variant_id = cx.tcx.lang_items().get(self.variant_lang_item)?;
         let item_id = cx.tcx.parent(variant_id);
         Some(format!(
             "using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
             cx.tcx.item_name(item_id),
-            Self::BAD_METHOD_NAME,
+            self.bad_method_name,
             cx.tcx.item_name(variant_id),
-            Self::GOOD_METHOD_NAME
+            self.good_method_name,
         ))
     }
 
     fn lint_closure_autofixable(
+        &self,
         cx: &LateContext<'_>,
         expr: &hir::Expr<'_>,
         recv: &hir::Expr<'_>,
@@ -71,9 +92,9 @@ pub(crate) trait BindInsteadOfMap {
     ) -> bool {
         if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind
             && let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind
-            && Self::is_variant(cx, path.res)
+            && self.is_variant(cx, path.res)
             && !contains_return(inner_expr)
-            && let Some(msg) = Self::lint_msg(cx)
+            && let Some(msg) = self.lint_msg(cx)
         {
             let mut app = Applicability::MachineApplicable;
             let some_inner_snip = snippet_with_context(cx, inner_expr.span, closure_expr.span.ctxt(), "_", &mut app).0;
@@ -82,7 +103,7 @@ pub(crate) trait BindInsteadOfMap {
             let option_snip = snippet(cx, recv.span, "..");
             let note = format!(
                 "{option_snip}.{}({closure_args_snip} {some_inner_snip})",
-                Self::GOOD_METHOD_NAME
+                self.good_method_name
             );
             span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, msg, "try", note, app);
             true
@@ -91,13 +112,13 @@ pub(crate) trait BindInsteadOfMap {
         }
     }
 
-    fn lint_closure(cx: &LateContext<'_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) -> bool {
+    fn lint_closure(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) -> bool {
         let mut suggs = Vec::new();
         let can_sugg: bool = find_all_ret_expressions(cx, closure_expr, |ret_expr| {
             if !ret_expr.span.from_expansion()
                 && let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind
                 && let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind
-                && Self::is_variant(cx, path.res)
+                && self.is_variant(cx, path.res)
                 && !contains_return(arg)
             {
                 suggs.push((ret_expr.span, arg.span.source_callsite()));
@@ -108,7 +129,7 @@ pub(crate) trait BindInsteadOfMap {
         });
         let (span, msg) = if can_sugg
             && let hir::ExprKind::MethodCall(segment, ..) = expr.kind
-            && let Some(msg) = Self::lint_msg(cx)
+            && let Some(msg) = self.lint_msg(cx)
         {
             (segment.ident.span, msg)
         } else {
@@ -119,7 +140,7 @@ pub(crate) trait BindInsteadOfMap {
                 diag,
                 "try",
                 Applicability::MachineApplicable,
-                std::iter::once((span, Self::GOOD_METHOD_NAME.into())).chain(
+                std::iter::once((span, self.good_method_name.into())).chain(
                     suggs
                         .into_iter()
                         .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
@@ -130,9 +151,9 @@ pub(crate) trait BindInsteadOfMap {
     }
 
     /// Lint use of `_.and_then(|x| Some(y))` for `Option`s
-    fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
+    fn check(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
         if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def()
-            && let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)
+            && let Some(vid) = cx.tcx.lang_items().get(self.variant_lang_item)
             && adt.did() == cx.tcx.parent(vid)
         {
         } else {
@@ -144,15 +165,15 @@ pub(crate) trait BindInsteadOfMap {
                 let closure_body = cx.tcx.hir().body(body);
                 let closure_expr = peel_blocks(closure_body.value);
 
-                if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) {
+                if self.lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) {
                     true
                 } else {
-                    Self::lint_closure(cx, expr, closure_expr)
+                    self.lint_closure(cx, expr, closure_expr)
                 }
             },
             // `_.and_then(Some)` case, which is no-op.
-            hir::ExprKind::Path(QPath::Resolved(_, path)) if Self::is_variant(cx, path.res) => {
-                if let Some(msg) = Self::no_op_msg(cx) {
+            hir::ExprKind::Path(QPath::Resolved(_, path)) if self.is_variant(cx, path.res) => {
+                if let Some(msg) = self.no_op_msg(cx) {
                     span_lint_and_sugg(
                         cx,
                         BIND_INSTEAD_OF_MAP,
@@ -169,9 +190,9 @@ pub(crate) trait BindInsteadOfMap {
         }
     }
 
-    fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
+    fn is_variant(&self, cx: &LateContext<'_>, res: Res) -> bool {
         if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
-            if let Some(variant_id) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM) {
+            if let Some(variant_id) = cx.tcx.lang_items().get(self.variant_lang_item) {
                 return cx.tcx.parent(id) == variant_id;
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index a846552cddf..aa4cad9342a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -131,8 +131,8 @@ mod waker_clone_wake;
 mod wrong_self_convention;
 mod zst_offset;
 
-use bind_instead_of_map::BindInsteadOfMap;
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::macros::FormatArgsStorage;
@@ -4131,27 +4131,20 @@ pub struct Methods {
     msrv: Msrv,
     allow_expect_in_tests: bool,
     allow_unwrap_in_tests: bool,
-    allowed_dotfiles: FxHashSet<String>,
+    allowed_dotfiles: FxHashSet<&'static str>,
     format_args: FormatArgsStorage,
 }
 
 impl Methods {
-    #[must_use]
-    pub fn new(
-        avoid_breaking_exported_api: bool,
-        msrv: Msrv,
-        allow_expect_in_tests: bool,
-        allow_unwrap_in_tests: bool,
-        mut allowed_dotfiles: FxHashSet<String>,
-        format_args: FormatArgsStorage,
-    ) -> Self {
-        allowed_dotfiles.extend(DEFAULT_ALLOWED_DOTFILES.iter().map(ToString::to_string));
+    pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self {
+        let mut allowed_dotfiles: FxHashSet<_> = conf.allowed_dotfiles.iter().map(|s| &**s).collect();
+        allowed_dotfiles.extend(DEFAULT_ALLOWED_DOTFILES);
 
         Self {
-            avoid_breaking_exported_api,
-            msrv,
-            allow_expect_in_tests,
-            allow_unwrap_in_tests,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
+            msrv: conf.msrv.clone(),
+            allow_expect_in_tests: conf.allow_expect_in_tests,
+            allow_unwrap_in_tests: conf.allow_unwrap_in_tests,
             allowed_dotfiles,
             format_args,
         }
@@ -4512,8 +4505,8 @@ impl Methods {
                     }
                 },
                 ("and_then", [arg]) => {
-                    let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
-                    let biom_result_linted = bind_instead_of_map::ResultAndThenOk::check(cx, expr, recv, arg);
+                    let biom_option_linted = bind_instead_of_map::check_and_then_some(cx, expr, recv, arg);
+                    let biom_result_linted = bind_instead_of_map::check_and_then_ok(cx, expr, recv, arg);
                     if !biom_option_linted && !biom_result_linted {
                         unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
                     }
@@ -4853,7 +4846,7 @@ impl Methods {
                     open_options::check(cx, expr, recv);
                 },
                 ("or_else", [arg]) => {
-                    if !bind_instead_of_map::ResultOrElseErrInfo::check(cx, expr, recv, arg) {
+                    if !bind_instead_of_map::check_or_else_err(cx, expr, recv, arg) {
                         unnecessary_lazy_eval::check(cx, expr, recv, arg, "or");
                     }
                 },
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 3d326bc99f9..ed3bed42eb3 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
@@ -10,6 +10,7 @@ use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_span::{sym, Span};
+use std::ops::ControlFlow;
 
 use super::MAP_UNWRAP_OR;
 
@@ -54,15 +55,14 @@ pub(super) fn check<'tcx>(
             let mut reference_visitor = ReferenceVisitor {
                 cx,
                 identifiers: unwrap_visitor.identifiers,
-                found_reference: false,
                 unwrap_or_span: unwrap_arg.span,
             };
 
             let map = cx.tcx.hir();
             let body = map.body_owned_by(map.enclosing_body_owner(expr.hir_id));
-            reference_visitor.visit_body(body);
 
-            if reference_visitor.found_reference {
+            // Visit the body, and return if we've found a reference
+            if reference_visitor.visit_body(body).is_break() {
                 return;
             }
         }
@@ -151,29 +151,27 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
 struct ReferenceVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     identifiers: FxHashSet<HirId>,
-    found_reference: bool,
     unwrap_or_span: Span,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::All;
-    fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) {
+    type Result = ControlFlow<()>;
+    fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> {
         // If we haven't found a reference yet, check if this references
         // one of the locals that was moved in the `unwrap_or` argument.
         // We are only interested in exprs that appear before the `unwrap_or` call.
-        if !self.found_reference {
-            if expr.span < self.unwrap_or_span
-                && let ExprKind::Path(ref path) = expr.kind
-                && let QPath::Resolved(_, path) = path
-                && let Res::Local(local_id) = path.res
-                && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
-                && let PatKind::Binding(_, local_id, ..) = pat.kind
-                && self.identifiers.contains(&local_id)
-            {
-                self.found_reference = true;
-            }
-            rustc_hir::intravisit::walk_expr(self, expr);
+        if expr.span < self.unwrap_or_span
+            && let ExprKind::Path(ref path) = expr.kind
+            && let QPath::Resolved(_, path) = path
+            && let Res::Local(local_id) = path.res
+            && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
+            && let PatKind::Binding(_, local_id, ..) = pat.kind
+            && self.identifiers.contains(&local_id)
+        {
+            return ControlFlow::Break(());
         }
+        rustc_hir::intravisit::walk_expr(self, expr)
     }
 
     fn nested_visit_map(&mut self) -> Self::Map {
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 583e04fb4b1..e4326cb958e 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
@@ -1,8 +1,13 @@
+use std::ops::ControlFlow;
+
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{expr_type_is_certain, implements_trait, is_type_diagnostic_item};
-use clippy_utils::{contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment};
+use clippy_utils::visitors::for_each_expr;
+use clippy_utils::{
+    contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment, peel_blocks,
+};
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -13,7 +18,7 @@ use {rustc_ast as ast, rustc_hir as hir};
 use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT};
 
 /// Checks for the `OR_FUN_CALL` lint.
-#[allow(clippy::too_many_lines)]
+#[expect(clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &hir::Expr<'_>,
@@ -26,7 +31,6 @@ pub(super) fn check<'tcx>(
     /// `or_insert(T::new())` or `or_insert(T::default())`.
     /// Similarly checks for `unwrap_or_else(T::new)`, `unwrap_or_else(T::default)`,
     /// `or_insert_with(T::new)` or `or_insert_with(T::default)`.
-    #[allow(clippy::too_many_arguments)]
     fn check_unwrap_or_default(
         cx: &LateContext<'_>,
         name: &str,
@@ -70,18 +74,31 @@ pub(super) fn check<'tcx>(
         };
 
         let receiver_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs();
-        let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| {
+        let Some(suggested_method_def_id) = receiver_ty.ty_adt_def().and_then(|adt_def| {
             cx.tcx
                 .inherent_impls(adt_def.did())
                 .into_iter()
                 .flatten()
                 .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
-                .any(|assoc| {
-                    assoc.fn_has_self_parameter
+                .find_map(|assoc| {
+                    if assoc.fn_has_self_parameter
                         && cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1
+                    {
+                        Some(assoc.def_id)
+                    } else {
+                        None
+                    }
                 })
-        });
-        if !has_suggested_method {
+        }) else {
+            return false;
+        };
+        let in_sugg_method_implementation = {
+            matches!(
+                suggested_method_def_id.as_local(),
+                Some(local_def_id) if local_def_id == cx.tcx.hir().get_parent_item(receiver.hir_id).def_id
+            )
+        };
+        if in_sugg_method_implementation {
             return false;
         }
 
@@ -110,8 +127,8 @@ pub(super) fn check<'tcx>(
     }
 
     /// Checks for `*or(foo())`.
-    #[allow(clippy::too_many_arguments)]
-    fn check_general_case<'tcx>(
+    #[expect(clippy::too_many_arguments)]
+    fn check_or_fn_call<'tcx>(
         cx: &LateContext<'tcx>,
         name: &str,
         method_span: Span,
@@ -122,7 +139,7 @@ pub(super) fn check<'tcx>(
         span: Span,
         // None if lambda is required
         fun_span: Option<Span>,
-    ) {
+    ) -> bool {
         // (path, fn_has_argument, methods, suffix)
         const KNOW_TYPES: [(Symbol, bool, &[&str], &str); 4] = [
             (sym::BTreeEntry, false, &["or_insert"], "with"),
@@ -172,54 +189,68 @@ pub(super) fn check<'tcx>(
                 format!("{name}_{suffix}({sugg})"),
                 app,
             );
-        }
-    }
-
-    let extract_inner_arg = |arg: &'tcx hir::Expr<'_>| {
-        if let hir::ExprKind::Block(
-            hir::Block {
-                stmts: [],
-                expr: Some(expr),
-                ..
-            },
-            _,
-        ) = arg.kind
-        {
-            expr
+            true
         } else {
-            arg
+            false
         }
-    };
+    }
 
     if let [arg] = args {
-        let inner_arg = extract_inner_arg(arg);
-        match inner_arg.kind {
-            hir::ExprKind::Call(fun, or_args) => {
-                let or_has_args = !or_args.is_empty();
-                if or_has_args
-                    || !check_unwrap_or_default(cx, name, receiver, fun, Some(inner_arg), expr.span, method_span)
-                {
-                    let fun_span = if or_has_args { None } else { Some(fun.span) };
-                    check_general_case(cx, name, method_span, receiver, arg, None, expr.span, fun_span);
-                }
-            },
-            hir::ExprKind::Path(..) | hir::ExprKind::Closure(..) => {
-                check_unwrap_or_default(cx, name, receiver, inner_arg, None, expr.span, method_span);
-            },
-            hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
-                check_general_case(cx, name, method_span, receiver, arg, None, expr.span, None);
-            },
-            _ => (),
-        }
+        let inner_arg = peel_blocks(arg);
+        for_each_expr(cx, inner_arg, |ex| {
+            // `or_fun_call` lint needs to take nested expr into account,
+            // but `unwrap_or_default` lint doesn't, we don't want something like:
+            // `opt.unwrap_or(Foo { inner: String::default(), other: 1 })` to get replaced by
+            // `opt.unwrap_or_default()`.
+            let is_nested_expr = ex.hir_id != inner_arg.hir_id;
+
+            let is_triggered = match ex.kind {
+                hir::ExprKind::Call(fun, fun_args) => {
+                    let inner_fun_has_args = !fun_args.is_empty();
+                    let fun_span = if inner_fun_has_args || is_nested_expr {
+                        None
+                    } else {
+                        Some(fun.span)
+                    };
+                    (!inner_fun_has_args
+                        && !is_nested_expr
+                        && check_unwrap_or_default(cx, name, receiver, fun, Some(ex), expr.span, method_span))
+                        || check_or_fn_call(cx, name, method_span, receiver, arg, None, expr.span, fun_span)
+                },
+                hir::ExprKind::Path(..) | hir::ExprKind::Closure(..) if !is_nested_expr => {
+                    check_unwrap_or_default(cx, name, receiver, ex, None, expr.span, method_span)
+                },
+                hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
+                    check_or_fn_call(cx, name, method_span, receiver, arg, None, expr.span, None)
+                },
+                _ => false,
+            };
+
+            if is_triggered {
+                ControlFlow::Break(())
+            } else {
+                ControlFlow::Continue(())
+            }
+        });
     }
 
     // `map_or` takes two arguments
     if let [arg, lambda] = args {
-        let inner_arg = extract_inner_arg(arg);
-        if let hir::ExprKind::Call(fun, or_args) = inner_arg.kind {
-            let fun_span = if or_args.is_empty() { Some(fun.span) } else { None };
-            check_general_case(cx, name, method_span, receiver, arg, Some(lambda), expr.span, fun_span);
-        }
+        let inner_arg = peel_blocks(arg);
+        for_each_expr(cx, inner_arg, |ex| {
+            let is_top_most_expr = ex.hir_id == inner_arg.hir_id;
+            if let hir::ExprKind::Call(fun, fun_args) = ex.kind {
+                let fun_span = if fun_args.is_empty() && is_top_most_expr {
+                    Some(fun.span)
+                } else {
+                    None
+                };
+                if check_or_fn_call(cx, name, method_span, receiver, arg, Some(lambda), expr.span, fun_span) {
+                    return ControlFlow::Break(());
+                }
+            }
+            ControlFlow::Continue(())
+        });
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
index 29f44ec2a4d..cfb823dbf5d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
@@ -21,7 +21,7 @@ pub(super) fn check(
     path: &Expr<'_>,
     expr: &Expr<'_>,
     msrv: &Msrv,
-    allowed_dotfiles: &FxHashSet<String>,
+    allowed_dotfiles: &FxHashSet<&'static str>,
 ) {
     if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv).peel_refs(), sym::Path)
         && !path.span.from_expansion()
diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
index e43b712021a..53fa444e93c 100644
--- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
 use rustc_data_structures::fx::FxHashSet;
@@ -39,13 +40,19 @@ declare_clippy_lint! {
 }
 impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]);
 
-#[derive(Clone)]
 pub struct MinIdentChars {
-    pub allowed_idents_below_min_chars: FxHashSet<String>,
-    pub min_ident_chars_threshold: u64,
+    allowed_idents_below_min_chars: &'static FxHashSet<String>,
+    min_ident_chars_threshold: u64,
 }
 
 impl MinIdentChars {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            allowed_idents_below_min_chars: &conf.allowed_idents_below_min_chars,
+            min_ident_chars_threshold: conf.min_ident_chars_threshold,
+        }
+    }
+
     #[expect(clippy::cast_possible_truncation)]
     fn is_ident_too_short(&self, cx: &LateContext<'_>, str: &str, span: Span) -> bool {
         !in_external_macro(cx.sess(), span)
@@ -132,11 +139,11 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
                 return;
             }
 
-            // `struct Awa<T>(T)`
-            //                ^
+            // `struct Array<T, const N: usize>([T; N])`
+            //                                   ^  ^
             if let Node::PathSegment(path) = node {
                 if let Res::Def(def_kind, ..) = path.res
-                    && let DefKind::TyParam = def_kind
+                    && let DefKind::TyParam | DefKind::ConstParam = def_kind
                 {
                     return;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 32c8731c537..a9aafe7ed56 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
@@ -114,40 +114,35 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
         k: FnKind<'tcx>,
         decl: &'tcx FnDecl<'_>,
         body: &'tcx Body<'_>,
-        span: Span,
+        _: Span,
         _: LocalDefId,
     ) {
-        if let FnKind::Closure = k {
-            // Does not apply to closures
-            return;
-        }
-        if in_external_macro(cx.tcx.sess, span) {
-            return;
-        }
-        for arg in iter_input_pats(decl, body) {
-            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
-            if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
-                return;
-            }
-            if let PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..) = arg.pat.kind {
-                span_lint(
-                    cx,
-                    TOPLEVEL_REF_ARG,
-                    arg.pat.span,
-                    "`ref` directly on a function argument is ignored. \
-                    Consider using a reference type instead",
-                );
+        if !matches!(k, FnKind::Closure) {
+            for arg in iter_input_pats(decl, body) {
+                if let PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..) = arg.pat.kind
+                    && is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id)
+                    && !in_external_macro(cx.tcx.sess, arg.span)
+                {
+                    span_lint_hir(
+                        cx,
+                        TOPLEVEL_REF_ARG,
+                        arg.hir_id,
+                        arg.pat.span,
+                        "`ref` directly on a function argument is ignored. \
+                        Consider using a reference type instead",
+                    );
+                }
             }
         }
     }
 
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if !in_external_macro(cx.tcx.sess, stmt.span)
-            && let StmtKind::Let(local) = stmt.kind
+        if let StmtKind::Let(local) = stmt.kind
             && let PatKind::Binding(BindingMode(ByRef::Yes(mutabl), _), .., name, None) = local.pat.kind
             && let Some(init) = local.init
             // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
             && is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id)
+            && !in_external_macro(cx.tcx.sess, stmt.span)
         {
             let ctxt = local.span.ctxt();
             let mut app = Applicability::MachineApplicable;
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 934b9f490ad..748289454be 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
@@ -49,12 +49,12 @@ declare_lint_pass!(TypeParamMismatch => [MISMATCHING_TYPE_PARAM_ORDER]);
 
 impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if !item.span.from_expansion()
-            && let ItemKind::Impl(imp) = &item.kind
+        if let ItemKind::Impl(imp) = &item.kind
             && let TyKind::Path(QPath::Resolved(_, path)) = &imp.self_ty.kind
-            && let Some(segment) = path.segments.iter().next()
+            && let [segment, ..] = path.segments
             && let Some(generic_args) = segment.args
             && !generic_args.args.is_empty()
+            && !item.span.from_expansion()
         {
             // get the name and span of the generic parameters in the Impl
             let mut impl_params = Vec::new();
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 ed5f46ddc8d..68c158330ab 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
 use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};
@@ -79,9 +80,10 @@ pub struct MissingConstForFn {
 }
 
 impl MissingConstForFn {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
index ab1b4aa3dee..954216038fb 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::macro_backtrace;
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
@@ -49,9 +50,10 @@ pub struct MissingConstForThreadLocal {
 }
 
 impl MissingConstForThreadLocal {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 250fd5cbd48..2166b0fe5a0 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -5,6 +5,7 @@
 // [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415
 //
 
+use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
@@ -51,18 +52,10 @@ pub struct MissingDoc {
     prev_span: Option<Span>,
 }
 
-impl Default for MissingDoc {
-    #[must_use]
-    fn default() -> Self {
-        Self::new(false)
-    }
-}
-
 impl MissingDoc {
-    #[must_use]
-    pub fn new(crate_items_only: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            crate_items_only,
+            crate_items_only: conf.missing_docs_in_crate_items,
             doc_hidden_stack: vec![false],
             prev_span: None,
         }
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 c6c188854fd..cdf6645b3df 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
@@ -1,12 +1,13 @@
-use clippy_config::types::Rename;
+use clippy_config::Conf;
+use clippy_utils::def_path_def_ids;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{Item, ItemKind, UseKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 use rustc_span::Symbol;
 
@@ -46,15 +47,18 @@ declare_clippy_lint! {
 }
 
 pub struct ImportRename {
-    conf_renames: Vec<Rename>,
-    renames: FxHashMap<DefId, Symbol>,
+    renames: DefIdMap<Symbol>,
 }
 
 impl ImportRename {
-    pub fn new(conf_renames: Vec<Rename>) -> Self {
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
         Self {
-            conf_renames,
-            renames: FxHashMap::default(),
+            renames: conf
+                .enforced_import_renames
+                .iter()
+                .map(|x| (x.path.split("::").collect::<Vec<_>>(), Symbol::intern(&x.rename)))
+                .flat_map(|(path, rename)| def_path_def_ids(tcx, &path).map(move |id| (id, rename)))
+                .collect(),
         }
     }
 }
@@ -62,15 +66,6 @@ impl ImportRename {
 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 {
-            let segs = path.split("::").collect::<Vec<_>>();
-            for id in clippy_utils::def_path_def_ids(cx, &segs) {
-                self.renames.insert(id, Symbol::intern(rename));
-            }
-        }
-    }
-
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         if let ItemKind::Use(path, UseKind::Single) = &item.kind {
             for &res in &path.res {
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 2eb534da092..83af9979b9e 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -1,9 +1,10 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::trait_ref_of_method;
 use clippy_utils::ty::InteriorMut;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
@@ -67,17 +68,12 @@ declare_clippy_lint! {
 }
 
 pub struct MutableKeyType<'tcx> {
-    ignore_interior_mutability: Vec<String>,
     interior_mut: InteriorMut<'tcx>,
 }
 
 impl_lint_pass!(MutableKeyType<'_> => [ MUTABLE_KEY_TYPE ]);
 
 impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        self.interior_mut = InteriorMut::without_pointers(cx, &self.ignore_interior_mutability);
-    }
-
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
             self.check_sig(cx, item.owner_id.def_id, sig.decl);
@@ -107,10 +103,9 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType<'tcx> {
 }
 
 impl<'tcx> MutableKeyType<'tcx> {
-    pub fn new(ignore_interior_mutability: Vec<String>) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self {
         Self {
-            ignore_interior_mutability,
-            interior_mut: InteriorMut::default(),
+            interior_mut: InteriorMut::without_pointers(tcx, &conf.ignore_interior_mutability),
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs
index bc7b2c6b7c1..60372121a7a 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs
@@ -35,33 +35,18 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
     }
 
     fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) {
-        if in_external_macro(cx.sess(), ty.span) {
-            return;
-        }
-
-        if let hir::TyKind::Ref(
-            _,
-            hir::MutTy {
-                ty: pty,
-                mutbl: hir::Mutability::Mut,
-            },
-        ) = ty.kind
+        if let hir::TyKind::Ref(_, mty) = ty.kind
+            && mty.mutbl == hir::Mutability::Mut
+            && let hir::TyKind::Ref(_, mty) = mty.ty.kind
+            && mty.mutbl == hir::Mutability::Mut
+            && !in_external_macro(cx.sess(), ty.span)
         {
-            if let hir::TyKind::Ref(
-                _,
-                hir::MutTy {
-                    mutbl: hir::Mutability::Mut,
-                    ..
-                },
-            ) = pty.kind
-            {
-                span_lint(
-                    cx,
-                    MUT_MUT,
-                    ty.span,
-                    "generally you want to avoid `&mut &mut _` if possible",
-                );
-            }
+            span_lint(
+                cx,
+                MUT_MUT,
+                ty.span,
+                "generally you want to avoid `&mut &mut _` if possible",
+            );
         }
     }
 }
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 fb02f24c9dc..098098718af 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
@@ -37,83 +37,75 @@ declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
 
 impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
     fn check_pat(&mut self, cx: &LateContext<'tcx>, ref_pat: &'tcx Pat<'_>) {
-        if ref_pat.span.from_expansion() {
-            // OK, simple enough, lints doesn't check in macro.
-            return;
-        }
-
-        // 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(ref_pat.hir_id) {
-            let Node::Pat(pat) = node else { break };
-
-            if matches!(pat.kind, PatKind::Or(_)) {
-                return;
+        if let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind
+            && !ref_pat.span.from_expansion()
+            && cx
+                .tcx
+                .hir()
+                .parent_iter(ref_pat.hir_id)
+                .map_while(|(_, parent)| if let Node::Pat(pat) = parent { Some(pat) } else { None })
+                // Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
+                .all(|pat| !matches!(pat.kind, PatKind::Or(_)))
+        {
+            match pat.kind {
+                // Check sub_pat got a `ref` keyword (excluding `ref mut`).
+                PatKind::Binding(BindingMode::REF, _, ident, None) => {
+                    span_lint_and_then(
+                        cx,
+                        NEEDLESS_BORROWED_REFERENCE,
+                        ref_pat.span,
+                        "this pattern takes a reference on something that is being dereferenced",
+                        |diag| {
+                            // `&ref ident`
+                            //  ^^^^^
+                            let span = ref_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,
+                ) => {
+                    check_subpatterns(
+                        cx,
+                        "dereferencing a slice pattern where every element takes a reference",
+                        ref_pat,
+                        pat,
+                        itertools::chain(before, after),
+                    );
+                },
+                PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
+                    check_subpatterns(
+                        cx,
+                        "dereferencing a tuple pattern where every element takes a reference",
+                        ref_pat,
+                        pat,
+                        subpatterns,
+                    );
+                },
+                PatKind::Struct(_, fields, _) => {
+                    check_subpatterns(
+                        cx,
+                        "dereferencing a struct pattern where every field's pattern takes a reference",
+                        ref_pat,
+                        pat,
+                        fields.iter().map(|field| field.pat),
+                    );
+                },
+                _ => {},
             }
         }
-
-        // Only lint immutable refs, because `&mut ref T` may be useful.
-        let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind else {
-            return;
-        };
-
-        match pat.kind {
-            // Check sub_pat got a `ref` keyword (excluding `ref mut`).
-            PatKind::Binding(BindingMode::REF, _, ident, None) => {
-                span_lint_and_then(
-                    cx,
-                    NEEDLESS_BORROWED_REFERENCE,
-                    ref_pat.span,
-                    "this pattern takes a reference on something that is being dereferenced",
-                    |diag| {
-                        // `&ref ident`
-                        //  ^^^^^
-                        let span = ref_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,
-            ) => {
-                check_subpatterns(
-                    cx,
-                    "dereferencing a slice pattern where every element takes a reference",
-                    ref_pat,
-                    pat,
-                    itertools::chain(before, after),
-                );
-            },
-            PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
-                check_subpatterns(
-                    cx,
-                    "dereferencing a tuple pattern where every element takes a reference",
-                    ref_pat,
-                    pat,
-                    subpatterns,
-                );
-            },
-            PatKind::Struct(_, fields, _) => {
-                check_subpatterns(
-                    cx,
-                    "dereferencing a struct pattern where every field's pattern takes a reference",
-                    ref_pat,
-                    pat,
-                    fields.iter().map(|field| field.pat),
-                );
-            },
-            _ => {},
-        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index 064ce59c234..67f9b52c352 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::mir::PossibleBorrowerMap;
 use clippy_utils::source::snippet_with_context;
@@ -67,11 +68,10 @@ pub struct NeedlessBorrowsForGenericArgs<'tcx> {
 impl_lint_pass!(NeedlessBorrowsForGenericArgs<'_> => [NEEDLESS_BORROWS_FOR_GENERIC_ARGS]);
 
 impl NeedlessBorrowsForGenericArgs<'_> {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
             possible_borrowers: Vec::new(),
-            msrv,
+            msrv: conf.msrv.clone(),
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 143acc2b1cb..6390e51f916 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -3,7 +3,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Block, BlockCheckMode, Closure, Expr, ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_trait_method;
@@ -55,16 +55,8 @@ declare_lint_pass!(NeedlessForEach => [NEEDLESS_FOR_EACH]);
 
 impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        let (StmtKind::Expr(expr) | StmtKind::Semi(expr)) = stmt.kind else {
-            return;
-        };
-
-        if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind
-            // Check the method name is `for_each`.
-            && method_name.ident.name == Symbol::intern("for_each")
-            // Check `for_each` is an associated function of `Iterator`.
-            && is_trait_method(cx, expr, sym::Iterator)
-            // Checks the receiver of `for_each` is also a method call.
+        if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
+            && let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind
             && let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind
             // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or
             // `v.foo().iter().for_each()` must be skipped.
@@ -72,6 +64,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
                 iter_recv.kind,
                 ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..)
             )
+            && method_name.ident.name.as_str() == "for_each"
+            && is_trait_method(cx, expr, sym::Iterator)
             // Checks the type of the `iter` method receiver is NOT a user defined type.
             && has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some()
             // Skip the lint if the body is not block because this is simpler than `for` loop.
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 5ffd41d78e0..d543fd467ab 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -1,8 +1,10 @@
 use super::needless_pass_by_value::requires_exact_signature;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{inherits_cfg, is_from_proc_macro, is_self};
+use core::ops::ControlFlow;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
@@ -20,8 +22,6 @@ use rustc_span::symbol::kw;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
-use core::ops::ControlFlow;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Check if a `&mut` function argument is actually used mutably.
@@ -51,7 +51,6 @@ declare_clippy_lint! {
     "using a `&mut` argument when it's not mutated"
 }
 
-#[derive(Clone)]
 pub struct NeedlessPassByRefMut<'tcx> {
     avoid_breaking_exported_api: bool,
     used_fn_def_ids: FxHashSet<LocalDefId>,
@@ -59,9 +58,9 @@ pub struct NeedlessPassByRefMut<'tcx> {
 }
 
 impl NeedlessPassByRefMut<'_> {
-    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            avoid_breaking_exported_api,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
             used_fn_def_ids: FxHashSet::default(),
             fn_def_ids_to_maybe_unused_mut: FxIndexMap::default(),
         }
diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
index f7621822b66..fa90ee60612 100644
--- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
@@ -45,10 +45,10 @@ declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]);
 
 impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if !in_external_macro(cx.sess(), expr.span)
-            && let ExprKind::Unary(UnOp::Not, inner) = expr.kind
+        if let ExprKind::Unary(UnOp::Not, inner) = expr.kind
             && let ExprKind::Binary(ref op, left, _) = inner.kind
             && let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node
+            && !in_external_macro(cx.sess(), expr.span)
         {
             let ty = cx.typeck_results().expr_ty(left);
 
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 6f5505e8a63..15bb328b446 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -4,6 +4,7 @@
 
 use std::ptr;
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::in_constant;
 use clippy_utils::macros::macro_backtrace;
@@ -179,17 +180,15 @@ fn lint<'tcx>(cx: &LateContext<'tcx>, source: Source<'tcx>) {
 }
 
 pub struct NonCopyConst<'tcx> {
-    ignore_interior_mutability: Vec<String>,
     interior_mut: InteriorMut<'tcx>,
 }
 
 impl_lint_pass!(NonCopyConst<'_> => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTERIOR_MUTABLE_CONST]);
 
 impl<'tcx> NonCopyConst<'tcx> {
-    pub fn new(ignore_interior_mutability: Vec<String>) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self {
         Self {
-            ignore_interior_mutability,
-            interior_mut: InteriorMut::default(),
+            interior_mut: InteriorMut::new(tcx, &conf.ignore_interior_mutability),
         }
     }
 
@@ -308,10 +307,6 @@ impl<'tcx> NonCopyConst<'tcx> {
 }
 
 impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        self.interior_mut = InteriorMut::new(cx, &self.ignore_interior_mutability);
-    }
-
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) {
         if let ItemKind::Const(.., body_id) = it.kind {
             let ty = cx.tcx.type_of(it.owner_id).instantiate_identity();
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 eacfe9ff328..832518d2d35 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use rustc_ast::ast::{
     self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
@@ -73,13 +74,20 @@ declare_clippy_lint! {
     "unclear name"
 }
 
-#[derive(Copy, Clone)]
 pub struct NonExpressiveNames {
     pub single_char_binding_names_threshold: u64,
 }
 
 impl_lint_pass!(NonExpressiveNames => [SIMILAR_NAMES, MANY_SINGLE_CHAR_NAMES, JUST_UNDERSCORES_AND_DIGITS]);
 
+impl NonExpressiveNames {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            single_char_binding_names_threshold: conf.single_char_binding_names_threshold,
+        }
+    }
+}
+
 struct ExistingName {
     interned: Symbol,
     span: Span,
@@ -90,7 +98,7 @@ struct ExistingName {
 struct SimilarNamesLocalVisitor<'a, 'tcx> {
     names: Vec<ExistingName>,
     cx: &'a EarlyContext<'tcx>,
-    lint: NonExpressiveNames,
+    threshold: u64,
 
     /// A stack of scopes containing the single-character bindings in each scope.
     single_char_names: Vec<Vec<Ident>>,
@@ -103,8 +111,7 @@ impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> {
         }
 
         let num_single_char_names = self.single_char_names.iter().flatten().count();
-        let threshold = self.lint.single_char_binding_names_threshold;
-        if num_single_char_names as u64 > threshold {
+        if num_single_char_names as u64 > self.threshold {
             let span = self
                 .single_char_names
                 .iter()
@@ -384,7 +391,7 @@ impl EarlyLintPass for NonExpressiveNames {
             ..
         }) = item.kind
         {
-            do_check(*self, cx, &item.attrs, &sig.decl, blk);
+            do_check(self, cx, &item.attrs, &sig.decl, blk);
         }
     }
 
@@ -399,17 +406,17 @@ impl EarlyLintPass for NonExpressiveNames {
             ..
         }) = item.kind
         {
-            do_check(*self, cx, &item.attrs, &sig.decl, blk);
+            do_check(self, cx, &item.attrs, &sig.decl, blk);
         }
     }
 }
 
-fn do_check(lint: NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) {
+fn do_check(lint: &NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) {
     if !attrs.iter().any(|attr| attr.has_name(sym::test)) {
         let mut visitor = SimilarNamesLocalVisitor {
             names: Vec::new(),
             cx,
-            lint,
+            threshold: lint.single_char_binding_names_threshold,
             single_char_names: vec![vec![]],
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index 74e6c57b52d..a60988ac5db 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_lint_allowed;
 use clippy_utils::source::snippet;
@@ -54,15 +55,14 @@ declare_clippy_lint! {
     "there is a field that is not safe to be sent to another thread in a `Send` struct"
 }
 
-#[derive(Copy, Clone)]
 pub struct NonSendFieldInSendTy {
     enable_raw_pointer_heuristic: bool,
 }
 
 impl NonSendFieldInSendTy {
-    pub fn new(enable_raw_pointer_heuristic: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            enable_raw_pointer_heuristic,
+            enable_raw_pointer_heuristic: conf.enable_raw_pointer_heuristic_for_send,
         }
     }
 }
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 88f2eabaccb..2aaf1e6ff46 100644
--- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
@@ -1,4 +1,5 @@
 use clippy_config::types::MacroMatcher;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
 use rustc_ast::ast;
@@ -35,17 +36,15 @@ declare_clippy_lint! {
 /// The (callsite span, (open brace, close brace), source snippet)
 type MacroInfo = (Span, (char, char), String);
 
-#[derive(Debug)]
 pub struct MacroBraces {
     macro_braces: FxHashMap<String, (char, char)>,
     done: FxHashSet<Span>,
 }
 
 impl MacroBraces {
-    pub fn new(conf: &[MacroMatcher]) -> Self {
-        let macro_braces = macro_braces(conf);
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            macro_braces,
+            macro_braces: macro_braces(&conf.standard_macro_braces),
             done: FxHashSet::default(),
         }
     }
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 7d6f26cde3e..a7e381be743 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,4 +1,5 @@
 use super::ARITHMETIC_SIDE_EFFECTS;
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_diagnostic_item;
@@ -11,19 +12,9 @@ use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
 use {rustc_ast as ast, rustc_hir as hir};
 
-const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]];
-const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
-const DISALLOWED_INT_METHODS: &[Symbol] = &[
-    sym::saturating_div,
-    sym::wrapping_div,
-    sym::wrapping_rem,
-    sym::wrapping_rem_euclid,
-];
-
-#[derive(Debug)]
 pub struct ArithmeticSideEffects {
-    allowed_binary: FxHashMap<String, FxHashSet<String>>,
-    allowed_unary: FxHashSet<String>,
+    allowed_binary: FxHashMap<&'static str, FxHashSet<&'static str>>,
+    allowed_unary: FxHashSet<&'static str>,
     // Used to check whether expressions are constants, such as in enum discriminants and consts
     const_span: Option<Span>,
     disallowed_int_methods: FxHashSet<Symbol>,
@@ -33,26 +24,38 @@ pub struct ArithmeticSideEffects {
 impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]);
 
 impl ArithmeticSideEffects {
-    #[must_use]
-    pub fn new(user_allowed_binary: Vec<[String; 2]>, user_allowed_unary: Vec<String>) -> Self {
-        let mut allowed_binary: FxHashMap<String, FxHashSet<String>> = <_>::default();
-        for [lhs, rhs] in user_allowed_binary.into_iter().chain(
-            HARD_CODED_ALLOWED_BINARY
-                .iter()
-                .copied()
-                .map(|[lhs, rhs]| [lhs.to_string(), rhs.to_string()]),
-        ) {
+    pub fn new(conf: &'static Conf) -> Self {
+        let mut allowed_binary = FxHashMap::<&'static str, FxHashSet<&'static str>>::default();
+        let mut allowed_unary = FxHashSet::<&'static str>::default();
+
+        allowed_unary.extend(["f32", "f64", "std::num::Saturating", "std::num::Wrapping"]);
+        allowed_unary.extend(conf.arithmetic_side_effects_allowed_unary.iter().map(|x| &**x));
+        allowed_binary.extend([
+            ("f32", FxHashSet::from_iter(["f32"])),
+            ("f64", FxHashSet::from_iter(["f64"])),
+            ("std::string::String", FxHashSet::from_iter(["str"])),
+        ]);
+        for [lhs, rhs] in &conf.arithmetic_side_effects_allowed_binary {
             allowed_binary.entry(lhs).or_default().insert(rhs);
         }
-        let allowed_unary = user_allowed_unary
-            .into_iter()
-            .chain(HARD_CODED_ALLOWED_UNARY.iter().copied().map(String::from))
-            .collect();
+        for s in &conf.arithmetic_side_effects_allowed {
+            allowed_binary.entry(s).or_default().insert("*");
+            allowed_binary.entry("*").or_default().insert(s);
+            allowed_unary.insert(s);
+        }
+
         Self {
             allowed_binary,
             allowed_unary,
+            disallowed_int_methods: [
+                sym::saturating_div,
+                sym::wrapping_div,
+                sym::wrapping_rem,
+                sym::wrapping_rem_euclid,
+            ]
+            .into_iter()
+            .collect(),
             const_span: None,
-            disallowed_int_methods: DISALLOWED_INT_METHODS.iter().copied().collect(),
             expr_span: None,
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 59834781a58..9baecff801f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -23,6 +23,7 @@ mod verbose_bit_mask;
 
 pub(crate) mod arithmetic_side_effects;
 
+use clippy_config::Conf;
 use rustc_hir::{Body, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
@@ -841,6 +842,16 @@ pub struct Operators {
     verbose_bit_mask_threshold: u64,
     modulo_arithmetic_allow_comparison_to_zero: bool,
 }
+impl Operators {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            arithmetic_context: numeric_arithmetic::Context::default(),
+            verbose_bit_mask_threshold: conf.verbose_bit_mask_threshold,
+            modulo_arithmetic_allow_comparison_to_zero: conf.allow_comparison_to_zero,
+        }
+    }
+}
+
 impl_lint_pass!(Operators => [
     ABSURD_EXTREME_COMPARISONS,
     ARITHMETIC_SIDE_EFFECTS,
@@ -869,15 +880,7 @@ impl_lint_pass!(Operators => [
     PTR_EQ,
     SELF_ASSIGNMENT,
 ]);
-impl Operators {
-    pub fn new(verbose_bit_mask_threshold: u64, modulo_arithmetic_allow_comparison_to_zero: bool) -> Self {
-        Self {
-            arithmetic_context: numeric_arithmetic::Context::default(),
-            verbose_bit_mask_threshold,
-            modulo_arithmetic_allow_comparison_to_zero,
-        }
-    }
-}
+
 impl<'tcx> LateLintPass<'tcx> for Operators {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         eq_op::check_assert(cx, e);
diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
index 4bfb26209d2..d16f5f8e112 100644
--- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
@@ -3,7 +3,7 @@ use clippy_utils::is_direct_expn_of;
 use rustc_ast::ast::{Expr, ExprKind, MethodCall};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -35,30 +35,18 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
 
 impl EarlyLintPass for OptionEnvUnwrap {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        fn lint(cx: &EarlyContext<'_>, span: Span) {
+        if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
+            && matches!(seg.ident.name, sym::expect | sym::unwrap)
+            && is_direct_expn_of(receiver.span, "option_env").is_some()
+        {
             span_lint_and_help(
                 cx,
                 OPTION_ENV_UNWRAP,
-                span,
+                expr.span,
                 "this will panic at run-time if the environment variable doesn't exist at compile-time",
                 None,
                 "consider using the `env!` macro instead",
             );
         }
-
-        if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind
-            && matches!(seg.ident.name, sym::expect | sym::unwrap)
-        {
-            if let ExprKind::Call(caller, _) = &receiver.kind &&
-            // If it exists, it will be ::core::option::Option::Some("<env var>").unwrap() (A method call in the HIR)
-            is_direct_expn_of(caller.span, "option_env").is_some()
-            {
-                lint(cx, expr.span);
-            } else if let ExprKind::Path(_, caller) = &receiver.kind && // If it doesn't exist, it will be ::core::option::Option::None::<&'static str>.unwrap() (A path in the HIR)
-            is_direct_expn_of(caller.span, "option_env").is_some()
-            {
-                lint(cx, expr.span);
-            }
-        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
index 80ef761906e..4eefd0065f6 100644
--- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_in_test;
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
@@ -5,9 +6,16 @@ use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 
-#[derive(Clone)]
 pub struct PanicUnimplemented {
-    pub allow_panic_in_tests: bool,
+    allow_panic_in_tests: bool,
+}
+
+impl PanicUnimplemented {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            allow_panic_in_tests: conf.allow_panic_in_tests,
+        }
+    }
 }
 
 declare_clippy_lint! {
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 128bfd49d9e..5ca244f0141 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
@@ -1,5 +1,6 @@
 use std::{cmp, iter};
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy};
@@ -14,7 +15,7 @@ use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, No
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, RegionKind};
+use rustc_middle::ty::{self, RegionKind, TyCtxt};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
@@ -103,7 +104,6 @@ declare_clippy_lint! {
     "functions taking large arguments by value"
 }
 
-#[derive(Copy, Clone)]
 pub struct PassByRefOrValue {
     ref_min_size: u64,
     value_max_size: u64,
@@ -111,14 +111,9 @@ pub struct PassByRefOrValue {
 }
 
 impl<'tcx> PassByRefOrValue {
-    pub fn new(
-        ref_min_size: Option<u64>,
-        value_max_size: u64,
-        avoid_breaking_exported_api: bool,
-        pointer_width: u32,
-    ) -> Self {
-        let ref_min_size = ref_min_size.unwrap_or_else(|| {
-            let bit_width = u64::from(pointer_width);
+    pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
+        let ref_min_size = conf.trivial_copy_size_limit.unwrap_or_else(|| {
+            let bit_width = u64::from(tcx.sess.target.pointer_width);
             // Cap the calculated bit width at 32-bits to reduce
             // portability problems between 32 and 64-bit targets
             let bit_width = cmp::min(bit_width, 32);
@@ -130,8 +125,8 @@ impl<'tcx> PassByRefOrValue {
 
         Self {
             ref_min_size,
-            value_max_size,
-            avoid_breaking_exported_api,
+            value_max_size: conf.pass_by_value_size_limit,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
new file mode 100644
index 00000000000..0008f154ae3
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
@@ -0,0 +1,193 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::path_to_local_id;
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_ast::{LitKind, StrStyle};
+use rustc_errors::Applicability;
+use rustc_hir::def::Res;
+use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, PatKind, QPath, Stmt, StmtKind, TyKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::impl_lint_pass;
+use rustc_span::{sym, Span, Symbol};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for calls to `push` immediately after creating a new `PathBuf`.
+    ///
+    /// ### Why is this bad?
+    /// Multiple `.join()` calls are usually easier to read than multiple `.push`
+    /// calls across multiple statements. It might also be possible to use
+    /// `PathBuf::from` instead.
+    ///
+    /// ### Known problems
+    /// `.join()` introduces an implicit `clone()`. `PathBuf::from` can alternativly be
+    /// used when the `PathBuf` is newly constructed. This will avoild the implicit clone.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::path::PathBuf;
+    /// let mut path_buf = PathBuf::new();
+    /// path_buf.push("foo");
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use std::path::PathBuf;
+    /// let path_buf = PathBuf::from("foo");
+    /// // or
+    /// let path_buf = PathBuf::new().join("foo");
+    /// ```
+    #[clippy::version = "1.81.0"]
+    pub PATHBUF_INIT_THEN_PUSH,
+    restriction,
+    "`push` immediately after `PathBuf` creation"
+}
+
+impl_lint_pass!(PathbufThenPush<'_> => [PATHBUF_INIT_THEN_PUSH]);
+
+#[derive(Default)]
+pub struct PathbufThenPush<'tcx> {
+    searcher: Option<PathbufPushSearcher<'tcx>>,
+}
+
+struct PathbufPushSearcher<'tcx> {
+    local_id: HirId,
+    lhs_is_let: bool,
+    let_ty_span: Option<Span>,
+    init_val: Expr<'tcx>,
+    arg: Option<Expr<'tcx>>,
+    name: Symbol,
+    err_span: Span,
+}
+
+impl<'tcx> PathbufPushSearcher<'tcx> {
+    /// Try to generate a suggestion with `PathBuf::from`.
+    /// Returns `None` if the suggestion would be invalid.
+    fn gen_pathbuf_from(&self, cx: &LateContext<'_>) -> Option<String> {
+        if let ExprKind::Call(iter_expr, []) = &self.init_val.kind
+            && let ExprKind::Path(QPath::TypeRelative(ty, segment)) = &iter_expr.kind
+            && let TyKind::Path(ty_path) = &ty.kind
+            && let QPath::Resolved(None, path) = ty_path
+            && let Res::Def(_, def_id) = &path.res
+            && cx.tcx.is_diagnostic_item(sym::PathBuf, *def_id)
+            && segment.ident.name == sym::new
+            && let Some(arg) = self.arg
+            && let ExprKind::Lit(x) = arg.kind
+            && let LitKind::Str(_, StrStyle::Cooked) = x.node
+            && let Some(s) = snippet_opt(cx, arg.span)
+        {
+            Some(format!(" = PathBuf::from({s});"))
+        } else {
+            None
+        }
+    }
+
+    fn gen_pathbuf_join(&self, cx: &LateContext<'_>) -> Option<String> {
+        let arg = self.arg?;
+        let arg_str = snippet_opt(cx, arg.span)?;
+        let init_val = snippet_opt(cx, self.init_val.span)?;
+        Some(format!(" = {init_val}.join({arg_str});"))
+    }
+
+    fn display_err(&self, cx: &LateContext<'_>) {
+        if clippy_utils::attrs::span_contains_cfg(cx, self.err_span) {
+            return;
+        }
+        let mut sugg = if self.lhs_is_let {
+            String::from("let mut ")
+        } else {
+            String::new()
+        };
+        sugg.push_str(self.name.as_str());
+        if let Some(span) = self.let_ty_span {
+            sugg.push_str(": ");
+            sugg.push_str(&snippet(cx, span, "_"));
+        }
+        match self.gen_pathbuf_from(cx) {
+            Some(value) => {
+                sugg.push_str(&value);
+            },
+            None => {
+                if let Some(value) = self.gen_pathbuf_join(cx) {
+                    sugg.push_str(&value);
+                } else {
+                    return;
+                }
+            },
+        }
+
+        span_lint_and_sugg(
+            cx,
+            PATHBUF_INIT_THEN_PUSH,
+            self.err_span,
+            "calls to `push` immediately after creation",
+            "consider using the `.join()`",
+            sugg,
+            Applicability::HasPlaceholders,
+        );
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for PathbufThenPush<'tcx> {
+    fn check_block(&mut self, _: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
+        self.searcher = None;
+    }
+
+    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
+        if let Some(init_expr) = local.init
+            && let PatKind::Binding(BindingMode::MUT, id, name, None) = local.pat.kind
+            && !in_external_macro(cx.sess(), local.span)
+            && let ty = cx.typeck_results().pat_ty(local.pat)
+            && is_type_diagnostic_item(cx, ty, sym::PathBuf)
+        {
+            self.searcher = Some(PathbufPushSearcher {
+                local_id: id,
+                lhs_is_let: true,
+                name: name.name,
+                let_ty_span: local.ty.map(|ty| ty.span),
+                err_span: local.span,
+                init_val: *init_expr,
+                arg: None,
+            });
+        }
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if let ExprKind::Assign(left, right, _) = expr.kind
+            && let ExprKind::Path(QPath::Resolved(None, path)) = left.kind
+            && let [name] = &path.segments
+            && let Res::Local(id) = path.res
+            && !in_external_macro(cx.sess(), expr.span)
+            && let ty = cx.typeck_results().expr_ty(left)
+            && is_type_diagnostic_item(cx, ty, sym::PathBuf)
+        {
+            self.searcher = Some(PathbufPushSearcher {
+                local_id: id,
+                lhs_is_let: false,
+                let_ty_span: None,
+                name: name.ident.name,
+                err_span: expr.span,
+                init_val: *right,
+                arg: None,
+            });
+        }
+    }
+
+    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
+        if let Some(mut searcher) = self.searcher.take() {
+            if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind
+                && let ExprKind::MethodCall(name, self_arg, [arg_expr], _) = expr.kind
+                && path_to_local_id(self_arg, searcher.local_id)
+                && name.ident.as_str() == "push"
+            {
+                searcher.err_span = searcher.err_span.to(stmt.span);
+                searcher.arg = Some(*arg_expr);
+                searcher.display_err(cx);
+            }
+        }
+    }
+
+    fn check_block_post(&mut self, _: &LateContext<'tcx>, _: &'tcx Block<'tcx>) {
+        self.searcher = None;
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
index 704acdc103e..dc142b6e157 100644
--- a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
+++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
@@ -31,10 +31,10 @@ declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALS
 impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind
-            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
-            && path.ident.name == sym!(set_readonly)
             && let ExprKind::Lit(lit) = &arg.kind
             && LitKind::Bool(false) == lit.node
+            && path.ident.name.as_str() == "set_readonly"
+            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
         {
             span_lint_and_then(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
index d20d4a605a2..77b707567e4 100644
--- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -1,4 +1,5 @@
 use clippy_config::types::PubUnderscoreFieldsBehaviour;
+use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::is_path_lang_item;
@@ -42,10 +43,18 @@ declare_clippy_lint! {
 }
 
 pub struct PubUnderscoreFields {
-    pub behavior: PubUnderscoreFieldsBehaviour,
+    behavior: PubUnderscoreFieldsBehaviour,
 }
 impl_lint_pass!(PubUnderscoreFields => [PUB_UNDERSCORE_FIELDS]);
 
+impl PubUnderscoreFields {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            behavior: conf.pub_underscore_fields_behavior,
+        }
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         // This lint only pertains to structs.
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 7cf98ad9e09..ef6b4d3aeab 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -2,6 +2,7 @@ use crate::manual_let_else::MANUAL_LET_ELSE;
 use crate::question_mark_used::QUESTION_MARK_USED;
 use clippy_config::msrvs::Msrv;
 use clippy_config::types::MatchLintBehaviour;
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
@@ -62,11 +63,10 @@ pub struct QuestionMark {
 impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]);
 
 impl QuestionMark {
-    #[must_use]
-    pub fn new(msrv: Msrv, matches_behaviour: MatchLintBehaviour) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            msrv,
-            matches_behaviour,
+            msrv: conf.msrv.clone(),
+            matches_behaviour: conf.matches_for_let_else,
             try_block_depth_stack: Vec::new(),
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 4fdaa9f00a1..829fb58bc65 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
@@ -164,9 +165,10 @@ pub struct Ranges {
 }
 
 impl Ranges {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs
index 3a004245459..3c19ee3522d 100644
--- a/src/tools/clippy/clippy_lints/src/raw_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs
@@ -1,8 +1,6 @@
-use std::iter::once;
-use std::ops::ControlFlow;
-
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_ast::token::LitKind;
 use rustc_errors::Applicability;
@@ -10,6 +8,8 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
 use rustc_span::{BytePos, Pos, Span};
+use std::iter::once;
+use std::ops::ControlFlow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -61,22 +61,27 @@ pub struct RawStrings {
     pub allow_one_hash_in_raw_strings: bool,
 }
 
+impl RawStrings {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            allow_one_hash_in_raw_strings: conf.allow_one_hash_in_raw_strings,
+        }
+    }
+}
+
 impl EarlyLintPass for RawStrings {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if !in_external_macro(cx.sess(), expr.span)
-            && let ExprKind::Lit(lit) = expr.kind
-            && let LitKind::StrRaw(max) | LitKind::ByteStrRaw(max) | LitKind::CStrRaw(max) = lit.kind
+        if let ExprKind::Lit(lit) = expr.kind
+            && let (prefix, max) = match lit.kind {
+                LitKind::StrRaw(max) => ("r", max),
+                LitKind::ByteStrRaw(max) => ("br", max),
+                LitKind::CStrRaw(max) => ("cr", max),
+                _ => return,
+            }
+            && !in_external_macro(cx.sess(), expr.span)
+            && expr.span.check_source_text(cx, |src| src.starts_with(prefix))
         {
             let str = lit.symbol.as_str();
-            let prefix = match lit.kind {
-                LitKind::StrRaw(..) => "r",
-                LitKind::ByteStrRaw(..) => "br",
-                LitKind::CStrRaw(..) => "cr",
-                _ => unreachable!(),
-            };
-            if !snippet(cx, expr.span, prefix).trim().starts_with(prefix) {
-                return;
-            }
             let descr = lit.kind.descr();
 
             if !str.contains(['\\', '"']) {
@@ -86,7 +91,7 @@ impl EarlyLintPass for RawStrings {
                     expr.span,
                     "unnecessary raw string literal",
                     |diag| {
-                        let (start, end) = hash_spans(expr.span, prefix, 0, max);
+                        let (start, end) = hash_spans(expr.span, prefix.len(), 0, max);
 
                         // BytePos: skip over the `b` in `br`, we checked the prefix appears in the source text
                         let r_pos = expr.span.lo() + BytePos::from_usize(prefix.len() - 1);
@@ -148,7 +153,7 @@ impl EarlyLintPass for RawStrings {
                     expr.span,
                     "unnecessary hashes around raw string literal",
                     |diag| {
-                        let (start, end) = hash_spans(expr.span, prefix, req, max);
+                        let (start, end) = hash_spans(expr.span, prefix.len(), req, max);
 
                         let message = match max - req {
                             _ if req == 0 => format!("remove all the hashes around the {descr} literal"),
@@ -174,11 +179,11 @@ impl EarlyLintPass for RawStrings {
 /// r###".."###
 ///   ^^    ^^
 /// ```
-fn hash_spans(literal_span: Span, prefix: &str, req: u8, max: u8) -> (Span, Span) {
+fn hash_spans(literal_span: Span, prefix_len: usize, req: u8, max: u8) -> (Span, Span) {
     let literal_span = literal_span.data();
 
     // BytePos: we checked prefix appears literally in the source text
-    let hash_start = literal_span.lo + BytePos::from_usize(prefix.len());
+    let hash_start = literal_span.lo + BytePos::from_usize(prefix_len);
     let hash_end = literal_span.hi;
 
     // BytePos: req/max are counts of the ASCII character #
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 47d3ed08b8e..bad9b979203 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -14,6 +14,7 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::ExpnKind;
+use std::ops::ControlFlow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -42,24 +43,15 @@ declare_clippy_lint! {
 declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]);
 
 // Used to find `return` statements or equivalents e.g., `?`
-struct ReturnVisitor {
-    found_return: bool,
-}
-
-impl ReturnVisitor {
-    #[must_use]
-    fn new() -> Self {
-        Self { found_return: false }
-    }
-}
+struct ReturnVisitor;
 
 impl<'tcx> Visitor<'tcx> for ReturnVisitor {
-    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
+    type Result = ControlFlow<()>;
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> ControlFlow<()> {
         if let ExprKind::Ret(_) | ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind {
-            self.found_return = true;
-        } else {
-            hir_visit::walk_expr(self, ex);
+            return ControlFlow::Break(());
         }
+        hir_visit::walk_expr(self, ex)
     }
 }
 
@@ -101,9 +93,8 @@ fn find_innermost_closure<'tcx>(
     while let ExprKind::Closure(closure) = expr.kind
         && let body = cx.tcx.hir().body(closure.body)
         && {
-            let mut visitor = ReturnVisitor::new();
-            visitor.visit_expr(body.value);
-            !visitor.found_return
+            let mut visitor = ReturnVisitor;
+            !visitor.visit_expr(body.value).is_break()
         }
         && steps > 0
     {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
index 17b031d5f01..0e637538615 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
@@ -40,9 +41,10 @@ pub struct RedundantFieldNames {
 }
 
 impl RedundantFieldNames {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
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 136e7db83bd..d6e741dd974 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind};
@@ -38,9 +39,10 @@ pub struct RedundantStaticLifetimes {
 }
 
 impl RedundantStaticLifetimes {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index e925ec0271c..8cacb646f51 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
         // `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform
         // the operation once and store the results
         let mut resolve = |path, kind| {
-            for id in def_path_def_ids(cx, path) {
+            for id in def_path_def_ids(cx.tcx, path) {
                 self.definitions.insert(id, kind);
             }
         };
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
index 0e77acdfd77..7615c21276d 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
@@ -64,21 +65,20 @@ declare_clippy_lint! {
 }
 impl_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
 
-#[derive(Copy, Clone)]
 pub struct SemicolonBlock {
     semicolon_inside_block_ignore_singleline: bool,
     semicolon_outside_block_ignore_multiline: bool,
 }
 
 impl SemicolonBlock {
-    pub fn new(semicolon_inside_block_ignore_singleline: bool, semicolon_outside_block_ignore_multiline: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            semicolon_inside_block_ignore_singleline,
-            semicolon_outside_block_ignore_multiline,
+            semicolon_inside_block_ignore_singleline: conf.semicolon_inside_block_ignore_singleline,
+            semicolon_outside_block_ignore_multiline: conf.semicolon_outside_block_ignore_multiline,
         }
     }
 
-    fn semicolon_inside_block(self, cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
+    fn semicolon_inside_block(&self, cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
         let insert_span = tail.span.source_callsite().shrink_to_hi();
         let remove_span = semi_span.with_lo(block.span.hi());
 
@@ -103,7 +103,7 @@ impl SemicolonBlock {
     }
 
     fn semicolon_outside_block(
-        self,
+        &self,
         cx: &LateContext<'_>,
         block: &Block<'_>,
         tail_stmt_expr: &Expr<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs
index f1ec91d7aff..fcf1c4cc5c2 100644
--- a/src/tools/clippy/clippy_lints/src/serde_api.rs
+++ b/src/tools/clippy/clippy_lints/src/serde_api.rs
@@ -32,7 +32,7 @@ impl<'tcx> LateLintPass<'tcx> for SerdeApi {
         }) = item.kind
         {
             let did = trait_ref.path.res.def_id();
-            if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
+            if let Some(visit_did) = get_trait_def_id(cx.tcx, &paths::SERDE_DE_VISITOR) {
                 if did == visit_did {
                     let mut seen_str = None;
                     let mut seen_string = None;
diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
index 23bbeae0e31..abe13a97c0d 100644
--- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::{is_from_proc_macro, is_in_test_function};
 use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
@@ -66,13 +67,19 @@ pub enum CallState {
     Multiple,
 }
 
-#[derive(Clone)]
 pub struct SingleCallFn {
-    pub avoid_breaking_exported_api: bool,
-    pub def_id_to_usage: FxIndexMap<LocalDefId, CallState>,
+    avoid_breaking_exported_api: bool,
+    def_id_to_usage: FxIndexMap<LocalDefId, CallState>,
 }
 
 impl SingleCallFn {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
+            def_id_to_usage: FxIndexMap::default(),
+        }
+    }
+
     fn is_function_allowed(
         &self,
         cx: &LateContext<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
index 0a9a3c6307a..e0558429638 100644
--- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
+++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
@@ -99,7 +99,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
             && let Some(start_snippet) = snippet_opt(cx, start.span)
             && let Some(end_snippet) = snippet_opt(cx, end.span)
         {
-            let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx, &["core", "iter", "Step"])
+            let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx.tcx, &["core", "iter", "Step"])
                 && implements_trait(cx, ty, step_def_id, &[])
             {
                 true
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
index 7ba58942a17..7e211d64da1 100644
--- a/src/tools/clippy/clippy_lints/src/string_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -1,6 +1,7 @@
 use std::ops::ControlFlow;
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::macros::matching_root_macro_call;
@@ -75,9 +76,10 @@ pub struct StringPatterns {
 }
 
 impl StringPatterns {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index 07390d6f430..59b74122f30 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
 use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
@@ -86,16 +87,17 @@ declare_clippy_lint! {
     "check if the same trait bounds are specified more than once during a generic declaration"
 }
 
-#[derive(Clone)]
 pub struct TraitBounds {
     max_trait_bounds: u64,
     msrv: Msrv,
 }
 
 impl TraitBounds {
-    #[must_use]
-    pub fn new(max_trait_bounds: u64, msrv: Msrv) -> Self {
-        Self { max_trait_bounds, msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            max_trait_bounds: conf.max_trait_bounds,
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
@@ -181,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
 
             // Iterate the bounds and add them to our seen hash
             // If we haven't yet seen it, add it to the fixed traits
-            for bound in bounds {
+            for (bound, _) in bounds {
                 let Some(def_id) = bound.trait_ref.trait_def_id() else {
                     continue;
                 };
@@ -196,9 +198,9 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
             // If the number of unique traits isn't the same as the number of traits in the bounds,
             // there must be 1 or more duplicates
             if bounds.len() != unique_traits.len() {
-                let mut bounds_span = bounds[0].span;
+                let mut bounds_span = bounds[0].0.span;
 
-                for bound in bounds.iter().skip(1) {
+                for (bound, _) in bounds.iter().skip(1) {
                     bounds_span = bounds_span.to(bound.span);
                 }
 
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index aa329ec3366..9c6813a54b9 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -20,6 +20,7 @@ mod utils;
 mod wrong_transmute;
 
 use clippy_config::msrvs::Msrv;
+use clippy_config::Conf;
 use clippy_utils::in_constant;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
@@ -577,9 +578,10 @@ impl_lint_pass!(Transmute => [
     MISSING_TRANSMUTE_ANNOTATIONS,
 ]);
 impl Transmute {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 impl<'tcx> LateLintPass<'tcx> for Transmute {
@@ -615,7 +617,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                 | missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id)
                 | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
                 | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
-                | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
+                | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv)
                 | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
                 | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
                 | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
index 1476ea8e7a4..0772b284968 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs
@@ -1,10 +1,11 @@
 use super::TRANSMUTE_PTR_TO_PTR;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 /// Checks for `transmute_ptr_to_ptr` lint.
 /// Returns `true` if it's triggered, otherwise returns `false`.
@@ -14,9 +15,10 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
+    msrv: &Msrv,
 ) -> bool {
-    match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::RawPtr(_, _), ty::RawPtr(to_ty, to_mutbl)) => {
+    match (from_ty.kind(), to_ty.kind()) {
+        (ty::RawPtr(from_pointee_ty, from_mutbl), ty::RawPtr(to_pointee_ty, to_mutbl)) => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_PTR_TO_PTR,
@@ -24,8 +26,39 @@ pub(super) fn check<'tcx>(
                 "transmute from a pointer to a pointer",
                 |diag| {
                     if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
-                        let sugg = arg.as_ty(Ty::new_ptr(cx.tcx, *to_ty, *to_mutbl));
-                        diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
+                        if from_mutbl == to_mutbl
+                            && to_pointee_ty.is_sized(cx.tcx, cx.param_env)
+                            && msrv.meets(msrvs::POINTER_CAST)
+                        {
+                            diag.span_suggestion_verbose(
+                                e.span,
+                                "use `pointer::cast` instead",
+                                format!("{}.cast::<{to_pointee_ty}>()", arg.maybe_par()),
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else if from_pointee_ty == to_pointee_ty
+                            && let Some(method) = match (from_mutbl, to_mutbl) {
+                                (ty::Mutability::Not, ty::Mutability::Mut) => Some("cast_mut"),
+                                (ty::Mutability::Mut, ty::Mutability::Not) => Some("cast_const"),
+                                _ => None,
+                            }
+                            && !from_pointee_ty.has_erased_regions()
+                            && msrv.meets(msrvs::POINTER_CAST_CONSTNESS)
+                        {
+                            diag.span_suggestion_verbose(
+                                e.span,
+                                format!("use `pointer::{method}` instead"),
+                                format!("{}.{method}()", arg.maybe_par()),
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            diag.span_suggestion_verbose(
+                                e.span,
+                                "use an `as` cast instead",
+                                arg.as_ty(to_ty),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
                     }
                 },
             );
diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
index 564b065d0ba..1d0de932754 100644
--- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{is_from_proc_macro, path_to_local};
@@ -42,9 +43,15 @@ declare_clippy_lint! {
 }
 impl_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]);
 
-#[derive(Clone)]
 pub struct TupleArrayConversions {
-    pub msrv: Msrv,
+    msrv: Msrv,
+}
+impl TupleArrayConversions {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
 }
 
 impl LateLintPass<'_> for TupleArrayConversions {
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 801e8862619..83cc9f2d8df 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -81,14 +81,17 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
 
 // Returns true if given type is `Any` trait.
 fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
-    if let TyKind::TraitObject(traits, ..) = t.kind
-        && !traits.is_empty()
-        && let Some(trait_did) = traits[0].trait_ref.trait_def_id()
-        // Only Send/Sync can be used as additional traits, so it is enough to
-        // check only the first trait.
-        && cx.tcx.is_diagnostic_item(sym::Any, trait_did)
-    {
-        return true;
+    if let TyKind::TraitObject(traits, ..) = t.kind {
+        return traits
+            .iter()
+            .any(|(bound, _)| {
+                if let Some(trait_did) = bound.trait_ref.trait_def_id()
+                    && cx.tcx.is_diagnostic_item(sym::Any, trait_did)
+                {
+                    return true;
+                }
+                false
+            });
     }
 
     false
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 62ef65ca122..3a14927802b 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -9,6 +9,7 @@ mod type_complexity;
 mod utils;
 mod vec_box;
 
+use clippy_config::Conf;
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
@@ -446,11 +447,11 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 }
 
 impl Types {
-    pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64, avoid_breaking_exported_api: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            vec_box_size_threshold,
-            type_complexity_threshold,
-            avoid_breaking_exported_api,
+            vec_box_size_threshold: conf.vec_box_size_threshold,
+            type_complexity_threshold: conf.type_complexity_threshold,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
index b6e765d7c39..7fcfd5c8f35 100644
--- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
@@ -55,6 +55,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
             TyKind::TraitObject(param_bounds, _, _) => {
                 let has_lifetime_parameters = param_bounds.iter().any(|bound| {
                     bound
+                        .0
                         .bound_generic_params
                         .iter()
                         .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 6ba98a92423..42100e1d755 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -16,6 +16,7 @@ use rustc_session::impl_lint_pass;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
+use std::ops::ControlFlow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -276,7 +277,6 @@ struct CheckCalls<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     map: Map<'tcx>,
     implemented_ty_id: DefId,
-    found_default_call: bool,
     method_span: Span,
 }
 
@@ -285,16 +285,14 @@ where
     'tcx: 'a,
 {
     type NestedFilter = nested_filter::OnlyBodies;
+    type Result = ControlFlow<()>;
 
     fn nested_visit_map(&mut self) -> Self::Map {
         self.map
     }
 
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if self.found_default_call {
-            return;
-        }
-        walk_expr(self, expr);
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> {
+        walk_expr(self, expr)?;
 
         if let ExprKind::Call(f, _) = expr.kind
             && let ExprKind::Path(qpath) = f.kind
@@ -303,9 +301,10 @@ where
             && let Some(trait_def_id) = self.cx.tcx.trait_of_item(method_def_id)
             && self.cx.tcx.is_diagnostic_item(sym::Default, trait_def_id)
         {
-            self.found_default_call = true;
             span_error(self.cx, self.method_span, expr);
+            return ControlFlow::Break(());
         }
+        ControlFlow::Continue(())
     }
 }
 
@@ -383,7 +382,6 @@ impl UnconditionalRecursion {
                 cx,
                 map: cx.tcx.hir(),
                 implemented_ty_id,
-                found_default_call: false,
                 method_span,
             };
             walk_body(&mut c, body);
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 93a1089a970..3ab30bf5dba 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -1,5 +1,6 @@
 use std::ops::ControlFlow;
 
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_lint_allowed;
 use clippy_utils::source::walk_span_to_context;
@@ -91,17 +92,16 @@ declare_clippy_lint! {
     "annotating safe code with a safety comment"
 }
 
-#[derive(Copy, Clone)]
 pub struct UndocumentedUnsafeBlocks {
     accept_comment_above_statement: bool,
     accept_comment_above_attributes: bool,
 }
 
 impl UndocumentedUnsafeBlocks {
-    pub fn new(accept_comment_above_statement: bool, accept_comment_above_attributes: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            accept_comment_above_statement,
-            accept_comment_above_attributes,
+            accept_comment_above_statement: conf.accept_comment_above_statement,
+            accept_comment_above_attributes: conf.accept_comment_above_attributes,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
index bfcefb26153..3f130bf5a67 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::approx_ty_size;
 use rustc_errors::Applicability;
@@ -47,10 +48,10 @@ pub struct UnnecessaryBoxReturns {
 impl_lint_pass!(UnnecessaryBoxReturns => [UNNECESSARY_BOX_RETURNS]);
 
 impl UnnecessaryBoxReturns {
-    pub fn new(avoid_breaking_exported_api: bool, maximum_size: u64) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            avoid_breaking_exported_api,
-            maximum_size,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
+            maximum_size: conf.unnecessary_box_size,
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
index 2da75334344..afdd3505cdd 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
@@ -2,14 +2,15 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_copy;
 use clippy_utils::{get_parent_expr, path_to_local};
-use rustc_hir::{BindingMode, Expr, ExprKind, Node, PatKind, UnOp};
+use rustc_hir::{BindingMode, Expr, ExprField, ExprKind, Node, PatKind, Path, QPath, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for initialization of a `struct` by copying a base without setting
-    /// any field.
+    /// Checks for initialization of an identical `struct` from another instance
+    /// of the type, either by copying a base without setting any field or by
+    /// moving all fields individually.
     ///
     /// ### Why is this bad?
     /// Readability suffers from unnecessary struct building.
@@ -29,9 +30,14 @@ declare_clippy_lint! {
     /// let b = a;
     /// ```
     ///
+    /// The struct literal ``S { ..a }`` in the assignment to ``b`` could be replaced
+    /// with just ``a``.
+    ///
     /// ### Known Problems
     /// Has false positives when the base is a place expression that cannot be
     /// moved out of, see [#10547](https://github.com/rust-lang/rust-clippy/issues/10547).
+    ///
+    /// Empty structs are ignored by the lint.
     #[clippy::version = "1.70.0"]
     pub UNNECESSARY_STRUCT_INITIALIZATION,
     nursery,
@@ -41,42 +47,111 @@ declare_lint_pass!(UnnecessaryStruct => [UNNECESSARY_STRUCT_INITIALIZATION]);
 
 impl LateLintPass<'_> for UnnecessaryStruct {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if let ExprKind::Struct(_, &[], Some(base)) = expr.kind {
-            if let Some(parent) = get_parent_expr(cx, expr)
-                && let parent_ty = cx.typeck_results().expr_ty_adjusted(parent)
-                && parent_ty.is_any_ptr()
-            {
-                if is_copy(cx, cx.typeck_results().expr_ty(expr)) && path_to_local(base).is_some() {
-                    // When the type implements `Copy`, a reference to the new struct works on the
-                    // copy. Using the original would borrow it.
-                    return;
-                }
-
-                if parent_ty.is_mutable_ptr() && !is_mutable(cx, base) {
-                    // The original can be used in a mutable reference context only if it is mutable.
-                    return;
-                }
-            }
+        let ExprKind::Struct(_, fields, base) = expr.kind else {
+            return;
+        };
 
-            // TODO: do not propose to replace *XX if XX is not Copy
-            if let ExprKind::Unary(UnOp::Deref, target) = base.kind
-                && matches!(target.kind, ExprKind::Path(..))
-                && !is_copy(cx, cx.typeck_results().expr_ty(expr))
-            {
-                // `*base` cannot be used instead of the struct in the general case if it is not Copy.
-                return;
-            }
+        if expr.span.from_expansion() {
+            // Prevent lint from hitting inside macro code
+            return;
+        }
+
+        let field_path = same_path_in_all_fields(cx, expr, fields);
+
+        let sugg = match (field_path, base) {
+            (Some(&path), None) => {
+                // all fields match, no base given
+                path.span
+            },
+            (Some(path), Some(base)) if base_is_suitable(cx, expr, base) && path_matches_base(path, base) => {
+                // all fields match, has base: ensure that the path of the base matches
+                base.span
+            },
+            (None, Some(base)) if fields.is_empty() && base_is_suitable(cx, expr, base) => {
+                // just the base, no explicit fields
+                base.span
+            },
+            _ => return,
+        };
+
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_STRUCT_INITIALIZATION,
+            expr.span,
+            "unnecessary struct building",
+            "replace with",
+            snippet(cx, sugg, "..").into_owned(),
+            rustc_errors::Applicability::MachineApplicable,
+        );
+    }
+}
+
+fn base_is_suitable(cx: &LateContext<'_>, expr: &Expr<'_>, base: &Expr<'_>) -> bool {
+    if !check_references(cx, expr, base) {
+        return false;
+    }
+
+    // TODO: do not propose to replace *XX if XX is not Copy
+    if let ExprKind::Unary(UnOp::Deref, target) = base.kind
+        && matches!(target.kind, ExprKind::Path(..))
+        && !is_copy(cx, cx.typeck_results().expr_ty(expr))
+    {
+        // `*base` cannot be used instead of the struct in the general case if it is not Copy.
+        return false;
+    }
+    true
+}
+
+/// Check whether all fields of a struct assignment match.
+/// Returns a [Path] item that one can obtain a span from for the lint suggestion.
+///
+/// Conditions that must be satisfied to trigger this variant of the lint:
+///
+/// - source struct of the assignment must be of same type as the destination
+/// - names of destination struct fields must match the field names of the source
+///
+/// We don’t check here if all struct fields are assigned as the remainder may
+/// be filled in from a base struct.
+fn same_path_in_all_fields<'tcx>(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    fields: &[ExprField<'tcx>],
+) -> Option<&'tcx Path<'tcx>> {
+    let ty = cx.typeck_results().expr_ty(expr);
+
+    let mut found = None;
 
-            span_lint_and_sugg(
-                cx,
-                UNNECESSARY_STRUCT_INITIALIZATION,
-                expr.span,
-                "unnecessary struct building",
-                "replace with",
-                snippet(cx, base.span, "..").into_owned(),
-                rustc_errors::Applicability::MachineApplicable,
-            );
+    for f in fields {
+        // fields are assigned from expression
+        if let ExprKind::Field(src_expr, ident) = f.expr.kind
+            // expression type matches
+            && ty == cx.typeck_results().expr_ty(src_expr)
+            // field name matches
+            && f.ident == ident
+            // assigned from a path expression
+            && let ExprKind::Path(QPath::Resolved(None, src_path)) = src_expr.kind
+        {
+            let Some((_, p)) = found else {
+                // this is the first field assignment in the list
+                found = Some((src_expr, src_path));
+                continue;
+            };
+
+            if p.res == src_path.res {
+                // subsequent field assignment with same origin struct as before
+                continue;
+            }
         }
+        // source of field assignment doesn’t qualify
+        return None;
+    }
+
+    if let Some((src_expr, src_path)) = found
+        && check_references(cx, expr, src_expr)
+    {
+        Some(src_path)
+    } else {
+        None
     }
 }
 
@@ -89,3 +164,43 @@ fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         true
     }
 }
+
+fn check_references(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
+    if let Some(parent) = get_parent_expr(cx, expr_a)
+        && let parent_ty = cx.typeck_results().expr_ty_adjusted(parent)
+        && parent_ty.is_any_ptr()
+    {
+        if is_copy(cx, cx.typeck_results().expr_ty(expr_a)) && path_to_local(expr_b).is_some() {
+            // When the type implements `Copy`, a reference to the new struct works on the
+            // copy. Using the original would borrow it.
+            return false;
+        }
+
+        if parent_ty.is_mutable_ptr() && !is_mutable(cx, expr_b) {
+            // The original can be used in a mutable reference context only if it is mutable.
+            return false;
+        }
+    }
+
+    true
+}
+
+/// When some fields are assigned from a base struct and others individually
+/// the lint applies only if the source of the field is the same as the base.
+/// This is enforced here by comparing the path of the base expression;
+/// needless to say the lint only applies if it (or whatever expression it is
+/// a reference of) actually has a path.
+fn path_matches_base(path: &Path<'_>, base: &Expr<'_>) -> bool {
+    let base_path = match base.kind {
+        ExprKind::Unary(UnOp::Deref, base_expr) => {
+            if let ExprKind::Path(QPath::Resolved(_, base_path)) = base_expr.kind {
+                base_path
+            } else {
+                return false;
+            }
+        },
+        ExprKind::Path(QPath::Resolved(_, base_path)) => base_path,
+        _ => return false,
+    };
+    path.res == base_path.res
+}
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 5c7fbbab988..e4e7f7d06e7 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::find_all_ret_expressions;
@@ -63,9 +64,9 @@ pub struct UnnecessaryWraps {
 impl_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]);
 
 impl UnnecessaryWraps {
-    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            avoid_breaking_exported_api,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 842046c941d..98f0be3135d 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -1,6 +1,7 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::over;
@@ -51,9 +52,10 @@ pub struct UnnestedOrPatterns {
 }
 
 impl UnnestedOrPatterns {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
-        Self { msrv }
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index e6f799335d7..86a811e17ca 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -8,6 +8,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
+use std::ops::ControlFlow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -70,15 +71,16 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
                     return;
                 }
 
-                for stmt in &block.stmts[idx..] {
-                    vis.visit_stmt(stmt);
-                }
+                let mut found_peek_call = block.stmts[idx..].iter().any(|stmt| vis.visit_stmt(stmt).is_break());
 
-                if let Some(expr) = block.expr {
-                    vis.visit_expr(expr);
+                if !found_peek_call
+                    && let Some(expr) = block.expr
+                    && vis.visit_expr(expr).is_break()
+                {
+                    found_peek_call = true;
                 }
 
-                if !vis.found_peek_call {
+                if !found_peek_call {
                     span_lint_hir_and_then(
                         cx,
                         UNUSED_PEEKABLE,
@@ -98,31 +100,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
 struct PeekableVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     expected_hir_id: HirId,
-    found_peek_call: bool,
 }
 
 impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
     fn new(cx: &'a LateContext<'tcx>, expected_hir_id: HirId) -> Self {
-        Self {
-            cx,
-            expected_hir_id,
-            found_peek_call: false,
-        }
+        Self { cx, expected_hir_id }
     }
 }
 
 impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
     type NestedFilter = OnlyBodies;
+    type Result = ControlFlow<()>;
 
     fn nested_visit_map(&mut self) -> Self::Map {
         self.cx.tcx.hir()
     }
 
-    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-        if self.found_peek_call {
-            return;
-        }
-
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> ControlFlow<()> {
         if path_to_local_id(ex, self.expected_hir_id) {
             for (_, node) in self.cx.tcx.hir().parent_iter(ex.hir_id) {
                 match node {
@@ -137,14 +131,14 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
                                     && func_did == into_iter_did
                                 {
                                     // Probably a for loop desugar, stop searching
-                                    return;
+                                    return ControlFlow::Continue(());
                                 }
 
                                 if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) {
-                                    self.found_peek_call = true;
+                                    return ControlFlow::Break(());
                                 }
 
-                                return;
+                                return ControlFlow::Continue(());
                             },
                             // Catch anything taking a Peekable mutably
                             ExprKind::MethodCall(
@@ -162,16 +156,14 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
                                 if matches!(method_name, "peek" | "peek_mut" | "next_if" | "next_if_eq")
                                     && arg_is_mut_peekable(self.cx, self_arg)
                                 {
-                                    self.found_peek_call = true;
-                                    return;
+                                    return ControlFlow::Break(());
                                 }
 
                                 // foo.some_method() excluding Iterator methods
                                 if remaining_args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg))
                                     && !is_trait_method(self.cx, expr, sym::Iterator)
                                 {
-                                    self.found_peek_call = true;
-                                    return;
+                                    return ControlFlow::Break(());
                                 }
 
                                 // foo.by_ref(), keep checking for `peek`
@@ -179,41 +171,42 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
                                     continue;
                                 }
 
-                                return;
+                                return ControlFlow::Continue(());
                             },
                             ExprKind::AddrOf(_, Mutability::Mut, _) | ExprKind::Unary(..) | ExprKind::DropTemps(_) => {
                             },
-                            ExprKind::AddrOf(_, Mutability::Not, _) => return,
+                            ExprKind::AddrOf(_, Mutability::Not, _) => return ControlFlow::Continue(()),
                             _ => {
-                                self.found_peek_call = true;
-                                return;
+                                return ControlFlow::Break(());
                             },
                         }
                     },
                     Node::LetStmt(LetStmt { init: Some(init), .. }) => {
                         if arg_is_mut_peekable(self.cx, init) {
-                            self.found_peek_call = true;
+                            return ControlFlow::Break(());
                         }
 
-                        return;
+                        return ControlFlow::Continue(());
                     },
                     Node::Stmt(stmt) => {
                         match stmt.kind {
-                            StmtKind::Let(_) | StmtKind::Item(_) => self.found_peek_call = true,
+                            StmtKind::Let(_) | StmtKind::Item(_) => {
+                                return ControlFlow::Break(());
+                            },
                             StmtKind::Expr(_) | StmtKind::Semi(_) => {},
                         }
 
-                        return;
+                        return ControlFlow::Continue(());
                     },
                     Node::Block(_) | Node::ExprField(_) => {},
                     _ => {
-                        return;
+                        return ControlFlow::Continue(());
                     },
                 }
             }
         }
 
-        walk_expr(self, ex);
+        walk_expr(self, ex)
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 3e6102f5982..781f51aa9b0 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::visitors::is_local_used;
@@ -43,9 +44,9 @@ pub struct UnusedSelf {
 impl_lint_pass!(UnusedSelf => [UNUSED_SELF]);
 
 impl UnusedSelf {
-    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            avoid_breaking_exported_api,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
         }
     }
 }
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 72392f8e1f7..8de062a8fc1 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use core::mem::replace;
 use rustc_errors::Applicability;
@@ -39,17 +40,16 @@ declare_clippy_lint! {
     "capitalized acronyms are against the naming convention"
 }
 
-#[derive(Default)]
 pub struct UpperCaseAcronyms {
     avoid_breaking_exported_api: bool,
     upper_case_acronyms_aggressive: bool,
 }
 
 impl UpperCaseAcronyms {
-    pub fn new(avoid_breaking_exported_api: bool, aggressive: bool) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            avoid_breaking_exported_api,
-            upper_case_acronyms_aggressive: aggressive,
+            avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
+            upper_case_acronyms_aggressive: conf.upper_case_acronyms_aggressive,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 0bab917607d..93785b45c27 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::same_type_and_consts;
@@ -60,10 +61,9 @@ pub struct UseSelf {
 }
 
 impl UseSelf {
-    #[must_use]
-    pub fn new(msrv: Msrv) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            msrv,
+            msrv: conf.msrv.clone(),
             stack: Vec::new(),
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index 07879e81fc2..b017a6bf665 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
         }
 
         for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
-            for def_id in def_path_def_ids(cx, module) {
+            for def_id in def_path_def_ids(cx.tcx, module) {
                 for item in cx.tcx.module_children(def_id) {
                     if let Res::Def(DefKind::Const, item_def_id) = item.res
                         && let ty = cx.tcx.type_of(item_def_id).instantiate_identity()
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 0beb0bb8ed4..980437259c3 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
 // 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).is_empty() {
+    if !def_path_res(cx.tcx, path).is_empty() {
         return true;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 8cf42832761..41183700f09 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -108,7 +108,7 @@ impl UnnecessaryDefPath {
             // Extract the path to the matched type
             && let Some(segments) = path_to_matched_type(cx, item_arg)
             && let segments = segments.iter().map(|sym| &**sym).collect::<Vec<_>>()
-            && let Some(def_id) = def_path_def_ids(cx, &segments[..]).next()
+            && let Some(def_id) = def_path_def_ids(cx.tcx, &segments[..]).next()
         {
             // Check if the target item is a diagnostic item or LangItem.
             #[rustfmt::skip]
@@ -206,7 +206,7 @@ impl UnnecessaryDefPath {
     fn check_array(&mut self, cx: &LateContext<'_>, elements: &[Expr<'_>], span: Span) {
         let Some(path) = path_from_array(elements) else { return };
 
-        for def_id in def_path_def_ids(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
+        for def_id in def_path_def_ids(cx.tcx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
             self.array_def_ids.insert((def_id, span));
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 9edf7579d48..a831234906b 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -2,6 +2,7 @@ use std::collections::BTreeMap;
 use std::ops::ControlFlow;
 
 use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet_opt;
@@ -17,12 +18,21 @@ use rustc_session::impl_lint_pass;
 use rustc_span::{sym, DesugaringKind, Span};
 
 #[expect(clippy::module_name_repetitions)]
-#[derive(Clone)]
 pub struct UselessVec {
-    pub too_large_for_stack: u64,
-    pub msrv: Msrv,
-    pub span_to_lint_map: BTreeMap<Span, Option<(HirId, SuggestedType, String, Applicability)>>,
-    pub allow_in_test: bool,
+    too_large_for_stack: u64,
+    msrv: Msrv,
+    span_to_lint_map: BTreeMap<Span, Option<(HirId, SuggestedType, String, Applicability)>>,
+    allow_in_test: bool,
+}
+impl UselessVec {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            too_large_for_stack: conf.too_large_for_stack,
+            msrv: conf.msrv.clone(),
+            span_to_lint_map: BTreeMap::new(),
+            allow_in_test: conf.allow_useless_vec_in_tests,
+        }
+    }
 }
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index a0a60ca8875..c4d64ee4609 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_in_test;
 use clippy_utils::source::{snippet, snippet_with_applicability};
@@ -97,17 +98,16 @@ declare_clippy_lint! {
     "lint `use _::*` statements"
 }
 
-#[derive(Default)]
 pub struct WildcardImports {
     warn_on_all: bool,
-    allowed_segments: FxHashSet<String>,
+    allowed_segments: &'static FxHashSet<String>,
 }
 
 impl WildcardImports {
-    pub fn new(warn_on_all: bool, allowed_wildcard_imports: FxHashSet<String>) -> Self {
+    pub fn new(conf: &'static Conf) -> Self {
         Self {
-            warn_on_all,
-            allowed_segments: allowed_wildcard_imports,
+            warn_on_all: conf.warn_on_all_wildcard_imports,
+            allowed_segments: &conf.allowed_wildcard_imports,
         }
     }
 }
@@ -181,7 +181,7 @@ impl WildcardImports {
     fn check_exceptions(&self, cx: &LateContext<'_>, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool {
         item.span.from_expansion()
             || is_prelude_import(segments)
-            || is_allowed_via_config(segments, &self.allowed_segments)
+            || is_allowed_via_config(segments, self.allowed_segments)
             || (is_super_only_import(segments) && is_in_test(cx.tcx, item.hir_id()))
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 96e53b7ef0b..54e7e92f0c4 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,3 +1,4 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::is_in_test;
 use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall};
@@ -237,7 +238,6 @@ declare_clippy_lint! {
     "writing a literal with a format string"
 }
 
-#[derive(Default)]
 pub struct Write {
     format_args: FormatArgsStorage,
     in_debug_impl: bool,
@@ -245,11 +245,11 @@ pub struct Write {
 }
 
 impl Write {
-    pub fn new(format_args: FormatArgsStorage, allow_print_in_tests: bool) -> Self {
+    pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self {
         Self {
             format_args,
-            allow_print_in_tests,
-            ..Default::default()
+            allow_print_in_tests: conf.allow_print_in_tests,
+            in_debug_impl: false,
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
index ad041e55bda..fdc1d06e67a 100644
--- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
@@ -3,10 +3,11 @@ use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use rustc_ast::LitKind;
+use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
-use rustc_hir::{ExprKind, Node};
+use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, ConstKind, Ty};
+use rustc_middle::ty::Ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
@@ -45,18 +46,27 @@ declare_clippy_lint! {
 declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
 
 impl LateLintPass<'_> for ZeroRepeatSideEffects {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &rustc_hir::Expr<'_>) {
+        let hir_map = cx.tcx.hir();
         if let Some(args) = VecArgs::hir(cx, expr)
             && let VecArgs::Repeat(inner_expr, len) = args
             && let ExprKind::Lit(l) = len.kind
-            && let LitKind::Int(i, _) = l.node
-            && i.0 == 0
+            && let LitKind::Int(Pu128(0), _) = l.node
         {
             inner_check(cx, expr, inner_expr, true);
-        } else if let ExprKind::Repeat(inner_expr, _) = expr.kind
-            && let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind()
-            && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
-            && element_count.to_target_usize(cx.tcx) == 0
+        }
+        // Lint only if the length is a literal zero, and not a path to any constants.
+        // NOTE(@y21): When reading `[f(); LEN]`, I intuitively expect that the function is called and it
+        // doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg.
+        // the const item depends on `#[cfg]s` and has different values in different compilation
+        // sessions).
+        else if let ExprKind::Repeat(inner_expr, length) = expr.kind
+            && let ArrayLen::Body(const_arg) = length
+            && let ConstArgKind::Anon(anon_const) = const_arg.kind
+            && let length_expr = hir_map.body(anon_const.body).value
+            && !length_expr.span.from_expansion()
+            && let ExprKind::Lit(literal) = length_expr.kind
+            && let LitKind::Int(Pu128(0), _) = literal.node
         {
             inner_check(cx, expr, inner_expr, false);
         }
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 6e53ff3ee6e..f0c64fdd573 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.81"
+version = "0.1.82"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 6c6a237a8b1..28178a61a93 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1157,7 +1157,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             match *arg {
                 GenericArg::Lifetime(l) => self.hash_lifetime(l),
                 GenericArg::Type(ty) => self.hash_ty(ty),
-                GenericArg::Const(ref ca) => self.hash_const_arg(ca),
+                GenericArg::Const(ca) => self.hash_const_arg(ca),
                 GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
             }
         }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 8c33c34fa1c..3a9714c49ae 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -90,13 +90,14 @@ use std::hash::BuildHasherDefault;
 use std::iter::{once, repeat};
 use std::sync::{Mutex, MutexGuard, OnceLock};
 
+use clippy_config::types::DisallowedPath;
 use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalModDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPath, DefPathData};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
@@ -678,7 +679,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
 /// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
 ///
 /// This function is expensive and should be used sparingly.
-pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
+pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
     fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
         tcx.crates(())
             .iter()
@@ -687,8 +688,6 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
             .map(CrateNum::as_def_id)
     }
 
-    let tcx = cx.tcx;
-
     let (base, mut path) = match *path {
         [primitive] => {
             return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
@@ -739,16 +738,28 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
 }
 
 /// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
-pub fn def_path_def_ids(cx: &LateContext<'_>, path: &[&str]) -> impl Iterator<Item = DefId> {
-    def_path_res(cx, path).into_iter().filter_map(|res| res.opt_def_id())
+pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator<Item = DefId> {
+    def_path_res(tcx, path).into_iter().filter_map(|res| res.opt_def_id())
+}
+
+/// Creates a map of disallowed items to the reason they were disallowed.
+pub fn create_disallowed_map(
+    tcx: TyCtxt<'_>,
+    disallowed: &'static [DisallowedPath],
+) -> DefIdMap<(&'static str, Option<&'static str>)> {
+    disallowed
+        .iter()
+        .map(|x| (x.path(), x.path().split("::").collect::<Vec<_>>(), x.reason()))
+        .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason))))
+        .collect()
 }
 
 /// Convenience function to get the `DefId` of a trait by path.
 /// It could be a trait or trait alias.
 ///
 /// This function is expensive and should be used sparingly.
-pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
-    def_path_res(cx, path).into_iter().find_map(|res| match res {
+pub fn get_trait_def_id(tcx: TyCtxt<'_>, path: &[&str]) -> Option<DefId> {
+    def_path_res(tcx, path).into_iter().find_map(|res| match res {
         Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
         _ => None,
     })
@@ -1411,7 +1422,7 @@ pub fn get_enclosing_loop_or_multi_call_closure<'tcx>(
                 ExprKind::Closure { .. } | ExprKind::Loop(..) => return Some(e),
                 _ => (),
             },
-            Node::Stmt(_) | Node::Block(_) | Node::LetStmt(_) | Node::Arm(_) => (),
+            Node::Stmt(_) | Node::Block(_) | Node::LetStmt(_) | Node::Arm(_) | Node::ExprField(_) => (),
             _ => break,
         }
     }
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index bbe4149fe2a..c5a34160e3d 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -164,6 +164,8 @@ impl<'a> NumericLiteral<'a> {
             if !exponent.is_empty() && exponent != "0" {
                 output.push_str(separator);
                 Self::group_digits(&mut output, exponent, group_size, true, false);
+            } else if exponent == "0" && self.fraction.is_none() && self.suffix.is_none() {
+                output.push_str(".0");
             }
         }
 
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 6319c7bfa6b..0f86d89c980 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -52,7 +52,8 @@ impl Display for Sugg<'_> {
 impl<'a> Sugg<'a> {
     /// Prepare a suggestion from an expression.
     pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> {
-        let get_snippet = |span| snippet(cx, span, "");
+        let ctxt = expr.span.ctxt();
+        let get_snippet = |span| snippet_with_context(cx, span, ctxt, "", &mut Applicability::Unspecified).0;
         snippet_opt(cx, expr.span).map(|_| Self::hir_from_snippet(expr, get_snippet))
     }
 
@@ -100,7 +101,9 @@ impl<'a> Sugg<'a> {
         applicability: &mut Applicability,
     ) -> Self {
         if expr.span.ctxt() == ctxt {
-            Self::hir_from_snippet(expr, |span| snippet(cx, span, default))
+            Self::hir_from_snippet(expr, |span| {
+                snippet_with_context(cx, span, ctxt, default, applicability).0
+            })
         } else {
             let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
             Sugg::NonParen(snip)
@@ -109,7 +112,7 @@ impl<'a> Sugg<'a> {
 
     /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*`
     /// function variants of `Sugg`, since these use different snippet functions.
-    fn hir_from_snippet(expr: &hir::Expr<'_>, get_snippet: impl Fn(Span) -> Cow<'a, str>) -> Self {
+    fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
         if let Some(range) = higher::Range::hir(expr) {
             let op = match range.limits {
                 ast::RangeLimits::HalfOpen => AssocOp::DotDot,
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index fc02b974ee1..812fb647fda 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -1182,12 +1182,12 @@ pub struct InteriorMut<'tcx> {
 }
 
 impl<'tcx> InteriorMut<'tcx> {
-    pub fn new(cx: &LateContext<'tcx>, ignore_interior_mutability: &[String]) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>, ignore_interior_mutability: &[String]) -> Self {
         let ignored_def_ids = ignore_interior_mutability
             .iter()
             .flat_map(|ignored_ty| {
                 let path: Vec<&str> = ignored_ty.split("::").collect();
-                def_path_def_ids(cx, path.as_slice())
+                def_path_def_ids(tcx, path.as_slice())
             })
             .collect();
 
@@ -1197,10 +1197,10 @@ impl<'tcx> InteriorMut<'tcx> {
         }
     }
 
-    pub fn without_pointers(cx: &LateContext<'tcx>, ignore_interior_mutability: &[String]) -> Self {
+    pub fn without_pointers(tcx: TyCtxt<'tcx>, ignore_interior_mutability: &[String]) -> Self {
         Self {
             ignore_pointers: true,
-            ..Self::new(cx, ignore_interior_mutability)
+            ..Self::new(tcx, ignore_interior_mutability)
         }
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index cba61c841ef..875ddec259e 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -281,7 +281,7 @@ fn update_res(cx: &LateContext<'_>, parent_certainty: Certainty, path_segment: &
     {
         let mut def_path = cx.get_def_path(def_id);
         def_path.push(path_segment.ident.name);
-        let reses = def_path_res(cx, &def_path.iter().map(Symbol::as_str).collect::<Vec<_>>());
+        let reses = def_path_res(cx.tcx, &def_path.iter().map(Symbol::as_str).collect::<Vec<_>>());
         if let [res] = reses.as_slice() { Some(*res) } else { None }
     } else {
         None
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 3a39e178515..7066c9ad2b9 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -109,23 +109,36 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
         res: Option<B>,
     }
     impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<B, F> {
-        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+        type Result = ControlFlow<()>;
+
+        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> ControlFlow<()> {
             if self.res.is_some() {
-                return;
+                return ControlFlow::Break(());
             }
             match (self.f)(e) {
                 ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
-                ControlFlow::Break(b) => self.res = Some(b),
-                ControlFlow::Continue(_) => (),
+                ControlFlow::Break(b) => {
+                    self.res = Some(b);
+                    ControlFlow::Break(())
+                },
+                ControlFlow::Continue(_) => ControlFlow::Continue(()),
             }
         }
 
         // Avoid unnecessary `walk_*` calls.
-        fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {}
-        fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
-        fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
+        fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> ControlFlow<()> {
+            ControlFlow::Continue(())
+        }
+        fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> ControlFlow<()> {
+            ControlFlow::Continue(())
+        }
+        fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> ControlFlow<()> {
+            ControlFlow::Continue(())
+        }
         // Avoid monomorphising all `visit_*` functions.
-        fn visit_nested_item(&mut self, _: ItemId) {}
+        fn visit_nested_item(&mut self, _: ItemId) -> ControlFlow<()> {
+            ControlFlow::Continue(())
+        }
     }
     let mut v = V { f, res: None };
     node.visit(&mut v);
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 86d945c14a5..80106f683c2 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.81"
+version = "0.1.82"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml
index 3c86dfe324f..350418eeeb8 100644
--- a/src/tools/clippy/lintcheck/Cargo.toml
+++ b/src/tools/clippy/lintcheck/Cargo.toml
@@ -16,7 +16,7 @@ clap = { version = "4.4", features = ["derive", "env"] }
 crossbeam-channel = "0.5.6"
 diff = "0.1.13"
 flate2 = "1.0"
-itertools = "0.12"
+itertools = "0.13"
 rayon = "1.5.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0.85"
diff --git a/src/tools/clippy/lintcheck/ci_crates.toml b/src/tools/clippy/lintcheck/ci_crates.toml
new file mode 100644
index 00000000000..9e3dbef6a9e
--- /dev/null
+++ b/src/tools/clippy/lintcheck/ci_crates.toml
@@ -0,0 +1,208 @@
+[crates]
+# Binaries projects
+cargo = {name = "cargo", version = '0.64.0', online_link = 'https://docs.rs/cargo/{version}/src/{file}.html#{line}'}
+ripgrep = {name = "ripgrep", version = '14.1.0'}
+bat = {name = "bat", version = '0.24.0'}
+fend = {name = "fend", version = '1.5.0'}
+mdbook = {name = "mdbook", version = '0.4.40'}
+
+# Bigger crates from ICE issues:
+wasmi = {name = "wasmi", version = '0.35.0'}
+wgpu = {name = "wgpu", version = '0.20.1'}
+bytes = {name = "bytes", version = '1.6.1'}
+skrifa = {name = "skrifa", version = '0.19.3'}
+
+# Random crates which are part of the default test set
+puffin = {name = "puffin", version = '0.19.0'}
+
+# Top ~200 crates from crates.io
+syn = { name = 'syn', version = '2.0.71' }
+bitflags = { name = 'bitflags', version = '2.6.0' }
+hashbrown = { name = 'hashbrown', version = '0.14.5' }
+base64 = { name = 'base64', version = '0.22.1' }
+regex-syntax = { name = 'regex-syntax', version = '0.8.4' }
+proc-macro2 = { name = 'proc-macro2', version = '1.0.86' }
+indexmap = { name = 'indexmap', version = '2.2.6' }
+quote = { name = 'quote', version = '1.0.36' }
+regex-automata = { name = 'regex-automata', version = '0.4.7' }
+libc = { name = 'libc', version = '0.2.155' }
+serde = { name = 'serde', version = '1.0.204' }
+itertools = { name = 'itertools', version = '0.13.0' }
+heck = { name = 'heck', version = '0.5.0' }
+memchr = { name = 'memchr', version = '2.7.4' }
+serde_derive = { name = 'serde_derive', version = '1.0.204' }
+unicode-ident = { name = 'unicode-ident', version = '1.0.12' }
+autocfg = { name = 'autocfg', version = '1.3.0' }
+cfg-if = { name = 'cfg-if', version = '1.0.0' }
+aho-corasick = { name = 'aho-corasick', version = '1.1.3' }
+getrandom = { name = 'getrandom', version = '0.2.15' }
+rand_core = { name = 'rand_core', version = '0.6.4' }
+serde_json = { name = 'serde_json', version = '1.0.120' }
+itoa = { name = 'itoa', version = '1.0.11' }
+rand = { name = 'rand', version = '0.8.5' }
+ryu = { name = 'ryu', version = '1.0.18' }
+once_cell = { name = 'once_cell', version = '1.19.0' }
+rustix = { name = 'rustix', version = '0.38.34' }
+regex = { name = 'regex', version = '1.10.5' }
+log = { name = 'log', version = '0.4.22' }
+parking_lot_core = { name = 'parking_lot_core', version = '0.9.10' }
+cc = { name = 'cc', version = '1.1.5' }
+strsim = { name = 'strsim', version = '0.11.1' }
+clap = { name = 'clap', version = '4.5.9' }
+parking_lot = { name = 'parking_lot', version = '0.12.3' }
+smallvec = { name = 'smallvec', version = '2.0.0-alpha.6' }
+thiserror-impl = { name = 'thiserror-impl', version = '1.0.63' }
+thiserror = { name = 'thiserror', version = '1.0.63' }
+linux-raw-sys = { name = 'linux-raw-sys', version = '0.6.4' }
+socket2 = { name = 'socket2', version = '0.5.7' }
+idna = { name = 'idna', version = '1.0.2' }
+fastrand = { name = 'fastrand', version = '2.1.0' }
+either = { name = 'either', version = '1.13.0' }
+num-traits = { name = 'num-traits', version = '0.2.19' }
+rand_chacha = { name = 'rand_chacha', version = '0.3.1' }
+lazy_static = { name = 'lazy_static', version = '1.5.0' }
+semver = { name = 'semver', version = '1.0.23' }
+lock_api = { name = 'lock_api', version = '0.4.12' }
+scopeguard = { name = 'scopeguard', version = '1.2.0' }
+ahash = { name = 'ahash', version = '0.8.11' }
+anyhow = { name = 'anyhow', version = '1.0.86' }
+rustls = { name = 'rustls', version = '0.23.11' }
+http = { name = 'http', version = '1.1.0' }
+toml_edit = { name = 'toml_edit', version = '0.22.16' }
+pin-project-lite = { name = 'pin-project-lite', version = '0.2.14' }
+spin = { name = 'spin', version = '0.9.8' }
+miniz_oxide = { name = 'miniz_oxide', version = '0.7.4' }
+memoffset = { name = 'memoffset', version = '0.9.1' }
+digest = { name = 'digest', version = '0.11.0-pre.8' }
+version_check = { name = 'version_check', version = '0.9.4' }
+clap_lex = { name = 'clap_lex', version = '0.7.1' }
+crossbeam-utils = { name = 'crossbeam-utils', version = '0.8.20' }
+toml = { name = 'toml', version = '0.8.15' }
+block-buffer = { name = 'block-buffer', version = '0.10.4' }
+time = { name = 'time', version = '0.3.36' }
+hyper = { name = 'hyper', version = '1.4.1' }
+url = { name = 'url', version = '2.5.2' }
+percent-encoding = { name = 'percent-encoding', version = '2.3.1' }
+tokio = { name = 'tokio', version = '1.38.1' }
+errno = { name = 'errno', version = '0.3.9' }
+uuid = { name = 'uuid', version = '1.10.0' }
+unicode-normalization = { name = 'unicode-normalization', version = '0.1.23' }
+ppv-lite86 = { name = 'ppv-lite86', version = '0.2.17' }
+futures-core = { name = 'futures-core', version = '0.3.30' }
+http-body = { name = 'http-body', version = '1.0.1' }
+tinyvec = { name = 'tinyvec', version = '1.8.0' }
+futures-util = { name = 'futures-util', version = '0.3.30' }
+futures-task = { name = 'futures-task', version = '0.3.30' }
+sha2 = { name = 'sha2', version = '0.11.0-pre.3' }
+ring = { name = 'ring', version = '0.17.8' }
+slab = { name = 'slab', version = '0.4.9' }
+chrono = { name = 'chrono', version = '0.4.38' }
+futures-sink = { name = 'futures-sink', version = '0.3.30' }
+futures-channel = { name = 'futures-channel', version = '0.3.30' }
+num_cpus = { name = 'num_cpus', version = '1.16.0' }
+untrusted = { name = 'untrusted', version = '0.9.0' }
+tinyvec_macros = { name = 'tinyvec_macros', version = '0.1.1' }
+mio = { name = 'mio', version = '1.0.0' }
+byteorder = { name = 'byteorder', version = '1.5.0' }
+form_urlencoded = { name = 'form_urlencoded', version = '1.2.1' }
+unicode-bidi = { name = 'unicode-bidi', version = '0.3.15' }
+futures-io = { name = 'futures-io', version = '0.3.30' }
+tokio-util = { name = 'tokio-util', version = '0.7.11' }
+rustls-pemfile = { name = 'rustls-pemfile', version = '2.1.2' }
+generic-array = { name = 'generic-array', version = '1.1.0' }
+tracing = { name = 'tracing', version = '0.1.40' }
+equivalent = { name = 'equivalent', version = '1.0.1' }
+tracing-core = { name = 'tracing-core', version = '0.1.32' }
+pin-utils = { name = 'pin-utils', version = '0.1.0' }
+tempfile = { name = 'tempfile', version = '3.10.1' }
+h2 = { name = 'h2', version = '0.4.5' }
+futures = { name = 'futures', version = '0.3.30' }
+typenum = { name = 'typenum', version = '1.17.0' }
+winnow = { name = 'winnow', version = '0.6.13' }
+cpufeatures = { name = 'cpufeatures', version = '0.2.12' }
+nix = { name = 'nix', version = '0.29.0' }
+fnv = { name = 'fnv', version = '1.0.7' }
+tokio-rustls = { name = 'tokio-rustls', version = '0.26.0' }
+iana-time-zone = { name = 'iana-time-zone', version = '0.1.60' }
+rustls-webpki = { name = 'rustls-webpki', version = '0.102.5' }
+crc32fast = { name = 'crc32fast', version = '1.4.2' }
+adler = { name = 'adler', version = '1.0.2' }
+pkg-config = { name = 'pkg-config', version = '0.3.30' }
+redox_syscall = { name = 'redox_syscall', version = '0.5.3' }
+nom = { name = 'nom', version = '8.0.0-alpha2' }
+rustc_version = { name = 'rustc_version', version = '0.4.0' }
+futures-macro = { name = 'futures-macro', version = '0.3.30' }
+clap_derive = { name = 'clap_derive', version = '4.5.8' }
+futures-executor = { name = 'futures-executor', version = '0.3.30' }
+event-listener = { name = 'event-listener', version = '5.3.1' }
+num-integer = { name = 'num-integer', version = '0.1.46' }
+time-macros = { name = 'time-macros', version = '0.2.18' }
+flate2 = { name = 'flate2', version = '1.0.30' }
+tokio-macros = { name = 'tokio-macros', version = '2.3.0' }
+strum_macros = { name = 'strum_macros', version = '0.26.4' }
+tracing-attributes = { name = 'tracing-attributes', version = '0.1.27' }
+async-trait = { name = 'async-trait', version = '0.1.81' }
+crypto-common = { name = 'crypto-common', version = '0.1.6' }
+unicode-width = { name = 'unicode-width', version = '0.1.13' }
+anstyle = { name = 'anstyle', version = '1.0.7' }
+object = { name = 'object', version = '0.36.1' }
+gimli = { name = 'gimli', version = '0.31.0' }
+crossbeam-epoch = { name = 'crossbeam-epoch', version = '0.9.18' }
+thread_local = { name = 'thread_local', version = '1.1.8' }
+strum = { name = 'strum', version = '0.26.3' }
+darling_core = { name = 'darling_core', version = '0.20.10' }
+darling_macro = { name = 'darling_macro', version = '0.20.10' }
+minimal-lexical = { name = 'minimal-lexical', version = '0.2.1' }
+clap_builder = { name = 'clap_builder', version = '4.5.9' }
+time-core = { name = 'time-core', version = '0.1.2' }
+httparse = { name = 'httparse', version = '1.9.4' }
+signal-hook-registry = { name = 'signal-hook-registry', version = '1.4.2' }
+hex = { name = 'hex', version = '0.4.3' }
+crossbeam-deque = { name = 'crossbeam-deque', version = '0.8.5' }
+zerocopy = { name = 'zerocopy', version = '0.7.35' }
+rustversion = { name = 'rustversion', version = '1.0.17' }
+env_logger = { name = 'env_logger', version = '0.11.3' }
+webpki-roots = { name = 'webpki-roots', version = '0.26.3' }
+rustc-demangle = { name = 'rustc-demangle', version = '0.1.24' }
+mime = { name = 'mime', version = '0.3.17' }
+termcolor = { name = 'termcolor', version = '1.4.1' }
+subtle = { name = 'subtle', version = '2.6.1' }
+walkdir = { name = 'walkdir', version = '2.5.0' }
+hermit-abi = { name = 'hermit-abi', version = '0.4.0' }
+pin-project = { name = 'pin-project', version = '1.1.5' }
+pin-project-internal = { name = 'pin-project-internal', version = '1.1.5' }
+try-lock = { name = 'try-lock', version = '0.2.5' }
+tracing-log = { name = 'tracing-log', version = '0.2.0' }
+httpdate = { name = 'httpdate', version = '1.0.3' }
+anstream = { name = 'anstream', version = '0.6.14' }
+crossbeam-channel = { name = 'crossbeam-channel', version = '0.5.13' }
+reqwest = { name = 'reqwest', version = '0.12.5' }
+want = { name = 'want', version = '0.3.1' }
+paste = { name = 'paste', version = '1.0.15' }
+anstyle-parse = { name = 'anstyle-parse', version = '0.2.4' }
+toml_datetime = { name = 'toml_datetime', version = '0.6.6' }
+anstyle-query = { name = 'anstyle-query', version = '1.1.0' }
+addr2line = { name = 'addr2line', version = '0.24.0' }
+glob = { name = 'glob', version = '0.3.1' }
+num-bigint = { name = 'num-bigint', version = '0.4.6' }
+backtrace = { name = 'backtrace', version = '0.3.73' }
+wasi = { name = 'wasi', version = '0.13.1+wasi-0.2.0' }
+tower-service = { name = 'tower-service', version = '0.3.2' }
+sync_wrapper = { name = 'sync_wrapper', version = '1.0.1' }
+libloading = { name = 'libloading', version = '0.8.4' }
+rayon = { name = 'rayon', version = '1.10.0' }
+colorchoice = { name = 'colorchoice', version = '1.0.1' }
+encoding_rs = { name = 'encoding_rs', version = '0.8.34' }
+deranged = { name = 'deranged', version = '0.3.11' }
+zeroize = { name = 'zeroize', version = '1.8.1' }
+utf8parse = { name = 'utf8parse', version = '0.2.2' }
+tracing-subscriber = { name = 'tracing-subscriber', version = '0.3.18' }
+hyper-rustls = { name = 'hyper-rustls', version = '0.27.2' }
+hmac = { name = 'hmac', version = '0.13.0-pre.3' }
+rayon-core = { name = 'rayon-core', version = '1.12.1' }
+same-file = { name = 'same-file', version = '1.0.6' }
+prost = { name = 'prost', version = '0.13.1' }
+sharded-slab = { name = 'sharded-slab', version = '0.1.7' }
+textwrap = { name = 'textwrap', version = '0.16.1' }
+bumpalo = {name = "bumpalo", version = '3.16.0'}
+arrayvec = { name = 'arrayvec', version = '0.7.4' }
diff --git a/src/tools/clippy/lintcheck/lintcheck_crates.toml b/src/tools/clippy/lintcheck/lintcheck_crates.toml
index ff608e6f935..d205c93c636 100644
--- a/src/tools/clippy/lintcheck/lintcheck_crates.toml
+++ b/src/tools/clippy/lintcheck/lintcheck_crates.toml
@@ -1,38 +1,44 @@
+# If you want to check a local project it's usually easier to use:
+# ```
+# cargo dev lint <path>
+# ```
+#
+# For testing you can also add sources to git and local repos like this:
+# ```
+# crate = {name = "crate", git_url = "https://github.com/name/repo.git", git_hash = "coo1cafe"}
+# crate = {name = "crate", path = "/path/to/project"}
+# ```
+
 [crates]
-# some of these are from cargotest
-cargo = {name = "cargo", version = '0.64.0'}
-iron = {name = "iron", version = '0.6.1'}
-ripgrep = {name = "ripgrep", version = '12.1.1'}
-xsv = {name = "xsv", version = '0.13.0'}
-# commented out because of 173K clippy::match_same_arms msgs in language_type.rs
-#tokei = { name = "tokei", version = '12.0.4'}
-rayon = {name = "rayon", version = '1.5.0'}
-serde = {name = "serde", version = '1.0.118'}
-# top 10 crates.io dls
-bitflags = {name = "bitflags", version = '1.2.1'}
-# crash = {name = "clippy_crash", path = "/tmp/clippy_crash"}
-libc = {name = "libc", version = '0.2.81'}
-log = {name = "log", version = '0.4.11'}
-proc-macro2 = {name = "proc-macro2", version = '1.0.24'}
-quote = {name = "quote", version = '1.0.7'}
-rand = {name = "rand", version = '0.7.3'}
-rand_core = {name = "rand_core", version = '0.6.0'}
-regex = {name = "regex", version = '1.3.2'}
-syn = {name = "syn", version = '1.0.54'}
-unicode-xid = {name = "unicode-xid", version = '0.2.1'}
-# some more of dtolnays crates
-anyhow = {name = "anyhow", version = '1.0.38'}
-async-trait = {name = "async-trait", version = '0.1.42'}
-cxx = {name = "cxx", version = '1.0.32'}
-ryu = {name = "ryu", version = '1.0.5'}
-serde_yaml = {name = "serde_yaml", version = '0.8.17'}
-thiserror = {name = "thiserror", version = '1.0.24'}
-# some embark crates, there are other interesting crates but
-# unfortunately adding them increases lintcheck runtime drastically
-cfg-expr = {name = "cfg-expr", version = '0.7.1'}
-puffin = {name = "puffin", git_url = "https://github.com/EmbarkStudios/puffin", git_hash = "02dd4a3"}
-rpmalloc = {name = "rpmalloc", version = '0.2.0'}
-tame-oidc = {name = "tame-oidc", version = '0.1.0'}
+
+# Some binaries
+cargo = {name = "cargo", version = '0.80.0', online_link = 'https://docs.rs/cargo/{version}/src/{file}.html#{line}'}
+ripgrep = {name = "ripgrep", version = '14.1.0'}
+mdbook = {name = "mdbook", version = '0.4.40'}
+
+# Common libraries
+rayon = {name = "rayon", version = '1.10.0'}
+serde = {name = "serde", version = '1.0.204'}
+bitflags = {name = "bitflags", version = '2.6.0'}
+log = {name = "log", version = '0.4.22'}
+quote = {name = "quote", version = '1.0.36'}
+proc-macro2 = {name = "proc-macro2", version = '1.0.86'}
+rand = {name = "rand", version = '0.8.5'}
+rand_core = {name = "rand_core", version = '0.6.4'}
+regex = {name = "regex", version = '1.10.5'}
+syn = {name = "syn", version = '2.0.71'}
+anyhow = {name = "anyhow", version = '1.0.86'}
+async-trait = { name = 'async-trait', version = '0.1.81' }
+cxx = {name = "cxx", version = '1.0.124'}
+ryu = {name = "ryu", version = '1.0.18'}
+thiserror = {name = "thiserror", version = '1.0.63'}
+serde_yaml = {name = "serde_yaml", version = '0.9.33'}
+puffin = {name = "puffin", version = '0.19.0'}
+bumpalo = {name = "bumpalo", version = '3.16.0'}
+wasmi = {name = "wasmi", version = '0.35.0'}
+base64 = { name = 'base64', version = '0.22.1' }
+once_cell = { name = 'once_cell', version = '1.19.0' }
+tokio = { name = 'tokio', version = '1.38.1' }
 
 [recursive]
 ignore = [
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index b35a62eed44..6bec1753fc7 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -53,7 +53,13 @@ pub(crate) struct LintcheckConfig {
 #[derive(Subcommand, Clone, Debug)]
 pub(crate) enum Commands {
     /// Display a markdown diff between two lintcheck log files in JSON format
-    Diff { old: PathBuf, new: PathBuf },
+    Diff {
+        old: PathBuf,
+        new: PathBuf,
+        /// This will limit the number of warnings that will be printed for each lint
+        #[clap(long)]
+        truncate: bool,
+    },
     /// Create a lintcheck crates TOML file containing the top N popular crates
     Popular {
         /// Output TOML file name
diff --git a/src/tools/clippy/lintcheck/src/driver.rs b/src/tools/clippy/lintcheck/src/driver.rs
index 041be5081f2..2fda2b00f87 100644
--- a/src/tools/clippy/lintcheck/src/driver.rs
+++ b/src/tools/clippy/lintcheck/src/driver.rs
@@ -11,6 +11,7 @@ use std::{env, mem};
 fn run_clippy(addr: &str) -> Option<i32> {
     let driver_info = DriverInfo {
         package_name: env::var("CARGO_PKG_NAME").ok()?,
+        version: env::var("CARGO_PKG_VERSION").ok()?,
     };
 
     let mut stream = BufReader::new(TcpStream::connect(addr).unwrap());
diff --git a/src/tools/clippy/lintcheck/src/input.rs b/src/tools/clippy/lintcheck/src/input.rs
index 3d034391c28..3b263674aa8 100644
--- a/src/tools/clippy/lintcheck/src/input.rs
+++ b/src/tools/clippy/lintcheck/src/input.rs
@@ -10,6 +10,10 @@ use walkdir::{DirEntry, WalkDir};
 
 use crate::{Crate, LINTCHECK_DOWNLOADS, LINTCHECK_SOURCES};
 
+const DEFAULT_DOCS_LINK: &str = "https://docs.rs/{krate}/{version}/src/{krate_}/{file}.html#{line}";
+const DEFAULT_GITHUB_LINK: &str = "{url}/blob/{hash}/src/{file}#L{line}";
+const DEFAULT_PATH_LINK: &str = "{path}/src/{file}:{line}";
+
 /// List of sources to check, loaded from a .toml file
 #[derive(Debug, Deserialize)]
 pub struct SourceList {
@@ -33,32 +37,62 @@ struct TomlCrate {
     git_hash: Option<String>,
     path: Option<String>,
     options: Option<Vec<String>>,
+    /// Magic values:
+    /// * `{krate}` will be replaced by `self.name`
+    /// * `{krate_}` will be replaced by `self.name` with all `-` replaced by `_`
+    /// * `{version}` will be replaced by `self.version`
+    /// * `{url}` will be replaced with `self.git_url`
+    /// * `{hash}` will be replaced with `self.git_hash`
+    /// * `{path}` will be replaced with `self.path`
+    /// * `{file}` will be replaced by the path after `src/`
+    /// * `{line}` will be replaced by the line
+    ///
+    /// If unset, this will be filled by [`read_crates`] since it depends on
+    /// the source.
+    online_link: Option<String>,
+}
+
+impl TomlCrate {
+    fn file_link(&self, default: &str) -> String {
+        let mut link = self.online_link.clone().unwrap_or_else(|| default.to_string());
+        link = link.replace("{krate}", &self.name);
+        link = link.replace("{krate_}", &self.name.replace('-', "_"));
+
+        if let Some(version) = &self.version {
+            link = link.replace("{version}", version);
+        }
+        if let Some(url) = &self.git_url {
+            link = link.replace("{url}", url);
+        }
+        if let Some(hash) = &self.git_hash {
+            link = link.replace("{hash}", hash);
+        }
+        if let Some(path) = &self.path {
+            link = link.replace("{path}", path);
+        }
+        link
+    }
 }
 
 /// Represents an archive we download from crates.io, or a git repo, or a local repo/folder
 /// Once processed (downloaded/extracted/cloned/copied...), this will be translated into a `Crate`
 #[derive(Debug, Deserialize, Eq, Hash, PartialEq, Ord, PartialOrd)]
+pub struct CrateWithSource {
+    pub name: String,
+    pub source: CrateSource,
+    pub file_link: String,
+    pub options: Option<Vec<String>>,
+}
+
+#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Ord, PartialOrd)]
 pub enum CrateSource {
-    CratesIo {
-        name: String,
-        version: String,
-        options: Option<Vec<String>>,
-    },
-    Git {
-        name: String,
-        url: String,
-        commit: String,
-        options: Option<Vec<String>>,
-    },
-    Path {
-        name: String,
-        path: PathBuf,
-        options: Option<Vec<String>>,
-    },
+    CratesIo { version: String },
+    Git { url: String, commit: String },
+    Path { path: PathBuf },
 }
 
 /// Read a `lintcheck_crates.toml` file
-pub fn read_crates(toml_path: &Path) -> (Vec<CrateSource>, RecursiveOptions) {
+pub fn read_crates(toml_path: &Path) -> (Vec<CrateWithSource>, RecursiveOptions) {
     let toml_content: String =
         fs::read_to_string(toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display()));
     let crate_list: SourceList =
@@ -71,23 +105,32 @@ pub fn read_crates(toml_path: &Path) -> (Vec<CrateSource>, RecursiveOptions) {
     let mut crate_sources = Vec::new();
     for tk in tomlcrates {
         if let Some(ref path) = tk.path {
-            crate_sources.push(CrateSource::Path {
+            crate_sources.push(CrateWithSource {
                 name: tk.name.clone(),
-                path: PathBuf::from(path),
+                source: CrateSource::Path {
+                    path: PathBuf::from(path),
+                },
+                file_link: tk.file_link(DEFAULT_PATH_LINK),
                 options: tk.options.clone(),
             });
         } else if let Some(ref version) = tk.version {
-            crate_sources.push(CrateSource::CratesIo {
+            crate_sources.push(CrateWithSource {
                 name: tk.name.clone(),
-                version: version.to_string(),
+                source: CrateSource::CratesIo {
+                    version: version.to_string(),
+                },
+                file_link: tk.file_link(DEFAULT_DOCS_LINK),
                 options: tk.options.clone(),
             });
         } else if tk.git_url.is_some() && tk.git_hash.is_some() {
             // otherwise, we should have a git source
-            crate_sources.push(CrateSource::Git {
+            crate_sources.push(CrateWithSource {
                 name: tk.name.clone(),
-                url: tk.git_url.clone().unwrap(),
-                commit: tk.git_hash.clone().unwrap(),
+                source: CrateSource::Git {
+                    url: tk.git_url.clone().unwrap(),
+                    commit: tk.git_hash.clone().unwrap(),
+                },
+                file_link: tk.file_link(DEFAULT_GITHUB_LINK),
                 options: tk.options.clone(),
             });
         } else {
@@ -117,12 +160,26 @@ pub fn read_crates(toml_path: &Path) -> (Vec<CrateSource>, RecursiveOptions) {
     (crate_sources, crate_list.recursive)
 }
 
-impl CrateSource {
+impl CrateWithSource {
+    pub fn download_and_prepare(&self) -> Crate {
+        let krate = self.download_and_extract();
+
+        // Downloaded crates might contain a `rust-toolchain` file. This file
+        // seems to be accessed when `build.rs` files are present. This access
+        // results in build errors since lintcheck and clippy will most certainly
+        // use a different toolchain.
+        // Lintcheck simply removes these files and assumes that our toolchain
+        // is more up to date.
+        let _ = fs::remove_file(krate.path.join("rust-toolchain"));
+        let _ = fs::remove_file(krate.path.join("rust-toolchain.toml"));
+
+        krate
+    }
     /// Makes the sources available on the disk for clippy to check.
     /// Clones a git repo and checks out the specified commit or downloads a crate from crates.io or
     /// copies a local folder
     #[expect(clippy::too_many_lines)]
-    pub fn download_and_extract(&self) -> Crate {
+    fn download_and_extract(&self) -> Crate {
         #[allow(clippy::result_large_err)]
         fn get(path: &str) -> Result<ureq::Response, ureq::Error> {
             const MAX_RETRIES: u8 = 4;
@@ -139,8 +196,11 @@ impl CrateSource {
                 retries += 1;
             }
         }
-        match self {
-            CrateSource::CratesIo { name, version, options } => {
+        let name = &self.name;
+        let options = &self.options;
+        let file_link = &self.file_link;
+        match &self.source {
+            CrateSource::CratesIo { version } => {
                 let extract_dir = PathBuf::from(LINTCHECK_SOURCES);
                 let krate_download_dir = PathBuf::from(LINTCHECK_DOWNLOADS);
 
@@ -171,14 +231,10 @@ impl CrateSource {
                     name: name.clone(),
                     path: extract_dir.join(format!("{name}-{version}/")),
                     options: options.clone(),
+                    base_url: file_link.clone(),
                 }
             },
-            CrateSource::Git {
-                name,
-                url,
-                commit,
-                options,
-            } => {
+            CrateSource::Git { url, commit } => {
                 let repo_path = {
                     let mut repo_path = PathBuf::from(LINTCHECK_SOURCES);
                     // add a -git suffix in case we have the same crate from crates.io and a git repo
@@ -217,9 +273,10 @@ impl CrateSource {
                     name: name.clone(),
                     path: repo_path,
                     options: options.clone(),
+                    base_url: file_link.clone(),
                 }
             },
-            CrateSource::Path { name, path, options } => {
+            CrateSource::Path { path } => {
                 fn is_cache_dir(entry: &DirEntry) -> bool {
                     fs::read(entry.path().join("CACHEDIR.TAG"))
                         .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55"))
@@ -256,6 +313,7 @@ impl CrateSource {
                     name: name.clone(),
                     path: dest_crate_root,
                     options: options.clone(),
+                    base_url: file_link.clone(),
                 }
             },
         }
diff --git a/src/tools/clippy/lintcheck/src/json.rs b/src/tools/clippy/lintcheck/src/json.rs
index 1a652927988..4211bce90b2 100644
--- a/src/tools/clippy/lintcheck/src/json.rs
+++ b/src/tools/clippy/lintcheck/src/json.rs
@@ -1,22 +1,32 @@
 use std::fs;
 use std::path::Path;
 
-use itertools::EitherOrBoth;
+use itertools::{EitherOrBoth, Itertools};
 use serde::{Deserialize, Serialize};
 
 use crate::ClippyWarning;
 
-#[derive(Deserialize, Serialize)]
+/// This is the total number. 300 warnings results in 100 messages per section.
+const DEFAULT_LIMIT_PER_LINT: usize = 300;
+const TRUNCATION_TOTAL_TARGET: usize = 1000;
+
+#[derive(Debug, Deserialize, Serialize)]
 struct LintJson {
     lint: String,
+    krate: String,
     file_name: String,
     byte_pos: (u32, u32),
+    file_link: String,
     rendered: String,
 }
 
 impl LintJson {
     fn key(&self) -> impl Ord + '_ {
-        (self.file_name.as_str(), self.byte_pos, self.lint.as_str())
+        (self.lint.as_str(), self.file_name.as_str(), self.byte_pos)
+    }
+
+    fn info_text(&self, action: &str) -> String {
+        format!("{action} `{}` in `{}` at {}", self.lint, self.krate, self.file_link)
     }
 }
 
@@ -29,6 +39,8 @@ pub(crate) fn output(clippy_warnings: Vec<ClippyWarning>) -> String {
             LintJson {
                 file_name: span.file_name.clone(),
                 byte_pos: (span.byte_start, span.byte_end),
+                krate: warning.krate,
+                file_link: warning.url,
                 lint: warning.lint,
                 rendered: warning.diag.rendered.unwrap(),
             }
@@ -44,28 +56,142 @@ fn load_warnings(path: &Path) -> Vec<LintJson> {
     serde_json::from_slice(&file).unwrap_or_else(|e| panic!("failed to deserialize {}: {e}", path.display()))
 }
 
-fn print_warnings(title: &str, warnings: &[LintJson]) {
+pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) {
+    let old_warnings = load_warnings(old_path);
+    let new_warnings = load_warnings(new_path);
+
+    let mut lint_warnings = vec![];
+
+    for (name, changes) in &itertools::merge_join_by(old_warnings, new_warnings, |old, new| old.key().cmp(&new.key()))
+        .chunk_by(|change| change.as_ref().into_left().lint.to_string())
+    {
+        let mut added = Vec::new();
+        let mut removed = Vec::new();
+        let mut changed = Vec::new();
+        for change in changes {
+            match change {
+                EitherOrBoth::Both(old, new) => {
+                    if old.rendered != new.rendered {
+                        changed.push((old, new));
+                    }
+                },
+                EitherOrBoth::Left(old) => removed.push(old),
+                EitherOrBoth::Right(new) => added.push(new),
+            }
+        }
+
+        if !added.is_empty() || !removed.is_empty() || !changed.is_empty() {
+            lint_warnings.push(LintWarnings {
+                name,
+                added,
+                removed,
+                changed,
+            });
+        }
+    }
+
+    print_summary_table(&lint_warnings);
+    println!();
+
+    if lint_warnings.is_empty() {
+        return;
+    }
+
+    let truncate_after = if truncate {
+        // Max 15 ensures that we at least have five messages per lint
+        DEFAULT_LIMIT_PER_LINT
+            .min(TRUNCATION_TOTAL_TARGET / lint_warnings.len())
+            .max(15)
+    } else {
+        // No lint should ever each this number of lint emissions, so this is equivialent to
+        // No truncation
+        usize::MAX
+    };
+
+    for lint in lint_warnings {
+        print_lint_warnings(&lint, truncate_after);
+    }
+}
+
+#[derive(Debug)]
+struct LintWarnings {
+    name: String,
+    added: Vec<LintJson>,
+    removed: Vec<LintJson>,
+    changed: Vec<(LintJson, LintJson)>,
+}
+
+fn print_lint_warnings(lint: &LintWarnings, truncate_after: usize) {
+    let name = &lint.name;
+    let html_id = to_html_id(name);
+
+    // The additional anchor is added for non GH viewers that don't prefix ID's
+    println!(r#"## `{name}` <a id="user-content-{html_id}"></a>"#);
+    println!();
+
+    print!(
+        r##"{}, {}, {}"##,
+        count_string(name, "added", lint.added.len()),
+        count_string(name, "removed", lint.removed.len()),
+        count_string(name, "changed", lint.changed.len()),
+    );
+    println!();
+
+    print_warnings("Added", &lint.added, truncate_after / 3);
+    print_warnings("Removed", &lint.removed, truncate_after / 3);
+    print_changed_diff(&lint.changed, truncate_after / 3);
+}
+
+fn print_summary_table(lints: &[LintWarnings]) {
+    println!("| Lint                                       | Added   | Removed | Changed |");
+    println!("| ------------------------------------------ | ------: | ------: | ------: |");
+
+    for lint in lints {
+        println!(
+            "| {:<62} | {:>7} | {:>7} | {:>7} |",
+            format!("[`{}`](#user-content-{})", lint.name, to_html_id(&lint.name)),
+            lint.added.len(),
+            lint.removed.len(),
+            lint.changed.len()
+        );
+    }
+}
+
+fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) {
     if warnings.is_empty() {
         return;
     }
 
-    println!("### {title}");
-    println!("```");
+    print_h3(&warnings[0].lint, title);
+    println!();
+
+    let warnings = truncate(warnings, truncate_after);
+
     for warning in warnings {
-        print!("{}", warning.rendered);
+        println!("{}", warning.info_text(title));
+        println!();
+        println!("```");
+        println!("{}", warning.rendered.trim_end());
+        println!("```");
+        println!();
     }
-    println!("```");
 }
 
-fn print_changed_diff(changed: &[(LintJson, LintJson)]) {
+fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) {
     if changed.is_empty() {
         return;
     }
 
-    println!("### Changed");
-    println!("```diff");
+    print_h3(&changed[0].0.lint, "Changed");
+    println!();
+
+    let changed = truncate(changed, truncate_after);
+
     for (old, new) in changed {
-        for change in diff::lines(&old.rendered, &new.rendered) {
+        println!("{}", new.info_text("Changed"));
+        println!();
+        println!("```diff");
+        for change in diff::lines(old.rendered.trim_end(), new.rendered.trim_end()) {
             use diff::Result::{Both, Left, Right};
 
             match change {
@@ -80,38 +206,48 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)]) {
                 },
             }
         }
+        println!("```");
     }
-    println!("```");
 }
 
-pub(crate) fn diff(old_path: &Path, new_path: &Path) {
-    let old_warnings = load_warnings(old_path);
-    let new_warnings = load_warnings(new_path);
-
-    let mut added = Vec::new();
-    let mut removed = Vec::new();
-    let mut changed = Vec::new();
-
-    for change in itertools::merge_join_by(old_warnings, new_warnings, |old, new| old.key().cmp(&new.key())) {
-        match change {
-            EitherOrBoth::Both(old, new) => {
-                if old.rendered != new.rendered {
-                    changed.push((old, new));
-                }
-            },
-            EitherOrBoth::Left(old) => removed.push(old),
-            EitherOrBoth::Right(new) => added.push(new),
-        }
+fn truncate<T>(list: &[T], truncate_after: usize) -> &[T] {
+    if list.len() > truncate_after {
+        println!(
+            "{} warnings have been truncated for this summary.",
+            list.len() - truncate_after
+        );
+        println!();
+
+        list.split_at(truncate_after).0
+    } else {
+        list
     }
+}
 
-    print!(
-        "{} added, {} removed, {} changed\n\n",
-        added.len(),
-        removed.len(),
-        changed.len()
-    );
+fn print_h3(lint: &str, title: &str) {
+    let html_id = to_html_id(lint);
+    // We have to use HTML here to be able to manually add an id.
+    println!(r#"### {title} <a id="user-content-{html_id}-{title}"></a>"#);
+}
 
-    print_warnings("Added", &added);
-    print_warnings("Removed", &removed);
-    print_changed_diff(&changed);
+/// GitHub's markdown parsers doesn't like IDs with `::` and `_`. This simplifies
+/// the lint name for the HTML ID.
+fn to_html_id(lint_name: &str) -> String {
+    lint_name.replace("clippy::", "").replace('_', "-")
+}
+
+/// This generates the `x added` string for the start of the job summery.
+/// It linkifies them if possible to jump to the respective heading.
+fn count_string(lint: &str, label: &str, count: usize) -> String {
+    // Headlines are only added, if anything will be displayed under the headline.
+    // We therefore only want to add links to them if they exist
+    if count == 0 {
+        format!("0 {label}")
+    } else {
+        let html_id = to_html_id(lint);
+        // GitHub's job summaries don't add HTML ids to headings. That's why we
+        // manually have to add them. GitHub prefixes these manual ids with
+        // `user-content-` and that's how we end up with these awesome links :D
+        format!("[{count} {label}](#user-content-{html_id}-{label})")
+    }
 }
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index e37ffab13ac..0dd62ded293 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -6,6 +6,7 @@
 // positives.
 
 #![feature(iter_collect_into)]
+#![feature(let_chains)]
 #![warn(
     trivial_casts,
     trivial_numeric_casts,
@@ -38,7 +39,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 use std::{env, fs};
 
 use cargo_metadata::Message;
-use input::{read_crates, CrateSource};
+use input::read_crates;
 use output::{ClippyCheckOutput, ClippyWarning, RustcIce};
 use rayon::prelude::*;
 
@@ -53,6 +54,7 @@ struct Crate {
     // path to the extracted sources that clippy can check
     path: PathBuf,
     options: Option<Vec<String>>,
+    base_url: String,
 }
 
 impl Crate {
@@ -86,8 +88,6 @@ impl Crate {
             );
         }
 
-        let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
-
         let cargo_home = env!("CARGO_HOME");
 
         // `src/lib.rs` -> `target/lintcheck/sources/crate-1.2.3/src/lib.rs`
@@ -131,7 +131,7 @@ impl Crate {
             // The wrapper is set to `lintcheck` itself so we can force enable linting and ignore certain crates
             // (see `crate::driver`)
             let status = cmd
-                .env("CARGO_TARGET_DIR", shared_target_dir.join("recursive"))
+                .env("CARGO_TARGET_DIR", shared_target_dir("recursive"))
                 .env("RUSTC_WRAPPER", env::current_exe().unwrap())
                 // Pass the absolute path so `crate::driver` can find `clippy-driver`, as it's executed in various
                 // different working directories
@@ -149,9 +149,10 @@ impl Crate {
             cmd.arg("--message-format=json");
         }
 
+        let shared_target_dir = shared_target_dir(&format!("_{thread_index:?}"));
         let all_output = cmd
             // use the looping index to create individual target dirs
-            .env("CARGO_TARGET_DIR", shared_target_dir.join(format!("_{thread_index:?}")))
+            .env("CARGO_TARGET_DIR", shared_target_dir.as_os_str())
             // Roughly equivalent to `cargo clippy`/`cargo clippy --fix`
             .env("RUSTC_WORKSPACE_WRAPPER", clippy_driver_path)
             .output()
@@ -185,7 +186,11 @@ impl Crate {
         // get all clippy warnings and ICEs
         let mut entries: Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
             .filter_map(|msg| match msg {
-                Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message),
+                Ok(Message::CompilerMessage(message)) => ClippyWarning::new(
+                    normalize_diag(message.message, shared_target_dir.to_str().unwrap()),
+                    &self.base_url,
+                    &self.name,
+                ),
                 _ => None,
             })
             .map(ClippyCheckOutput::ClippyWarning)
@@ -201,6 +206,31 @@ impl Crate {
     }
 }
 
+/// The target directory can sometimes be stored in the file name of spans.
+/// This is problematic since the directory in constructed from the thread
+/// ID and also used in our CI to determine if two lint emissions are the
+/// same or not. This function simply normalizes the `_<thread_id>` to `_*`.
+fn normalize_diag(
+    mut message: cargo_metadata::diagnostic::Diagnostic,
+    thread_target_dir: &str,
+) -> cargo_metadata::diagnostic::Diagnostic {
+    let mut dir_found = false;
+    message
+        .spans
+        .iter_mut()
+        .filter(|span| span.file_name.starts_with(thread_target_dir))
+        .for_each(|span| {
+            dir_found = true;
+            span.file_name
+                .replace_range(0..thread_target_dir.len(), shared_target_dir("_*").to_str().unwrap());
+        });
+
+    if dir_found && let Some(rendered) = &mut message.rendered {
+        *rendered = rendered.replace(thread_target_dir, shared_target_dir("_*").to_str().unwrap());
+    }
+    message
+}
+
 /// Builds clippy inside the repo to make sure we have a clippy executable we can use.
 fn build_clippy() -> String {
     let output = Command::new("cargo")
@@ -230,7 +260,7 @@ fn main() {
     let config = LintcheckConfig::new();
 
     match config.subcommand {
-        Some(Commands::Diff { old, new }) => json::diff(&old, &new),
+        Some(Commands::Diff { old, new, truncate }) => json::diff(&old, &new, truncate),
         Some(Commands::Popular { output, number }) => popular_crates::fetch(output, number).unwrap(),
         None => lintcheck(config),
     }
@@ -292,18 +322,12 @@ fn lintcheck(config: LintcheckConfig) {
         .into_iter()
         .filter(|krate| {
             if let Some(only_one_crate) = &config.only {
-                let name = match krate {
-                    CrateSource::CratesIo { name, .. }
-                    | CrateSource::Git { name, .. }
-                    | CrateSource::Path { name, .. } => name,
-                };
-
-                name == only_one_crate
+                krate.name == *only_one_crate
             } else {
                 true
             }
         })
-        .map(|krate| krate.download_and_extract())
+        .map(|krate| krate.download_and_prepare())
         .collect();
 
     if crates.is_empty() {
@@ -393,6 +417,15 @@ fn clippy_project_root() -> &'static Path {
     Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap()
 }
 
+/// The qualifier can be used to separate different threads from another. By
+/// default it should be set to `_<thread_id>`
+#[must_use]
+fn shared_target_dir(qualifier: &str) -> PathBuf {
+    clippy_project_root()
+        .join("target/lintcheck/shared_target_dir")
+        .join(qualifier)
+}
+
 #[test]
 fn lintcheck_test() {
     let args = [
diff --git a/src/tools/clippy/lintcheck/src/output.rs b/src/tools/clippy/lintcheck/src/output.rs
index 4bfc554ef9e..15378630695 100644
--- a/src/tools/clippy/lintcheck/src/output.rs
+++ b/src/tools/clippy/lintcheck/src/output.rs
@@ -53,11 +53,13 @@ impl RustcIce {
 pub struct ClippyWarning {
     pub lint: String,
     pub diag: Diagnostic,
+    pub krate: String,
+    /// The URL that points to the file and line of the lint emission
+    pub url: String,
 }
 
-#[allow(unused)]
 impl ClippyWarning {
-    pub fn new(mut diag: Diagnostic) -> Option<Self> {
+    pub fn new(mut diag: Diagnostic, base_url: &str, krate: &str) -> Option<Self> {
         let lint = diag.code.clone()?.code;
         if !(lint.contains("clippy") || diag.message.contains("clippy"))
             || diag.message.contains("could not read cargo metadata")
@@ -69,7 +71,32 @@ impl ClippyWarning {
         let rendered = diag.rendered.as_mut().unwrap();
         *rendered = strip_ansi_escapes::strip_str(&rendered);
 
-        Some(Self { lint, diag })
+        // Turns out that there are lints without spans... For example Rust's
+        // `renamed_and_removed_lints` if the lint is given via the CLI.
+        let span = diag
+            .spans
+            .iter()
+            .find(|span| span.is_primary)
+            .or(diag.spans.first())
+            .unwrap_or_else(|| panic!("Diagnostic without span: {diag}"));
+        let file = &span.file_name;
+        let url = if let Some(src_split) = file.find("/src/") {
+            // This removes the initial `target/lintcheck/sources/<crate>-<version>/`
+            let src_split = src_split + "/src/".len();
+            let (_, file) = file.split_at(src_split);
+
+            let line_no = span.line_start;
+            base_url.replace("{file}", file).replace("{line}", &line_no.to_string())
+        } else {
+            file.clone()
+        };
+
+        Some(Self {
+            lint,
+            diag,
+            url,
+            krate: krate.to_string(),
+        })
     }
 
     pub fn span(&self) -> &DiagnosticSpan {
diff --git a/src/tools/clippy/lintcheck/src/recursive.rs b/src/tools/clippy/lintcheck/src/recursive.rs
index 373ca6f9918..6a662970ae8 100644
--- a/src/tools/clippy/lintcheck/src/recursive.rs
+++ b/src/tools/clippy/lintcheck/src/recursive.rs
@@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize};
 #[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize)]
 pub(crate) struct DriverInfo {
     pub package_name: String,
+    pub version: String,
 }
 
 pub(crate) fn serialize_line<T, W>(value: &T, writer: &mut W)
@@ -61,10 +62,17 @@ fn process_stream(
     let mut stderr = String::new();
     stream.read_to_string(&mut stderr).unwrap();
 
+    // It's 99% likely that dependencies compiled with recursive mode are on crates.io
+    // and therefore on docs.rs. This links to the sources directly, do avoid invalid
+    // links due to remaped paths. See rust-lang/docs.rs#2551 for more details.
+    let base_url = format!(
+        "https://docs.rs/crate/{}/{}/source/src/{{file}}#{{line}}",
+        driver_info.package_name, driver_info.version
+    );
     let messages = stderr
         .lines()
         .filter_map(|json_msg| serde_json::from_str::<Diagnostic>(json_msg).ok())
-        .filter_map(ClippyWarning::new);
+        .filter_map(|diag| ClippyWarning::new(diag, &base_url, &driver_info.package_name));
 
     for message in messages {
         sender.send(message).unwrap();
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index a61c22c59f9..69fb11a4824 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-07-11"
+channel = "nightly-2024-07-25"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 333a2ab5857..ea3a0a93ecc 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -5,7 +5,7 @@
 
 use ui_test::custom_flags::rustfix::RustfixMode;
 use ui_test::spanned::Spanned;
-use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, Mode, OutputConflictHandling};
+use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling};
 
 use std::collections::BTreeMap;
 use std::env::{self, set_var, var_os};
@@ -122,7 +122,8 @@ fn base_config(test_dir: &str) -> (Config, Args) {
         out_dir: target_dir.join("ui_test"),
         ..Config::rustc(Path::new("tests").join(test_dir))
     };
-    config.comment_defaults.base().mode = Some(Spanned::dummy(Mode::Yolo)).into();
+    config.comment_defaults.base().exit_status = None.into();
+    config.comment_defaults.base().require_annotations = None.into();
     config
         .comment_defaults
         .base()
@@ -267,15 +268,6 @@ fn run_ui_cargo() {
 }
 
 fn main() {
-    // Support being run by cargo nextest - https://nexte.st/book/custom-test-harnesses.html
-    if env::args().any(|arg| arg == "--list") {
-        if !env::args().any(|arg| arg == "--ignored") {
-            println!("compile_test: test");
-        }
-
-        return;
-    }
-
     set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
     // The SPEEDTEST_* env variables can be used to check Clippy's performance on your PR. It runs the
     // affected test 1000 times and gets the average.
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 36a7a651c4d..c8a761bf509 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -7,23 +7,41 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
 use itertools::Itertools;
+use std::fs::File;
+use std::io::{self, IsTerminal};
 use std::path::PathBuf;
 use std::process::Command;
+use std::time::SystemTime;
 use test_utils::IS_RUSTC_TEST_SUITE;
+use ui_test::Args;
 
 mod test_utils;
 
-#[test]
-fn dogfood_clippy() {
+fn main() {
     if IS_RUSTC_TEST_SUITE {
         return;
     }
 
+    let args = Args::test().unwrap();
+
+    if args.list {
+        if !args.ignored {
+            println!("dogfood: test");
+        }
+    } else if !args.skip.iter().any(|arg| arg == "dogfood") {
+        if args.filters.iter().any(|arg| arg == "collect_metadata") {
+            collect_metadata();
+        } else {
+            dogfood();
+        }
+    }
+}
+
+fn dogfood() {
     let mut failed_packages = Vec::new();
 
-    // "" is the root package
     for package in [
-        "",
+        "./",
         "clippy_dev",
         "clippy_lints",
         "clippy_utils",
@@ -31,6 +49,7 @@ fn dogfood_clippy() {
         "lintcheck",
         "rustc_tools_util",
     ] {
+        println!("linting {package}");
         if !run_clippy_for_package(package, &["-D", "clippy::all", "-D", "clippy::pedantic"]) {
             failed_packages.push(if package.is_empty() { "root" } else { package });
         }
@@ -43,12 +62,8 @@ fn dogfood_clippy() {
     );
 }
 
-#[test]
-#[ignore]
-#[cfg(feature = "internal")]
-fn run_metadata_collection_lint() {
-    use std::fs::File;
-    use std::time::SystemTime;
+fn collect_metadata() {
+    assert!(cfg!(feature = "internal"));
 
     // Setup for validation
     let metadata_output_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/lints.json");
@@ -101,6 +116,10 @@ fn run_clippy_for_package(project: &str, args: &[&str]) -> bool {
         .arg("--all-targets")
         .arg("--all-features");
 
+    if !io::stdout().is_terminal() {
+        command.arg("-q");
+    }
+
     if let Ok(dogfood_args) = std::env::var("__CLIPPY_DOGFOOD_ARGS") {
         for arg in dogfood_args.split_whitespace() {
             command.arg(arg);
@@ -119,11 +138,5 @@ fn run_clippy_for_package(project: &str, args: &[&str]) -> bool {
         command.args(["-A", "unknown_lints"]);
     }
 
-    let output = command.output().unwrap();
-
-    println!("status: {}", output.status);
-    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
-    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
-
-    output.status.success()
+    command.status().unwrap().success()
 }
diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs
index 19c5f3a4133..77b7bb6a7bf 100644
--- a/src/tools/clippy/tests/integration.rs
+++ b/src/tools/clippy/tests/integration.rs
@@ -29,8 +29,10 @@ fn integration_test() {
         .nth(1)
         .expect("repo name should have format `<org>/<name>`");
 
-    let mut repo_dir = tempfile::tempdir().expect("couldn't create temp dir").into_path();
-    repo_dir.push(crate_name);
+    let repo_dir = tempfile::tempdir()
+        .expect("couldn't create temp dir")
+        .into_path()
+        .join(crate_name);
 
     let st = Command::new("git")
         .args([
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
index 66eda44f745..16e1487f2bb 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -4,7 +4,7 @@ error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
 LL |     cx.span_lint(lint, span, |lint| {
    |        ^^^^^^^^^
    |
-   = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead (from clippy.toml)
+   = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead
    = note: `-D clippy::disallowed-methods` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
 
@@ -14,7 +14,7 @@ error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_
 LL |     tcx.node_span_lint(lint, hir_id, span, |lint| {
    |         ^^^^^^^^^^^^^^
    |
-   = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead (from clippy.toml)
+   = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
index 016ee502c24..39b8634be10 100644
--- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
+++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
@@ -1,26 +1,26 @@
-error: `std::string::String` may not be held across an await point per `clippy.toml`
+error: holding a disallowed type across an await point `std::string::String`
   --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:5:9
    |
 LL |     let _x = String::from("hello");
    |         ^^
    |
-   = note: strings are bad (from clippy.toml)
+   = note: strings are bad
    = note: `-D clippy::await-holding-invalid-type` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::await_holding_invalid_type)]`
 
-error: `std::net::Ipv4Addr` may not be held across an await point per `clippy.toml`
+error: holding a disallowed type across an await point `std::net::Ipv4Addr`
   --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:10:9
    |
 LL |     let x = Ipv4Addr::new(127, 0, 0, 1);
    |         ^
 
-error: `std::string::String` may not be held across an await point per `clippy.toml`
+error: holding a disallowed type across an await point `std::string::String`
   --> tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.rs:33:13
    |
 LL |         let _x = String::from("hi!");
    |             ^^
    |
-   = note: strings are bad (from clippy.toml)
+   = note: strings are bad
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
index 290cd3d0010..ddeb2f8cc70 100644
--- a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
+++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
@@ -31,7 +31,7 @@ error: use of a disallowed macro `serde::Serialize`
 LL |     #[derive(Serialize)]
    |              ^^^^^^^^^
    |
-   = note: no serializing (from clippy.toml)
+   = note: no serializing
 
 error: use of a disallowed macro `macros::expr`
   --> tests/ui-toml/disallowed_macros/disallowed_macros.rs:21:13
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
deleted file mode 100644
index 36540bf1dcf..00000000000
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed
+++ /dev/null
@@ -1,24 +0,0 @@
-#![deny(clippy::index_refutable_slice)]
-
-fn below_limit() {
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-    if let Some([_, _, _, _, _, _, _, slice_7, ..]) = slice {
-        //~^ ERROR: binding can be a slice pattern
-        // This would usually not be linted but is included now due to the
-        // index limit in the config file
-        println!("{}", slice_7);
-    }
-}
-
-fn above_limit() {
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-    if let Some(slice) = slice {
-        // This will not be linted as 8 is above the limit
-        println!("{}", slice[8]);
-    }
-}
-
-fn main() {
-    below_limit();
-    above_limit();
-}
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
index da76bb20fd9..e64c8ff3290 100644
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
+++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
@@ -1,5 +1,7 @@
 #![deny(clippy::index_refutable_slice)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 fn below_limit() {
     let slice: Option<&[u32]> = Some(&[1, 2, 3]);
     if let Some(slice) = slice {
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
index 0b989e5cf06..3ea600c7d7b 100644
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
+++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr
@@ -1,5 +1,5 @@
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:5:17
+  --> tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs:7:17
    |
 LL |     if let Some(slice) = slice {
    |                 ^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
index f661e76cc74..e77b2b95949 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
@@ -13,7 +13,7 @@ error: use of a disallowed method `regex::Regex::is_match`
 LL |     re.is_match("abc");
    |        ^^^^^^^^
    |
-   = note: no matching allowed (from clippy.toml)
+   = note: no matching allowed
 
 error: use of a disallowed method `std::iter::Iterator::sum`
   --> tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs:39:14
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr
index 20df8e88d36..322cde15526 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.stderr
@@ -1,4 +1,4 @@
-error: `std::sync::atomic::AtomicU32` is not allowed according to config
+error: use of a disallowed type `std::sync::atomic::AtomicU32`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:7:1
    |
 LL | use std::sync::atomic::AtomicU32;
@@ -7,123 +7,123 @@ LL | use std::sync::atomic::AtomicU32;
    = note: `-D clippy::disallowed-types` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::disallowed_types)]`
 
-error: `std::time::Instant` is not allowed according to config
+error: use of a disallowed type `std::time::Instant`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:8:1
    |
 LL | use std::time::Instant as Sneaky;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::time::Instant` is not allowed according to config
+error: use of a disallowed type `std::time::Instant`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:12:33
    |
 LL | fn bad_return_type() -> fn() -> Sneaky {
    |                                 ^^^^^^
 
-error: `std::time::Instant` is not allowed according to config
+error: use of a disallowed type `std::time::Instant`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:16:28
    |
 LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {}
    |                            ^^^^^^
 
-error: `std::sync::atomic::AtomicU32` is not allowed according to config
+error: use of a disallowed type `std::sync::atomic::AtomicU32`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:16:39
    |
 LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {}
    |                                       ^^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::io::Read` is not allowed according to config
+error: use of a disallowed type `std::io::Read`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:18:22
    |
 LL | fn trait_obj(_: &dyn std::io::Read) {}
    |                      ^^^^^^^^^^^^^
 
-error: `usize` is not allowed according to config
+error: use of a disallowed type `std::primitive::usize`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:20:33
    |
 LL | fn full_and_single_path_prim(_: usize, _: bool) {}
    |                                 ^^^^^
 
-error: `bool` is not allowed according to config
+error: use of a disallowed type `bool`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:20:43
    |
 LL | fn full_and_single_path_prim(_: usize, _: bool) {}
    |                                           ^^^^
 
-error: `usize` is not allowed according to config
+error: use of a disallowed type `std::primitive::usize`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:22:28
    |
 LL | fn const_generics<const C: usize>() {}
    |                            ^^^^^
 
-error: `usize` is not allowed according to config
+error: use of a disallowed type `std::primitive::usize`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:24:24
    |
 LL | struct GenArg<const U: usize>([u8; U]);
    |                        ^^^^^
 
-error: `std::net::Ipv4Addr` is not allowed according to config
+error: use of a disallowed type `std::net::Ipv4Addr`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:28:10
    |
 LL | fn ip(_: std::net::Ipv4Addr) {}
    |          ^^^^^^^^^^^^^^^^^^
    |
-   = note: no IPv4 allowed (from clippy.toml)
+   = note: no IPv4 allowed
 
-error: `std::net::TcpListener` is not allowed according to config
+error: use of a disallowed type `std::net::TcpListener`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:30:16
    |
 LL | fn listener(_: std::net::TcpListener) {}
    |                ^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::collections::HashMap` is not allowed according to config
+error: use of a disallowed type `std::collections::HashMap`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:34:48
    |
 LL |     let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
    |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::collections::HashMap` is not allowed according to config
+error: use of a disallowed type `std::collections::HashMap`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:34:12
    |
 LL |     let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::time::Instant` is not allowed according to config
+error: use of a disallowed type `std::time::Instant`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:35:13
    |
 LL |     let _ = Sneaky::now();
    |             ^^^^^^
 
-error: `std::sync::atomic::AtomicU32` is not allowed according to config
+error: use of a disallowed type `std::sync::atomic::AtomicU32`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:36:13
    |
 LL |     let _ = foo::atomic::AtomicU32::new(0);
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::sync::atomic::AtomicU32` is not allowed according to config
+error: use of a disallowed type `std::sync::atomic::AtomicU32`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:37:17
    |
 LL |     static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `std::sync::atomic::AtomicU32` is not allowed according to config
+error: use of a disallowed type `std::sync::atomic::AtomicU32`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:37:48
    |
 LL |     static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
    |                                                ^^^^^^^^^^^^^^^^^^^^^^
 
-error: `syn::TypePath` is not allowed according to config
+error: use of a disallowed type `syn::TypePath`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:38:43
    |
 LL |     let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
    |                                           ^^^^^^^^^^^^^
 
-error: `syn::Ident` is not allowed according to config
+error: use of a disallowed type `proc_macro2::Ident`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:39:13
    |
 LL |     let _ = syn::Ident::new("", todo!());
    |             ^^^^^^^^^^
 
-error: `usize` is not allowed according to config
+error: use of a disallowed type `std::primitive::usize`
   --> tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs:41:12
    |
 LL |     let _: usize = 64_usize;
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.stderr b/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
index b47b35461f6..82d6b2e4b8e 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
@@ -1,95 +1,184 @@
-error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
+error: casts from `bool` to `u8` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:8:13
    |
 LL |     let _ = true as u8;
-   |             ^^^^^^^^^^ help: try: `u8::from(true)`
+   |             ^^^^^^^^^^
    |
+   = help: an `as` cast can become silently lossy if the types change in the future
    = note: `-D clippy::cast-lossless` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
+help: use `u8::from` instead
+   |
+LL |     let _ = u8::from(true);
+   |             ~~~~~~~~~~~~~~
 
-error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
+error: casts from `bool` to `u16` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:9:13
    |
 LL |     let _ = true as u16;
-   |             ^^^^^^^^^^^ help: try: `u16::from(true)`
+   |             ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u16::from` instead
+   |
+LL |     let _ = u16::from(true);
+   |             ~~~~~~~~~~~~~~~
 
-error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)`
+error: casts from `bool` to `u32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:10:13
    |
 LL |     let _ = true as u32;
-   |             ^^^^^^^^^^^ help: try: `u32::from(true)`
+   |             ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u32::from` instead
+   |
+LL |     let _ = u32::from(true);
+   |             ~~~~~~~~~~~~~~~
 
-error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)`
+error: casts from `bool` to `u64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:11:13
    |
 LL |     let _ = true as u64;
-   |             ^^^^^^^^^^^ help: try: `u64::from(true)`
+   |             ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u64::from` instead
+   |
+LL |     let _ = u64::from(true);
+   |             ~~~~~~~~~~~~~~~
 
-error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)`
+error: casts from `bool` to `u128` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:12:13
    |
 LL |     let _ = true as u128;
-   |             ^^^^^^^^^^^^ help: try: `u128::from(true)`
+   |             ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u128::from` instead
+   |
+LL |     let _ = u128::from(true);
+   |             ~~~~~~~~~~~~~~~~
 
-error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)`
+error: casts from `bool` to `usize` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:13:13
    |
 LL |     let _ = true as usize;
-   |             ^^^^^^^^^^^^^ help: try: `usize::from(true)`
+   |             ^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `usize::from` instead
+   |
+LL |     let _ = usize::from(true);
+   |             ~~~~~~~~~~~~~~~~~
 
-error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)`
+error: casts from `bool` to `i8` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:15:13
    |
 LL |     let _ = true as i8;
-   |             ^^^^^^^^^^ help: try: `i8::from(true)`
+   |             ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i8::from` instead
+   |
+LL |     let _ = i8::from(true);
+   |             ~~~~~~~~~~~~~~
 
-error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)`
+error: casts from `bool` to `i16` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:16:13
    |
 LL |     let _ = true as i16;
-   |             ^^^^^^^^^^^ help: try: `i16::from(true)`
+   |             ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i16::from` instead
+   |
+LL |     let _ = i16::from(true);
+   |             ~~~~~~~~~~~~~~~
 
-error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)`
+error: casts from `bool` to `i32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:17:13
    |
 LL |     let _ = true as i32;
-   |             ^^^^^^^^^^^ help: try: `i32::from(true)`
+   |             ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
+   |
+LL |     let _ = i32::from(true);
+   |             ~~~~~~~~~~~~~~~
 
-error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)`
+error: casts from `bool` to `i64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:18:13
    |
 LL |     let _ = true as i64;
-   |             ^^^^^^^^^^^ help: try: `i64::from(true)`
+   |             ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
+   |
+LL |     let _ = i64::from(true);
+   |             ~~~~~~~~~~~~~~~
 
-error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)`
+error: casts from `bool` to `i128` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:19:13
    |
 LL |     let _ = true as i128;
-   |             ^^^^^^^^^^^^ help: try: `i128::from(true)`
+   |             ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     let _ = i128::from(true);
+   |             ~~~~~~~~~~~~~~~~
 
-error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)`
+error: casts from `bool` to `isize` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:20:13
    |
 LL |     let _ = true as isize;
-   |             ^^^^^^^^^^^^^ help: try: `isize::from(true)`
+   |             ^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `isize::from` instead
+   |
+LL |     let _ = isize::from(true);
+   |             ~~~~~~~~~~~~~~~~~
 
-error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
+error: casts from `bool` to `u16` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:23:13
    |
 LL |     let _ = (true | false) as u16;
-   |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u16::from` instead
+   |
+LL |     let _ = u16::from(true | false);
+   |             ~~~~~~~~~~~~~~~~~~~~~~~
 
-error: casting `bool` to `U8` is more cleanly stated with `U8::from(_)`
+error: casts from `bool` to `u8` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:25:13
    |
 LL |     let _ = true as U8;
-   |             ^^^^^^^^^^ help: try: `U8::from(true)`
+   |             ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `U8::from` instead
+   |
+LL |     let _ = U8::from(true);
+   |             ~~~~~~~~~~~~~~
 
-error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
+error: casts from `bool` to `u8` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_bool.rs:53:13
    |
 LL |     let _ = true as u8;
-   |             ^^^^^^^^^^ help: try: `u8::from(true)`
+   |             ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u8::from` instead
+   |
+LL |     let _ = u8::from(true);
+   |             ~~~~~~~~~~~~~~
 
 error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cast_lossless_float.stderr b/src/tools/clippy/tests/ui/cast_lossless_float.stderr
index f2ba4e3b990..b36f8bcecf5 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_float.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_float.stderr
@@ -1,83 +1,160 @@
-error: casting `i8` to `f32` may become silently lossy if you later change the type
+error: casts from `i8` to `f32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:12:13
    |
 LL |     let _ = x0 as f32;
-   |             ^^^^^^^^^ help: try: `f32::from(x0)`
+   |             ^^^^^^^^^
    |
+   = help: an `as` cast can become silently lossy if the types change in the future
    = note: `-D clippy::cast-lossless` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
+help: use `f32::from` instead
+   |
+LL |     let _ = f32::from(x0);
+   |             ~~~~~~~~~~~~~
 
-error: casting `i8` to `f64` may become silently lossy if you later change the type
+error: casts from `i8` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:13:13
    |
 LL |     let _ = x0 as f64;
-   |             ^^^^^^^^^ help: try: `f64::from(x0)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(x0);
+   |             ~~~~~~~~~~~~~
 
-error: casting `i8` to `F32` may become silently lossy if you later change the type
+error: casts from `i8` to `f32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:14:13
    |
 LL |     let _ = x0 as F32;
-   |             ^^^^^^^^^ help: try: `F32::from(x0)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `F32::from` instead
+   |
+LL |     let _ = F32::from(x0);
+   |             ~~~~~~~~~~~~~
 
-error: casting `i8` to `F64` may become silently lossy if you later change the type
+error: casts from `i8` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:15:13
    |
 LL |     let _ = x0 as F64;
-   |             ^^^^^^^^^ help: try: `F64::from(x0)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `F64::from` instead
+   |
+LL |     let _ = F64::from(x0);
+   |             ~~~~~~~~~~~~~
 
-error: casting `u8` to `f32` may become silently lossy if you later change the type
+error: casts from `u8` to `f32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:17:13
    |
 LL |     let _ = x1 as f32;
-   |             ^^^^^^^^^ help: try: `f32::from(x1)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f32::from` instead
+   |
+LL |     let _ = f32::from(x1);
+   |             ~~~~~~~~~~~~~
 
-error: casting `u8` to `f64` may become silently lossy if you later change the type
+error: casts from `u8` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:18:13
    |
 LL |     let _ = x1 as f64;
-   |             ^^^^^^^^^ help: try: `f64::from(x1)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(x1);
+   |             ~~~~~~~~~~~~~
 
-error: casting `i16` to `f32` may become silently lossy if you later change the type
+error: casts from `i16` to `f32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:20:13
    |
 LL |     let _ = x2 as f32;
-   |             ^^^^^^^^^ help: try: `f32::from(x2)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f32::from` instead
+   |
+LL |     let _ = f32::from(x2);
+   |             ~~~~~~~~~~~~~
 
-error: casting `i16` to `f64` may become silently lossy if you later change the type
+error: casts from `i16` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:21:13
    |
 LL |     let _ = x2 as f64;
-   |             ^^^^^^^^^ help: try: `f64::from(x2)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(x2);
+   |             ~~~~~~~~~~~~~
 
-error: casting `u16` to `f32` may become silently lossy if you later change the type
+error: casts from `u16` to `f32` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:23:13
    |
 LL |     let _ = x3 as f32;
-   |             ^^^^^^^^^ help: try: `f32::from(x3)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f32::from` instead
+   |
+LL |     let _ = f32::from(x3);
+   |             ~~~~~~~~~~~~~
 
-error: casting `u16` to `f64` may become silently lossy if you later change the type
+error: casts from `u16` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:24:13
    |
 LL |     let _ = x3 as f64;
-   |             ^^^^^^^^^ help: try: `f64::from(x3)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(x3);
+   |             ~~~~~~~~~~~~~
 
-error: casting `i32` to `f64` may become silently lossy if you later change the type
+error: casts from `i32` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:26:13
    |
 LL |     let _ = x4 as f64;
-   |             ^^^^^^^^^ help: try: `f64::from(x4)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(x4);
+   |             ~~~~~~~~~~~~~
 
-error: casting `u32` to `f64` may become silently lossy if you later change the type
+error: casts from `u32` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:28:13
    |
 LL |     let _ = x5 as f64;
-   |             ^^^^^^^^^ help: try: `f64::from(x5)`
+   |             ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(x5);
+   |             ~~~~~~~~~~~~~
 
-error: casting `f32` to `f64` may become silently lossy if you later change the type
+error: casts from `f32` to `f64` can be expressed infallibly using `From`
   --> tests/ui/cast_lossless_float.rs:31:13
    |
 LL |     let _ = 1.0f32 as f64;
-   |             ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)`
+   |             ^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `f64::from` instead
+   |
+LL |     let _ = f64::from(1.0f32);
+   |             ~~~~~~~~~~~~~~~~~
 
 error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
index 291556a9774..cdb06567836 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
@@ -1,39 +1,93 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
 #![warn(clippy::cast_lossless)]
 
-type I64 = i64;
-type U128 = u128;
+type I64Alias = i64;
 
 fn main() {
     // Test clippy::cast_lossless with casts to integer types
-    let _ = i16::from(1i8);
-    let _ = i32::from(1i8);
-    let _ = i64::from(1i8);
-    let _ = i16::from(1u8);
-    let _ = i32::from(1u8);
-    let _ = i64::from(1u8);
-    let _ = u16::from(1u8);
-    let _ = u32::from(1u8);
-    let _ = u64::from(1u8);
-    let _ = i32::from(1i16);
-    let _ = i64::from(1i16);
-    let _ = i32::from(1u16);
-    let _ = i64::from(1u16);
-    let _ = u32::from(1u16);
-    let _ = u64::from(1u16);
-    let _ = i64::from(1i32);
-    let _ = i64::from(1u32);
-    let _ = u64::from(1u32);
+    u16::from(0u8);
+    //~^ cast_lossless
+    i16::from(0u8);
+    //~^ cast_lossless
+    u32::from(0u8);
+    //~^ cast_lossless
+    i32::from(0u8);
+    //~^ cast_lossless
+    u64::from(0u8);
+    //~^ cast_lossless
+    i64::from(0u8);
+    //~^ cast_lossless
+    u128::from(0u8);
+    //~^ cast_lossless
+    i128::from(0u8);
+    //~^ cast_lossless
+
+    u32::from(0u16);
+    //~^ cast_lossless
+    i32::from(0u16);
+    //~^ cast_lossless
+    u64::from(0u16);
+    //~^ cast_lossless
+    i64::from(0u16);
+    //~^ cast_lossless
+    u128::from(0u16);
+    //~^ cast_lossless
+    i128::from(0u16);
+    //~^ cast_lossless
+
+    u64::from(0u32);
+    //~^ cast_lossless
+    i64::from(0u32);
+    //~^ cast_lossless
+    u128::from(0u32);
+    //~^ cast_lossless
+    i128::from(0u32);
+    //~^ cast_lossless
+
+    u128::from(0u64);
+    //~^ cast_lossless
+    i128::from(0u64);
+    //~^ cast_lossless
+
+    i16::from(0i8);
+    //~^ cast_lossless
+    i32::from(0i8);
+    //~^ cast_lossless
+    i64::from(0i8);
+    //~^ cast_lossless
+    i128::from(0i8);
+    //~^ cast_lossless
+
+    i32::from(0i16);
+    //~^ cast_lossless
+    i64::from(0i16);
+    //~^ cast_lossless
+    i128::from(0i16);
+    //~^ cast_lossless
+
+    i64::from(0i32);
+    //~^ cast_lossless
+    i128::from(0i32);
+    //~^ cast_lossless
+
+    i128::from(0i64);
+    //~^ cast_lossless
 
     // Test with an expression wrapped in parens
     let _ = u16::from(1u8 + 1u8);
+    //~^ cast_lossless
 
-    let _ = I64::from(1i8);
+    let _ = I64Alias::from(1i8);
+    //~^ cast_lossless
 
-    // Do not lint if destination type is u128
-    // see https://github.com/rust-lang/rust-clippy/issues/12492
-    let _ = 1u8 as u128;
-    let _ = 1u8 as U128;
+    let _: u16 = 0u8.into();
+    //~^ cast_lossless
+    let _: i16 = (-1i8).into();
+    //~^ cast_lossless
+    let _: u16 = (1u8 + 2).into();
+    //~^ cast_lossless
+    let _: u32 = (1i8 as u16).into();
+    //~^ cast_lossless
 }
 
 // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,
@@ -68,5 +122,30 @@ fn issue11458() {
     }
     let x = 10_u128;
     let _ = i32::from(sign_cast!(x, u8, i8));
+    //~^ cast_lossless
     let _ = i32::from(sign_cast!(x, u8, i8) + 1);
+    //~^ cast_lossless
+}
+
+fn issue12695() {
+    macro_rules! in_macro {
+        () => {
+            u32::from(1u8)
+            //~^ cast_lossless
+        };
+    }
+
+    let _ = in_macro!();
 }
+
+fn ty_from_macro() {
+    macro_rules! ty {
+        () => {
+            u32
+        };
+    }
+
+    let _ = <ty!()>::from(0u8);
+}
+
+const IN_CONST: u64 = 0u8 as u64;
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.rs b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
index a917c7a371d..1f510b1a303 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
@@ -1,39 +1,93 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
 #![warn(clippy::cast_lossless)]
 
-type I64 = i64;
-type U128 = u128;
+type I64Alias = i64;
 
 fn main() {
     // Test clippy::cast_lossless with casts to integer types
-    let _ = 1i8 as i16;
-    let _ = 1i8 as i32;
-    let _ = 1i8 as i64;
-    let _ = 1u8 as i16;
-    let _ = 1u8 as i32;
-    let _ = 1u8 as i64;
-    let _ = 1u8 as u16;
-    let _ = 1u8 as u32;
-    let _ = 1u8 as u64;
-    let _ = 1i16 as i32;
-    let _ = 1i16 as i64;
-    let _ = 1u16 as i32;
-    let _ = 1u16 as i64;
-    let _ = 1u16 as u32;
-    let _ = 1u16 as u64;
-    let _ = 1i32 as i64;
-    let _ = 1u32 as i64;
-    let _ = 1u32 as u64;
+    0u8 as u16;
+    //~^ cast_lossless
+    0u8 as i16;
+    //~^ cast_lossless
+    0u8 as u32;
+    //~^ cast_lossless
+    0u8 as i32;
+    //~^ cast_lossless
+    0u8 as u64;
+    //~^ cast_lossless
+    0u8 as i64;
+    //~^ cast_lossless
+    0u8 as u128;
+    //~^ cast_lossless
+    0u8 as i128;
+    //~^ cast_lossless
+
+    0u16 as u32;
+    //~^ cast_lossless
+    0u16 as i32;
+    //~^ cast_lossless
+    0u16 as u64;
+    //~^ cast_lossless
+    0u16 as i64;
+    //~^ cast_lossless
+    0u16 as u128;
+    //~^ cast_lossless
+    0u16 as i128;
+    //~^ cast_lossless
+
+    0u32 as u64;
+    //~^ cast_lossless
+    0u32 as i64;
+    //~^ cast_lossless
+    0u32 as u128;
+    //~^ cast_lossless
+    0u32 as i128;
+    //~^ cast_lossless
+
+    0u64 as u128;
+    //~^ cast_lossless
+    0u64 as i128;
+    //~^ cast_lossless
+
+    0i8 as i16;
+    //~^ cast_lossless
+    0i8 as i32;
+    //~^ cast_lossless
+    0i8 as i64;
+    //~^ cast_lossless
+    0i8 as i128;
+    //~^ cast_lossless
+
+    0i16 as i32;
+    //~^ cast_lossless
+    0i16 as i64;
+    //~^ cast_lossless
+    0i16 as i128;
+    //~^ cast_lossless
+
+    0i32 as i64;
+    //~^ cast_lossless
+    0i32 as i128;
+    //~^ cast_lossless
+
+    0i64 as i128;
+    //~^ cast_lossless
 
     // Test with an expression wrapped in parens
     let _ = (1u8 + 1u8) as u16;
+    //~^ cast_lossless
 
-    let _ = 1i8 as I64;
+    let _ = 1i8 as I64Alias;
+    //~^ cast_lossless
 
-    // Do not lint if destination type is u128
-    // see https://github.com/rust-lang/rust-clippy/issues/12492
-    let _ = 1u8 as u128;
-    let _ = 1u8 as U128;
+    let _: u16 = 0u8 as _;
+    //~^ cast_lossless
+    let _: i16 = -1i8 as _;
+    //~^ cast_lossless
+    let _: u16 = (1u8 + 2) as _;
+    //~^ cast_lossless
+    let _: u32 = 1i8 as u16 as _;
+    //~^ cast_lossless
 }
 
 // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,
@@ -68,5 +122,30 @@ fn issue11458() {
     }
     let x = 10_u128;
     let _ = sign_cast!(x, u8, i8) as i32;
+    //~^ cast_lossless
     let _ = (sign_cast!(x, u8, i8) + 1) as i32;
+    //~^ cast_lossless
+}
+
+fn issue12695() {
+    macro_rules! in_macro {
+        () => {
+            1u8 as u32
+            //~^ cast_lossless
+        };
+    }
+
+    let _ = in_macro!();
 }
+
+fn ty_from_macro() {
+    macro_rules! ty {
+        () => {
+            u32
+        };
+    }
+
+    let _ = 0u8 as ty!();
+}
+
+const IN_CONST: u64 = 0u8 as u64;
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr
index aaece939285..c93ecb8fb56 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr
@@ -1,137 +1,488 @@
-error: casting `i8` to `i16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:9:13
+error: casts from `u8` to `u16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:8:5
    |
-LL |     let _ = 1i8 as i16;
-   |             ^^^^^^^^^^ help: try: `i16::from(1i8)`
+LL |     0u8 as u16;
+   |     ^^^^^^^^^^
    |
+   = help: an `as` cast can become silently lossy if the types change in the future
    = note: `-D clippy::cast-lossless` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
+help: use `u16::from` instead
+   |
+LL |     u16::from(0u8);
+   |     ~~~~~~~~~~~~~~
+
+error: casts from `u8` to `i16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:10:5
+   |
+LL |     0u8 as i16;
+   |     ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i16::from` instead
+   |
+LL |     i16::from(0u8);
+   |     ~~~~~~~~~~~~~~
+
+error: casts from `u8` to `u32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:12:5
+   |
+LL |     0u8 as u32;
+   |     ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u32::from` instead
+   |
+LL |     u32::from(0u8);
+   |     ~~~~~~~~~~~~~~
+
+error: casts from `u8` to `i32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:14:5
+   |
+LL |     0u8 as i32;
+   |     ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
+   |
+LL |     i32::from(0u8);
+   |     ~~~~~~~~~~~~~~
+
+error: casts from `u8` to `u64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:16:5
+   |
+LL |     0u8 as u64;
+   |     ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u64::from` instead
+   |
+LL |     u64::from(0u8);
+   |     ~~~~~~~~~~~~~~
+
+error: casts from `u8` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:18:5
+   |
+LL |     0u8 as i64;
+   |     ^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
+   |
+LL |     i64::from(0u8);
+   |     ~~~~~~~~~~~~~~
+
+error: casts from `u8` to `u128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:20:5
+   |
+LL |     0u8 as u128;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u128::from` instead
+   |
+LL |     u128::from(0u8);
+   |     ~~~~~~~~~~~~~~~
+
+error: casts from `u8` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:22:5
+   |
+LL |     0u8 as i128;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0u8);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `i8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:10:13
+error: casts from `u16` to `u32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:25:5
    |
-LL |     let _ = 1i8 as i32;
-   |             ^^^^^^^^^^ help: try: `i32::from(1i8)`
+LL |     0u16 as u32;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u32::from` instead
+   |
+LL |     u32::from(0u16);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `i8` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:11:13
+error: casts from `u16` to `i32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:27:5
+   |
+LL |     0u16 as i32;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
    |
-LL |     let _ = 1i8 as i64;
-   |             ^^^^^^^^^^ help: try: `i64::from(1i8)`
+LL |     i32::from(0u16);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u8` to `i16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:12:13
+error: casts from `u16` to `u64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:29:5
    |
-LL |     let _ = 1u8 as i16;
-   |             ^^^^^^^^^^ help: try: `i16::from(1u8)`
+LL |     0u16 as u64;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u64::from` instead
+   |
+LL |     u64::from(0u16);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:13:13
+error: casts from `u16` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:31:5
+   |
+LL |     0u16 as i64;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
    |
-LL |     let _ = 1u8 as i32;
-   |             ^^^^^^^^^^ help: try: `i32::from(1u8)`
+LL |     i64::from(0u16);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u8` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:14:13
+error: casts from `u16` to `u128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:33:5
+   |
+LL |     0u16 as u128;
+   |     ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u128::from` instead
+   |
+LL |     u128::from(0u16);
+   |     ~~~~~~~~~~~~~~~~
+
+error: casts from `u16` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:35:5
+   |
+LL |     0u16 as i128;
+   |     ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0u16);
+   |     ~~~~~~~~~~~~~~~~
+
+error: casts from `u32` to `u64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:38:5
+   |
+LL |     0u32 as u64;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u64::from` instead
+   |
+LL |     u64::from(0u32);
+   |     ~~~~~~~~~~~~~~~
+
+error: casts from `u32` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:40:5
+   |
+LL |     0u32 as i64;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
+   |
+LL |     i64::from(0u32);
+   |     ~~~~~~~~~~~~~~~
+
+error: casts from `u32` to `u128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:42:5
+   |
+LL |     0u32 as u128;
+   |     ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u128::from` instead
+   |
+LL |     u128::from(0u32);
+   |     ~~~~~~~~~~~~~~~~
+
+error: casts from `u32` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:44:5
+   |
+LL |     0u32 as i128;
+   |     ^^^^^^^^^^^^
    |
-LL |     let _ = 1u8 as i64;
-   |             ^^^^^^^^^^ help: try: `i64::from(1u8)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0u32);
+   |     ~~~~~~~~~~~~~~~~
 
-error: casting `u8` to `u16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:15:13
+error: casts from `u64` to `u128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:47:5
+   |
+LL |     0u64 as u128;
+   |     ^^^^^^^^^^^^
    |
-LL |     let _ = 1u8 as u16;
-   |             ^^^^^^^^^^ help: try: `u16::from(1u8)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u128::from` instead
+   |
+LL |     u128::from(0u64);
+   |     ~~~~~~~~~~~~~~~~
 
-error: casting `u8` to `u32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:16:13
+error: casts from `u64` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:49:5
+   |
+LL |     0u64 as i128;
+   |     ^^^^^^^^^^^^
    |
-LL |     let _ = 1u8 as u32;
-   |             ^^^^^^^^^^ help: try: `u32::from(1u8)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0u64);
+   |     ~~~~~~~~~~~~~~~~
 
-error: casting `u8` to `u64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:17:13
+error: casts from `i8` to `i16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:52:5
+   |
+LL |     0i8 as i16;
+   |     ^^^^^^^^^^
    |
-LL |     let _ = 1u8 as u64;
-   |             ^^^^^^^^^^ help: try: `u64::from(1u8)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i16::from` instead
+   |
+LL |     i16::from(0i8);
+   |     ~~~~~~~~~~~~~~
 
-error: casting `i16` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:18:13
+error: casts from `i8` to `i32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:54:5
+   |
+LL |     0i8 as i32;
+   |     ^^^^^^^^^^
    |
-LL |     let _ = 1i16 as i32;
-   |             ^^^^^^^^^^^ help: try: `i32::from(1i16)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
+   |
+LL |     i32::from(0i8);
+   |     ~~~~~~~~~~~~~~
 
-error: casting `i16` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:19:13
+error: casts from `i8` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:56:5
+   |
+LL |     0i8 as i64;
+   |     ^^^^^^^^^^
    |
-LL |     let _ = 1i16 as i64;
-   |             ^^^^^^^^^^^ help: try: `i64::from(1i16)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
+   |
+LL |     i64::from(0i8);
+   |     ~~~~~~~~~~~~~~
 
-error: casting `u16` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:20:13
+error: casts from `i8` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:58:5
+   |
+LL |     0i8 as i128;
+   |     ^^^^^^^^^^^
    |
-LL |     let _ = 1u16 as i32;
-   |             ^^^^^^^^^^^ help: try: `i32::from(1u16)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0i8);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u16` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:21:13
+error: casts from `i16` to `i32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:61:5
+   |
+LL |     0i16 as i32;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
    |
-LL |     let _ = 1u16 as i64;
-   |             ^^^^^^^^^^^ help: try: `i64::from(1u16)`
+LL |     i32::from(0i16);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u16` to `u32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:22:13
+error: casts from `i16` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:63:5
    |
-LL |     let _ = 1u16 as u32;
-   |             ^^^^^^^^^^^ help: try: `u32::from(1u16)`
+LL |     0i16 as i64;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
+   |
+LL |     i64::from(0i16);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u16` to `u64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:23:13
+error: casts from `i16` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:65:5
+   |
+LL |     0i16 as i128;
+   |     ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
    |
-LL |     let _ = 1u16 as u64;
-   |             ^^^^^^^^^^^ help: try: `u64::from(1u16)`
+LL |     i128::from(0i16);
+   |     ~~~~~~~~~~~~~~~~
 
-error: casting `i32` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:24:13
+error: casts from `i32` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:68:5
    |
-LL |     let _ = 1i32 as i64;
-   |             ^^^^^^^^^^^ help: try: `i64::from(1i32)`
+LL |     0i32 as i64;
+   |     ^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i64::from` instead
+   |
+LL |     i64::from(0i32);
+   |     ~~~~~~~~~~~~~~~
 
-error: casting `u32` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:25:13
+error: casts from `i32` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:70:5
+   |
+LL |     0i32 as i128;
+   |     ^^^^^^^^^^^^
    |
-LL |     let _ = 1u32 as i64;
-   |             ^^^^^^^^^^^ help: try: `i64::from(1u32)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0i32);
+   |     ~~~~~~~~~~~~~~~~
 
-error: casting `u32` to `u64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:26:13
+error: casts from `i64` to `i128` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:73:5
+   |
+LL |     0i64 as i128;
+   |     ^^^^^^^^^^^^
    |
-LL |     let _ = 1u32 as u64;
-   |             ^^^^^^^^^^^ help: try: `u64::from(1u32)`
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i128::from` instead
+   |
+LL |     i128::from(0i64);
+   |     ~~~~~~~~~~~~~~~~
 
-error: casting `u8` to `u16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:29:13
+error: casts from `u8` to `u16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:77:13
    |
 LL |     let _ = (1u8 + 1u8) as u16;
-   |             ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)`
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `u16::from` instead
+   |
+LL |     let _ = u16::from(1u8 + 1u8);
+   |             ~~~~~~~~~~~~~~~~~~~~
+
+error: casts from `i8` to `i64` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:80:13
+   |
+LL |     let _ = 1i8 as I64Alias;
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `I64Alias::from` instead
+   |
+LL |     let _ = I64Alias::from(1i8);
+   |             ~~~~~~~~~~~~~~~~~~~
+
+error: casts from `u8` to `u16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:83:18
+   |
+LL |     let _: u16 = 0u8 as _;
+   |                  ^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `Into::into` instead
+   |
+LL |     let _: u16 = 0u8.into();
+   |                  ~~~~~~~~~~
 
-error: casting `i8` to `I64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:31:13
+error: casts from `i8` to `i16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:85:18
+   |
+LL |     let _: i16 = -1i8 as _;
+   |                  ^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `Into::into` instead
    |
-LL |     let _ = 1i8 as I64;
-   |             ^^^^^^^^^^ help: try: `I64::from(1i8)`
+LL |     let _: i16 = (-1i8).into();
+   |                  ~~~~~~~~~~~~~
 
-error: casting `i8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:70:13
+error: casts from `u8` to `u16` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:87:18
+   |
+LL |     let _: u16 = (1u8 + 2) as _;
+   |                  ^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `Into::into` instead
+   |
+LL |     let _: u16 = (1u8 + 2).into();
+   |                  ~~~~~~~~~~~~~~~~
+
+error: casts from `u16` to `u32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:89:18
+   |
+LL |     let _: u32 = 1i8 as u16 as _;
+   |                  ^^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `Into::into` instead
+   |
+LL |     let _: u32 = (1i8 as u16).into();
+   |                  ~~~~~~~~~~~~~~~~~~~
+
+error: casts from `i8` to `i32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:124:13
    |
 LL |     let _ = sign_cast!(x, u8, i8) as i32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
+   |
+LL |     let _ = i32::from(sign_cast!(x, u8, i8));
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-error: casting `i8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:71:13
+error: casts from `i8` to `i32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:126:13
    |
 LL |     let _ = (sign_cast!(x, u8, i8) + 1) as i32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8) + 1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `i32::from` instead
+   |
+LL |     let _ = i32::from(sign_cast!(x, u8, i8) + 1);
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: casts from `u8` to `u32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:133:13
+   |
+LL |             1u8 as u32
+   |             ^^^^^^^^^^
+...
+LL |     let _ = in_macro!();
+   |             ----------- in this macro invocation
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+   = note: this error originates in the macro `in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use `u32::from` instead
+   |
+LL |             u32::from(1u8)
+   |
+
+error: casts from `u8` to `u32` can be expressed infallibly using `From`
+  --> tests/ui/cast_lossless_integer.rs:148:13
+   |
+LL |     let _ = 0u8 as ty!();
+   |             ^^^^^^^^^^^^
+   |
+   = help: an `as` cast can become silently lossy if the types change in the future
+help: use `<ty!()>::from` instead
+   |
+LL |     let _ = <ty!()>::from(0u8);
+   |             ~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 22 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.fixed b/src/tools/clippy/tests/ui/crashes/ice-3717.fixed
deleted file mode 100644
index 3f54b326979..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-3717.fixed
+++ /dev/null
@@ -1,11 +0,0 @@
-#![deny(clippy::implicit_hasher)]
-
-use std::collections::HashSet;
-
-fn main() {}
-
-pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) {
-    //~^ ERROR: parameter of type `HashSet` should be generalized over different hashers
-    let _ = [0u8; 0];
-    let _: HashSet<usize> = HashSet::default();
-}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.rs b/src/tools/clippy/tests/ui/crashes/ice-3717.rs
index 2890a9277c7..770f6cf448a 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3717.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3717.rs
@@ -1,5 +1,7 @@
 #![deny(clippy::implicit_hasher)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 use std::collections::HashSet;
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr
index 54b18a9641a..01627ff5b94 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr
@@ -1,5 +1,5 @@
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> tests/ui/crashes/ice-3717.rs:7:21
+  --> tests/ui/crashes/ice-3717.rs:9:21
    |
 LL | pub fn ice_3717(_: &HashSet<usize>) {
    |                     ^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/deref_addrof.fixed b/src/tools/clippy/tests/ui/deref_addrof.fixed
index b6278c6ca8a..f412c57d650 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.fixed
+++ b/src/tools/clippy/tests/ui/deref_addrof.fixed
@@ -45,7 +45,7 @@ fn main() {
     let _ = unsafe { *core::ptr::addr_of!(a) };
 
     let _repeat = [0; 64];
-    // do NOT lint for array as sematic differences with/out `*&`.
+    // do NOT lint for array as semantic differences with/out `*&`.
     let _arr = *&[0, 1, 2, 3, 4];
 }
 
diff --git a/src/tools/clippy/tests/ui/deref_addrof.rs b/src/tools/clippy/tests/ui/deref_addrof.rs
index 572b0fdb102..67836b0de52 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.rs
+++ b/src/tools/clippy/tests/ui/deref_addrof.rs
@@ -45,7 +45,7 @@ fn main() {
     let _ = unsafe { *core::ptr::addr_of!(a) };
 
     let _repeat = *&[0; 64];
-    // do NOT lint for array as sematic differences with/out `*&`.
+    // do NOT lint for array as semantic differences with/out `*&`.
     let _arr = *&[0, 1, 2, 3, 4];
 }
 
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
deleted file mode 100644
index c85f384fd6e..00000000000
--- a/src/tools/clippy/tests/ui/derivable_impls.fixed
+++ /dev/null
@@ -1,295 +0,0 @@
-#![allow(dead_code)]
-
-use std::collections::HashMap;
-
-#[derive(Default)]
-struct FooDefault<'a> {
-    a: bool,
-    b: i32,
-    c: u64,
-    d: Vec<i32>,
-    e: FooND1,
-    f: FooND2,
-    g: HashMap<i32, i32>,
-    h: (i32, Vec<i32>),
-    i: [Vec<i32>; 3],
-    j: [i32; 5],
-    k: Option<i32>,
-    l: &'a [i32],
-}
-
-
-#[derive(Default)]
-struct TupleDefault(bool, i32, u64);
-
-
-struct FooND1 {
-    a: bool,
-}
-
-impl std::default::Default for FooND1 {
-    fn default() -> Self {
-        Self { a: true }
-    }
-}
-
-struct FooND2 {
-    a: i32,
-}
-
-impl std::default::Default for FooND2 {
-    fn default() -> Self {
-        Self { a: 5 }
-    }
-}
-
-struct FooNDNew {
-    a: bool,
-}
-
-impl FooNDNew {
-    fn new() -> Self {
-        Self { a: true }
-    }
-}
-
-impl Default for FooNDNew {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-struct FooNDVec(Vec<i32>);
-
-impl Default for FooNDVec {
-    fn default() -> Self {
-        Self(vec![5, 12])
-    }
-}
-
-#[derive(Default)]
-struct StrDefault<'a>(&'a str);
-
-
-#[derive(Default)]
-struct AlreadyDerived(i32, bool);
-
-macro_rules! mac {
-    () => {
-        0
-    };
-    ($e:expr) => {
-        struct X(u32);
-        impl Default for X {
-            fn default() -> Self {
-                Self($e)
-            }
-        }
-    };
-}
-
-mac!(0);
-
-#[derive(Default)]
-struct Y(u32);
-
-struct RustIssue26925<T> {
-    a: Option<T>,
-}
-
-// We should watch out for cases where a manual impl is needed because a
-// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
-// For example, a struct with Option<T> does not require T: Default, but a derive adds
-// that type bound anyways. So until #26925 get fixed we should disable lint
-// for the following case
-impl<T> Default for RustIssue26925<T> {
-    fn default() -> Self {
-        Self { a: None }
-    }
-}
-
-struct SpecializedImpl<A, B> {
-    a: A,
-    b: B,
-}
-
-impl<T: Default> Default for SpecializedImpl<T, T> {
-    fn default() -> Self {
-        Self {
-            a: T::default(),
-            b: T::default(),
-        }
-    }
-}
-
-#[derive(Default)]
-struct WithoutSelfCurly {
-    a: bool,
-}
-
-
-#[derive(Default)]
-struct WithoutSelfParan(bool);
-
-
-// https://github.com/rust-lang/rust-clippy/issues/7655
-
-pub struct SpecializedImpl2<T> {
-    v: Vec<T>,
-}
-
-impl Default for SpecializedImpl2<String> {
-    fn default() -> Self {
-        Self { v: Vec::new() }
-    }
-}
-
-// https://github.com/rust-lang/rust-clippy/issues/7654
-
-pub struct Color {
-    pub r: u8,
-    pub g: u8,
-    pub b: u8,
-}
-
-/// `#000000`
-impl Default for Color {
-    fn default() -> Self {
-        Color { r: 0, g: 0, b: 0 }
-    }
-}
-
-pub struct Color2 {
-    pub r: u8,
-    pub g: u8,
-    pub b: u8,
-}
-
-impl Default for Color2 {
-    /// `#000000`
-    fn default() -> Self {
-        Self { r: 0, g: 0, b: 0 }
-    }
-}
-
-#[derive(Default)]
-pub struct RepeatDefault1 {
-    a: [i8; 32],
-}
-
-
-pub struct RepeatDefault2 {
-    a: [i8; 33],
-}
-
-impl Default for RepeatDefault2 {
-    fn default() -> Self {
-        RepeatDefault2 { a: [0; 33] }
-    }
-}
-
-// https://github.com/rust-lang/rust-clippy/issues/7753
-
-pub enum IntOrString {
-    Int(i32),
-    String(String),
-}
-
-impl Default for IntOrString {
-    fn default() -> Self {
-        IntOrString::Int(0)
-    }
-}
-
-#[derive(Default)]
-pub enum SimpleEnum {
-    Foo,
-    #[default]
-    Bar,
-}
-
-
-pub enum NonExhaustiveEnum {
-    Foo,
-    #[non_exhaustive]
-    Bar,
-}
-
-impl Default for NonExhaustiveEnum {
-    fn default() -> Self {
-        NonExhaustiveEnum::Bar
-    }
-}
-
-// https://github.com/rust-lang/rust-clippy/issues/10396
-
-#[derive(Default)]
-struct DefaultType;
-
-struct GenericType<T = DefaultType> {
-    t: T,
-}
-
-impl Default for GenericType {
-    fn default() -> Self {
-        Self { t: Default::default() }
-    }
-}
-
-struct InnerGenericType<T> {
-    t: T,
-}
-
-impl Default for InnerGenericType<DefaultType> {
-    fn default() -> Self {
-        Self { t: Default::default() }
-    }
-}
-
-struct OtherGenericType<T = DefaultType> {
-    inner: InnerGenericType<T>,
-}
-
-impl Default for OtherGenericType {
-    fn default() -> Self {
-        Self {
-            inner: Default::default(),
-        }
-    }
-}
-
-mod issue10158 {
-    pub trait T {}
-
-    #[derive(Default)]
-    pub struct S {}
-    impl T for S {}
-
-    pub struct Outer {
-        pub inner: Box<dyn T>,
-    }
-
-    impl Default for Outer {
-        fn default() -> Self {
-            Outer {
-                // Box::<S>::default() adjusts to Box<dyn T>
-                inner: Box::<S>::default(),
-            }
-        }
-    }
-}
-
-mod issue11368 {
-    pub struct A {
-        a: u32,
-    }
-
-    impl Default for A {
-        #[track_caller]
-        fn default() -> Self {
-            Self { a: 0 }
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index 21d73ba8b77..58f7771b627 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -1,5 +1,7 @@
 #![allow(dead_code)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 use std::collections::HashMap;
 
 struct FooDefault<'a> {
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
index 0adb422373d..d3adfa60e10 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.stderr
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -1,5 +1,5 @@
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:20:1
+  --> tests/ui/derivable_impls.rs:22:1
    |
 LL | / impl std::default::Default for FooDefault<'_> {
 LL | |     fn default() -> Self {
@@ -20,7 +20,7 @@ LL | struct FooDefault<'a> {
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:41:1
+  --> tests/ui/derivable_impls.rs:43:1
    |
 LL | / impl std::default::Default for TupleDefault {
 LL | |     fn default() -> Self {
@@ -37,7 +37,7 @@ LL | struct TupleDefault(bool, i32, u64);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:93:1
+  --> tests/ui/derivable_impls.rs:95:1
    |
 LL | / impl Default for StrDefault<'_> {
 LL | |     fn default() -> Self {
@@ -54,7 +54,7 @@ LL | struct StrDefault<'a>(&'a str);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:119:1
+  --> tests/ui/derivable_impls.rs:121:1
    |
 LL | / impl Default for Y {
 LL | |     fn default() -> Self {
@@ -71,7 +71,7 @@ LL | struct Y(u32);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:158:1
+  --> tests/ui/derivable_impls.rs:160:1
    |
 LL | / impl Default for WithoutSelfCurly {
 LL | |     fn default() -> Self {
@@ -88,7 +88,7 @@ LL | struct WithoutSelfCurly {
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:166:1
+  --> tests/ui/derivable_impls.rs:168:1
    |
 LL | / impl Default for WithoutSelfParan {
 LL | |     fn default() -> Self {
@@ -105,7 +105,7 @@ LL | struct WithoutSelfParan(bool);
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:216:1
+  --> tests/ui/derivable_impls.rs:218:1
    |
 LL | / impl Default for RepeatDefault1 {
 LL | |     fn default() -> Self {
@@ -122,7 +122,7 @@ LL | pub struct RepeatDefault1 {
    |
 
 error: this `impl` can be derived
-  --> tests/ui/derivable_impls.rs:250:1
+  --> tests/ui/derivable_impls.rs:252:1
    |
 LL | / impl Default for SimpleEnum {
 LL | |     fn default() -> Self {
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index 84673f1f43f..edfffe8fcfe 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -54,21 +54,24 @@ fn test_units() {
 
 /// This tests allowed identifiers.
 /// KiB MiB GiB TiB PiB EiB
-/// DirectX
+/// AccessKit
+/// CoreFoundation CoreGraphics CoreText
+/// Direct2D Direct3D DirectWrite DirectX
 /// ECMAScript
 /// GPLv2 GPLv3
 /// GitHub GitLab
 /// IPv4 IPv6
-/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript
 /// WebAssembly
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
-/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
-/// WebGL WebGL2 WebGPU
+/// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
+/// OpenType
+/// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport
 /// TensorFlow
 /// TrueType
-/// iOS macOS FreeBSD
+/// iOS macOS FreeBSD NetBSD OpenBSD
 /// TeX LaTeX BibTeX BibLaTeX
 /// MinGW
 /// CamelCase (see also #2395)
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index 4d017a99e0f..3c0f6913e32 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -54,21 +54,24 @@ fn test_units() {
 
 /// This tests allowed identifiers.
 /// KiB MiB GiB TiB PiB EiB
-/// DirectX
+/// AccessKit
+/// CoreFoundation CoreGraphics CoreText
+/// Direct2D Direct3D DirectWrite DirectX
 /// ECMAScript
 /// GPLv2 GPLv3
 /// GitHub GitLab
 /// IPv4 IPv6
-/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript
 /// WebAssembly
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
-/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
-/// WebGL WebGL2 WebGPU
+/// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
+/// OpenType
+/// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport
 /// TensorFlow
 /// TrueType
-/// iOS macOS FreeBSD
+/// iOS macOS FreeBSD NetBSD OpenBSD
 /// TeX LaTeX BibTeX BibLaTeX
 /// MinGW
 /// CamelCase (see also #2395)
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
index a9263f62d38..67c0464149c 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -133,7 +133,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:75:5
+  --> tests/ui/doc/doc-fixable.rs:78:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +144,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:92:5
+  --> tests/ui/doc/doc-fixable.rs:95:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -155,7 +155,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:100:8
+  --> tests/ui/doc/doc-fixable.rs:103:8
    |
 LL | /// ## CamelCaseThing
    |        ^^^^^^^^^^^^^^
@@ -166,7 +166,7 @@ LL | /// ## `CamelCaseThing`
    |        ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:103:7
+  --> tests/ui/doc/doc-fixable.rs:106:7
    |
 LL | /// # CamelCaseThing
    |       ^^^^^^^^^^^^^^
@@ -177,7 +177,7 @@ LL | /// # `CamelCaseThing`
    |       ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:105:22
+  --> tests/ui/doc/doc-fixable.rs:108:22
    |
 LL | /// Not a title #897 CamelCaseThing
    |                      ^^^^^^^^^^^^^^
@@ -188,7 +188,7 @@ LL | /// Not a title #897 `CamelCaseThing`
    |                      ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:106:5
+  --> tests/ui/doc/doc-fixable.rs:109:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -199,7 +199,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:113:5
+  --> tests/ui/doc/doc-fixable.rs:116:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -210,7 +210,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:126:5
+  --> tests/ui/doc/doc-fixable.rs:129:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -221,7 +221,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:137:43
+  --> tests/ui/doc/doc-fixable.rs:140:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -232,7 +232,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
    |                                           ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:142:5
+  --> tests/ui/doc/doc-fixable.rs:145:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -243,7 +243,7 @@ LL | And `BarQuz` too.
    |     ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:143:1
+  --> tests/ui/doc/doc-fixable.rs:146:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -254,7 +254,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:148:43
+  --> tests/ui/doc/doc-fixable.rs:151:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -265,7 +265,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
    |                                           ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:153:5
+  --> tests/ui/doc/doc-fixable.rs:156:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -276,7 +276,7 @@ LL | And `BarQuz` too.
    |     ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:154:1
+  --> tests/ui/doc/doc-fixable.rs:157:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -287,7 +287,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:165:5
+  --> tests/ui/doc/doc-fixable.rs:168:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -298,7 +298,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:184:22
+  --> tests/ui/doc/doc-fixable.rs:187:22
    |
 LL | /// An iterator over mycrate::Collection's values.
    |                      ^^^^^^^^^^^^^^^^^^^
@@ -309,7 +309,7 @@ LL | /// An iterator over `mycrate::Collection`'s values.
    |                      ~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:208:34
+  --> tests/ui/doc/doc-fixable.rs:211:34
    |
 LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint
    |                                  ^^^^^^^^^^^^^^^
@@ -320,7 +320,7 @@ LL | /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint`
    |                                  ~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:231:22
+  --> tests/ui/doc/doc-fixable.rs:234:22
    |
 LL | /// There is no try (do() or do_not()).
    |                      ^^^^
@@ -331,7 +331,7 @@ LL | /// There is no try (`do()` or do_not()).
    |                      ~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:231:30
+  --> tests/ui/doc/doc-fixable.rs:234:30
    |
 LL | /// There is no try (do() or do_not()).
    |                              ^^^^^^^^
@@ -342,7 +342,7 @@ LL | /// There is no try (do() or `do_not()`).
    |                              ~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:234:5
+  --> tests/ui/doc/doc-fixable.rs:237:5
    |
 LL | /// ABes
    |     ^^^^
@@ -353,7 +353,7 @@ LL | /// `ABes`
    |     ~~~~~~
 
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc-fixable.rs:240:9
+  --> tests/ui/doc/doc-fixable.rs:243:9
    |
 LL |     /// foo()
    |         ^^^^^
@@ -364,7 +364,7 @@ LL |     /// `foo()`
    |         ~~~~~~~
 
 error: you should put bare URLs between `<`/`>` or make a proper Markdown link
-  --> tests/ui/doc/doc-fixable.rs:244:5
+  --> tests/ui/doc/doc-fixable.rs:247:5
    |
 LL | /// https://github.com/rust-lang/rust-clippy/pull/12836
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<https://github.com/rust-lang/rust-clippy/pull/12836>`
diff --git a/src/tools/clippy/tests/ui/excessive_precision.fixed b/src/tools/clippy/tests/ui/excessive_precision.fixed
index cc553103530..372f64f7d99 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.fixed
+++ b/src/tools/clippy/tests/ui/excessive_precision.fixed
@@ -78,4 +78,8 @@ fn main() {
     const NEG_INF1: f32 = -1.0e+33f32;
     const NEG_INF2: f64 = -1.0e+3300f64;
     const NEG_INF3: f32 = -3.40282357e+38_f32;
+
+    // issue #12954
+    const _: f64 = 3.0;
+    const _: f64 = 3.0000000000000000;
 }
diff --git a/src/tools/clippy/tests/ui/excessive_precision.rs b/src/tools/clippy/tests/ui/excessive_precision.rs
index fff986a8296..1e40efbf245 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.rs
+++ b/src/tools/clippy/tests/ui/excessive_precision.rs
@@ -78,4 +78,8 @@ fn main() {
     const NEG_INF1: f32 = -1.0e+33f32;
     const NEG_INF2: f64 = -1.0e+3300f64;
     const NEG_INF3: f32 = -3.40282357e+38_f32;
+
+    // issue #12954
+    const _: f64 = 3.0000000000000000e+00;
+    const _: f64 = 3.0000000000000000;
 }
diff --git a/src/tools/clippy/tests/ui/excessive_precision.stderr b/src/tools/clippy/tests/ui/excessive_precision.stderr
index 22dd96e53bd..6d8e166a649 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.stderr
+++ b/src/tools/clippy/tests/ui/excessive_precision.stderr
@@ -91,5 +91,11 @@ error: float has excessive precision
 LL |     let _ = 1.000_000_000_000_001e-324_f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64`
 
-error: aborting due to 15 previous errors
+error: float has excessive precision
+  --> tests/ui/excessive_precision.rs:83:20
+   |
+LL |     const _: f64 = 3.0000000000000000e+00;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `3.0`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.fixed b/src/tools/clippy/tests/ui/floating_point_powf.fixed
index a44938fdf69..25f09a63795 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_powf.fixed
@@ -25,6 +25,14 @@ fn main() {
     let _ = 1.5_f64.sqrt();
     let _ = 1.5_f64.powi(3);
 
+    macro_rules! m {
+        ($e:expr) => {
+            5.5 - $e
+        };
+    }
+
+    let _ = (1f32 + m!(2.0)).exp2();
+
     // Cases where the lint shouldn't be applied
     let _ = x.powf(2.1);
     let _ = x.powf(-2.1);
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.rs b/src/tools/clippy/tests/ui/floating_point_powf.rs
index 80f6c1791d7..9e9878de4ba 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.rs
+++ b/src/tools/clippy/tests/ui/floating_point_powf.rs
@@ -25,6 +25,14 @@ fn main() {
     let _ = 1.5_f64.powf(1.0 / 2.0);
     let _ = 1.5_f64.powf(3.0);
 
+    macro_rules! m {
+        ($e:expr) => {
+            5.5 - $e
+        };
+    }
+
+    let _ = 2f32.powf(1f32 + m!(2.0));
+
     // Cases where the lint shouldn't be applied
     let _ = x.powf(2.1);
     let _ = x.powf(-2.1);
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.stderr b/src/tools/clippy/tests/ui/floating_point_powf.stderr
index 671383401b5..c944f14fa34 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_powf.stderr
@@ -119,76 +119,82 @@ LL |     let _ = 1.5_f64.powf(3.0);
    |             ^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.powi(3)`
 
 error: exponent for bases 2 and e can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:35:13
+  --> tests/ui/floating_point_powf.rs:34:13
+   |
+LL |     let _ = 2f32.powf(1f32 + m!(2.0));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(1f32 + m!(2.0)).exp2()`
+
+error: exponent for bases 2 and e can be computed more accurately
+  --> tests/ui/floating_point_powf.rs:43:13
    |
 LL |     let _ = 2f64.powf(x);
    |             ^^^^^^^^^^^^ help: consider using: `x.exp2()`
 
 error: exponent for bases 2 and e can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:36:13
+  --> tests/ui/floating_point_powf.rs:44:13
    |
 LL |     let _ = 2f64.powf(3.1);
    |             ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()`
 
 error: exponent for bases 2 and e can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:37:13
+  --> tests/ui/floating_point_powf.rs:45:13
    |
 LL |     let _ = 2f64.powf(-3.1);
    |             ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()`
 
 error: exponent for bases 2 and e can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:38:13
+  --> tests/ui/floating_point_powf.rs:46:13
    |
 LL |     let _ = std::f64::consts::E.powf(x);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
 
 error: exponent for bases 2 and e can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:39:13
+  --> tests/ui/floating_point_powf.rs:47:13
    |
 LL |     let _ = std::f64::consts::E.powf(3.1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()`
 
 error: exponent for bases 2 and e can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:40:13
+  --> tests/ui/floating_point_powf.rs:48:13
    |
 LL |     let _ = std::f64::consts::E.powf(-3.1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()`
 
 error: square-root of a number can be computed more efficiently and accurately
-  --> tests/ui/floating_point_powf.rs:41:13
+  --> tests/ui/floating_point_powf.rs:49:13
    |
 LL |     let _ = x.powf(1.0 / 2.0);
    |             ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
 
 error: cube-root of a number can be computed more accurately
-  --> tests/ui/floating_point_powf.rs:42:13
+  --> tests/ui/floating_point_powf.rs:50:13
    |
 LL |     let _ = x.powf(1.0 / 3.0);
    |             ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
 
 error: exponentiation with integer powers can be computed more efficiently
-  --> tests/ui/floating_point_powf.rs:43:13
+  --> tests/ui/floating_point_powf.rs:51:13
    |
 LL |     let _ = x.powf(3.0);
    |             ^^^^^^^^^^^ help: consider using: `x.powi(3)`
 
 error: exponentiation with integer powers can be computed more efficiently
-  --> tests/ui/floating_point_powf.rs:44:13
+  --> tests/ui/floating_point_powf.rs:52:13
    |
 LL |     let _ = x.powf(-2.0);
    |             ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
 
 error: exponentiation with integer powers can be computed more efficiently
-  --> tests/ui/floating_point_powf.rs:45:13
+  --> tests/ui/floating_point_powf.rs:53:13
    |
 LL |     let _ = x.powf(-2_147_483_648.0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)`
 
 error: exponentiation with integer powers can be computed more efficiently
-  --> tests/ui/floating_point_powf.rs:46:13
+  --> tests/ui/floating_point_powf.rs:54:13
    |
 LL |     let _ = x.powf(2_147_483_647.0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)`
 
-error: aborting due to 31 previous errors
+error: aborting due to 32 previous errors
 
diff --git a/src/tools/clippy/tests/ui/from_str_radix_10.fixed b/src/tools/clippy/tests/ui/from_str_radix_10.fixed
index f9ce1defda1..6c582190b44 100644
--- a/src/tools/clippy/tests/ui/from_str_radix_10.fixed
+++ b/src/tools/clippy/tests/ui/from_str_radix_10.fixed
@@ -1,4 +1,3 @@
-#![feature(const_int_from_str)]
 #![warn(clippy::from_str_radix_10)]
 
 mod some_mod {
@@ -61,7 +60,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     Ok(())
 }
 
-fn issue_12732() {
+// https://github.com/rust-lang/rust-clippy/issues/12731
+fn issue_12731() {
     const A: Result<u32, std::num::ParseIntError> = u32::from_str_radix("123", 10);
     const B: () = {
         let _ = u32::from_str_radix("123", 10);
diff --git a/src/tools/clippy/tests/ui/from_str_radix_10.rs b/src/tools/clippy/tests/ui/from_str_radix_10.rs
index 2d5b351f8da..0df6a0a202a 100644
--- a/src/tools/clippy/tests/ui/from_str_radix_10.rs
+++ b/src/tools/clippy/tests/ui/from_str_radix_10.rs
@@ -1,4 +1,3 @@
-#![feature(const_int_from_str)]
 #![warn(clippy::from_str_radix_10)]
 
 mod some_mod {
@@ -61,7 +60,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     Ok(())
 }
 
-fn issue_12732() {
+// https://github.com/rust-lang/rust-clippy/issues/12731
+fn issue_12731() {
     const A: Result<u32, std::num::ParseIntError> = u32::from_str_radix("123", 10);
     const B: () = {
         let _ = u32::from_str_radix("123", 10);
diff --git a/src/tools/clippy/tests/ui/from_str_radix_10.stderr b/src/tools/clippy/tests/ui/from_str_radix_10.stderr
index 01a1bf8940a..4aa84eca261 100644
--- a/src/tools/clippy/tests/ui/from_str_radix_10.stderr
+++ b/src/tools/clippy/tests/ui/from_str_radix_10.stderr
@@ -1,5 +1,5 @@
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:29:5
+  --> tests/ui/from_str_radix_10.rs:28:5
    |
 LL |     u32::from_str_radix("30", 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"30".parse::<u32>()`
@@ -8,43 +8,43 @@ LL |     u32::from_str_radix("30", 10)?;
    = help: to override `-D warnings` add `#[allow(clippy::from_str_radix_10)]`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:32:5
+  --> tests/ui/from_str_radix_10.rs:31:5
    |
 LL |     i64::from_str_radix("24", 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"24".parse::<i64>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:34:5
+  --> tests/ui/from_str_radix_10.rs:33:5
    |
 LL |     isize::from_str_radix("100", 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"100".parse::<isize>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:36:5
+  --> tests/ui/from_str_radix_10.rs:35:5
    |
 LL |     u8::from_str_radix("7", 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"7".parse::<u8>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:38:5
+  --> tests/ui/from_str_radix_10.rs:37:5
    |
 LL |     u16::from_str_radix(&("10".to_owned() + "5"), 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `("10".to_owned() + "5").parse::<u16>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:40:5
+  --> tests/ui/from_str_radix_10.rs:39:5
    |
 LL |     i128::from_str_radix(Test + Test, 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(Test + Test).parse::<i128>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:44:5
+  --> tests/ui/from_str_radix_10.rs:43:5
    |
 LL |     i32::from_str_radix(string, 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.parse::<i32>()`
 
 error: this call to `from_str_radix` can be replaced with a call to `str::parse`
-  --> tests/ui/from_str_radix_10.rs:48:5
+  --> tests/ui/from_str_radix_10.rs:47:5
    |
 LL |     i32::from_str_radix(&stringier, 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `stringier.parse::<i32>()`
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.fixed b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.fixed
deleted file mode 100644
index 13f0cbe9cc8..00000000000
--- a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.fixed
+++ /dev/null
@@ -1,177 +0,0 @@
-#![deny(clippy::index_refutable_slice)]
-#![allow(clippy::uninlined_format_args)]
-
-enum SomeEnum<T> {
-    One(T),
-    Two(T),
-    Three(T),
-    Four(T),
-}
-
-fn lintable_examples() {
-    // Try with reference
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-    if let Some([slice_0, ..]) = slice {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{}", slice_0);
-    }
-
-    // Try with copy
-    let slice: Option<[u32; 3]> = Some([1, 2, 3]);
-    if let Some([slice_0, ..]) = slice {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{}", slice_0);
-    }
-
-    // Try with long slice and small indices
-    let slice: Option<[u32; 9]> = Some([1, 2, 3, 4, 5, 6, 7, 8, 9]);
-    if let Some([slice_0, _, slice_2, ..]) = slice {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{}", slice_2);
-        println!("{}", slice_0);
-    }
-
-    // Multiple bindings
-    let slice_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([5, 6, 7]);
-    if let SomeEnum::One([slice_0, ..]) | SomeEnum::Three([slice_0, ..]) = slice_wrapped {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{}", slice_0);
-    }
-
-    // Two lintable slices in one if let
-    let a_wrapped: SomeEnum<[u32; 3]> = SomeEnum::One([9, 5, 1]);
-    let b_wrapped: Option<[u32; 2]> = Some([4, 6]);
-    if let (SomeEnum::Three([_, _, a_2, ..]), Some([_, b_1, ..])) = (a_wrapped, b_wrapped) {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        //~| ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{} -> {}", a_2, b_1);
-    }
-
-    // This requires the slice values to be borrowed as the slice values can only be
-    // borrowed and `String` doesn't implement copy
-    let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
-    if let Some([_, ref slice_1, ..]) = slice {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{:?}", slice_1);
-    }
-    println!("{:?}", slice);
-
-    // This should not suggest using the `ref` keyword as the scrutinee is already
-    // a reference
-    let slice: Option<[String; 2]> = Some([String::from("1"), String::from("2")]);
-    if let Some([slice_0, ..]) = &slice {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        println!("{:?}", slice_0);
-    }
-    println!("{:?}", slice);
-}
-
-fn slice_index_above_limit() {
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-
-    if let Some(slice) = slice {
-        // Would cause a panic, IDK
-        println!("{}", slice[7]);
-    }
-}
-
-fn slice_is_used() {
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-    if let Some(slice) = slice {
-        println!("{:?}", slice.len());
-    }
-
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-    if let Some(slice) = slice {
-        println!("{:?}", slice.to_vec());
-    }
-
-    let opt: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
-    if let Some(slice) = opt {
-        if !slice.is_empty() {
-            println!("first: {}", slice[0]);
-        }
-    }
-}
-
-/// The slice is used by an external function and should therefore not be linted
-fn check_slice_as_arg() {
-    fn is_interesting<T>(slice: &[T; 2]) -> bool {
-        !slice.is_empty()
-    }
-
-    let slice_wrapped: Option<[String; 2]> = Some([String::from("Hello"), String::from("world")]);
-    if let Some(slice) = &slice_wrapped {
-        if is_interesting(slice) {
-            println!("This is interesting {}", slice[0]);
-        }
-    }
-    println!("{:?}", slice_wrapped);
-}
-
-fn check_slice_in_struct() {
-    #[derive(Debug)]
-    struct Wrapper<'a> {
-        inner: Option<&'a [String]>,
-        is_awesome: bool,
-    }
-
-    impl<'a> Wrapper<'a> {
-        fn is_super_awesome(&self) -> bool {
-            self.is_awesome
-        }
-    }
-
-    let inner = &[String::from("New"), String::from("World")];
-    let wrap = Wrapper {
-        inner: Some(inner),
-        is_awesome: true,
-    };
-
-    // Test 1: Field access
-    if let Some([slice_0, ..]) = wrap.inner {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        if wrap.is_awesome {
-            println!("This is awesome! {}", slice_0);
-        }
-    }
-
-    // Test 2: function access
-    if let Some([slice_0, ..]) = wrap.inner {
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        if wrap.is_super_awesome() {
-            println!("This is super awesome! {}", slice_0);
-        }
-    }
-    println!("Complete wrap: {:?}", wrap);
-}
-
-/// This would be a nice additional feature to have in the future, but adding it
-/// now would make the PR too large. This is therefore only a test that we don't
-/// lint cases we can't make a reasonable suggestion for
-fn mutable_slice_index() {
-    // Mut access
-    let mut slice: Option<[String; 1]> = Some([String::from("Penguin")]);
-    if let Some(ref mut slice) = slice {
-        slice[0] = String::from("Mr. Penguin");
-    }
-    println!("Use after modification: {:?}", slice);
-
-    // Mut access on reference
-    let mut slice: Option<[String; 1]> = Some([String::from("Cat")]);
-    if let Some(slice) = &mut slice {
-        slice[0] = String::from("Lord Meow Meow");
-    }
-    println!("Use after modification: {:?}", slice);
-}
-
-/// The lint will ignore bindings with sub patterns as it would be hard
-/// to build correct suggestions for these instances :)
-fn binding_with_sub_pattern() {
-    let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-    if let Some(slice @ [_, _, _]) = slice {
-        println!("{:?}", slice[2]);
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs
index d8d38c167fa..5bbdabcaad1 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs
@@ -1,6 +1,8 @@
 #![deny(clippy::index_refutable_slice)]
 #![allow(clippy::uninlined_format_args)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 enum SomeEnum<T> {
     One(T),
     Two(T),
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr
index 14e0f931f24..8819cb0e28b 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr
@@ -1,5 +1,5 @@
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:14:17
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:16:17
    |
 LL |     if let Some(slice) = slice {
    |                 ^^^^^
@@ -19,7 +19,7 @@ LL |         println!("{}", slice_0);
    |                        ~~~~~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:21:17
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:23:17
    |
 LL |     if let Some(slice) = slice {
    |                 ^^^^^
@@ -34,7 +34,7 @@ LL |         println!("{}", slice_0);
    |                        ~~~~~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:28:17
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:30:17
    |
 LL |     if let Some(slice) = slice {
    |                 ^^^^^
@@ -50,7 +50,7 @@ LL ~         println!("{}", slice_0);
    |
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:36:26
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:38:26
    |
 LL |     if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped {
    |                          ^^^^^
@@ -65,7 +65,7 @@ LL |         println!("{}", slice_0);
    |                        ~~~~~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:29
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:46:29
    |
 LL |     if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
    |                             ^
@@ -80,7 +80,7 @@ LL |         println!("{} -> {}", a_2, b[1]);
    |                              ~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:44:38
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:46:38
    |
 LL |     if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
    |                                      ^
@@ -95,7 +95,7 @@ LL |         println!("{} -> {}", a[2], b_1);
    |                                    ~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:53:21
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:55:21
    |
 LL |     if let Some(ref slice) = slice {
    |                     ^^^^^
@@ -110,7 +110,7 @@ LL |         println!("{:?}", slice_1);
    |                          ~~~~~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:62:17
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:64:17
    |
 LL |     if let Some(slice) = &slice {
    |                 ^^^^^
@@ -125,7 +125,7 @@ LL |         println!("{:?}", slice_0);
    |                          ~~~~~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:132:17
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:134:17
    |
 LL |     if let Some(slice) = wrap.inner {
    |                 ^^^^^
@@ -140,7 +140,7 @@ LL |             println!("This is awesome! {}", slice_0);
    |                                             ~~~~~~~
 
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:140:17
+  --> tests/ui/index_refutable_slice/if_let_slice_binding.rs:142:17
    |
 LL |     if let Some(slice) = wrap.inner {
    |                 ^^^^^
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed
deleted file mode 100644
index 72edc539f04..00000000000
--- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed
+++ /dev/null
@@ -1,29 +0,0 @@
-#![deny(clippy::index_refutable_slice)]
-
-extern crate if_chain;
-use if_chain::if_chain;
-
-macro_rules! if_let_slice_macro {
-    () => {
-        // This would normally be linted
-        let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-        if let Some(slice) = slice {
-            println!("{}", slice[0]);
-        }
-    };
-}
-
-fn main() {
-    // Don't lint this
-    if_let_slice_macro!();
-
-    // Do lint this
-    if_chain! {
-        let slice: Option<&[u32]> = Some(&[1, 2, 3]);
-        if let Some([slice_0, ..]) = slice;
-        //~^ ERROR: this binding can be a slice pattern to avoid indexing
-        then {
-            println!("{}", slice_0);
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
index 7b474ba423b..5d9fad48889 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs
@@ -1,5 +1,7 @@
 #![deny(clippy::index_refutable_slice)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 extern crate if_chain;
 use if_chain::if_chain;
 
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr
index caccd0f9295..69f0aaa9777 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr
@@ -1,5 +1,5 @@
 error: this binding can be a slice pattern to avoid indexing
-  --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:23:21
+  --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:25:21
    |
 LL |         if let Some(slice) = slice;
    |                     ^^^^^
diff --git a/src/tools/clippy/tests/ui/let_unit.fixed b/src/tools/clippy/tests/ui/let_unit.fixed
deleted file mode 100644
index 3456e274f6a..00000000000
--- a/src/tools/clippy/tests/ui/let_unit.fixed
+++ /dev/null
@@ -1,196 +0,0 @@
-#![warn(clippy::let_unit_value)]
-#![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)]
-
-macro_rules! let_and_return {
-    ($n:expr) => {{
-        let ret = $n;
-    }};
-}
-
-fn main() {
-    println!("x");
-    let _y = 1; // this is fine
-    let _z = ((), 1); // this as well
-    if true {
-        // do not lint this, since () is explicit
-        let _a = ();
-        let () = dummy();
-        let () = ();
-        () = dummy();
-        () = ();
-        let _a: () = ();
-        let _a: () = dummy();
-    }
-
-    consume_units_with_for_loop(); // should be fine as well
-
-    multiline_sugg();
-
-    let_and_return!(()) // should be fine
-}
-
-fn dummy() {}
-
-// Related to issue #1964
-fn consume_units_with_for_loop() {
-    // `for_let_unit` lint should not be triggered by consuming them using for loop.
-    let v = vec![(), (), ()];
-    let mut count = 0;
-    for _ in v {
-        count += 1;
-    }
-    assert_eq!(count, 3);
-
-    // Same for consuming from some other Iterator<Item = ()>.
-    let (tx, rx) = ::std::sync::mpsc::channel();
-    tx.send(()).unwrap();
-    drop(tx);
-
-    count = 0;
-    for _ in rx.iter() {
-        count += 1;
-    }
-    assert_eq!(count, 1);
-}
-
-fn multiline_sugg() {
-    let v: Vec<u8> = vec![2];
-
-    v
-        .into_iter()
-        .map(|i| i * 2)
-        .filter(|i| i % 2 == 0)
-        .map(|_| ())
-        .next()
-        .unwrap();
-}
-
-#[derive(Copy, Clone)]
-pub struct ContainsUnit(()); // should be fine
-
-fn _returns_generic() {
-    fn f<T>() -> T {
-        unimplemented!()
-    }
-    fn f2<T, U>(_: T) -> U {
-        unimplemented!()
-    }
-    fn f3<T>(x: T) -> T {
-        x
-    }
-    fn f5<T: Default>(x: bool) -> Option<T> {
-        x.then(|| T::default())
-    }
-
-    let _: () = f();
-    let x: () = f();
-
-    let _: () = f2(0i32);
-    let x: () = f2(0i32);
-
-    let _: () = f3(());
-    let x: () = f3(());
-
-    fn f4<T>(mut x: Vec<T>) -> T {
-        x.pop().unwrap()
-    }
-    let _: () = f4(vec![()]);
-    let x: () = f4(vec![()]);
-
-    let _: () = {
-        let x = 5;
-        f2(x)
-    };
-
-    let _: () = if true { f() } else { f2(0) };
-    let x: () = if true { f() } else { f2(0) };
-
-    match Some(0) {
-        None => f2(1),
-        Some(0) => f(),
-        Some(1) => f2(3),
-        Some(_) => (),
-    };
-
-    let _: () = f5(true).unwrap();
-
-    #[allow(clippy::let_unit_value)]
-    {
-        let x = f();
-        let y;
-        let z;
-        match 0 {
-            0 => {
-                y = f();
-                z = f();
-            },
-            1 => {
-                println!("test");
-                y = f();
-                z = f3(());
-            },
-            _ => panic!(),
-        }
-
-        let x1;
-        let x2;
-        if true {
-            x1 = f();
-            x2 = x1;
-        } else {
-            x2 = f();
-            x1 = x2;
-        }
-
-        let opt;
-        match f5(true) {
-            Some(x) => opt = x,
-            None => panic!(),
-        };
-
-        #[warn(clippy::let_unit_value)]
-        {
-            let _: () = x;
-            let _: () = y;
-            let _: () = z;
-            let _: () = x1;
-            let _: () = x2;
-            let _: () = opt;
-        }
-    }
-
-    let () = f();
-}
-
-fn attributes() {
-    fn f() {}
-
-    #[allow(clippy::let_unit_value)]
-    let _ = f();
-    #[expect(clippy::let_unit_value)]
-    let _ = f();
-}
-
-async fn issue10433() {
-    let _pending: () = std::future::pending().await;
-}
-
-pub async fn issue11502(a: ()) {}
-
-pub fn issue12594() {
-    fn returns_unit() {}
-
-    fn returns_result<T>(res: T) -> Result<T, ()> {
-        Ok(res)
-    }
-
-    fn actual_test() {
-        // create first a unit value'd value
-        returns_unit();
-        returns_result(()).unwrap();
-        returns_result(()).unwrap();
-        // make sure we replace only the first variable
-        let res = 1;
-        returns_result(res).unwrap();
-    }
-}
diff --git a/src/tools/clippy/tests/ui/let_unit.rs b/src/tools/clippy/tests/ui/let_unit.rs
index e2dafbcb771..530103ffaf6 100644
--- a/src/tools/clippy/tests/ui/let_unit.rs
+++ b/src/tools/clippy/tests/ui/let_unit.rs
@@ -1,6 +1,8 @@
 #![warn(clippy::let_unit_value)]
 #![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 macro_rules! let_and_return {
     ($n:expr) => {{
         let ret = $n;
diff --git a/src/tools/clippy/tests/ui/let_unit.stderr b/src/tools/clippy/tests/ui/let_unit.stderr
index 2f62c33c887..6f149454af2 100644
--- a/src/tools/clippy/tests/ui/let_unit.stderr
+++ b/src/tools/clippy/tests/ui/let_unit.stderr
@@ -1,5 +1,5 @@
 error: this let-binding has unit value
-  --> tests/ui/let_unit.rs:11:5
+  --> tests/ui/let_unit.rs:13:5
    |
 LL |     let _x = println!("x");
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `println!("x");`
@@ -8,7 +8,7 @@ LL |     let _x = println!("x");
    = help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
 
 error: this let-binding has unit value
-  --> tests/ui/let_unit.rs:59:5
+  --> tests/ui/let_unit.rs:61:5
    |
 LL | /     let _ = v
 LL | |         .into_iter()
@@ -31,7 +31,7 @@ LL +         .unwrap();
    |
 
 error: this let-binding has unit value
-  --> tests/ui/let_unit.rs:108:5
+  --> tests/ui/let_unit.rs:110:5
    |
 LL | /     let x = match Some(0) {
 LL | |         None => f2(1),
@@ -52,7 +52,7 @@ LL +     };
    |
 
 error: this let-binding has unit value
-  --> tests/ui/let_unit.rs:189:9
+  --> tests/ui/let_unit.rs:191:9
    |
 LL |         let res = returns_unit();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
deleted file mode 100644
index 75835780801..00000000000
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ /dev/null
@@ -1,76 +0,0 @@
-//@revisions: edition2018 edition2021
-//@[edition2018] edition:2018
-//@[edition2021] edition:2021
-
-#![warn(clippy::manual_assert)]
-#![allow(dead_code, unused_doc_comments)]
-#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
-
-macro_rules! one {
-    () => {
-        1
-    };
-}
-
-fn main() {
-    let a = vec![1, 2, 3];
-    let c = Some(2);
-    if !a.is_empty()
-        && a.len() == 3
-        && c.is_some()
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-    {
-        panic!("qaqaq{:?}", a);
-    }
-    assert!(a.is_empty(), "qaqaq{:?}", a);
-    assert!(a.is_empty(), "qwqwq");
-    if a.len() == 3 {
-        println!("qwq");
-        println!("qwq");
-        println!("qwq");
-    }
-    if let Some(b) = c {
-        panic!("orz {}", b);
-    }
-    if a.len() == 3 {
-        panic!("qaqaq");
-    } else {
-        println!("qwq");
-    }
-    let b = vec![1, 2, 3];
-    assert!(!b.is_empty(), "panic1");
-    assert!(!(b.is_empty() && a.is_empty()), "panic2");
-    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
-    assert!(!(b.is_empty() || a.is_empty()), "panic4");
-    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
-    assert!(!a.is_empty(), "with expansion {}", one!());
-    if a.is_empty() {
-        let _ = 0;
-    } else if a.len() == 1 {
-        panic!("panic6");
-    }
-}
-
-fn issue7730(a: u8) {
-    // Suggestion should preserve comment
-    // comment
-/* this is a
-        multiline
-        comment */
-/// Doc comment
-// comment after `panic!`
-assert!(!(a > 2), "panic with comment");
-}
-
-fn issue12505() {
-    struct Foo<T, const N: usize>(T);
-
-    impl<T, const N: usize> Foo<T, N> {
-        const BAR: () = assert!(!(N == 0), );
-    }
-}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
index 1eebe1bfe17..004463720e2 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
@@ -1,5 +1,5 @@
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:30:5
+  --> tests/ui/manual_assert.rs:32:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qaqaq{:?}", a);
@@ -10,7 +10,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::manual_assert)]`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:33:5
+  --> tests/ui/manual_assert.rs:35:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qwqwq");
@@ -18,7 +18,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:50:5
+  --> tests/ui/manual_assert.rs:52:5
    |
 LL | /     if b.is_empty() {
 LL | |         panic!("panic1");
@@ -26,7 +26,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:53:5
+  --> tests/ui/manual_assert.rs:55:5
    |
 LL | /     if b.is_empty() && a.is_empty() {
 LL | |         panic!("panic2");
@@ -34,7 +34,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:56:5
+  --> tests/ui/manual_assert.rs:58:5
    |
 LL | /     if a.is_empty() && !b.is_empty() {
 LL | |         panic!("panic3");
@@ -42,7 +42,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:59:5
+  --> tests/ui/manual_assert.rs:61:5
    |
 LL | /     if b.is_empty() || a.is_empty() {
 LL | |         panic!("panic4");
@@ -50,7 +50,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:62:5
+  --> tests/ui/manual_assert.rs:64:5
    |
 LL | /     if a.is_empty() || !b.is_empty() {
 LL | |         panic!("panic5");
@@ -58,7 +58,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:65:5
+  --> tests/ui/manual_assert.rs:67:5
    |
 LL | /     if a.is_empty() {
 LL | |         panic!("with expansion {}", one!())
@@ -66,7 +66,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:77:5
+  --> tests/ui/manual_assert.rs:79:5
    |
 LL | /     if a > 2 {
 LL | |         // comment
@@ -83,7 +83,7 @@ LL |     assert!(!(a > 2), "panic with comment");
    |
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:91:25
+  --> tests/ui/manual_assert.rs:93:25
    |
 LL |           const BAR: () = if N == 0 {
    |  _________________________^
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
deleted file mode 100644
index 75835780801..00000000000
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
+++ /dev/null
@@ -1,76 +0,0 @@
-//@revisions: edition2018 edition2021
-//@[edition2018] edition:2018
-//@[edition2021] edition:2021
-
-#![warn(clippy::manual_assert)]
-#![allow(dead_code, unused_doc_comments)]
-#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
-
-macro_rules! one {
-    () => {
-        1
-    };
-}
-
-fn main() {
-    let a = vec![1, 2, 3];
-    let c = Some(2);
-    if !a.is_empty()
-        && a.len() == 3
-        && c.is_some()
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-        && !a.is_empty()
-        && a.len() == 3
-    {
-        panic!("qaqaq{:?}", a);
-    }
-    assert!(a.is_empty(), "qaqaq{:?}", a);
-    assert!(a.is_empty(), "qwqwq");
-    if a.len() == 3 {
-        println!("qwq");
-        println!("qwq");
-        println!("qwq");
-    }
-    if let Some(b) = c {
-        panic!("orz {}", b);
-    }
-    if a.len() == 3 {
-        panic!("qaqaq");
-    } else {
-        println!("qwq");
-    }
-    let b = vec![1, 2, 3];
-    assert!(!b.is_empty(), "panic1");
-    assert!(!(b.is_empty() && a.is_empty()), "panic2");
-    assert!(!(a.is_empty() && !b.is_empty()), "panic3");
-    assert!(!(b.is_empty() || a.is_empty()), "panic4");
-    assert!(!(a.is_empty() || !b.is_empty()), "panic5");
-    assert!(!a.is_empty(), "with expansion {}", one!());
-    if a.is_empty() {
-        let _ = 0;
-    } else if a.len() == 1 {
-        panic!("panic6");
-    }
-}
-
-fn issue7730(a: u8) {
-    // Suggestion should preserve comment
-    // comment
-/* this is a
-        multiline
-        comment */
-/// Doc comment
-// comment after `panic!`
-assert!(!(a > 2), "panic with comment");
-}
-
-fn issue12505() {
-    struct Foo<T, const N: usize>(T);
-
-    impl<T, const N: usize> Foo<T, N> {
-        const BAR: () = assert!(!(N == 0), );
-    }
-}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
index 1eebe1bfe17..004463720e2 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
@@ -1,5 +1,5 @@
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:30:5
+  --> tests/ui/manual_assert.rs:32:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qaqaq{:?}", a);
@@ -10,7 +10,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::manual_assert)]`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:33:5
+  --> tests/ui/manual_assert.rs:35:5
    |
 LL | /     if !a.is_empty() {
 LL | |         panic!("qwqwq");
@@ -18,7 +18,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:50:5
+  --> tests/ui/manual_assert.rs:52:5
    |
 LL | /     if b.is_empty() {
 LL | |         panic!("panic1");
@@ -26,7 +26,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:53:5
+  --> tests/ui/manual_assert.rs:55:5
    |
 LL | /     if b.is_empty() && a.is_empty() {
 LL | |         panic!("panic2");
@@ -34,7 +34,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:56:5
+  --> tests/ui/manual_assert.rs:58:5
    |
 LL | /     if a.is_empty() && !b.is_empty() {
 LL | |         panic!("panic3");
@@ -42,7 +42,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:59:5
+  --> tests/ui/manual_assert.rs:61:5
    |
 LL | /     if b.is_empty() || a.is_empty() {
 LL | |         panic!("panic4");
@@ -50,7 +50,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:62:5
+  --> tests/ui/manual_assert.rs:64:5
    |
 LL | /     if a.is_empty() || !b.is_empty() {
 LL | |         panic!("panic5");
@@ -58,7 +58,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:65:5
+  --> tests/ui/manual_assert.rs:67:5
    |
 LL | /     if a.is_empty() {
 LL | |         panic!("with expansion {}", one!())
@@ -66,7 +66,7 @@ LL | |     }
    | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:77:5
+  --> tests/ui/manual_assert.rs:79:5
    |
 LL | /     if a > 2 {
 LL | |         // comment
@@ -83,7 +83,7 @@ LL |     assert!(!(a > 2), "panic with comment");
    |
 
 error: only a `panic!` in `if`-then statement
-  --> tests/ui/manual_assert.rs:91:25
+  --> tests/ui/manual_assert.rs:93:25
    |
 LL |           const BAR: () = if N == 0 {
    |  _________________________^
diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs
index 363bafdf05d..6337920a3ee 100644
--- a/src/tools/clippy/tests/ui/manual_assert.rs
+++ b/src/tools/clippy/tests/ui/manual_assert.rs
@@ -2,6 +2,8 @@
 //@[edition2018] edition:2018
 //@[edition2021] edition:2021
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 #![warn(clippy::manual_assert)]
 #![allow(dead_code, unused_doc_comments)]
 #![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed
deleted file mode 100644
index 18444090a42..00000000000
--- a/src/tools/clippy/tests/ui/manual_async_fn.fixed
+++ /dev/null
@@ -1,115 +0,0 @@
-#![warn(clippy::manual_async_fn)]
-#![allow(clippy::needless_pub_self, unused)]
-
-use std::future::Future;
-
-async fn fut() -> i32 { 42 }
-
-#[rustfmt::skip]
-async fn fut2() -> i32 { 42 }
-
-#[rustfmt::skip]
-async fn fut3() -> i32 { 42 }
-
-async fn empty_fut() {}
-
-#[rustfmt::skip]
-async fn empty_fut2() {}
-
-#[rustfmt::skip]
-async fn empty_fut3() {}
-
-async fn core_fut() -> i32 { 42 }
-
-// should be ignored
-fn has_other_stmts() -> impl core::future::Future<Output = i32> {
-    let _ = 42;
-    async move { 42 }
-}
-
-// should be ignored
-fn not_fut() -> i32 {
-    42
-}
-
-// should be ignored
-async fn already_async() -> impl Future<Output = i32> {
-    async { 42 }
-}
-
-struct S;
-impl S {
-    async fn inh_fut() -> i32 {
-        // NOTE: this code is here just to check that the indentation is correct in the suggested fix
-        let a = 42;
-        let b = 21;
-        if a < b {
-            let c = 21;
-            let d = 42;
-            if c < d {
-                let _ = 42;
-            }
-        }
-        42
-    }
-
-    // should be ignored
-    fn not_fut(&self) -> i32 {
-        42
-    }
-
-    // should be ignored
-    fn has_other_stmts() -> impl core::future::Future<Output = i32> {
-        let _ = 42;
-        async move { 42 }
-    }
-
-    // should be ignored
-    async fn already_async(&self) -> impl Future<Output = i32> {
-        async { 42 }
-    }
-}
-
-// Tests related to lifetime capture
-
-async fn elided(_: &i32) -> i32 { 42 }
-
-// should be ignored
-fn elided_not_bound(_: &i32) -> impl Future<Output = i32> {
-    async { 42 }
-}
-
-async fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> i32 { 42 }
-
-// should be ignored
-#[allow(clippy::needless_lifetimes)]
-fn explicit_not_bound<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> {
-    async { 42 }
-}
-
-// should be ignored
-mod issue_5765 {
-    use std::future::Future;
-
-    struct A;
-    impl A {
-        fn f(&self) -> impl Future<Output = ()> {
-            async {}
-        }
-    }
-
-    fn test() {
-        let _future = {
-            let a = A;
-            a.f()
-        };
-    }
-}
-
-pub async fn issue_10450() -> i32 { 42 }
-
-pub(crate) async fn issue_10450_2() -> i32 { 42 }
-
-pub(self) async fn issue_10450_3() -> i32 { 42 }
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs
index d42165bbe3d..6b8ac5033a9 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.rs
+++ b/src/tools/clippy/tests/ui/manual_async_fn.rs
@@ -1,6 +1,8 @@
 #![warn(clippy::manual_async_fn)]
 #![allow(clippy::needless_pub_self, unused)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 use std::future::Future;
 
 fn fut() -> impl Future<Output = i32> {
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.stderr b/src/tools/clippy/tests/ui/manual_async_fn.stderr
index c50af5a4988..f88fc30b3b5 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.stderr
+++ b/src/tools/clippy/tests/ui/manual_async_fn.stderr
@@ -1,5 +1,5 @@
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:6:1
+  --> tests/ui/manual_async_fn.rs:8:1
    |
 LL | fn fut() -> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | fn fut() -> impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:11:1
+  --> tests/ui/manual_async_fn.rs:13:1
    |
 LL | fn fut2() ->impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL | fn fut2() ->impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:16:1
+  --> tests/ui/manual_async_fn.rs:18:1
    |
 LL | fn fut3()-> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL | fn fut3()-> impl Future<Output = i32> { 42 }
    |                                       ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:20:1
+  --> tests/ui/manual_async_fn.rs:22:1
    |
 LL | fn empty_fut() -> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL | fn empty_fut() -> impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:25:1
+  --> tests/ui/manual_async_fn.rs:27:1
    |
 LL | fn empty_fut2() ->impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,7 +76,7 @@ LL | fn empty_fut2() ->impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:30:1
+  --> tests/ui/manual_async_fn.rs:32:1
    |
 LL | fn empty_fut3()-> impl Future<Output = ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -91,7 +91,7 @@ LL | fn empty_fut3()-> impl Future<Output = ()> {}
    |                                            ~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:34:1
+  --> tests/ui/manual_async_fn.rs:36:1
    |
 LL | fn core_fut() -> impl core::future::Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 }
    |                                                          ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:56:5
+  --> tests/ui/manual_async_fn.rs:58:5
    |
 LL |     fn inh_fut() -> impl Future<Output = i32> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -133,7 +133,7 @@ LL +     }
    |
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:91:1
+  --> tests/ui/manual_async_fn.rs:93:1
    |
 LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@ LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ { 42 }
    |                                                      ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:100:1
+  --> tests/ui/manual_async_fn.rs:102:1
    |
 LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -163,7 +163,7 @@ LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> +
    |                                                                                    ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:129:1
+  --> tests/ui/manual_async_fn.rs:131:1
    |
 LL | pub fn issue_10450() -> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -178,7 +178,7 @@ LL | pub fn issue_10450() -> impl Future<Output = i32> { 42 }
    |                                                   ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:133:1
+  --> tests/ui/manual_async_fn.rs:135:1
    |
 LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@ LL | pub(crate) fn issue_10450_2() -> impl Future<Output = i32> { 42 }
    |                                                            ~~~~~~
 
 error: this function can be simplified using the `async fn` syntax
-  --> tests/ui/manual_async_fn.rs:137:1
+  --> tests/ui/manual_async_fn.rs:139:1
    |
 LL | pub(self) fn issue_10450_3() -> impl Future<Output = i32> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/manual_split_once.fixed b/src/tools/clippy/tests/ui/manual_split_once.fixed
deleted file mode 100644
index aaac6a048e1..00000000000
--- a/src/tools/clippy/tests/ui/manual_split_once.fixed
+++ /dev/null
@@ -1,144 +0,0 @@
-#![warn(clippy::manual_split_once)]
-#![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)]
-
-extern crate itertools;
-
-#[allow(unused_imports)]
-use itertools::Itertools;
-
-fn main() {
-    let _ = "key=value".splitn(2, '=').nth(2);
-    let _ = "key=value".split_once('=').unwrap().1;
-    let _ = "key=value".split_once('=').unwrap().1;
-    let (_, _) = "key=value".split_once('=').unwrap();
-
-    let s = String::from("key=value");
-    let _ = s.split_once('=').unwrap().1;
-
-    let s = Box::<str>::from("key=value");
-    let _ = s.split_once('=').unwrap().1;
-
-    let s = &"key=value";
-    let _ = s.split_once('=').unwrap().1;
-
-    fn _f(s: &str) -> Option<&str> {
-        let _ = s.split_once('=')?.1;
-        let _ = s.split_once('=')?.1;
-        let _ = s.rsplit_once('=')?.0;
-        let _ = s.rsplit_once('=')?.0;
-        None
-    }
-
-    // Don't lint, slices don't have `split_once`
-    let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
-
-    // `rsplitn` gives the results in the reverse order of `rsplit_once`
-    let _ = "key=value".rsplit_once('=').unwrap().0;
-    let (_, _) = "key=value".rsplit_once('=').map(|(x, y)| (y, x)).unwrap();
-    let _ = s.rsplit_once('=').map(|x| x.0);
-}
-
-fn indirect() -> Option<()> {
-    let (l, r) = "a.b.c".split_once('.').unwrap();
-    
-    
-
-    let (l, r) = "a.b.c".split_once('.')?;
-    
-    
-
-    let (l, r) = "a.b.c".rsplit_once('.').unwrap();
-    
-    
-
-    let (l, r) = "a.b.c".rsplit_once('.')?;
-    
-    
-
-    // could lint, currently doesn't
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let other = 1;
-    let l = iter.next()?;
-    let r = iter.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let mut mut_binding = iter.next()?;
-    let r = iter.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let tuple = (iter.next()?, iter.next()?);
-
-    // should not lint
-
-    let mut missing_unwrap = "a.b.c".splitn(2, '.');
-    let l = missing_unwrap.next();
-    let r = missing_unwrap.next();
-
-    let mut mixed_unrap = "a.b.c".splitn(2, '.');
-    let unwrap = mixed_unrap.next().unwrap();
-    let question_mark = mixed_unrap.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let same_name = iter.next()?;
-    let same_name = iter.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let shadows_existing = "d";
-    let shadows_existing = iter.next()?;
-    let r = iter.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let becomes_shadowed = iter.next()?;
-    let becomes_shadowed = "d";
-    let r = iter.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let l = iter.next()?;
-    let r = iter.next()?;
-    let third_usage = iter.next()?;
-
-    let mut n_three = "a.b.c".splitn(3, '.');
-    let l = n_three.next()?;
-    let r = n_three.next()?;
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    {
-        let in_block = iter.next()?;
-    }
-    let r = iter.next()?;
-
-    let mut lacks_binding = "a.b.c".splitn(2, '.');
-    let _ = lacks_binding.next()?;
-    let r = lacks_binding.next()?;
-
-    let mut mapped = "a.b.c".splitn(2, '.').map(|_| "~");
-    let l = iter.next()?;
-    let r = iter.next()?;
-
-    let mut assigned = "";
-    let mut iter = "a.b.c".splitn(2, '.');
-    let l = iter.next()?;
-    assigned = iter.next()?;
-
-    None
-}
-
-#[clippy::msrv = "1.51"]
-fn _msrv_1_51() {
-    // `str::split_once` was stabilized in 1.52. Do not lint this
-    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
-
-    let mut iter = "a.b.c".splitn(2, '.');
-    let a = iter.next().unwrap();
-    let b = iter.next().unwrap();
-}
-
-#[clippy::msrv = "1.52"]
-fn _msrv_1_52() {
-    let _ = "key=value".split_once('=').unwrap().1;
-
-    let (a, b) = "a.b.c".split_once('.').unwrap();
-    
-    
-}
diff --git a/src/tools/clippy/tests/ui/manual_split_once.rs b/src/tools/clippy/tests/ui/manual_split_once.rs
index 113e1737c97..e13c827468b 100644
--- a/src/tools/clippy/tests/ui/manual_split_once.rs
+++ b/src/tools/clippy/tests/ui/manual_split_once.rs
@@ -1,6 +1,8 @@
 #![warn(clippy::manual_split_once)]
 #![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 extern crate itertools;
 
 #[allow(unused_imports)]
diff --git a/src/tools/clippy/tests/ui/manual_split_once.stderr b/src/tools/clippy/tests/ui/manual_split_once.stderr
index c5c9be3ac63..566204ad876 100644
--- a/src/tools/clippy/tests/ui/manual_split_once.stderr
+++ b/src/tools/clippy/tests/ui/manual_split_once.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:11:13
+  --> tests/ui/manual_split_once.rs:13:13
    |
 LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1`
@@ -8,79 +8,79 @@ LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
    = help: to override `-D warnings` add `#[allow(clippy::manual_split_once)]`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:12:13
+  --> tests/ui/manual_split_once.rs:14:13
    |
 LL |     let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:13:18
+  --> tests/ui/manual_split_once.rs:15:18
    |
 LL |     let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=')`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:16:13
+  --> tests/ui/manual_split_once.rs:18:13
    |
 LL |     let _ = s.splitn(2, '=').nth(1).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:19:13
+  --> tests/ui/manual_split_once.rs:21:13
    |
 LL |     let _ = s.splitn(2, '=').nth(1).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:22:13
+  --> tests/ui/manual_split_once.rs:24:13
    |
 LL |     let _ = s.splitn(2, '=').skip(1).next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=').unwrap().1`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:25:17
+  --> tests/ui/manual_split_once.rs:27:17
    |
 LL |         let _ = s.splitn(2, '=').nth(1)?;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:26:17
+  --> tests/ui/manual_split_once.rs:28:17
    |
 LL |         let _ = s.splitn(2, '=').skip(1).next()?;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.split_once('=')?.1`
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:27:17
+  --> tests/ui/manual_split_once.rs:29:17
    |
 LL |         let _ = s.rsplitn(2, '=').nth(1)?;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0`
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:28:17
+  --> tests/ui/manual_split_once.rs:30:17
    |
 LL |         let _ = s.rsplitn(2, '=').skip(1).next()?;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=')?.0`
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:36:13
+  --> tests/ui/manual_split_once.rs:38:13
    |
 LL |     let _ = "key=value".rsplitn(2, '=').nth(1).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').unwrap().0`
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:37:18
+  --> tests/ui/manual_split_once.rs:39:18
    |
 LL |     let (_, _) = "key=value".rsplitn(2, '=').next_tuple().unwrap();
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".rsplit_once('=').map(|(x, y)| (y, x))`
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:38:13
+  --> tests/ui/manual_split_once.rs:40:13
    |
 LL |     let _ = s.rsplitn(2, '=').nth(1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.rsplit_once('=').map(|x| x.0)`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:42:5
+  --> tests/ui/manual_split_once.rs:44:5
    |
 LL |     let mut iter = "a.b.c".splitn(2, '.');
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -103,7 +103,7 @@ LL -     let r = iter.next().unwrap();
    |
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:46:5
+  --> tests/ui/manual_split_once.rs:48:5
    |
 LL |     let mut iter = "a.b.c".splitn(2, '.');
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -126,7 +126,7 @@ LL -     let r = iter.next()?;
    |
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:50:5
+  --> tests/ui/manual_split_once.rs:52:5
    |
 LL |     let mut iter = "a.b.c".rsplitn(2, '.');
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,7 +149,7 @@ LL -     let l = iter.next().unwrap();
    |
 
 error: manual implementation of `rsplit_once`
-  --> tests/ui/manual_split_once.rs:54:5
+  --> tests/ui/manual_split_once.rs:56:5
    |
 LL |     let mut iter = "a.b.c".rsplitn(2, '.');
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -172,13 +172,13 @@ LL -     let l = iter.next()?;
    |
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:139:13
+  --> tests/ui/manual_split_once.rs:141:13
    |
 LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"key=value".split_once('=').unwrap().1`
 
 error: manual implementation of `split_once`
-  --> tests/ui/manual_split_once.rs:141:5
+  --> tests/ui/manual_split_once.rs:143:5
    |
 LL |     let mut iter = "a.b.c".splitn(2, '.');
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
index 74afa00e12f..07e4bdd483a 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
@@ -234,4 +234,20 @@ fn implicit_deref_ref() {
     };
 }
 
+mod issue_13018 {
+    use std::collections::HashMap;
+
+    type RefName = i32;
+    pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
+        if let Some(names) = index.get(&id) { names } else { &[] }
+    }
+
+    pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
+        match index.get(&id) {
+            Some(names) => names,
+            None => &[],
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
index 2d01b8ceaaa..cdbe51a4121 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
@@ -284,4 +284,20 @@ fn implicit_deref_ref() {
     };
 }
 
+mod issue_13018 {
+    use std::collections::HashMap;
+
+    type RefName = i32;
+    pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
+        if let Some(names) = index.get(&id) { names } else { &[] }
+    }
+
+    pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
+        match index.get(&id) {
+            Some(names) => names,
+            None => &[],
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.fixed b/src/tools/clippy/tests/ui/match_same_arms2.fixed
deleted file mode 100644
index 09e960ddd6a..00000000000
--- a/src/tools/clippy/tests/ui/match_same_arms2.fixed
+++ /dev/null
@@ -1,258 +0,0 @@
-#![warn(clippy::match_same_arms)]
-#![allow(
-    clippy::disallowed_names,
-    clippy::diverging_sub_expression,
-    clippy::uninlined_format_args,
-    clippy::match_single_binding,
-    clippy::match_like_matches_macro
-)]
-fn bar<T>(_: T) {}
-fn foo() -> bool {
-    unimplemented!()
-}
-
-fn match_same_arms() {
-    let _ = match 42 {
-        _ => {
-            foo();
-            let mut a = 42 + [23].len() as i32;
-            if true {
-                a += 7;
-            }
-            a = -31 - a;
-            a
-        },
-    };
-    //~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm
-
-    let _ = match 42 {
-        51 | 42 => foo(), //~ ERROR: this match arm has an identical body to another arm
-        _ => true,
-    };
-
-    let _ = match Some(42) {
-        None | Some(_) => 24, //~ ERROR: this match arm has an identical body to another arm
-    };
-
-    let _ = match Some(42) {
-        Some(foo) => 24,
-        None => 24,
-    };
-
-    let _ = match Some(42) {
-        Some(42) => 24,
-        Some(a) => 24, // bindings are different
-        None => 0,
-    };
-
-    let _ = match Some(42) {
-        Some(a) if a > 0 => 24,
-        Some(a) => 24, // one arm has a guard
-        None => 0,
-    };
-
-    match (Some(42), Some(42)) {
-        (None, Some(a)) | (Some(a), None) => bar(a), //~ ERROR: this match arm has an identical body to another arm
-        _ => (),
-    }
-
-    // No warning because guards are different
-    let _ = match Some(42) {
-        Some(a) if a == 42 => a,
-        Some(a) if a == 24 => a,
-        Some(_) => 24,
-        None => 0,
-    };
-
-    let _ = match (Some(42), Some(42)) {
-        (None, Some(a)) | (Some(a), None) if a == 42 => a, //~ ERROR: this match arm has an identical body to another arm
-        _ => 0,
-    };
-
-    match (Some(42), Some(42)) {
-        (Some(a), ..) | (.., Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm
-        _ => (),
-    }
-
-    let _ = match Some(()) {
-        Some(()) => 0.0,
-        None => -0.0,
-    };
-
-    match (Some(42), Some("")) {
-        (Some(a), None) => bar(a),
-        (None, Some(a)) => bar(a), // bindings have different types
-        _ => (),
-    }
-
-    let x: Result<i32, &str> = Ok(3);
-
-    // No warning because of the guard.
-    match x {
-        Ok(x) if x * x == 64 => println!("ok"),
-        Ok(_) => println!("ok"),
-        Err(_) => println!("err"),
-    }
-
-    // This used to be a false positive; see issue #1996.
-    match x {
-        Ok(3) => println!("ok"),
-        Ok(x) if x * x == 64 => println!("ok 64"),
-        Ok(_) => println!("ok"),
-        Err(_) => println!("err"),
-    }
-
-    match (x, Some(1i32)) {
-        (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm
-        _ => println!("err"),
-    }
-
-    // No warning; different types for `x`.
-    match (x, Some(1.0f64)) {
-        (Ok(x), Some(_)) => println!("ok {}", x),
-        (Ok(_), Some(x)) => println!("ok {}", x),
-        _ => println!("err"),
-    }
-
-    // False negative #2251.
-    match x {
-        Ok(_tmp) => println!("ok"),
-        Ok(_) | Ok(3) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm
-        Err(_) => {
-            unreachable!();
-        },
-    }
-
-    // False positive #1390
-    macro_rules! empty {
-        ($e:expr) => {};
-    }
-    match 0 {
-        0 => {
-            empty!(0);
-        },
-        1 => {
-            empty!(1);
-        },
-        x => {
-            empty!(x);
-        },
-    };
-
-    // still lint if the tokens are the same
-    match 0 {
-        1 | 0 => {
-            empty!(0);
-        },
-        x => {
-            empty!(x);
-        },
-    }
-    //~^^^^^^^ ERROR: this match arm has an identical body to another arm
-
-    match_expr_like_matches_macro_priority();
-}
-
-fn match_expr_like_matches_macro_priority() {
-    enum E {
-        A,
-        B,
-        C,
-    }
-    let x = E::A;
-    let _ans = match x {
-        E::A => false,
-        E::B => false,
-        _ => true,
-    };
-}
-
-fn main() {
-    let _ = match Some(0) {
-        Some(0) => 0,
-        Some(1) => 1,
-        #[cfg(feature = "foo")]
-        Some(2) => 2,
-        _ => 1,
-    };
-
-    enum Foo {
-        X(u32),
-        Y(u32),
-        Z(u32),
-    }
-
-    // Don't lint. `Foo::X(0)` and `Foo::Z(_)` overlap with the arm in between.
-    let _ = match Foo::X(0) {
-        Foo::X(0) => 1,
-        Foo::X(_) | Foo::Y(_) | Foo::Z(0) => 2,
-        Foo::Z(_) => 1,
-        _ => 0,
-    };
-
-    // Suggest moving `Foo::Z(_)` up.
-    let _ = match Foo::X(0) {
-        Foo::X(0) | Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm
-        Foo::X(_) | Foo::Y(_) => 2,
-        _ => 0,
-    };
-
-    // Suggest moving `Foo::X(0)` down.
-    let _ = match Foo::X(0) {
-        Foo::Y(_) | Foo::Z(0) => 2,
-        Foo::Z(_) | Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm
-        _ => 0,
-    };
-
-    // Don't lint.
-    let _ = match 0 {
-        -2 => 1,
-        -5..=50 => 2,
-        -150..=88 => 1,
-        _ => 3,
-    };
-
-    struct Bar {
-        x: u32,
-        y: u32,
-        z: u32,
-    }
-
-    // Lint.
-    let _ = match None {
-        Some(Bar { y: 10, z: 0, .. }) => 2,
-        None => 50,
-        Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm
-        _ => 200,
-    };
-
-    let _ = match 0 {
-        0 => todo!(),
-        1 => todo!(),
-        2 => core::convert::identity::<u32>(todo!()),
-        3 => core::convert::identity::<u32>(todo!()),
-        _ => 5,
-    };
-
-    let _ = match 0 {
-        1 | 0 => cfg!(not_enable),
-        _ => false,
-    };
-}
-
-// issue #8919, fixed on https://github.com/rust-lang/rust/pull/97312
-mod with_lifetime {
-    enum MaybeStaticStr<'a> {
-        Static(&'static str),
-        Borrowed(&'a str),
-    }
-
-    impl<'a> MaybeStaticStr<'a> {
-        fn get(&self) -> &'a str {
-            match *self {
-                MaybeStaticStr::Borrowed(s) | MaybeStaticStr::Static(s) => s,
-                //~^ ERROR: this match arm has an identical body to another arm
-            }
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index cc7425135cc..dedd02e7873 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -6,6 +6,9 @@
     clippy::match_single_binding,
     clippy::match_like_matches_macro
 )]
+
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 fn bar<T>(_: T) {}
 fn foo() -> bool {
     unimplemented!()
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index a5d137c658b..3a28b5afc2b 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -1,5 +1,5 @@
 error: this match arm has an identical body to the `_` wildcard arm
-  --> tests/ui/match_same_arms2.rs:16:9
+  --> tests/ui/match_same_arms2.rs:19:9
    |
 LL | /         42 => {
 LL | |             foo();
@@ -12,7 +12,7 @@ LL | |         _ => {
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> tests/ui/match_same_arms2.rs:25:9
+  --> tests/ui/match_same_arms2.rs:28:9
    |
 LL | /         _ => {
 LL | |             foo();
@@ -26,7 +26,7 @@ LL | |         },
    = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:39:9
+  --> tests/ui/match_same_arms2.rs:42:9
    |
 LL |         51 => foo(),
    |         ^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL -         42 => foo(),
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:45:9
+  --> tests/ui/match_same_arms2.rs:48:9
    |
 LL |         None => 24,
    |         ^^^^^^^^^^
@@ -58,7 +58,7 @@ LL -         Some(_) => 24,
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:67:9
+  --> tests/ui/match_same_arms2.rs:70:9
    |
 LL |         (None, Some(a)) => bar(a),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,7 +74,7 @@ LL -         (Some(a), None) => bar(a),
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:81:9
+  --> tests/ui/match_same_arms2.rs:84:9
    |
 LL |         (None, Some(a)) if a == 42 => a,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL -         (Some(a), None) if a == 42 => a,
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:86:9
+  --> tests/ui/match_same_arms2.rs:89:9
    |
 LL |         (Some(a), ..) => bar(a),
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL -         (.., Some(a)) => bar(a),
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:120:9
+  --> tests/ui/match_same_arms2.rs:123:9
    |
 LL |         (Ok(x), Some(_)) => println!("ok {}", x),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -122,7 +122,7 @@ LL -         (Ok(_), Some(x)) => println!("ok {}", x),
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:136:9
+  --> tests/ui/match_same_arms2.rs:139:9
    |
 LL |         Ok(_) => println!("ok"),
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,7 +138,7 @@ LL -         Ok(3) => println!("ok"),
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:163:9
+  --> tests/ui/match_same_arms2.rs:166:9
    |
 LL | /         1 => {
 LL | |             empty!(0);
@@ -158,7 +158,7 @@ LL -         },
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:214:9
+  --> tests/ui/match_same_arms2.rs:217:9
    |
 LL |         Foo::X(0) => 1,
    |         ^^^^^^^^^^^^^^
@@ -174,7 +174,7 @@ LL -         Foo::Z(_) => 1,
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:224:9
+  --> tests/ui/match_same_arms2.rs:227:9
    |
 LL |         Foo::Z(_) => 1,
    |         ^^^^^^^^^^^^^^
@@ -190,7 +190,7 @@ LL -         Foo::X(0) => 1,
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:247:9
+  --> tests/ui/match_same_arms2.rs:250:9
    |
 LL |         Some(Bar { y: 0, x: 5, .. }) => 1,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,7 +206,7 @@ LL -         Some(Bar { x: 0, y: 5, .. }) => 1,
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:261:9
+  --> tests/ui/match_same_arms2.rs:264:9
    |
 LL |         1 => cfg!(not_enable),
    |         ^^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +222,7 @@ LL -         0 => cfg!(not_enable),
    |
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:277:17
+  --> tests/ui/match_same_arms2.rs:280:17
    |
 LL |                 MaybeStaticStr::Borrowed(s) => s,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr
index 7fbd8462fdc..3dd5c9561fd 100644
--- a/src/tools/clippy/tests/ui/min_ident_chars.stderr
+++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr
@@ -193,11 +193,5 @@ error: this ident consists of a single char
 LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
    |                             ^
 
-error: this ident consists of a single char
-  --> tests/ui/min_ident_chars.rs:93:41
-   |
-LL |     struct Array<T, const N: usize>([T; N]);
-   |                                         ^
-
-error: aborting due to 33 previous errors
+error: aborting due to 32 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
index dbd739eee13..f54503ada97 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -200,7 +200,7 @@ mod with_ty_alias {
     }
     // NOTE: When checking the type of a function param, make sure it is not an alias with
     // `AliasTyKind::Projection` before calling `TyCtxt::type_of` to find out what the actual type
-    // is. Because the associate ty could have no default, therefore would cause ICE, as demostrated
+    // is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated
     // in this test.
     const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
 }
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
index 4ac56f4c803..2c229068e4d 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -200,7 +200,7 @@ mod with_ty_alias {
     }
     // NOTE: When checking the type of a function param, make sure it is not an alias with
     // `AliasTyKind::Projection` before calling `TyCtxt::type_of` to find out what the actual type
-    // is. Because the associate ty could have no default, therefore would cause ICE, as demostrated
+    // is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated
     // in this test.
     fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
 }
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
index 58f56eba0f5..84eaf12fc13 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
@@ -52,3 +52,21 @@ struct S<'a> {
 fn from_field<'a>(s: &'a mut S<'a>) -> Option<&'a mut usize> {
     s.opt.as_deref_mut()
 }
+
+mod issue_non_copy_13077 {
+    pub fn something(mut maybe_side_effect: Option<&mut String>) {
+        for _ in 0..10 {
+            let _ = S {
+                field: other(maybe_side_effect.as_deref_mut()),
+            };
+        }
+    }
+
+    fn other(_maybe_side_effect: Option<&mut String>) {
+        unimplemented!()
+    }
+
+    pub struct S {
+        pub field: (),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.rs b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
index 842e025f669..fff1e45d846 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.rs
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
@@ -52,3 +52,21 @@ struct S<'a> {
 fn from_field<'a>(s: &'a mut S<'a>) -> Option<&'a mut usize> {
     s.opt.as_deref_mut()
 }
+
+mod issue_non_copy_13077 {
+    pub fn something(mut maybe_side_effect: Option<&mut String>) {
+        for _ in 0..10 {
+            let _ = S {
+                field: other(maybe_side_effect.as_deref_mut()),
+            };
+        }
+    }
+
+    fn other(_maybe_side_effect: Option<&mut String>) {
+        unimplemented!()
+    }
+
+    pub struct S {
+        pub field: (),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index c76f7a81843..7452eb77688 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -318,4 +318,51 @@ fn host_effect() {
     Add::<i32>::add(1, 1).add(i32::MIN);
 }
 
+mod issue_10228 {
+    struct Entry;
+
+    impl Entry {
+        fn or_insert(self, _default: i32) {}
+        fn or_default(self) {
+            // Don't lint, suggested code is an infinite recursion
+            self.or_insert(Default::default())
+        }
+    }
+}
+
+// issue #12973
+fn fn_call_in_nested_expr() {
+    struct Foo {
+        val: String,
+    }
+
+    fn f() -> i32 {
+        1
+    }
+    let opt: Option<i32> = Some(1);
+
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt.unwrap_or_else(f); // suggest `.unwrap_or_else(f)`
+    //
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt.unwrap_or_else(|| f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
+    //
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt.unwrap_or_else(|| {
+        let x = f();
+        x + 1
+    });
+    //~v ERROR: use of `map_or` followed by a function call
+    let _ = opt.map_or_else(|| f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
+    //
+    //~v ERROR: use of `unwrap_or` to construct default value
+    let _ = opt.unwrap_or_default();
+
+    let opt_foo = Some(Foo {
+        val: String::from("123"),
+    });
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt_foo.unwrap_or_else(|| Foo { val: String::default() });
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index 97cf496d3ac..cd6f7bb2070 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -318,4 +318,51 @@ fn host_effect() {
     Add::<i32>::add(1, 1).add(i32::MIN);
 }
 
+mod issue_10228 {
+    struct Entry;
+
+    impl Entry {
+        fn or_insert(self, _default: i32) {}
+        fn or_default(self) {
+            // Don't lint, suggested code is an infinite recursion
+            self.or_insert(Default::default())
+        }
+    }
+}
+
+// issue #12973
+fn fn_call_in_nested_expr() {
+    struct Foo {
+        val: String,
+    }
+
+    fn f() -> i32 {
+        1
+    }
+    let opt: Option<i32> = Some(1);
+
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
+    //
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
+    //
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt.unwrap_or({
+        let x = f();
+        x + 1
+    });
+    //~v ERROR: use of `map_or` followed by a function call
+    let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
+    //
+    //~v ERROR: use of `unwrap_or` to construct default value
+    let _ = opt.unwrap_or({ i32::default() });
+
+    let opt_foo = Some(Foo {
+        val: String::from("123"),
+    });
+    //~v ERROR: use of `unwrap_or` followed by a function call
+    let _ = opt_foo.unwrap_or(Foo { val: String::default() });
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index 3070db22fc5..06f804fb41e 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -196,5 +196,53 @@ error: use of `unwrap_or_else` to construct default value
 LL |         let _ = stringy.unwrap_or_else(String::new);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
-error: aborting due to 32 previous errors
+error: use of `unwrap_or` followed by a function call
+  --> tests/ui/or_fun_call.rs:345:17
+   |
+LL |     let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
+   |                 ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)`
+
+error: use of `unwrap_or` followed by a function call
+  --> tests/ui/or_fun_call.rs:348:17
+   |
+LL |     let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
+   |                 ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)`
+
+error: use of `unwrap_or` followed by a function call
+  --> tests/ui/or_fun_call.rs:351:17
+   |
+LL |       let _ = opt.unwrap_or({
+   |  _________________^
+LL | |         let x = f();
+LL | |         x + 1
+LL | |     });
+   | |______^
+   |
+help: try
+   |
+LL ~     let _ = opt.unwrap_or_else(|| {
+LL +         let x = f();
+LL +         x + 1
+LL ~     });
+   |
+
+error: use of `map_or` followed by a function call
+  --> tests/ui/or_fun_call.rs:356:17
+   |
+LL |     let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)`
+
+error: use of `unwrap_or` to construct default value
+  --> tests/ui/or_fun_call.rs:359:17
+   |
+LL |     let _ = opt.unwrap_or({ i32::default() });
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
+
+error: use of `unwrap_or` followed by a function call
+  --> tests/ui/or_fun_call.rs:365:21
+   |
+LL |     let _ = opt_foo.unwrap_or(Foo { val: String::default() });
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })`
+
+error: aborting due to 38 previous errors
 
diff --git a/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed b/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed
index 86e3e5bbdaf..1a46d72378f 100644
--- a/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed
+++ b/src/tools/clippy/tests/ui/path_buf_push_overwrite.fixed
@@ -1,6 +1,7 @@
 use std::path::PathBuf;
 
-#[warn(clippy::all, clippy::path_buf_push_overwrite)]
+#[warn(clippy::path_buf_push_overwrite)]
+#[allow(clippy::pathbuf_init_then_push)]
 fn main() {
     let mut x = PathBuf::from("/foo");
     x.push("bar");
diff --git a/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs b/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs
index 460cc254e94..3e3f84b17a4 100644
--- a/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/tests/ui/path_buf_push_overwrite.rs
@@ -1,6 +1,7 @@
 use std::path::PathBuf;
 
-#[warn(clippy::all, clippy::path_buf_push_overwrite)]
+#[warn(clippy::path_buf_push_overwrite)]
+#[allow(clippy::pathbuf_init_then_push)]
 fn main() {
     let mut x = PathBuf::from("/foo");
     x.push("/bar");
diff --git a/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr b/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr
index c9f36ecf48f..48334235d11 100644
--- a/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr
+++ b/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr
@@ -1,5 +1,5 @@
 error: calling `push` with '/' or '\' (file system root) will overwrite the previous path definition
-  --> tests/ui/path_buf_push_overwrite.rs:6:12
+  --> tests/ui/path_buf_push_overwrite.rs:7:12
    |
 LL |     x.push("/bar");
    |            ^^^^^^ help: try: `"bar"`
diff --git a/src/tools/clippy/tests/ui/pathbuf_init_then_push.fixed b/src/tools/clippy/tests/ui/pathbuf_init_then_push.fixed
new file mode 100644
index 00000000000..2a90b8ce281
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pathbuf_init_then_push.fixed
@@ -0,0 +1,22 @@
+#![warn(clippy::pathbuf_init_then_push)]
+
+use std::path::PathBuf;
+
+fn main() {
+    let mut path_buf = PathBuf::from("foo");
+
+    path_buf = PathBuf::from("foo").join("bar");
+
+    let bar = "bar";
+    path_buf = PathBuf::from("foo").join(bar);
+
+    let mut path_buf = PathBuf::from("foo").join("bar").join("buz");
+
+    let mut x = PathBuf::new();
+    println!("{}", x.display());
+    x.push("Duck");
+
+    let mut path_buf = PathBuf::new();
+    #[cfg(cats)]
+    path_buf.push("foo");
+}
diff --git a/src/tools/clippy/tests/ui/pathbuf_init_then_push.rs b/src/tools/clippy/tests/ui/pathbuf_init_then_push.rs
new file mode 100644
index 00000000000..4a7ae00a735
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pathbuf_init_then_push.rs
@@ -0,0 +1,26 @@
+#![warn(clippy::pathbuf_init_then_push)]
+
+use std::path::PathBuf;
+
+fn main() {
+    let mut path_buf = PathBuf::new(); //~ ERROR: calls to `push` immediately after creation
+    path_buf.push("foo");
+
+    path_buf = PathBuf::from("foo"); //~ ERROR: calls to `push` immediately after creation
+    path_buf.push("bar");
+
+    let bar = "bar";
+    path_buf = PathBuf::from("foo"); //~ ERROR: calls to `push` immediately after creation
+    path_buf.push(bar);
+
+    let mut path_buf = PathBuf::from("foo").join("bar"); //~ ERROR: calls to `push` immediately after creation
+    path_buf.push("buz");
+
+    let mut x = PathBuf::new();
+    println!("{}", x.display());
+    x.push("Duck");
+
+    let mut path_buf = PathBuf::new();
+    #[cfg(cats)]
+    path_buf.push("foo");
+}
diff --git a/src/tools/clippy/tests/ui/pathbuf_init_then_push.stderr b/src/tools/clippy/tests/ui/pathbuf_init_then_push.stderr
new file mode 100644
index 00000000000..e7aa291035d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pathbuf_init_then_push.stderr
@@ -0,0 +1,33 @@
+error: calls to `push` immediately after creation
+  --> tests/ui/pathbuf_init_then_push.rs:6:5
+   |
+LL | /     let mut path_buf = PathBuf::new();
+LL | |     path_buf.push("foo");
+   | |_________________________^ help: consider using the `.join()`: `let mut path_buf = PathBuf::from("foo");`
+   |
+   = note: `-D clippy::pathbuf-init-then-push` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::pathbuf_init_then_push)]`
+
+error: calls to `push` immediately after creation
+  --> tests/ui/pathbuf_init_then_push.rs:9:5
+   |
+LL | /     path_buf = PathBuf::from("foo");
+LL | |     path_buf.push("bar");
+   | |_________________________^ help: consider using the `.join()`: `path_buf = PathBuf::from("foo").join("bar");`
+
+error: calls to `push` immediately after creation
+  --> tests/ui/pathbuf_init_then_push.rs:13:5
+   |
+LL | /     path_buf = PathBuf::from("foo");
+LL | |     path_buf.push(bar);
+   | |_______________________^ help: consider using the `.join()`: `path_buf = PathBuf::from("foo").join(bar);`
+
+error: calls to `push` immediately after creation
+  --> tests/ui/pathbuf_init_then_push.rs:16:5
+   |
+LL | /     let mut path_buf = PathBuf::from("foo").join("bar");
+LL | |     path_buf.push("buz");
+   | |_________________________^ help: consider using the `.join()`: `let mut path_buf = PathBuf::from("foo").join("bar").join("buz");`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
index 33c0725faad..21ac42196e1 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
@@ -46,6 +46,10 @@ fn main() {
     let _ = external!($ptr as *const u32);
 }
 
+fn lifetime_to_static(v: *mut &()) -> *const &'static () {
+    v as _
+}
+
 #[clippy::msrv = "1.64"]
 fn _msrv_1_64() {
     let ptr: *const u32 = &42_u32;
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.rs b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
index 24d959856db..5ce590b2b7e 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.rs
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
@@ -46,6 +46,10 @@ fn main() {
     let _ = external!($ptr as *const u32);
 }
 
+fn lifetime_to_static(v: *mut &()) -> *const &'static () {
+    v as _
+}
+
 #[clippy::msrv = "1.64"]
 fn _msrv_1_64() {
     let ptr: *const u32 = &42_u32;
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
index 322c3585e62..2c52ebd3464 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
@@ -32,13 +32,13 @@ LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:64:13
+  --> tests/ui/ptr_cast_constness.rs:68:13
    |
 LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:65:13
+  --> tests/ui/ptr_cast_constness.rs:69:13
    |
 LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index 1f79b5e5360..1d04cca9b9e 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -3,6 +3,7 @@
 #![allow(
     clippy::drop_non_drop,
     clippy::implicit_clone,
+    clippy::pathbuf_init_then_push,
     clippy::uninlined_format_args,
     clippy::unnecessary_literal_unwrap
 )]
diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs
index 6909faebc99..738744fec98 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.rs
+++ b/src/tools/clippy/tests/ui/redundant_clone.rs
@@ -3,6 +3,7 @@
 #![allow(
     clippy::drop_non_drop,
     clippy::implicit_clone,
+    clippy::pathbuf_init_then_push,
     clippy::uninlined_format_args,
     clippy::unnecessary_literal_unwrap
 )]
diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr
index d66972bcb5b..3c37288f550 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.stderr
+++ b/src/tools/clippy/tests/ui/redundant_clone.stderr
@@ -1,11 +1,11 @@
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:14:42
+  --> tests/ui/redundant_clone.rs:15:42
    |
 LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
    |                                          ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:14:14
+  --> tests/ui/redundant_clone.rs:15:14
    |
 LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,169 +13,169 @@ LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
    = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]`
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:17:15
+  --> tests/ui/redundant_clone.rs:18:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:17:14
+  --> tests/ui/redundant_clone.rs:18:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:20:15
+  --> tests/ui/redundant_clone.rs:21:15
    |
 LL |     let _s = s.to_string();
    |               ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:20:14
+  --> tests/ui/redundant_clone.rs:21:14
    |
 LL |     let _s = s.to_string();
    |              ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:23:15
+  --> tests/ui/redundant_clone.rs:24:15
    |
 LL |     let _s = s.to_owned();
    |               ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:23:14
+  --> tests/ui/redundant_clone.rs:24:14
    |
 LL |     let _s = s.to_owned();
    |              ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:25:42
+  --> tests/ui/redundant_clone.rs:26:42
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_owned();
    |                                          ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:25:14
+  --> tests/ui/redundant_clone.rs:26:14
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_owned();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:27:42
+  --> tests/ui/redundant_clone.rs:28:42
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_path_buf();
    |                                          ^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:27:14
+  --> tests/ui/redundant_clone.rs:28:14
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_path_buf();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:29:29
+  --> tests/ui/redundant_clone.rs:30:29
    |
 LL |     let _s = OsString::new().to_owned();
    |                             ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:29:14
+  --> tests/ui/redundant_clone.rs:30:14
    |
 LL |     let _s = OsString::new().to_owned();
    |              ^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:31:29
+  --> tests/ui/redundant_clone.rs:32:29
    |
 LL |     let _s = OsString::new().to_os_string();
    |                             ^^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:31:14
+  --> tests/ui/redundant_clone.rs:32:14
    |
 LL |     let _s = OsString::new().to_os_string();
    |              ^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:42:19
+  --> tests/ui/redundant_clone.rs:43:19
    |
 LL |     let _t = tup.0.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:42:14
+  --> tests/ui/redundant_clone.rs:43:14
    |
 LL |     let _t = tup.0.clone();
    |              ^^^^^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:74:25
+  --> tests/ui/redundant_clone.rs:75:25
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                         ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:74:24
+  --> tests/ui/redundant_clone.rs:75:24
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                        ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:131:15
+  --> tests/ui/redundant_clone.rs:132:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:131:14
+  --> tests/ui/redundant_clone.rs:132:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:132:15
+  --> tests/ui/redundant_clone.rs:133:15
    |
 LL |     let _t = t.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:132:14
+  --> tests/ui/redundant_clone.rs:133:14
    |
 LL |     let _t = t.clone();
    |              ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:142:19
+  --> tests/ui/redundant_clone.rs:143:19
    |
 LL |         let _f = f.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:142:18
+  --> tests/ui/redundant_clone.rs:143:18
    |
 LL |         let _f = f.clone();
    |                  ^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:154:14
+  --> tests/ui/redundant_clone.rs:155:14
    |
 LL |     let y = x.clone().join("matthias");
    |              ^^^^^^^^ help: remove this
    |
 note: cloned value is neither consumed nor mutated
-  --> tests/ui/redundant_clone.rs:154:13
+  --> tests/ui/redundant_clone.rs:155:13
    |
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/redundant_clone.rs:208:11
+  --> tests/ui/redundant_clone.rs:209:11
    |
 LL |     foo(&x.clone(), move || {
    |           ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/redundant_clone.rs:208:10
+  --> tests/ui/redundant_clone.rs:209:10
    |
 LL |     foo(&x.clone(), move || {
    |          ^
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
deleted file mode 100644
index ed05f6e0c8d..00000000000
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
+++ /dev/null
@@ -1,144 +0,0 @@
-#![warn(clippy::significant_drop_tightening)]
-
-use std::sync::Mutex;
-
-pub fn complex_return_triggers_the_lint() -> i32 {
-    fn foo() -> i32 {
-        1
-    }
-    let mutex = Mutex::new(1);
-    let lock = mutex.lock().unwrap();
-    let _ = *lock;
-    let _ = *lock;
-    drop(lock);
-    foo()
-}
-
-pub fn issue_10413() {
-    let mutex = Mutex::new(Some(1));
-    let opt = Some(1);
-    if opt.is_some() {
-        let lock = mutex.lock().unwrap();
-        let _ = *lock;
-        if opt.is_some() {
-            let _ = *lock;
-        }
-    }
-}
-
-pub fn issue_11128() {
-    use std::mem::drop as unlock;
-
-    struct Foo {
-        droppable: Option<Vec<i32>>,
-        mutex: Mutex<Vec<i32>>,
-    }
-
-    impl Drop for Foo {
-        fn drop(&mut self) {
-            if let Some(droppable) = self.droppable.take() {
-                let lock = self.mutex.lock().unwrap();
-                let idx_opt = lock.iter().copied().find(|el| Some(el) == droppable.first());
-                if let Some(idx) = idx_opt {
-                    let local_droppable = vec![lock.first().copied().unwrap_or_default()];
-                    unlock(lock);
-                    drop(local_droppable);
-                }
-            }
-        }
-    }
-}
-
-pub fn issue_11160() -> bool {
-    let mutex = Mutex::new(1i32);
-    let lock = mutex.lock().unwrap();
-    let _ = lock.abs();
-    true
-}
-
-pub fn issue_11189() {
-    struct Number {
-        pub value: u32,
-    }
-
-    fn do_something() -> Result<(), ()> {
-        let number = Mutex::new(Number { value: 1 });
-        let number2 = Mutex::new(Number { value: 2 });
-        let number3 = Mutex::new(Number { value: 3 });
-        let mut lock = number.lock().unwrap();
-        let mut lock2 = number2.lock().unwrap();
-        let mut lock3 = number3.lock().unwrap();
-        lock.value += 1;
-        lock2.value += 1;
-        lock3.value += 1;
-        drop((lock, lock2, lock3));
-        Ok(())
-    }
-}
-
-pub fn path_return_can_be_ignored() -> i32 {
-    let mutex = Mutex::new(1);
-    let lock = mutex.lock().unwrap();
-    let rslt = *lock;
-    let _ = *lock;
-    rslt
-}
-
-pub fn post_bindings_can_be_ignored() {
-    let mutex = Mutex::new(1);
-    let lock = mutex.lock().unwrap();
-    let rslt = *lock;
-    let another = rslt;
-    let _ = another;
-}
-
-pub fn unnecessary_contention_with_multiple_owned_results() {
-    {
-        let mutex = Mutex::new(1i32);
-        let lock = mutex.lock().unwrap();
-        let _ = lock.abs();
-        let _ = lock.is_positive();
-    }
-
-    {
-        let mutex = Mutex::new(1i32);
-        let lock = mutex.lock().unwrap();
-        let rslt0 = lock.abs();
-        let rslt1 = lock.is_positive();
-        drop(lock);
-        do_heavy_computation_that_takes_time((rslt0, rslt1));
-    }
-}
-
-pub fn unnecessary_contention_with_single_owned_results() {
-    {
-        let mutex = Mutex::new(1i32);
-        let lock = mutex.lock().unwrap();
-        let _ = lock.abs();
-    }
-    {
-        let mutex = Mutex::new(vec![1i32]);
-        let mut lock = mutex.lock().unwrap();
-        lock.clear();
-    }
-
-    {
-        let mutex = Mutex::new(1i32);
-        
-        let rslt0 = mutex.lock().unwrap().abs();
-        
-        do_heavy_computation_that_takes_time(rslt0);
-    }
-    {
-        let mutex = Mutex::new(vec![1i32]);
-        
-        mutex.lock().unwrap().clear();
-        
-        do_heavy_computation_that_takes_time(());
-    }
-}
-
-// Marker used for illustration purposes.
-pub fn do_heavy_computation_that_takes_time<T>(_: T) {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.rs b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
index e5f17278f0f..77538167548 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.rs
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
@@ -1,5 +1,7 @@
 #![warn(clippy::significant_drop_tightening)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 use std::sync::Mutex;
 
 pub fn complex_return_triggers_the_lint() -> i32 {
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
index 5fc66279f00..2d7da4f394d 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
@@ -1,5 +1,5 @@
 error: temporary with significant `Drop` can be early dropped
-  --> tests/ui/significant_drop_tightening.rs:10:9
+  --> tests/ui/significant_drop_tightening.rs:12:9
    |
 LL |   pub fn complex_return_triggers_the_lint() -> i32 {
    |  __________________________________________________-
@@ -24,7 +24,7 @@ LL +     drop(lock);
    |
 
 error: temporary with significant `Drop` can be early dropped
-  --> tests/ui/significant_drop_tightening.rs:104:13
+  --> tests/ui/significant_drop_tightening.rs:106:13
    |
 LL | /     {
 LL | |         let mutex = Mutex::new(1i32);
@@ -44,7 +44,7 @@ LL +         drop(lock);
    |
 
 error: temporary with significant `Drop` can be early dropped
-  --> tests/ui/significant_drop_tightening.rs:125:13
+  --> tests/ui/significant_drop_tightening.rs:127:13
    |
 LL | /     {
 LL | |         let mutex = Mutex::new(1i32);
@@ -67,7 +67,7 @@ LL -         let rslt0 = lock.abs();
    |
 
 error: temporary with significant `Drop` can be early dropped
-  --> tests/ui/significant_drop_tightening.rs:131:17
+  --> tests/ui/significant_drop_tightening.rs:133:17
    |
 LL | /     {
 LL | |         let mutex = Mutex::new(vec![1i32]);
diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed
index 4e59c763198..64cbd5e9c90 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.fixed
+++ b/src/tools/clippy/tests/ui/single_element_loop.fixed
@@ -57,4 +57,12 @@ fn main() {
             }
         };
     }
+
+    // Should lint with correct suggestion (issue #12782)
+    let res_void: Result<bool, bool> = Ok(true);
+
+    {
+        let (Ok(mut _x) | Err(mut _x)) = res_void;
+        let ptr: *const bool = std::ptr::null();
+    }
 }
diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs
index a55ece6b065..92406f1c1ca 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.rs
+++ b/src/tools/clippy/tests/ui/single_element_loop.rs
@@ -54,4 +54,11 @@ fn main() {
             }
         };
     }
+
+    // Should lint with correct suggestion (issue #12782)
+    let res_void: Result<bool, bool> = Ok(true);
+
+    for (Ok(mut _x) | Err(mut _x)) in [res_void] {
+        let ptr: *const bool = std::ptr::null();
+    }
 }
diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr
index dfae5605b57..73453dd2dfd 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.stderr
+++ b/src/tools/clippy/tests/ui/single_element_loop.stderr
@@ -83,5 +83,21 @@ LL +         };
 LL +     }
    |
 
-error: aborting due to 7 previous errors
+error: for loop over a single element
+  --> tests/ui/single_element_loop.rs:61:5
+   |
+LL | /     for (Ok(mut _x) | Err(mut _x)) in [res_void] {
+LL | |         let ptr: *const bool = std::ptr::null();
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     {
+LL +         let (Ok(mut _x) | Err(mut _x)) = res_void;
+LL +         let ptr: *const bool = std::ptr::null();
+LL +     }
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
index ff5cd7abbb6..3eb47a5b5fd 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
@@ -36,4 +36,6 @@ fn main() {
 
     // do not lint in external macro
     external!(let ref _y = 42;);
+
+    fn f(#[allow(clippy::toplevel_ref_arg)] ref x: i32) {}
 }
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
index ab79b895960..cd731387de9 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
@@ -36,4 +36,6 @@ fn main() {
 
     // do not lint in external macro
     external!(let ref _y = 42;);
+
+    fn f(#[allow(clippy::toplevel_ref_arg)] ref x: i32) {}
 }
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed
index b696a574ae3..39e67b25052 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed
@@ -1,17 +1,19 @@
 #![warn(clippy::transmute_ptr_to_ptr)]
 #![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
 
+use std::mem::transmute;
+
 // Make sure we can modify lifetimes, which is one of the recommended uses
 // of transmute
 
 // Make sure we can do static lifetime transmutes
 unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
-    std::mem::transmute::<&'a T, &'static T>(t)
+    transmute::<&'a T, &'static T>(t)
 }
 
 // Make sure we can do non-static lifetime transmutes
 unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
-    std::mem::transmute::<&'a T, &'b T>(t)
+    transmute::<&'a T, &'b T>(t)
 }
 
 struct LifetimeParam<'a> {
@@ -27,39 +29,40 @@ fn transmute_ptr_to_ptr() {
     let mut_ptr = &mut 1u32 as *mut u32;
     unsafe {
         // pointer-to-pointer transmutes; bad
-        let _: *const f32 = ptr as *const f32;
-        //~^ ERROR: transmute from a pointer to a pointer
-        //~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
-        let _: *mut f32 = mut_ptr as *mut f32;
-        //~^ ERROR: transmute from a pointer to a pointer
+        let _: *const f32 = ptr.cast::<f32>();
+        //~^ transmute_ptr_to_ptr
+        let _: *mut f32 = mut_ptr.cast::<f32>();
+        //~^ transmute_ptr_to_ptr
         // ref-ref transmutes; bad
         let _: &f32 = &*(&1u32 as *const u32 as *const f32);
-        //~^ ERROR: transmute from a reference to a reference
+        //~^ transmute_ptr_to_ptr
         let _: &f32 = &*(&1f64 as *const f64 as *const f32);
-        //~^ ERROR: transmute from a reference to a reference
+        //~^ transmute_ptr_to_ptr
         //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
         // the same type
         let _: &mut f32 = &mut *(&mut 1u32 as *mut u32 as *mut f32);
-        //~^ ERROR: transmute from a reference to a reference
+        //~^ transmute_ptr_to_ptr
         let _: &GenericParam<f32> = &*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>);
-        //~^ ERROR: transmute from a reference to a reference
+        //~^ transmute_ptr_to_ptr
         let u64_ref: &u64 = &0u64;
-        let u8_ref: &u8 = unsafe { &*(u64_ref as *const u64 as *const u8) };
-        //~^ ERROR: transmute from a reference to a reference
+        let u8_ref: &u8 = &*(u64_ref as *const u64 as *const u8);
+        //~^ transmute_ptr_to_ptr
+        let _: *const u32 = mut_ptr.cast_const();
+        //~^ transmute_ptr_to_ptr
+        let _: *mut u32 = ptr.cast_mut();
+        //~^ transmute_ptr_to_ptr
     }
 
-    // these are recommendations for solving the above; if these lint we need to update
-    // those suggestions
-    let _ = ptr as *const f32;
-    let _ = mut_ptr as *mut f32;
-    let _ = unsafe { &*(&1u32 as *const u32 as *const f32) };
-    let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) };
-
     // transmute internal lifetimes, should not lint
     let s = "hello world".to_owned();
     let lp = LifetimeParam { s: &s };
-    let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) };
-    let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) };
+    let _: &LifetimeParam<'static> = unsafe { transmute(&lp) };
+    let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
+}
+
+fn lifetime_to_static(v: *mut &()) -> *const &'static () {
+    unsafe { v as *const &() }
+    //~^ transmute_ptr_to_ptr
 }
 
 // dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959)
@@ -67,7 +70,37 @@ const _: &() = {
     struct Zst;
     let zst = &Zst;
 
-    unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) }
+    unsafe { transmute::<&'static Zst, &'static ()>(zst) }
 };
 
+#[clippy::msrv = "1.37"]
+fn msrv_1_37(ptr: *const u8) {
+    unsafe {
+        let _: *const i8 = ptr as *const i8;
+    }
+}
+
+#[clippy::msrv = "1.38"]
+fn msrv_1_38(ptr: *const u8) {
+    unsafe {
+        let _: *const i8 = ptr.cast::<i8>();
+    }
+}
+
+#[clippy::msrv = "1.64"]
+fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) {
+    unsafe {
+        let _: *mut u8 = ptr as *mut u8;
+        let _: *const u8 = mut_ptr as *const u8;
+    }
+}
+
+#[clippy::msrv = "1.65"]
+fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) {
+    unsafe {
+        let _: *mut u8 = ptr.cast_mut();
+        let _: *const u8 = mut_ptr.cast_const();
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
index 85cc1d7802c..580b2855173 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
@@ -1,17 +1,19 @@
 #![warn(clippy::transmute_ptr_to_ptr)]
 #![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
 
+use std::mem::transmute;
+
 // Make sure we can modify lifetimes, which is one of the recommended uses
 // of transmute
 
 // Make sure we can do static lifetime transmutes
 unsafe fn transmute_lifetime_to_static<'a, T>(t: &'a T) -> &'static T {
-    std::mem::transmute::<&'a T, &'static T>(t)
+    transmute::<&'a T, &'static T>(t)
 }
 
 // Make sure we can do non-static lifetime transmutes
 unsafe fn transmute_lifetime<'a, 'b, T>(t: &'a T, u: &'b T) -> &'b T {
-    std::mem::transmute::<&'a T, &'b T>(t)
+    transmute::<&'a T, &'b T>(t)
 }
 
 struct LifetimeParam<'a> {
@@ -27,39 +29,40 @@ fn transmute_ptr_to_ptr() {
     let mut_ptr = &mut 1u32 as *mut u32;
     unsafe {
         // pointer-to-pointer transmutes; bad
-        let _: *const f32 = std::mem::transmute(ptr);
-        //~^ ERROR: transmute from a pointer to a pointer
-        //~| NOTE: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
-        let _: *mut f32 = std::mem::transmute(mut_ptr);
-        //~^ ERROR: transmute from a pointer to a pointer
+        let _: *const f32 = transmute(ptr);
+        //~^ transmute_ptr_to_ptr
+        let _: *mut f32 = transmute(mut_ptr);
+        //~^ transmute_ptr_to_ptr
         // ref-ref transmutes; bad
-        let _: &f32 = std::mem::transmute(&1u32);
-        //~^ ERROR: transmute from a reference to a reference
-        let _: &f32 = std::mem::transmute(&1f64);
-        //~^ ERROR: transmute from a reference to a reference
+        let _: &f32 = transmute(&1u32);
+        //~^ transmute_ptr_to_ptr
+        let _: &f32 = transmute(&1f64);
+        //~^ transmute_ptr_to_ptr
         //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
         // the same type
-        let _: &mut f32 = std::mem::transmute(&mut 1u32);
-        //~^ ERROR: transmute from a reference to a reference
-        let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
-        //~^ ERROR: transmute from a reference to a reference
+        let _: &mut f32 = transmute(&mut 1u32);
+        //~^ transmute_ptr_to_ptr
+        let _: &GenericParam<f32> = transmute(&GenericParam { t: 1u32 });
+        //~^ transmute_ptr_to_ptr
         let u64_ref: &u64 = &0u64;
-        let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) };
-        //~^ ERROR: transmute from a reference to a reference
+        let u8_ref: &u8 = transmute(u64_ref);
+        //~^ transmute_ptr_to_ptr
+        let _: *const u32 = transmute(mut_ptr);
+        //~^ transmute_ptr_to_ptr
+        let _: *mut u32 = transmute(ptr);
+        //~^ transmute_ptr_to_ptr
     }
 
-    // these are recommendations for solving the above; if these lint we need to update
-    // those suggestions
-    let _ = ptr as *const f32;
-    let _ = mut_ptr as *mut f32;
-    let _ = unsafe { &*(&1u32 as *const u32 as *const f32) };
-    let _ = unsafe { &mut *(&mut 1u32 as *mut u32 as *mut f32) };
-
     // transmute internal lifetimes, should not lint
     let s = "hello world".to_owned();
     let lp = LifetimeParam { s: &s };
-    let _: &LifetimeParam<'static> = unsafe { std::mem::transmute(&lp) };
-    let _: &GenericParam<&LifetimeParam<'static>> = unsafe { std::mem::transmute(&GenericParam { t: &lp }) };
+    let _: &LifetimeParam<'static> = unsafe { transmute(&lp) };
+    let _: &GenericParam<&LifetimeParam<'static>> = unsafe { transmute(&GenericParam { t: &lp }) };
+}
+
+fn lifetime_to_static(v: *mut &()) -> *const &'static () {
+    unsafe { transmute(v) }
+    //~^ transmute_ptr_to_ptr
 }
 
 // dereferencing raw pointers in const contexts, should not lint as it's unstable (issue 5959)
@@ -67,7 +70,37 @@ const _: &() = {
     struct Zst;
     let zst = &Zst;
 
-    unsafe { std::mem::transmute::<&'static Zst, &'static ()>(zst) }
+    unsafe { transmute::<&'static Zst, &'static ()>(zst) }
 };
 
+#[clippy::msrv = "1.37"]
+fn msrv_1_37(ptr: *const u8) {
+    unsafe {
+        let _: *const i8 = transmute(ptr);
+    }
+}
+
+#[clippy::msrv = "1.38"]
+fn msrv_1_38(ptr: *const u8) {
+    unsafe {
+        let _: *const i8 = transmute(ptr);
+    }
+}
+
+#[clippy::msrv = "1.64"]
+fn msrv_1_64(ptr: *const u8, mut_ptr: *mut u8) {
+    unsafe {
+        let _: *mut u8 = transmute(ptr);
+        let _: *const u8 = transmute(mut_ptr);
+    }
+}
+
+#[clippy::msrv = "1.65"]
+fn msrv_1_65(ptr: *const u8, mut_ptr: *mut u8) {
+    unsafe {
+        let _: *mut u8 = transmute(ptr);
+        let _: *const u8 = transmute(mut_ptr);
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr
index cd1f1f398dc..8801eb943ce 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr
@@ -1,47 +1,155 @@
 error: transmute from a pointer to a pointer
-  --> tests/ui/transmute_ptr_to_ptr.rs:30:29
+  --> tests/ui/transmute_ptr_to_ptr.rs:32:29
    |
-LL |         let _: *const f32 = std::mem::transmute(ptr);
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32`
+LL |         let _: *const f32 = transmute(ptr);
+   |                             ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ptr)]`
+help: use `pointer::cast` instead
+   |
+LL |         let _: *const f32 = ptr.cast::<f32>();
+   |                             ~~~~~~~~~~~~~~~~~
 
 error: transmute from a pointer to a pointer
-  --> tests/ui/transmute_ptr_to_ptr.rs:33:27
+  --> tests/ui/transmute_ptr_to_ptr.rs:34:27
+   |
+LL |         let _: *mut f32 = transmute(mut_ptr);
+   |                           ^^^^^^^^^^^^^^^^^^
+   |
+help: use `pointer::cast` instead
    |
-LL |         let _: *mut f32 = std::mem::transmute(mut_ptr);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32`
+LL |         let _: *mut f32 = mut_ptr.cast::<f32>();
+   |                           ~~~~~~~~~~~~~~~~~~~~~
 
 error: transmute from a reference to a reference
-  --> tests/ui/transmute_ptr_to_ptr.rs:36:23
+  --> tests/ui/transmute_ptr_to_ptr.rs:37:23
    |
-LL |         let _: &f32 = std::mem::transmute(&1u32);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)`
+LL |         let _: &f32 = transmute(&1u32);
+   |                       ^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)`
 
 error: transmute from a reference to a reference
-  --> tests/ui/transmute_ptr_to_ptr.rs:38:23
+  --> tests/ui/transmute_ptr_to_ptr.rs:39:23
    |
-LL |         let _: &f32 = std::mem::transmute(&1f64);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)`
+LL |         let _: &f32 = transmute(&1f64);
+   |                       ^^^^^^^^^^^^^^^^ help: try: `&*(&1f64 as *const f64 as *const f32)`
 
 error: transmute from a reference to a reference
-  --> tests/ui/transmute_ptr_to_ptr.rs:42:27
+  --> tests/ui/transmute_ptr_to_ptr.rs:43:27
    |
-LL |         let _: &mut f32 = std::mem::transmute(&mut 1u32);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)`
+LL |         let _: &mut f32 = transmute(&mut 1u32);
+   |                           ^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)`
 
 error: transmute from a reference to a reference
-  --> tests/ui/transmute_ptr_to_ptr.rs:44:37
+  --> tests/ui/transmute_ptr_to_ptr.rs:45:37
    |
-LL |         let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
+LL |         let _: &GenericParam<f32> = transmute(&GenericParam { t: 1u32 });
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
 
 error: transmute from a reference to a reference
-  --> tests/ui/transmute_ptr_to_ptr.rs:47:36
+  --> tests/ui/transmute_ptr_to_ptr.rs:48:27
+   |
+LL |         let u8_ref: &u8 = transmute(u64_ref);
+   |                           ^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)`
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:50:29
+   |
+LL |         let _: *const u32 = transmute(mut_ptr);
+   |                             ^^^^^^^^^^^^^^^^^^
+   |
+help: use `pointer::cast_const` instead
+   |
+LL |         let _: *const u32 = mut_ptr.cast_const();
+   |                             ~~~~~~~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:52:27
+   |
+LL |         let _: *mut u32 = transmute(ptr);
+   |                           ^^^^^^^^^^^^^^
+   |
+help: use `pointer::cast_mut` instead
+   |
+LL |         let _: *mut u32 = ptr.cast_mut();
+   |                           ~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:64:14
+   |
+LL |     unsafe { transmute(v) }
+   |              ^^^^^^^^^^^^
+   |
+help: use an `as` cast instead
+   |
+LL |     unsafe { v as *const &() }
+   |              ~~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:79:28
+   |
+LL |         let _: *const i8 = transmute(ptr);
+   |                            ^^^^^^^^^^^^^^
+   |
+help: use an `as` cast instead
+   |
+LL |         let _: *const i8 = ptr as *const i8;
+   |                            ~~~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:86:28
+   |
+LL |         let _: *const i8 = transmute(ptr);
+   |                            ^^^^^^^^^^^^^^
+   |
+help: use `pointer::cast` instead
+   |
+LL |         let _: *const i8 = ptr.cast::<i8>();
+   |                            ~~~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:93:26
+   |
+LL |         let _: *mut u8 = transmute(ptr);
+   |                          ^^^^^^^^^^^^^^
+   |
+help: use an `as` cast instead
+   |
+LL |         let _: *mut u8 = ptr as *mut u8;
+   |                          ~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:94:28
+   |
+LL |         let _: *const u8 = transmute(mut_ptr);
+   |                            ^^^^^^^^^^^^^^^^^^
+   |
+help: use an `as` cast instead
+   |
+LL |         let _: *const u8 = mut_ptr as *const u8;
+   |                            ~~~~~~~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:101:26
+   |
+LL |         let _: *mut u8 = transmute(ptr);
+   |                          ^^^^^^^^^^^^^^
+   |
+help: use `pointer::cast_mut` instead
+   |
+LL |         let _: *mut u8 = ptr.cast_mut();
+   |                          ~~~~~~~~~~~~~~
+
+error: transmute from a pointer to a pointer
+  --> tests/ui/transmute_ptr_to_ptr.rs:102:28
+   |
+LL |         let _: *const u8 = transmute(mut_ptr);
+   |                            ^^^^^^^^^^^^^^^^^^
+   |
+help: use `pointer::cast_const` instead
    |
-LL |         let u8_ref: &u8 = unsafe { std::mem::transmute(u64_ref) };
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(u64_ref as *const u64 as *const u8)`
+LL |         let _: *const u8 = mut_ptr.cast_const();
+   |                            ~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 7 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 51682da4a98..e95054a7ccb 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -18,7 +18,7 @@ fn main() {
     let ptr_i32 = usize::MAX as *const i32;
 
     // e has type *T, U is *U_0, and either U_0: Sized ...
-    let _ptr_i8_transmute = unsafe { ptr_i32 as *const i8 };
+    let _ptr_i8_transmute = unsafe { ptr_i32.cast::<i8>() };
     let _ptr_i8 = ptr_i32 as *const i8;
 
     let slice_ptr = &[0, 1, 2, 3] as *const [i32];
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
index 2ca44485826..2d74967ede5 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
@@ -11,16 +11,25 @@ error: transmute from a pointer to a pointer
   --> tests/ui/transmutes_expressible_as_ptr_casts.rs:21:38
    |
 LL |     let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) };
-   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8`
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ptr)]`
+help: use `pointer::cast` instead
+   |
+LL |     let _ptr_i8_transmute = unsafe { ptr_i32.cast::<i8>() };
+   |                                      ~~~~~~~~~~~~~~~~~~~~
 
 error: transmute from a pointer to a pointer
   --> tests/ui/transmutes_expressible_as_ptr_casts.rs:27:46
    |
 LL |     let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u32]`
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use an `as` cast instead
+   |
+LL |     let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] };
+   |                                              ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead
   --> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50
diff --git a/src/tools/clippy/tests/ui/types.fixed b/src/tools/clippy/tests/ui/types.fixed
deleted file mode 100644
index 6f1f55f0e62..00000000000
--- a/src/tools/clippy/tests/ui/types.fixed
+++ /dev/null
@@ -1,13 +0,0 @@
-#![allow(dead_code, unused_variables)]
-#![warn(clippy::cast_lossless)]
-
-// should not warn on lossy casting in constant types
-// because not supported yet
-const C: i32 = 42;
-const C_I64: i64 = C as i64;
-
-fn main() {
-    // should suggest i64::from(c)
-    let c: i32 = 42;
-    let c_i64: i64 = i64::from(c);
-}
diff --git a/src/tools/clippy/tests/ui/types.rs b/src/tools/clippy/tests/ui/types.rs
deleted file mode 100644
index 960aee4600c..00000000000
--- a/src/tools/clippy/tests/ui/types.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![allow(dead_code, unused_variables)]
-#![warn(clippy::cast_lossless)]
-
-// should not warn on lossy casting in constant types
-// because not supported yet
-const C: i32 = 42;
-const C_I64: i64 = C as i64;
-
-fn main() {
-    // should suggest i64::from(c)
-    let c: i32 = 42;
-    let c_i64: i64 = c as i64;
-}
diff --git a/src/tools/clippy/tests/ui/types.stderr b/src/tools/clippy/tests/ui/types.stderr
deleted file mode 100644
index 02e75018129..00000000000
--- a/src/tools/clippy/tests/ui/types.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: casting `i32` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/types.rs:12:22
-   |
-LL |     let c_i64: i64 = c as i64;
-   |                      ^^^^^^^^ help: try: `i64::from(c)`
-   |
-   = note: `-D clippy::cast-lossless` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
deleted file mode 100644
index dc5e163ff04..00000000000
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
+++ /dev/null
@@ -1,201 +0,0 @@
-#![allow(unused_assignments)]
-#![warn(clippy::unnecessary_to_owned)]
-
-#[allow(dead_code)]
-#[derive(Clone, Copy)]
-enum FileType {
-    Account,
-    PrivateKey,
-    Certificate,
-}
-
-fn main() {
-    let path = std::path::Path::new("x");
-
-    let _ = check_files(&[(FileType::Account, path)]);
-    let _ = check_files_vec(vec![(FileType::Account, path)]);
-
-    // negative tests
-    let _ = check_files_ref(&[(FileType::Account, path)]);
-    let _ = check_files_mut(&[(FileType::Account, path)]);
-    let _ = check_files_ref_mut(&[(FileType::Account, path)]);
-    let _ = check_files_self_and_arg(&[(FileType::Account, path)]);
-    let _ = check_files_mut_path_buf(&[(FileType::Account, std::path::PathBuf::new())]);
-
-    check_mut_iteratee_and_modify_inner_variable();
-}
-
-// `check_files` and its variants are based on:
-// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
-fn check_files(files: &[(FileType, &std::path::Path)]) -> bool {
-    for (t, path) in files {
-        let other = match get_file_path(t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-fn check_files_vec(files: Vec<(FileType, &std::path::Path)>) -> bool {
-    for (t, path) in files.iter() {
-        let other = match get_file_path(t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-fn check_files_ref(files: &[(FileType, &std::path::Path)]) -> bool {
-    for (ref t, path) in files.iter().copied() {
-        let other = match get_file_path(t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-#[allow(unused_assignments)]
-fn check_files_mut(files: &[(FileType, &std::path::Path)]) -> bool {
-    for (mut t, path) in files.iter().copied() {
-        t = FileType::PrivateKey;
-        let other = match get_file_path(&t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-fn check_files_ref_mut(files: &[(FileType, &std::path::Path)]) -> bool {
-    for (ref mut t, path) in files.iter().copied() {
-        *t = FileType::PrivateKey;
-        let other = match get_file_path(t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-fn check_files_self_and_arg(files: &[(FileType, &std::path::Path)]) -> bool {
-    for (t, path) in files.iter().copied() {
-        let other = match get_file_path(&t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.join(path).is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-#[allow(unused_assignments)]
-fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool {
-    for (mut t, path) in files.iter().cloned() {
-        t = FileType::PrivateKey;
-        let other = match get_file_path(&t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() || !other.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
-    Ok(std::path::PathBuf::new())
-}
-
-// Issue 12098
-// https://github.com/rust-lang/rust-clippy/issues/12098
-// no message emits
-fn check_mut_iteratee_and_modify_inner_variable() {
-    struct Test {
-        list: Vec<String>,
-        mut_this: bool,
-    }
-
-    impl Test {
-        fn list(&self) -> &[String] {
-            &self.list
-        }
-    }
-
-    let mut test = Test {
-        list: vec![String::from("foo"), String::from("bar")],
-        mut_this: false,
-    };
-
-    for _item in test.list().to_vec() {
-        println!("{}", _item);
-
-        test.mut_this = true;
-        {
-            test.mut_this = true;
-        }
-    }
-}
-
-mod issue_12821 {
-    fn foo() {
-        let v: Vec<_> = "hello".chars().collect();
-        for c in v.iter() {
-            //~^ ERROR: unnecessary use of `cloned`
-            println!("{c}"); // should not suggest to remove `&`
-        }
-    }
-
-    fn bar() {
-        let v: Vec<_> = "hello".chars().collect();
-        for c in v.iter() {
-            //~^ ERROR: unnecessary use of `cloned`
-            let ref_c = c; //~ HELP: remove any references to the binding
-            println!("{ref_c}");
-        }
-    }
-
-    fn baz() {
-        let v: Vec<_> = "hello".chars().enumerate().collect();
-        for (i, c) in v.iter() {
-            //~^ ERROR: unnecessary use of `cloned`
-            let ref_c = c; //~ HELP: remove any references to the binding
-            let ref_i = i;
-            println!("{i} {ref_c}"); // should not suggest to remove `&` from `i`
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
index 8f797ac717f..331b7b25271 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
@@ -1,6 +1,8 @@
 #![allow(unused_assignments)]
 #![warn(clippy::unnecessary_to_owned)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 #[allow(dead_code)]
 #[derive(Clone, Copy)]
 enum FileType {
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr
index 0bdb37a521f..e3592e3cbbd 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr
@@ -1,5 +1,5 @@
 error: unnecessary use of `copied`
-  --> tests/ui/unnecessary_iter_cloned.rs:31:22
+  --> tests/ui/unnecessary_iter_cloned.rs:33:22
    |
 LL |     for (t, path) in files.iter().copied() {
    |                      ^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL +         let other = match get_file_path(t) {
    |
 
 error: unnecessary use of `copied`
-  --> tests/ui/unnecessary_iter_cloned.rs:46:22
+  --> tests/ui/unnecessary_iter_cloned.rs:48:22
    |
 LL |     for (t, path) in files.iter().copied() {
    |                      ^^^^^^^^^^^^^^^^^^^^^
@@ -33,13 +33,13 @@ LL +         let other = match get_file_path(t) {
    |
 
 error: unnecessary use of `cloned`
-  --> tests/ui/unnecessary_iter_cloned.rs:177:18
+  --> tests/ui/unnecessary_iter_cloned.rs:179:18
    |
 LL |         for c in v.iter().cloned() {
    |                  ^^^^^^^^^^^^^^^^^ help: use: `v.iter()`
 
 error: unnecessary use of `cloned`
-  --> tests/ui/unnecessary_iter_cloned.rs:185:18
+  --> tests/ui/unnecessary_iter_cloned.rs:187:18
    |
 LL |         for c in v.iter().cloned() {
    |                  ^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL +             let ref_c = c;
    |
 
 error: unnecessary use of `cloned`
-  --> tests/ui/unnecessary_iter_cloned.rs:194:23
+  --> tests/ui/unnecessary_iter_cloned.rs:196:23
    |
 LL |         for (i, c) in v.iter().cloned() {
    |                       ^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
index f3cf65da2d6..b0e8f454635 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
@@ -26,6 +26,11 @@ struct V {
     f: u32,
 }
 
+struct W {
+    f1: u32,
+    f2: u32,
+}
+
 impl Clone for V {
     fn clone(&self) -> Self {
         // Lint: `Self` implements `Copy`
@@ -68,4 +73,69 @@ fn main() {
 
     // Should lint: the result of an expression is mutable and temporary
     let p = &mut *Box::new(T { f: 5 });
+
+    // Should lint: all fields of `q` would be consumed anyway
+    let q = W { f1: 42, f2: 1337 };
+    let r = q;
+
+    // Should not lint: not all fields of `t` from same source
+    let s = W { f1: 1337, f2: 42 };
+    let t = W { f1: s.f1, f2: r.f2 };
+
+    // Should not lint: different fields of `s` assigned
+    let u = W { f1: s.f2, f2: s.f1 };
+
+    // Should lint: all fields of `v` would be consumed anyway
+    let v = W { f1: 42, f2: 1337 };
+    let w = v;
+
+    // Should not lint: source differs between fields and base
+    let x = W { f1: 42, f2: 1337 };
+    let y = W { f1: w.f1, ..x };
+
+    // Should lint: range desugars to struct
+    let r1 = 0..5;
+    let r2 = r1;
+
+    references();
+    shorthand();
+}
+
+fn references() {
+    // Should not lint as `a` is not mutable
+    let a = W { f1: 42, f2: 1337 };
+    let b = &mut W { f1: a.f1, f2: a.f2 };
+
+    // Should lint as `d` is a shared reference
+    let c = W { f1: 42, f2: 1337 };
+    let d = &c;
+
+    // Should not lint as `e` is not mutable
+    let e = W { f1: 42, f2: 1337 };
+    let f = &mut W { f1: e.f1, ..e };
+
+    // Should lint as `h` is a shared reference
+    let g = W { f1: 42, f2: 1337 };
+    let h = &g;
+
+    // Should not lint as `j` is copy
+    let i = V { f: 0x1701d };
+    let j = &V { ..i };
+
+    // Should not lint as `k` is copy
+    let k = V { f: 0x1701d };
+    let l = &V { f: k.f };
+}
+
+fn shorthand() {
+    struct S1 {
+        a: i32,
+        b: i32,
+    }
+
+    let a = 42;
+    let s = S1 { a: 3, b: 4 };
+
+    // Should not lint: `a` is not from `s`
+    let s = S1 { a, b: s.b };
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
index bd5302f9d85..b0db71af4d4 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
@@ -26,6 +26,11 @@ struct V {
     f: u32,
 }
 
+struct W {
+    f1: u32,
+    f2: u32,
+}
+
 impl Clone for V {
     fn clone(&self) -> Self {
         // Lint: `Self` implements `Copy`
@@ -72,4 +77,69 @@ fn main() {
     let p = &mut T {
         ..*Box::new(T { f: 5 })
     };
+
+    // Should lint: all fields of `q` would be consumed anyway
+    let q = W { f1: 42, f2: 1337 };
+    let r = W { f1: q.f1, f2: q.f2 };
+
+    // Should not lint: not all fields of `t` from same source
+    let s = W { f1: 1337, f2: 42 };
+    let t = W { f1: s.f1, f2: r.f2 };
+
+    // Should not lint: different fields of `s` assigned
+    let u = W { f1: s.f2, f2: s.f1 };
+
+    // Should lint: all fields of `v` would be consumed anyway
+    let v = W { f1: 42, f2: 1337 };
+    let w = W { f1: v.f1, ..v };
+
+    // Should not lint: source differs between fields and base
+    let x = W { f1: 42, f2: 1337 };
+    let y = W { f1: w.f1, ..x };
+
+    // Should lint: range desugars to struct
+    let r1 = 0..5;
+    let r2 = r1.start..r1.end;
+
+    references();
+    shorthand();
+}
+
+fn references() {
+    // Should not lint as `a` is not mutable
+    let a = W { f1: 42, f2: 1337 };
+    let b = &mut W { f1: a.f1, f2: a.f2 };
+
+    // Should lint as `d` is a shared reference
+    let c = W { f1: 42, f2: 1337 };
+    let d = &W { f1: c.f1, f2: c.f2 };
+
+    // Should not lint as `e` is not mutable
+    let e = W { f1: 42, f2: 1337 };
+    let f = &mut W { f1: e.f1, ..e };
+
+    // Should lint as `h` is a shared reference
+    let g = W { f1: 42, f2: 1337 };
+    let h = &W { f1: g.f1, ..g };
+
+    // Should not lint as `j` is copy
+    let i = V { f: 0x1701d };
+    let j = &V { ..i };
+
+    // Should not lint as `k` is copy
+    let k = V { f: 0x1701d };
+    let l = &V { f: k.f };
+}
+
+fn shorthand() {
+    struct S1 {
+        a: i32,
+        b: i32,
+    }
+
+    let a = 42;
+    let s = S1 { a: 3, b: 4 };
+
+    // Should not lint: `a` is not from `s`
+    let s = S1 { a, b: s.b };
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.stderr b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.stderr
index 8bc308c7567..56982cc0a39 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.stderr
@@ -1,5 +1,5 @@
 error: unnecessary struct building
-  --> tests/ui/unnecessary_struct_initialization.rs:32:9
+  --> tests/ui/unnecessary_struct_initialization.rs:37:9
    |
 LL |         Self { ..*self }
    |         ^^^^^^^^^^^^^^^^ help: replace with: `*self`
@@ -8,25 +8,25 @@ LL |         Self { ..*self }
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_struct_initialization)]`
 
 error: unnecessary struct building
-  --> tests/ui/unnecessary_struct_initialization.rs:39:17
+  --> tests/ui/unnecessary_struct_initialization.rs:44:17
    |
 LL |     let mut b = S { ..a };
    |                 ^^^^^^^^^ help: replace with: `a`
 
 error: unnecessary struct building
-  --> tests/ui/unnecessary_struct_initialization.rs:42:18
+  --> tests/ui/unnecessary_struct_initialization.rs:47:18
    |
 LL |     let c = &mut S { ..b };
    |                  ^^^^^^^^^ help: replace with: `b`
 
 error: unnecessary struct building
-  --> tests/ui/unnecessary_struct_initialization.rs:50:14
+  --> tests/ui/unnecessary_struct_initialization.rs:55:14
    |
 LL |     let g = &S { ..f };
    |              ^^^^^^^^^ help: replace with: `f`
 
 error: unnecessary struct building
-  --> tests/ui/unnecessary_struct_initialization.rs:53:18
+  --> tests/ui/unnecessary_struct_initialization.rs:58:18
    |
 LL |       let h = &mut S {
    |  __________________^
@@ -35,7 +35,7 @@ LL | |     };
    | |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })`
 
 error: unnecessary struct building
-  --> tests/ui/unnecessary_struct_initialization.rs:72:18
+  --> tests/ui/unnecessary_struct_initialization.rs:77:18
    |
 LL |       let p = &mut T {
    |  __________________^
@@ -43,5 +43,35 @@ LL | |         ..*Box::new(T { f: 5 })
 LL | |     };
    | |_____^ help: replace with: `*Box::new(T { f: 5 })`
 
-error: aborting due to 6 previous errors
+error: unnecessary struct building
+  --> tests/ui/unnecessary_struct_initialization.rs:83:13
+   |
+LL |     let r = W { f1: q.f1, f2: q.f2 };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `q`
+
+error: unnecessary struct building
+  --> tests/ui/unnecessary_struct_initialization.rs:94:13
+   |
+LL |     let w = W { f1: v.f1, ..v };
+   |             ^^^^^^^^^^^^^^^^^^^ help: replace with: `v`
+
+error: unnecessary struct building
+  --> tests/ui/unnecessary_struct_initialization.rs:102:14
+   |
+LL |     let r2 = r1.start..r1.end;
+   |              ^^^^^^^^^^^^^^^^ help: replace with: `r1`
+
+error: unnecessary struct building
+  --> tests/ui/unnecessary_struct_initialization.rs:115:14
+   |
+LL |     let d = &W { f1: c.f1, f2: c.f2 };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `c`
+
+error: unnecessary struct building
+  --> tests/ui/unnecessary_struct_initialization.rs:123:14
+   |
+LL |     let h = &W { f1: g.f1, ..g };
+   |              ^^^^^^^^^^^^^^^^^^^ help: replace with: `g`
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
deleted file mode 100644
index fdcac8fb08d..00000000000
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
+++ /dev/null
@@ -1,587 +0,0 @@
-#![allow(
-    clippy::needless_borrow,
-    clippy::needless_borrows_for_generic_args,
-    clippy::ptr_arg,
-    clippy::manual_async_fn,
-    clippy::needless_lifetimes
-)]
-#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
-
-use std::borrow::Cow;
-use std::ffi::{CStr, CString, OsStr, OsString};
-use std::ops::Deref;
-
-#[derive(Clone)]
-struct X(String);
-
-impl Deref for X {
-    type Target = [u8];
-    fn deref(&self) -> &[u8] {
-        self.0.as_bytes()
-    }
-}
-
-impl AsRef<str> for X {
-    fn as_ref(&self) -> &str {
-        self.0.as_str()
-    }
-}
-
-#[allow(clippy::to_string_trait_impl)]
-impl ToString for X {
-    fn to_string(&self) -> String {
-        self.0.to_string()
-    }
-}
-
-impl X {
-    fn join(&self, other: impl AsRef<str>) -> Self {
-        let mut s = self.0.clone();
-        s.push_str(other.as_ref());
-        Self(s)
-    }
-}
-
-#[allow(dead_code)]
-#[derive(Clone)]
-enum FileType {
-    Account,
-    PrivateKey,
-    Certificate,
-}
-
-fn main() {
-    let c_str = CStr::from_bytes_with_nul(&[0]).unwrap();
-    let os_str = OsStr::new("x");
-    let path = std::path::Path::new("x");
-    let s = "x";
-    let array = ["x"];
-    let array_ref = &["x"];
-    let slice = &["x"][..];
-    let x = X(String::from("x"));
-    let x_ref = &x;
-
-    require_c_str(&Cow::from(c_str));
-    require_c_str(c_str);
-
-    require_os_str(os_str);
-    require_os_str(&Cow::from(os_str));
-    require_os_str(os_str);
-
-    require_path(path);
-    require_path(&Cow::from(path));
-    require_path(path);
-
-    require_str(s);
-    require_str(&Cow::from(s));
-    require_str(s);
-    require_str(x_ref.as_ref());
-
-    require_slice(slice);
-    require_slice(&Cow::from(slice));
-    require_slice(array.as_ref());
-    require_slice(array_ref.as_ref());
-    require_slice(slice);
-    require_slice(&x_ref.to_owned()); // No longer flagged because of #8759.
-
-    require_x(&Cow::<X>::Owned(x.clone()));
-    require_x(&x_ref.to_owned()); // No longer flagged because of #8759.
-
-    require_deref_c_str(c_str);
-    require_deref_os_str(os_str);
-    require_deref_path(path);
-    require_deref_str(s);
-    require_deref_slice(slice);
-
-    require_impl_deref_c_str(c_str);
-    require_impl_deref_os_str(os_str);
-    require_impl_deref_path(path);
-    require_impl_deref_str(s);
-    require_impl_deref_slice(slice);
-
-    require_deref_str_slice(s, slice);
-    require_deref_slice_str(slice, s);
-
-    require_as_ref_c_str(c_str);
-    require_as_ref_os_str(os_str);
-    require_as_ref_path(path);
-    require_as_ref_str(s);
-    require_as_ref_str(&x);
-    require_as_ref_slice(array);
-    require_as_ref_slice(array_ref);
-    require_as_ref_slice(slice);
-
-    require_impl_as_ref_c_str(c_str);
-    require_impl_as_ref_os_str(os_str);
-    require_impl_as_ref_path(path);
-    require_impl_as_ref_str(s);
-    require_impl_as_ref_str(&x);
-    require_impl_as_ref_slice(array);
-    require_impl_as_ref_slice(array_ref);
-    require_impl_as_ref_slice(slice);
-
-    require_as_ref_str_slice(s, array);
-    require_as_ref_str_slice(s, array_ref);
-    require_as_ref_str_slice(s, slice);
-    require_as_ref_slice_str(array, s);
-    require_as_ref_slice_str(array_ref, s);
-    require_as_ref_slice_str(slice, s);
-
-    let _ = x.join(x_ref);
-
-    let _ = slice.iter().copied();
-    let _ = slice.iter().copied();
-    let _ = [std::path::PathBuf::new()][..].iter().cloned();
-    let _ = [std::path::PathBuf::new()][..].iter().cloned();
-
-    let _ = slice.iter().copied();
-    let _ = slice.iter().copied();
-    let _ = [std::path::PathBuf::new()][..].iter().cloned();
-    let _ = [std::path::PathBuf::new()][..].iter().cloned();
-
-    let _ = check_files(&[FileType::Account]);
-
-    // negative tests
-    require_string(&s.to_string());
-    require_string(&Cow::from(s).into_owned());
-    require_string(&s.to_owned());
-    require_string(&x_ref.to_string());
-
-    // `X` isn't copy.
-    require_slice(&x.to_owned());
-    require_deref_slice(x.to_owned());
-
-    // The following should be flagged by `redundant_clone`, but not by this lint.
-    require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap());
-    require_os_str(&OsString::from("x"));
-    require_path(&std::path::PathBuf::from("x"));
-    require_str(&String::from("x"));
-    require_slice(&[String::from("x")]);
-
-    let slice = [0u8; 1024];
-    let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8");
-    let _ref_str: &str = core::str::from_utf8(b"foo").unwrap();
-    let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap();
-    // Expression is of type `&String`, can't suggest `str::from_utf8` here
-    let _ref_string = &String::from_utf8(b"foo".to_vec()).unwrap();
-    macro_rules! arg_from_macro {
-        () => {
-            b"foo".to_vec()
-        };
-    }
-    macro_rules! string_from_utf8_from_macro {
-        () => {
-            &String::from_utf8(b"foo".to_vec()).unwrap()
-        };
-    }
-    let _ref_str: &str = &String::from_utf8(arg_from_macro!()).unwrap();
-    let _ref_str: &str = string_from_utf8_from_macro!();
-}
-
-fn require_c_str(_: &CStr) {}
-fn require_os_str(_: &OsStr) {}
-fn require_path(_: &std::path::Path) {}
-fn require_str(_: &str) {}
-fn require_slice<T>(_: &[T]) {}
-fn require_x(_: &X) {}
-
-fn require_deref_c_str<T: Deref<Target = CStr>>(_: T) {}
-fn require_deref_os_str<T: Deref<Target = OsStr>>(_: T) {}
-fn require_deref_path<T: Deref<Target = std::path::Path>>(_: T) {}
-fn require_deref_str<T: Deref<Target = str>>(_: T) {}
-fn require_deref_slice<T, U: Deref<Target = [T]>>(_: U) {}
-
-fn require_impl_deref_c_str(_: impl Deref<Target = CStr>) {}
-fn require_impl_deref_os_str(_: impl Deref<Target = OsStr>) {}
-fn require_impl_deref_path(_: impl Deref<Target = std::path::Path>) {}
-fn require_impl_deref_str(_: impl Deref<Target = str>) {}
-fn require_impl_deref_slice<T>(_: impl Deref<Target = [T]>) {}
-
-fn require_deref_str_slice<T: Deref<Target = str>, U, V: Deref<Target = [U]>>(_: T, _: V) {}
-fn require_deref_slice_str<T, U: Deref<Target = [T]>, V: Deref<Target = str>>(_: U, _: V) {}
-
-fn require_as_ref_c_str<T: AsRef<CStr>>(_: T) {}
-fn require_as_ref_os_str<T: AsRef<OsStr>>(_: T) {}
-fn require_as_ref_path<T: AsRef<std::path::Path>>(_: T) {}
-fn require_as_ref_str<T: AsRef<str>>(_: T) {}
-fn require_as_ref_slice<T, U: AsRef<[T]>>(_: U) {}
-
-fn require_impl_as_ref_c_str(_: impl AsRef<CStr>) {}
-fn require_impl_as_ref_os_str(_: impl AsRef<OsStr>) {}
-fn require_impl_as_ref_path(_: impl AsRef<std::path::Path>) {}
-fn require_impl_as_ref_str(_: impl AsRef<str>) {}
-fn require_impl_as_ref_slice<T>(_: impl AsRef<[T]>) {}
-
-fn require_as_ref_str_slice<T: AsRef<str>, U, V: AsRef<[U]>>(_: T, _: V) {}
-fn require_as_ref_slice_str<T, U: AsRef<[T]>, V: AsRef<str>>(_: U, _: V) {}
-
-// `check_files` is based on:
-// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
-fn check_files(file_types: &[FileType]) -> bool {
-    for t in file_types {
-        let path = match get_file_path(t) {
-            Ok(p) => p,
-            Err(_) => {
-                return false;
-            },
-        };
-        if !path.is_file() {
-            return false;
-        }
-    }
-    true
-}
-
-fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
-    Ok(std::path::PathBuf::new())
-}
-
-fn require_string(_: &String) {}
-
-#[clippy::msrv = "1.35"]
-fn _msrv_1_35() {
-    // `copied` was stabilized in 1.36, so clippy should use `cloned`.
-    let _ = &["x"][..].iter().cloned();
-}
-
-#[clippy::msrv = "1.36"]
-fn _msrv_1_36() {
-    let _ = &["x"][..].iter().copied();
-}
-
-// https://github.com/rust-lang/rust-clippy/issues/8507
-mod issue_8507 {
-    #![allow(dead_code)]
-
-    struct Opaque<P>(P);
-
-    pub trait Abstracted {}
-
-    impl<P> Abstracted for Opaque<P> {}
-
-    fn build<P>(p: P) -> Opaque<P>
-    where
-        P: AsRef<str>,
-    {
-        Opaque(p)
-    }
-
-    // Should not lint.
-    fn test_str(s: &str) -> Box<dyn Abstracted> {
-        Box::new(build(s.to_string()))
-    }
-
-    // Should not lint.
-    fn test_x(x: super::X) -> Box<dyn Abstracted> {
-        Box::new(build(x))
-    }
-
-    #[derive(Clone, Copy)]
-    struct Y(&'static str);
-
-    impl AsRef<str> for Y {
-        fn as_ref(&self) -> &str {
-            self.0
-        }
-    }
-
-    #[allow(clippy::to_string_trait_impl)]
-    impl ToString for Y {
-        fn to_string(&self) -> String {
-            self.0.to_string()
-        }
-    }
-
-    // Should lint because Y is copy.
-    fn test_y(y: Y) -> Box<dyn Abstracted> {
-        Box::new(build(y))
-    }
-}
-
-// https://github.com/rust-lang/rust-clippy/issues/8759
-mod issue_8759 {
-    #![allow(dead_code)]
-
-    #[derive(Default)]
-    struct View {}
-
-    impl std::borrow::ToOwned for View {
-        type Owned = View;
-        fn to_owned(&self) -> Self::Owned {
-            View {}
-        }
-    }
-
-    #[derive(Default)]
-    struct RenderWindow {
-        default_view: View,
-    }
-
-    impl RenderWindow {
-        fn default_view(&self) -> &View {
-            &self.default_view
-        }
-        fn set_view(&mut self, _view: &View) {}
-    }
-
-    fn main() {
-        let mut rw = RenderWindow::default();
-        rw.set_view(&rw.default_view().to_owned());
-    }
-}
-
-mod issue_8759_variant {
-    #![allow(dead_code)]
-
-    #[derive(Clone, Default)]
-    struct View {}
-
-    #[derive(Default)]
-    struct RenderWindow {
-        default_view: View,
-    }
-
-    impl RenderWindow {
-        fn default_view(&self) -> &View {
-            &self.default_view
-        }
-        fn set_view(&mut self, _view: &View) {}
-    }
-
-    fn main() {
-        let mut rw = RenderWindow::default();
-        rw.set_view(&rw.default_view().to_owned());
-    }
-}
-
-mod issue_9317 {
-    #![allow(dead_code)]
-
-    struct Bytes {}
-
-    #[allow(clippy::to_string_trait_impl)]
-    impl ToString for Bytes {
-        fn to_string(&self) -> String {
-            "123".to_string()
-        }
-    }
-
-    impl AsRef<[u8]> for Bytes {
-        fn as_ref(&self) -> &[u8] {
-            &[1, 2, 3]
-        }
-    }
-
-    fn consume<C: AsRef<[u8]>>(c: C) {
-        let _ = c;
-    }
-
-    pub fn main() {
-        let b = Bytes {};
-        // Should not lint.
-        consume(b.to_string());
-    }
-}
-
-mod issue_9351 {
-    #![allow(dead_code)]
-
-    use std::ops::Deref;
-    use std::path::{Path, PathBuf};
-
-    fn require_deref_path<T: Deref<Target = std::path::Path>>(x: T) -> T {
-        x
-    }
-
-    fn generic_arg_used_elsewhere<T: AsRef<Path>>(_x: T, _y: T) {}
-
-    fn id<T: AsRef<str>>(x: T) -> T {
-        x
-    }
-
-    fn predicates_are_satisfied(_x: impl std::fmt::Write) {}
-
-    // Should lint
-    fn single_return() -> impl AsRef<str> {
-        id("abc")
-    }
-
-    // Should not lint
-    fn multiple_returns(b: bool) -> impl AsRef<str> {
-        if b {
-            return String::new();
-        }
-
-        id("abc".to_string())
-    }
-
-    struct S1(String);
-
-    // Should not lint
-    fn fields1() -> S1 {
-        S1(id("abc".to_string()))
-    }
-
-    struct S2 {
-        s: String,
-    }
-
-    // Should not lint
-    fn fields2() {
-        let mut s = S2 { s: "abc".into() };
-        s.s = id("abc".to_string());
-    }
-
-    pub fn main() {
-        let path = std::path::Path::new("x");
-        let path_buf = path.to_owned();
-
-        // Should not lint.
-        let _x: PathBuf = require_deref_path(path.to_owned());
-        generic_arg_used_elsewhere(path.to_owned(), path_buf);
-        predicates_are_satisfied(id("abc".to_string()));
-    }
-}
-
-mod issue_9504 {
-    #![allow(dead_code)]
-
-    async fn foo<S: AsRef<str>>(_: S) {}
-    async fn bar() {
-        foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
-    }
-}
-
-mod issue_9771a {
-    #![allow(dead_code)]
-
-    use std::marker::PhantomData;
-
-    pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>);
-
-    impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> {
-        pub fn new(key: K) -> Key<K, V> {
-            Key(key, PhantomData)
-        }
-    }
-
-    pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> {
-        Key::new([b"pkh-", pkh].concat().to_vec())
-    }
-}
-
-mod issue_9771b {
-    #![allow(dead_code)]
-
-    pub struct Key<K: AsRef<[u8]>>(K);
-
-    pub fn from(c: &[u8]) -> Key<Vec<u8>> {
-        let v = [c].concat();
-        Key(v.to_vec())
-    }
-}
-
-// This is a watered down version of the code in: https://github.com/oxigraph/rio
-// The ICE is triggered by the call to `to_owned` on this line:
-// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
-mod issue_10021 {
-    #![allow(unused)]
-
-    pub struct Iri<T>(T);
-
-    impl<T: AsRef<str>> Iri<T> {
-        pub fn parse(iri: T) -> Result<Self, ()> {
-            unimplemented!()
-        }
-    }
-
-    pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
-        let base_iri = Iri::parse(url.to_owned())?;
-        Ok(())
-    }
-}
-
-mod issue_10033 {
-    #![allow(dead_code)]
-    use std::fmt::Display;
-    use std::ops::Deref;
-
-    fn _main() {
-        let f = Foo;
-
-        // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
-        // deref to `str`)
-        foo(&f.to_string());
-    }
-
-    fn foo(s: &str) {
-        println!("{}", s);
-    }
-
-    struct Foo;
-
-    impl Deref for Foo {
-        type Target = str;
-
-        fn deref(&self) -> &Self::Target {
-            "str"
-        }
-    }
-
-    impl Display for Foo {
-        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-            write!(f, "Foo")
-        }
-    }
-}
-
-mod issue_11952 {
-    use core::future::{Future, IntoFuture};
-
-    fn foo<'a, T: AsRef<[u8]>>(x: T, y: &'a i32) -> impl 'a + Future<Output = Result<(), ()>> {
-        async move {
-            let _y = y;
-            Ok(())
-        }
-    }
-
-    fn bar() {
-        IntoFuture::into_future(foo([], &0));
-    }
-}
-
-fn borrow_checks() {
-    use std::borrow::Borrow;
-    use std::collections::HashSet;
-
-    fn inner(a: &[&str]) {
-        let mut s = HashSet::from([vec!["a"]]);
-        s.remove(a); //~ ERROR: unnecessary use of `to_vec`
-    }
-
-    let mut s = HashSet::from(["a".to_string()]);
-    s.remove("b"); //~ ERROR: unnecessary use of `to_owned`
-    s.remove("b"); //~ ERROR: unnecessary use of `to_string`
-    // Should not warn.
-    s.remove("b");
-
-    let mut s = HashSet::from([vec!["a"]]);
-    s.remove(["b"].as_slice()); //~ ERROR: unnecessary use of `to_vec`
-    s.remove((&["b"]).as_slice()); //~ ERROR: unnecessary use of `to_vec`
-
-    // Should not warn.
-    s.remove(&["b"].to_vec().clone());
-    s.remove(["a"].as_slice());
-
-    trait SetExt {
-        fn foo<Q: Borrow<str>>(&self, _: &String);
-    }
-
-    impl<K> SetExt for HashSet<K> {
-        fn foo<Q: Borrow<str>>(&self, _: &String) {}
-    }
-
-    // Should not lint!
-    HashSet::<i32>::new().foo::<&str>(&"".to_owned());
-    HashSet::<String>::new().get(&1.to_string());
-}
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
index 10a9727a9a7..da0c761f795 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
@@ -7,6 +7,8 @@
 )]
 #![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
 
+//@no-rustfix: need to change the suggestion to a multipart suggestion
+
 use std::borrow::Cow;
 use std::ffi::{CStr, CString, OsStr, OsString};
 use std::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
index 511b4ae119f..7ab1f667d9b 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
@@ -1,11 +1,11 @@
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:155:64
+  --> tests/ui/unnecessary_to_owned.rs:157:64
    |
 LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
    |                                                                ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:155:20
+  --> tests/ui/unnecessary_to_owned.rs:157:20
    |
 LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,55 +13,55 @@ LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned())
    = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]`
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:156:40
+  --> tests/ui/unnecessary_to_owned.rs:158:40
    |
 LL |     require_os_str(&OsString::from("x").to_os_string());
    |                                        ^^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:156:21
+  --> tests/ui/unnecessary_to_owned.rs:158:21
    |
 LL |     require_os_str(&OsString::from("x").to_os_string());
    |                     ^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:157:48
+  --> tests/ui/unnecessary_to_owned.rs:159:48
    |
 LL |     require_path(&std::path::PathBuf::from("x").to_path_buf());
    |                                                ^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:157:19
+  --> tests/ui/unnecessary_to_owned.rs:159:19
    |
 LL |     require_path(&std::path::PathBuf::from("x").to_path_buf());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:158:35
+  --> tests/ui/unnecessary_to_owned.rs:160:35
    |
 LL |     require_str(&String::from("x").to_string());
    |                                   ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:158:18
+  --> tests/ui/unnecessary_to_owned.rs:160:18
    |
 LL |     require_str(&String::from("x").to_string());
    |                  ^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> tests/ui/unnecessary_to_owned.rs:159:39
+  --> tests/ui/unnecessary_to_owned.rs:161:39
    |
 LL |     require_slice(&[String::from("x")].to_owned());
    |                                       ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> tests/ui/unnecessary_to_owned.rs:159:20
+  --> tests/ui/unnecessary_to_owned.rs:161:20
    |
 LL |     require_slice(&[String::from("x")].to_owned());
    |                    ^^^^^^^^^^^^^^^^^^^
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:64:36
+  --> tests/ui/unnecessary_to_owned.rs:66:36
    |
 LL |     require_c_str(&Cow::from(c_str).into_owned());
    |                                    ^^^^^^^^^^^^^ help: remove this
@@ -70,415 +70,415 @@ LL |     require_c_str(&Cow::from(c_str).into_owned());
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:65:19
+  --> tests/ui/unnecessary_to_owned.rs:67:19
    |
 LL |     require_c_str(&c_str.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_os_string`
-  --> tests/ui/unnecessary_to_owned.rs:67:20
+  --> tests/ui/unnecessary_to_owned.rs:69:20
    |
 LL |     require_os_str(&os_str.to_os_string());
    |                    ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:68:38
+  --> tests/ui/unnecessary_to_owned.rs:70:38
    |
 LL |     require_os_str(&Cow::from(os_str).into_owned());
    |                                      ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:69:20
+  --> tests/ui/unnecessary_to_owned.rs:71:20
    |
 LL |     require_os_str(&os_str.to_owned());
    |                    ^^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_path_buf`
-  --> tests/ui/unnecessary_to_owned.rs:71:18
+  --> tests/ui/unnecessary_to_owned.rs:73:18
    |
 LL |     require_path(&path.to_path_buf());
    |                  ^^^^^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:72:34
+  --> tests/ui/unnecessary_to_owned.rs:74:34
    |
 LL |     require_path(&Cow::from(path).into_owned());
    |                                  ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:73:18
+  --> tests/ui/unnecessary_to_owned.rs:75:18
    |
 LL |     require_path(&path.to_owned());
    |                  ^^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:75:17
+  --> tests/ui/unnecessary_to_owned.rs:77:17
    |
 LL |     require_str(&s.to_string());
    |                 ^^^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:76:30
+  --> tests/ui/unnecessary_to_owned.rs:78:30
    |
 LL |     require_str(&Cow::from(s).into_owned());
    |                              ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:77:17
+  --> tests/ui/unnecessary_to_owned.rs:79:17
    |
 LL |     require_str(&s.to_owned());
    |                 ^^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:78:17
+  --> tests/ui/unnecessary_to_owned.rs:80:17
    |
 LL |     require_str(&x_ref.to_string());
    |                 ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:80:19
+  --> tests/ui/unnecessary_to_owned.rs:82:19
    |
 LL |     require_slice(&slice.to_vec());
    |                   ^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:81:36
+  --> tests/ui/unnecessary_to_owned.rs:83:36
    |
 LL |     require_slice(&Cow::from(slice).into_owned());
    |                                    ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:82:19
+  --> tests/ui/unnecessary_to_owned.rs:84:19
    |
 LL |     require_slice(&array.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:83:19
+  --> tests/ui/unnecessary_to_owned.rs:85:19
    |
 LL |     require_slice(&array_ref.to_owned());
    |                   ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:84:19
+  --> tests/ui/unnecessary_to_owned.rs:86:19
    |
 LL |     require_slice(&slice.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `into_owned`
-  --> tests/ui/unnecessary_to_owned.rs:87:42
+  --> tests/ui/unnecessary_to_owned.rs:89:42
    |
 LL |     require_x(&Cow::<X>::Owned(x.clone()).into_owned());
    |                                          ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:90:25
+  --> tests/ui/unnecessary_to_owned.rs:92:25
    |
 LL |     require_deref_c_str(c_str.to_owned());
    |                         ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:91:26
+  --> tests/ui/unnecessary_to_owned.rs:93:26
    |
 LL |     require_deref_os_str(os_str.to_owned());
    |                          ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:92:24
+  --> tests/ui/unnecessary_to_owned.rs:94:24
    |
 LL |     require_deref_path(path.to_owned());
    |                        ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:93:23
+  --> tests/ui/unnecessary_to_owned.rs:95:23
    |
 LL |     require_deref_str(s.to_owned());
    |                       ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:94:25
+  --> tests/ui/unnecessary_to_owned.rs:96:25
    |
 LL |     require_deref_slice(slice.to_owned());
    |                         ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:96:30
+  --> tests/ui/unnecessary_to_owned.rs:98:30
    |
 LL |     require_impl_deref_c_str(c_str.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:97:31
+  --> tests/ui/unnecessary_to_owned.rs:99:31
    |
 LL |     require_impl_deref_os_str(os_str.to_owned());
    |                               ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:98:29
+  --> tests/ui/unnecessary_to_owned.rs:100:29
    |
 LL |     require_impl_deref_path(path.to_owned());
    |                             ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:99:28
+  --> tests/ui/unnecessary_to_owned.rs:101:28
    |
 LL |     require_impl_deref_str(s.to_owned());
    |                            ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:100:30
+  --> tests/ui/unnecessary_to_owned.rs:102:30
    |
 LL |     require_impl_deref_slice(slice.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:102:29
+  --> tests/ui/unnecessary_to_owned.rs:104:29
    |
 LL |     require_deref_str_slice(s.to_owned(), slice.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:102:43
+  --> tests/ui/unnecessary_to_owned.rs:104:43
    |
 LL |     require_deref_str_slice(s.to_owned(), slice.to_owned());
    |                                           ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:103:29
+  --> tests/ui/unnecessary_to_owned.rs:105:29
    |
 LL |     require_deref_slice_str(slice.to_owned(), s.to_owned());
    |                             ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:103:47
+  --> tests/ui/unnecessary_to_owned.rs:105:47
    |
 LL |     require_deref_slice_str(slice.to_owned(), s.to_owned());
    |                                               ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:105:26
+  --> tests/ui/unnecessary_to_owned.rs:107:26
    |
 LL |     require_as_ref_c_str(c_str.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:106:27
+  --> tests/ui/unnecessary_to_owned.rs:108:27
    |
 LL |     require_as_ref_os_str(os_str.to_owned());
    |                           ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:107:25
+  --> tests/ui/unnecessary_to_owned.rs:109:25
    |
 LL |     require_as_ref_path(path.to_owned());
    |                         ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:108:24
+  --> tests/ui/unnecessary_to_owned.rs:110:24
    |
 LL |     require_as_ref_str(s.to_owned());
    |                        ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:109:24
+  --> tests/ui/unnecessary_to_owned.rs:111:24
    |
 LL |     require_as_ref_str(x.to_owned());
    |                        ^^^^^^^^^^^^ help: use: `&x`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:110:26
+  --> tests/ui/unnecessary_to_owned.rs:112:26
    |
 LL |     require_as_ref_slice(array.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:111:26
+  --> tests/ui/unnecessary_to_owned.rs:113:26
    |
 LL |     require_as_ref_slice(array_ref.to_owned());
    |                          ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:112:26
+  --> tests/ui/unnecessary_to_owned.rs:114:26
    |
 LL |     require_as_ref_slice(slice.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:114:31
+  --> tests/ui/unnecessary_to_owned.rs:116:31
    |
 LL |     require_impl_as_ref_c_str(c_str.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:115:32
+  --> tests/ui/unnecessary_to_owned.rs:117:32
    |
 LL |     require_impl_as_ref_os_str(os_str.to_owned());
    |                                ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:116:30
+  --> tests/ui/unnecessary_to_owned.rs:118:30
    |
 LL |     require_impl_as_ref_path(path.to_owned());
    |                              ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:117:29
+  --> tests/ui/unnecessary_to_owned.rs:119:29
    |
 LL |     require_impl_as_ref_str(s.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:118:29
+  --> tests/ui/unnecessary_to_owned.rs:120:29
    |
 LL |     require_impl_as_ref_str(x.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `&x`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:119:31
+  --> tests/ui/unnecessary_to_owned.rs:121:31
    |
 LL |     require_impl_as_ref_slice(array.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:120:31
+  --> tests/ui/unnecessary_to_owned.rs:122:31
    |
 LL |     require_impl_as_ref_slice(array_ref.to_owned());
    |                               ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:121:31
+  --> tests/ui/unnecessary_to_owned.rs:123:31
    |
 LL |     require_impl_as_ref_slice(slice.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:123:30
+  --> tests/ui/unnecessary_to_owned.rs:125:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:123:44
+  --> tests/ui/unnecessary_to_owned.rs:125:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array.to_owned());
    |                                            ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:124:30
+  --> tests/ui/unnecessary_to_owned.rs:126:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:124:44
+  --> tests/ui/unnecessary_to_owned.rs:126:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
    |                                            ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:125:30
+  --> tests/ui/unnecessary_to_owned.rs:127:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:125:44
+  --> tests/ui/unnecessary_to_owned.rs:127:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
    |                                            ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:126:30
+  --> tests/ui/unnecessary_to_owned.rs:128:30
    |
 LL |     require_as_ref_slice_str(array.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:126:48
+  --> tests/ui/unnecessary_to_owned.rs:128:48
    |
 LL |     require_as_ref_slice_str(array.to_owned(), s.to_owned());
    |                                                ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:127:30
+  --> tests/ui/unnecessary_to_owned.rs:129:30
    |
 LL |     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:127:52
+  --> tests/ui/unnecessary_to_owned.rs:129:52
    |
 LL |     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
    |                                                    ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:128:30
+  --> tests/ui/unnecessary_to_owned.rs:130:30
    |
 LL |     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:128:48
+  --> tests/ui/unnecessary_to_owned.rs:130:48
    |
 LL |     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
    |                                                ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:130:20
+  --> tests/ui/unnecessary_to_owned.rs:132:20
    |
 LL |     let _ = x.join(&x_ref.to_string());
    |                    ^^^^^^^^^^^^^^^^^^ help: use: `x_ref`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:132:13
+  --> tests/ui/unnecessary_to_owned.rs:134:13
    |
 LL |     let _ = slice.to_vec().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:133:13
+  --> tests/ui/unnecessary_to_owned.rs:135:13
    |
 LL |     let _ = slice.to_owned().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:134:13
+  --> tests/ui/unnecessary_to_owned.rs:136:13
    |
 LL |     let _ = [std::path::PathBuf::new()][..].to_vec().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:135:13
+  --> tests/ui/unnecessary_to_owned.rs:137:13
    |
 LL |     let _ = [std::path::PathBuf::new()][..].to_owned().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:137:13
+  --> tests/ui/unnecessary_to_owned.rs:139:13
    |
 LL |     let _ = IntoIterator::into_iter(slice.to_vec());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:138:13
+  --> tests/ui/unnecessary_to_owned.rs:140:13
    |
 LL |     let _ = IntoIterator::into_iter(slice.to_owned());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:139:13
+  --> tests/ui/unnecessary_to_owned.rs:141:13
    |
 LL |     let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:140:13
+  --> tests/ui/unnecessary_to_owned.rs:142:13
    |
 LL |     let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
 
 error: allocating a new `String` only to create a temporary `&str` from it
-  --> tests/ui/unnecessary_to_owned.rs:162:26
+  --> tests/ui/unnecessary_to_owned.rs:164:26
    |
 LL |     let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8");
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -490,7 +490,7 @@ LL +     let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8");
    |
 
 error: allocating a new `String` only to create a temporary `&str` from it
-  --> tests/ui/unnecessary_to_owned.rs:163:26
+  --> tests/ui/unnecessary_to_owned.rs:165:26
    |
 LL |     let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -502,7 +502,7 @@ LL +     let _ref_str: &str = core::str::from_utf8(b"foo").unwrap();
    |
 
 error: allocating a new `String` only to create a temporary `&str` from it
-  --> tests/ui/unnecessary_to_owned.rs:164:26
+  --> tests/ui/unnecessary_to_owned.rs:166:26
    |
 LL |     let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -514,7 +514,7 @@ LL +     let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap();
    |
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:221:14
+  --> tests/ui/unnecessary_to_owned.rs:223:14
    |
 LL |     for t in file_types.to_vec() {
    |              ^^^^^^^^^^^^^^^^^^^
@@ -530,61 +530,61 @@ LL +         let path = match get_file_path(t) {
    |
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:244:14
+  --> tests/ui/unnecessary_to_owned.rs:246:14
    |
 LL |     let _ = &["x"][..].to_vec().into_iter();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:249:14
+  --> tests/ui/unnecessary_to_owned.rs:251:14
    |
 LL |     let _ = &["x"][..].to_vec().into_iter();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:297:24
+  --> tests/ui/unnecessary_to_owned.rs:299:24
    |
 LL |         Box::new(build(y.to_string()))
    |                        ^^^^^^^^^^^^^ help: use: `y`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:406:12
+  --> tests/ui/unnecessary_to_owned.rs:408:12
    |
 LL |         id("abc".to_string())
    |            ^^^^^^^^^^^^^^^^^ help: use: `"abc"`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:549:37
+  --> tests/ui/unnecessary_to_owned.rs:551:37
    |
 LL |         IntoFuture::into_future(foo([].to_vec(), &0));
    |                                     ^^^^^^^^^^^ help: use: `[]`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:559:18
+  --> tests/ui/unnecessary_to_owned.rs:561:18
    |
 LL |         s.remove(&a.to_vec());
    |                  ^^^^^^^^^^^ help: replace it with: `a`
 
 error: unnecessary use of `to_owned`
-  --> tests/ui/unnecessary_to_owned.rs:563:14
+  --> tests/ui/unnecessary_to_owned.rs:565:14
    |
 LL |     s.remove(&"b".to_owned());
    |              ^^^^^^^^^^^^^^^ help: replace it with: `"b"`
 
 error: unnecessary use of `to_string`
-  --> tests/ui/unnecessary_to_owned.rs:564:14
+  --> tests/ui/unnecessary_to_owned.rs:566:14
    |
 LL |     s.remove(&"b".to_string());
    |              ^^^^^^^^^^^^^^^^ help: replace it with: `"b"`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:569:14
+  --> tests/ui/unnecessary_to_owned.rs:571:14
    |
 LL |     s.remove(&["b"].to_vec());
    |              ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()`
 
 error: unnecessary use of `to_vec`
-  --> tests/ui/unnecessary_to_owned.rs:570:14
+  --> tests/ui/unnecessary_to_owned.rs:572:14
    |
 LL |     s.remove(&(&["b"]).to_vec());
    |              ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()`
diff --git a/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed b/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed
index 6f132521926..989e8ae70e5 100644
--- a/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed
+++ b/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed
@@ -16,13 +16,11 @@ fn main() {
 
     // on arrays
     f(); let a: [i32; 0] = [];
-    f(); let a: [i32; 0] = [];
     let mut b;
     f(); b = [] as [i32; 0];
-    f(); b = [] as [i32; 0];
 
     // on vecs
-    // vecs dont support infering value of consts
+    // vecs dont support inferring value of consts
     f(); let c: std::vec::Vec<i32> = vec![];
     let d;
     f(); d = vec![] as std::vec::Vec<i32>;
@@ -39,9 +37,11 @@ fn main() {
     // when singled out/not part of assignment/local
     { f(); vec![] as std::vec::Vec<i32> };
     { f(); [] as [i32; 0] };
-    { f(); [] as [i32; 0] };
 
     // should not trigger
+    let a = [f(); N];
+    b = [f(); N];
+    [f(); N];
 
     // on arrays with > 0 repeat
     let a = [f(); 1];
@@ -58,3 +58,15 @@ fn main() {
     // as function param
     drop(vec![f(); 1]);
 }
+
+macro_rules! LEN {
+    () => {
+        0
+    };
+}
+
+fn issue_13110() {
+    let _data = [f(); LEN!()];
+    const LENGTH: usize = LEN!();
+    let _data = [f(); LENGTH];
+}
diff --git a/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs b/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs
index 9d9c367375a..68511f41a95 100644
--- a/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs
+++ b/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs
@@ -16,13 +16,11 @@ fn main() {
 
     // on arrays
     let a = [f(); 0];
-    let a = [f(); N];
     let mut b;
     b = [f(); 0];
-    b = [f(); N];
 
     // on vecs
-    // vecs dont support infering value of consts
+    // vecs dont support inferring value of consts
     let c = vec![f(); 0];
     let d;
     d = vec![f(); 0];
@@ -39,9 +37,11 @@ fn main() {
     // when singled out/not part of assignment/local
     vec![f(); 0];
     [f(); 0];
-    [f(); N];
 
     // should not trigger
+    let a = [f(); N];
+    b = [f(); N];
+    [f(); N];
 
     // on arrays with > 0 repeat
     let a = [f(); 1];
@@ -58,3 +58,15 @@ fn main() {
     // as function param
     drop(vec![f(); 1]);
 }
+
+macro_rules! LEN {
+    () => {
+        0
+    };
+}
+
+fn issue_13110() {
+    let _data = [f(); LEN!()];
+    const LENGTH: usize = LEN!();
+    let _data = [f(); LENGTH];
+}
diff --git a/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr b/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr
index afdc6054253..d578e22b971 100644
--- a/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr
@@ -8,70 +8,52 @@ LL |     let a = [f(); 0];
    = help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:19:5
-   |
-LL |     let a = [f(); N];
-   |     ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];`
-
-error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:21:5
+  --> tests/ui/zero_repeat_side_effects.rs:20:5
    |
 LL |     b = [f(); 0];
    |     ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:22:5
-   |
-LL |     b = [f(); N];
-   |     ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
-
-error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:26:5
+  --> tests/ui/zero_repeat_side_effects.rs:24:5
    |
 LL |     let c = vec![f(); 0];
    |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec<i32> = vec![];`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:28:5
+  --> tests/ui/zero_repeat_side_effects.rs:26:5
    |
 LL |     d = vec![f(); 0];
    |     ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec<i32>`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:31:5
+  --> tests/ui/zero_repeat_side_effects.rs:29:5
    |
 LL |     let e = [println!("side effect"); 0];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:34:5
+  --> tests/ui/zero_repeat_side_effects.rs:32:5
    |
 LL |     let g = [{ f() }; 0];
    |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:37:10
+  --> tests/ui/zero_repeat_side_effects.rs:35:10
    |
 LL |     drop(vec![f(); 0]);
    |          ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:40:5
+  --> tests/ui/zero_repeat_side_effects.rs:38:5
    |
 LL |     vec![f(); 0];
    |     ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
 
 error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:41:5
+  --> tests/ui/zero_repeat_side_effects.rs:39:5
    |
 LL |     [f(); 0];
    |     ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
 
-error: function or method calls as the initial value in zero-sized array initializers may cause side effects
-  --> tests/ui/zero_repeat_side_effects.rs:42:5
-   |
-LL |     [f(); N];
-   |     ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
-
-error: aborting due to 12 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 0f0e62670ff..dcf00e4e384 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -31,10 +31,10 @@ users_on_vacation = [
 "*" = [
     "@Manishearth",
     "@llogiq",
+    "@xFrednet",
     "@Alexendoo",
     "@dswij",
     "@Jarcho",
-    "@blyxyas",
     "@y21",
     "@Centri3",
 ]
diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html
index 8de36fc4005..0c0f28e4fbd 100644
--- a/src/tools/clippy/util/gh-pages/index.html
+++ b/src/tools/clippy/util/gh-pages/index.html
@@ -57,20 +57,17 @@ Otherwise, have a great day =^.^=
             background-color: var(--theme-hover);
         }
 
-        div.panel div.panel-body button.dropdown-toggle {
+        div.panel div.panel-body button {
             background: var(--searchbar-bg);
             color: var(--searchbar-fg);
             border-color: var(--theme-popup-border);
         }
 
-        div.panel div.panel-body button.dropdown-toggle:hover {
+        div.panel div.panel-body button:hover {
             box-shadow: 0 0 3px var(--searchbar-shadow-color);
         }
 
-        div.panel div.panel-body .open button.dropdown-toggle {
-            background: var(--searchbar-bg);
-            color: var(--searchbar-fg);
-            border-color: var(--theme-popup-border);
+        div.panel div.panel-body  button.open {
             filter: brightness(90%);
         }
 
@@ -96,7 +93,6 @@ Otherwise, have a great day =^.^=
         @media (min-width: 992px) {
             .search-control {
                 margin-top: 0;
-                float: right;
             }
         }
 
@@ -361,6 +357,24 @@ Otherwise, have a great day =^.^=
             opacity: 30%;
         }
 
+        .expansion-group {
+            margin-top: 15px;
+            padding: 0px 8px;
+            display: flex;
+            flex-wrap: nowrap;
+        }
+
+        @media (min-width: 992px) {
+            .expansion-group {
+                margin-top: 0;
+                padding: 0px 15px;
+            }
+        }
+
+        .expansion-control {
+            width: 50%;
+        }
+
         :not(pre) > code {
             color: var(--inline-code-color);
             background-color: var(--inline-code-bg);
@@ -405,7 +419,7 @@ Otherwise, have a great day =^.^=
 
             <div class="panel panel-default" ng-show="data">
                 <div class="panel-body row">
-                    <div id="upper-filters" class="col-12 col-md-6">
+                    <div id="upper-filters" class="col-12 col-md-5">
                         <div class="btn-group" filter-dropdown>
                             <button type="button" class="btn btn-default dropdown-toggle">
                                 Lint levels <span class="badge">{{selectedValuesCount(levels)}}</span> <span class="caret"></span>
@@ -524,7 +538,7 @@ Otherwise, have a great day =^.^=
                             </ul>
                         </div>
                     </div>
-                    <div class="col-12 col-md-6 search-control">
+                    <div class="col-12 col-md-5 search-control">
                         <div class="input-group">
                             <label class="input-group-addon" id="filter-label" for="search-input">Filter:</label>
                             <input type="text" class="form-control filter-input" placeholder="Keywords or search string" id="search-input"
@@ -537,6 +551,14 @@ Otherwise, have a great day =^.^=
                             </span>
                         </div>
                     </div>
+                    <div class="col-12 col-md-2 btn-group expansion-group">
+                        <button title="Collapse All" class="btn btn-default expansion-control" type="button" ng-click="toggleExpansion(data, false)">
+                            <span class="glyphicon glyphicon-collapse-up"></span>
+                        </button>
+                        <button title="Expand All" class="btn btn-default expansion-control" type="button" ng-click="toggleExpansion(data, true)">
+                            <span class="glyphicon glyphicon-collapse-down"></span>
+                        </button>
+                    </div>
                 </div>
             </div>
             <!-- The order of the filters should be from most likely to remove a lint to least likely to improve performance. -->
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index 921bb0376f6..661f80a6d34 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -469,6 +469,12 @@
                 $location.path(lint.id);
             };
 
+            $scope.toggleExpansion = function(lints, isExpanded) {
+                lints.forEach(lint => {
+                    $scope.open[lint.id] = isExpanded;
+                });
+            }
+
             $scope.copyToClipboard = function (lint) {
                 const clipboard = document.getElementById("clipboard-" + lint.id);
                 if (clipboard) {
diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs
index 6735e9faa7a..c356f4266f0 100644
--- a/src/tools/compiletest/src/command-list.rs
+++ b/src/tools/compiletest/src/command-list.rs
@@ -201,6 +201,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "only-wasm32-wasip1",
     "only-watchos",
     "only-windows",
+    "only-windows-gnu",
     "only-x86",
     "only-x86_64",
     "only-x86_64-fortanix-unknown-sgx",
diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs
index 840bfa0d2b4..19a89705acc 100644
--- a/src/tools/run-make-support/src/external_deps/cc.rs
+++ b/src/tools/run-make-support/src/external_deps/cc.rs
@@ -15,6 +15,13 @@ pub fn cc() -> Cc {
     Cc::new()
 }
 
+/// Construct a new platform-specific CXX compiler invocation.
+/// CXX_DEFAULT_FLAGS is passed from compiletest.
+#[track_caller]
+pub fn cxx() -> Cc {
+    Cc::new_cxx()
+}
+
 /// A platform-specific C compiler invocation builder. The specific C compiler used is
 /// passed down from compiletest.
 #[derive(Debug)]
@@ -44,6 +51,22 @@ impl Cc {
         Self { cmd }
     }
 
+    /// Construct a new platform-specific CXX compiler invocation.
+    /// CXX_DEFAULT_FLAGS is passed from compiletest.
+    #[track_caller]
+    pub fn new_cxx() -> Self {
+        let compiler = env_var("CXX");
+
+        let mut cmd = Command::new(compiler);
+
+        let default_cflags = env_var("CXX_DEFAULT_FLAGS");
+        for flag in default_cflags.split(char::is_whitespace) {
+            cmd.arg(flag);
+        }
+
+        Self { cmd }
+    }
+
     /// Specify path of the input file.
     pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg(path.as_ref());
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index a4bb9056346..085120764b4 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -44,7 +44,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust
 
 // These rely on external dependencies.
 pub use c_build::{build_native_dynamic_lib, build_native_static_lib};
-pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
+pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
 pub use clang::{clang, Clang};
 pub use htmldocck::htmldocck;
 pub use llvm::{
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 36f7f68ef7b..c3993e41a50 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,8 +1,6 @@
 run-make/branch-protection-check-IBT/Makefile
-run-make/c-unwind-abi-catch-lib-panic/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/cdylib-dylib-linkage/Makefile
-run-make/compiler-rt-works-on-mingw/Makefile
 run-make/cross-lang-lto-clang/Makefile
 run-make/cross-lang-lto-pgo-smoketest/Makefile
 run-make/cross-lang-lto-upstream-rlibs/Makefile
@@ -10,18 +8,12 @@ run-make/cross-lang-lto/Makefile
 run-make/dep-info-doesnt-run-much/Makefile
 run-make/dep-info-spaces/Makefile
 run-make/dep-info/Makefile
-run-make/dump-ice-to-disk/Makefile
 run-make/emit-to-stdout/Makefile
-run-make/export-executable-symbols/Makefile
-run-make/extern-flag-disambiguates/Makefile
 run-make/extern-fn-reachable/Makefile
 run-make/fmt-write-bloat/Makefile
 run-make/foreign-double-unwind/Makefile
 run-make/foreign-exceptions/Makefile
-run-make/foreign-rust-exceptions/Makefile
 run-make/incr-add-rust-src-component/Makefile
-run-make/incr-foreign-head-span/Makefile
-run-make/interdependent-c-libraries/Makefile
 run-make/issue-35164/Makefile
 run-make/issue-36710/Makefile
 run-make/issue-47551/Makefile
@@ -42,7 +34,6 @@ run-make/native-link-modifier-bundle/Makefile
 run-make/native-link-modifier-whole-archive/Makefile
 run-make/no-alloc-shim/Makefile
 run-make/no-builtins-attribute/Makefile
-run-make/panic-abort-eh_frame/Makefile
 run-make/pdb-buildinfo-cl-cmd/Makefile
 run-make/pgo-gen-lto/Makefile
 run-make/pgo-indirect-call-promotion/Makefile