about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-07-27 05:22:40 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-07-27 05:22:40 +0000
commit00e89d3cb6c549d195c41557ee467ddc559b3efe (patch)
tree1facc011e12f747c51718d5acb5dd4f0f9719ed6
parent80a32f86187f897cc075a314cd689c6bd45c4671 (diff)
parenta526d7ce45fd2284e0e7c7556ccba2425b9d25e5 (diff)
downloadrust-00e89d3cb6c549d195c41557ee467ddc559b3efe.tar.gz
rust-00e89d3cb6c549d195c41557ee467ddc559b3efe.zip
Merge from rustc
-rw-r--r--Cargo.lock31
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs16
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs34
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs28
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs5
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs6
-rw-r--r--compiler/rustc_hir/src/intravisit.rs4
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl13
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs27
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs135
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs77
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs9
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs5
-rw-r--r--compiler/rustc_lint/messages.ftl19
-rw-r--r--compiler/rustc_lint/src/builtin.rs139
-rw-r--r--compiler/rustc_lint/src/lints.rs141
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs4
-rw-r--r--compiler/rustc_lint/src/traits.rs6
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs6
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs4
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs5
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs11
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs123
-rw-r--r--compiler/rustc_parse/src/parser/item.rs9
-rw-r--r--compiler/rustc_passes/src/dead.rs32
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs5
-rw-r--r--compiler/rustc_resolve/src/errors.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs17
-rw-r--r--compiler/rustc_type_ir/src/visit.rs4
-rw-r--r--config.example.toml2
-rw-r--r--library/core/src/clone.rs3
-rw-r--r--library/core/src/fmt/builders.rs12
-rw-r--r--library/core/src/iter/traits/iterator.rs2
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/num/error.rs2
-rw-r--r--library/core/src/num/mod.rs5
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/rtstartup/rsbegin.rs2
-rw-r--r--library/rtstartup/rsend.rs2
-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
-rw-r--r--tests/assembly/simd-intrinsic-mask-load.rs1
-rw-r--r--tests/assembly/simd-intrinsic-mask-store.rs1
-rw-r--r--tests/codegen/avr/avr-func-addrspace.rs1
-rw-r--r--tests/codegen/clone-shims.rs15
-rw-r--r--tests/codegen/emcripten-catch-unwind.rs2
-rw-r--r--tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs1
-rw-r--r--tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs1
-rw-r--r--tests/run-make/README.md5
-rw-r--r--tests/run-make/c-unwind-abi-catch-lib-panic/Makefile35
-rw-r--r--tests/run-make/c-unwind-abi-catch-lib-panic/rmake.rs36
-rw-r--r--tests/run-make/compiler-rt-works-on-mingw/Makefile9
-rw-r--r--tests/run-make/compiler-rt-works-on-mingw/rmake.rs15
-rw-r--r--tests/run-make/dump-ice-to-disk/Makefile10
-rw-r--r--tests/run-make/dump-ice-to-disk/check.sh64
-rw-r--r--tests/run-make/dump-ice-to-disk/lib.rs (renamed from tests/run-make/dump-ice-to-disk/src/lib.rs)0
-rw-r--r--tests/run-make/dump-ice-to-disk/rmake.rs81
-rw-r--r--tests/run-make/export-executable-symbols/Makefile11
-rw-r--r--tests/run-make/export-executable-symbols/rmake.rs25
-rw-r--r--tests/run-make/extern-flag-disambiguates/Makefile26
-rw-r--r--tests/run-make/extern-flag-disambiguates/rmake.rs30
-rw-r--r--tests/run-make/foreign-rust-exceptions/Makefile13
-rw-r--r--tests/run-make/foreign-rust-exceptions/rmake.rs23
-rw-r--r--tests/run-make/incr-foreign-head-span/Makefile21
-rw-r--r--tests/run-make/incr-foreign-head-span/rmake.rs25
-rw-r--r--tests/run-make/interdependent-c-libraries/Makefile15
-rw-r--r--tests/run-make/interdependent-c-libraries/rmake.rs21
-rw-r--r--tests/run-make/panic-abort-eh_frame/Makefile10
-rw-r--r--tests/run-make/panic-abort-eh_frame/rmake.rs24
-rw-r--r--tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs20
-rw-r--r--tests/ui/associated-inherent-types/type-alias-bounds.rs29
-rw-r--r--tests/ui/associated-inherent-types/type-alias-bounds.stderr16
-rw-r--r--tests/ui/associated-type-bounds/type-alias.stderr204
-rw-r--r--tests/ui/async-await/async-closures/clone-closure.rs24
-rw-r--r--tests/ui/async-await/async-closures/clone-closure.run.stdout2
-rw-r--r--tests/ui/async-await/async-closures/move-consuming-capture.stderr9
-rw-r--r--tests/ui/async-await/async-closures/not-clone-closure.rs36
-rw-r--r--tests/ui/async-await/async-closures/not-clone-closure.stderr20
-rw-r--r--tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs2
-rw-r--r--tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr18
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type-alias-bounds.neg.stderr63
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs71
-rw-r--r--tests/ui/consts/const-eval/parse_ints.rs2
-rw-r--r--tests/ui/consts/const-eval/parse_ints.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs24
-rw-r--r--tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr71
-rw-r--r--tests/ui/lang-items/missing-clone-for-suggestion.rs20
-rw-r--r--tests/ui/lang-items/missing-clone-for-suggestion.stderr21
-rw-r--r--tests/ui/lint/dead-code/unused-impl-for-non-adts.rs45
-rw-r--r--tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr20
-rw-r--r--tests/ui/macros/issue-118786.rs1
-rw-r--r--tests/ui/macros/issue-118786.stderr6
-rw-r--r--tests/ui/maybe-bounds.stderr15
-rw-r--r--tests/ui/parser/issues/issue-19398.rs6
-rw-r--r--tests/ui/parser/issues/issue-19398.stderr14
-rw-r--r--tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.rs16
-rw-r--r--tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.stderr13
-rw-r--r--tests/ui/parser/trait-object-trait-parens.stderr18
-rw-r--r--tests/ui/privacy/private-in-public-warn.rs4
-rw-r--r--tests/ui/privacy/private-in-public-warn.stderr34
-rw-r--r--tests/ui/resolve/issue-118295.rs6
-rw-r--r--tests/ui/resolve/issue-118295.stderr18
-rw-r--r--tests/ui/resolve/issue-55673.stderr2
-rw-r--r--tests/ui/traits/maybe-polarity-pass.rs27
-rw-r--r--tests/ui/traits/maybe-polarity-pass.stderr20
-rw-r--r--tests/ui/traits/maybe-polarity-repeated.rs9
-rw-r--r--tests/ui/traits/maybe-polarity-repeated.stderr21
-rw-r--r--tests/ui/traits/wf-object/maybe-bound.stderr26
-rw-r--r--tests/ui/traits/wf-object/only-maybe-bound.stderr8
-rw-r--r--tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr17
-rw-r--r--tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.eager.stderr36
-rw-r--r--tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr40
-rw-r--r--tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs26
-rw-r--r--tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs2
-rw-r--r--tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr15
-rw-r--r--tests/ui/type/type-alias-bounds.rs21
-rw-r--r--tests/ui/type/type-alias-bounds.stderr163
-rw-r--r--tests/ui/unsized/maybe-bounds-where.stderr31
437 files changed, 6831 insertions, 6168 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1dec7d0c11e..f89ecc92add 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -573,7 +573,7 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
 
 [[package]]
 name = "clippy"
-version = "0.1.81"
+version = "0.1.82"
 dependencies = [
  "anstream",
  "clippy_config",
@@ -594,13 +594,13 @@ dependencies = [
  "termize",
  "tokio",
  "toml 0.7.8",
- "ui_test 0.23.0",
+ "ui_test 0.24.0",
  "walkdir",
 ]
 
 [[package]]
 name = "clippy_config"
-version = "0.1.81"
+version = "0.1.82"
 dependencies = [
  "rustc-semver",
  "serde",
@@ -623,7 +623,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.81"
+version = "0.1.82"
 dependencies = [
  "arrayvec",
  "cargo_metadata 0.18.1",
@@ -648,7 +648,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.81"
+version = "0.1.82"
 dependencies = [
  "arrayvec",
  "clippy_config",
@@ -969,7 +969,7 @@ dependencies = [
 
 [[package]]
 name = "declare_clippy_lint"
-version = "0.1.81"
+version = "0.1.82"
 dependencies = [
  "itertools",
  "quote",
@@ -2978,6 +2978,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "prettydiff"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abec3fb083c10660b3854367697da94c674e9e82aa7511014dc958beeb7215e9"
+dependencies = [
+ "owo-colors",
+ "pad",
+]
+
+[[package]]
 name = "proc-macro-hack"
 version = "0.5.20+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5825,7 +5835,7 @@ dependencies = [
  "indicatif",
  "lazy_static",
  "levenshtein",
- "prettydiff",
+ "prettydiff 0.6.4",
  "regex",
  "rustc_version",
  "rustfix 0.6.1",
@@ -5836,9 +5846,9 @@ dependencies = [
 
 [[package]]
 name = "ui_test"
-version = "0.23.0"
+version = "0.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29e5f4ffcbab82453958fbf59990e981b8e8a177dcd60c2bd8f9b52c3036a6e1"
+checksum = "bc1c6c78d55482388711c8d417b8e547263046a607512278fed274c54633bbe4"
 dependencies = [
  "annotate-snippets 0.11.4",
  "anyhow",
@@ -5852,14 +5862,13 @@ dependencies = [
  "indicatif",
  "lazy_static",
  "levenshtein",
- "prettydiff",
+ "prettydiff 0.7.0",
  "regex",
  "rustc_version",
  "rustfix 0.8.1",
  "serde",
  "serde_json",
  "spanned",
- "tempfile",
 ]
 
 [[package]]
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index f990b4ba69b..6e6aac1ddfc 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -172,7 +172,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         id: NodeId,
         hir_id: hir::HirId,
         ident: &mut Ident,
-        attrs: Option<&'hir [Attribute]>,
+        attrs: &'hir [Attribute],
         vis_span: Span,
         i: &ItemKind,
     ) -> hir::ItemKind<'hir> {
@@ -488,7 +488,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         id: NodeId,
         vis_span: Span,
         ident: &mut Ident,
-        attrs: Option<&'hir [Attribute]>,
+        attrs: &'hir [Attribute],
     ) -> hir::ItemKind<'hir> {
         let path = &tree.prefix;
         let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
@@ -566,7 +566,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         // `ItemLocalId` and the new owner. (See `lower_node_id`)
                         let kind =
                             this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
-                        if let Some(attrs) = attrs {
+                        if !attrs.is_empty() {
                             this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
                         }
 
@@ -1525,8 +1525,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     continue;
                 }
                 let is_param = *is_param.get_or_insert_with(compute_is_param);
-                if !is_param {
-                    self.dcx().emit_err(MisplacedRelaxTraitBound { span: bound.span() });
+                if !is_param && !self.tcx.features().more_maybe_bounds {
+                    self.tcx
+                        .sess
+                        .create_feature_err(
+                            MisplacedRelaxTraitBound { span: bound.span() },
+                            sym::more_maybe_bounds,
+                        )
+                        .emit();
                 }
             }
         }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0f5f4d8023b..d44f953010a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -913,15 +913,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         ret
     }
 
-    fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
+    fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [Attribute] {
         if attrs.is_empty() {
-            None
+            &[]
         } else {
             debug_assert_eq!(id.owner, self.current_hir_id_owner);
             let ret = self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)));
             debug_assert!(!ret.is_empty());
             self.attrs.insert(id.local_id, ret);
-            Some(ret)
+            ret
         }
     }
 
@@ -1216,6 +1216,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     itctx,
                     TraitBoundModifiers::NONE,
                 );
+                let bound = (bound, hir::TraitBoundModifier::None);
                 let bounds = this.arena.alloc_from_iter([bound]);
                 let lifetime_bound = this.elided_dyn_bound(t.span);
                 (bounds, lifetime_bound)
@@ -1348,21 +1349,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             // We can safely ignore constness here since AST validation
                             // takes care of rejecting invalid modifier combinations and
                             // const trait bounds in trait object types.
-                            GenericBound::Trait(ty, modifiers) => match modifiers.polarity {
-                                BoundPolarity::Positive | BoundPolarity::Negative(_) => {
-                                    Some(this.lower_poly_trait_ref(
-                                        ty,
-                                        itctx,
-                                        // Still, don't pass along the constness here; we don't want to
-                                        // synthesize any host effect args, it'd only cause problems.
-                                        TraitBoundModifiers {
-                                            constness: BoundConstness::Never,
-                                            ..*modifiers
-                                        },
-                                    ))
-                                }
-                                BoundPolarity::Maybe(_) => None,
-                            },
+                            GenericBound::Trait(ty, modifiers) => {
+                                // Still, don't pass along the constness here; we don't want to
+                                // synthesize any host effect args, it'd only cause problems.
+                                let modifiers = TraitBoundModifiers {
+                                    constness: BoundConstness::Never,
+                                    ..*modifiers
+                                };
+                                let trait_ref = this.lower_poly_trait_ref(ty, itctx, modifiers);
+                                let polarity = this.lower_trait_bound_modifiers(modifiers);
+                                Some((trait_ref, polarity))
+                            }
                             GenericBound::Outlives(lifetime) => {
                                 if lifetime_bound.is_none() {
                                     lifetime_bound = Some(this.lower_lifetime(lifetime));
@@ -2688,6 +2685,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
                             span: self.lower_span(span),
                         };
+                        let principal = (principal, hir::TraitBoundModifier::None);
 
                         // The original ID is taken by the `PolyTraitRef`,
                         // so the `Ty` itself needs a different one.
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1088db74cc9..9b063a330b7 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1345,14 +1345,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         match bound {
             GenericBound::Trait(trait_ref, modifiers) => {
                 match (ctxt, modifiers.constness, modifiers.polarity) {
-                    (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
-                        self.dcx().emit_err(errors::OptionalTraitSupertrait {
-                            span: trait_ref.span,
-                            path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
-                        });
+                    (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
+                        if !self.features.more_maybe_bounds =>
+                    {
+                        self.session
+                            .create_feature_err(
+                                errors::OptionalTraitSupertrait {
+                                    span: trait_ref.span,
+                                    path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
+                                },
+                                sym::more_maybe_bounds,
+                            )
+                            .emit();
                     }
-                    (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
-                        self.dcx().emit_err(errors::OptionalTraitObject { span: trait_ref.span });
+                    (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
+                        if !self.features.more_maybe_bounds =>
+                    {
+                        self.session
+                            .create_feature_err(
+                                errors::OptionalTraitObject { span: trait_ref.span },
+                                sym::more_maybe_bounds,
+                            )
+                            .emit();
                     }
                     (
                         BoundKind::TraitObject,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 2d9bc45ebc8..e5bc4b38748 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1442,9 +1442,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
             // See `tests/ui/moves/needs-clone-through-deref.rs`
             return false;
         }
+        // We don't want to suggest `.clone()` in a move closure, since the value has already been captured.
         if self.in_move_closure(expr) {
             return false;
         }
+        // We also don't want to suggest cloning a closure itself, since the value has already been captured.
+        if let hir::ExprKind::Closure(_) = expr.kind {
+            return false;
+        }
         // Try to find predicates on *generic params* that would allow copying `ty`
         let mut suggestion =
             if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 9b5ed3b0876..d3d07181096 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -205,6 +205,8 @@ declare_features! (
     (unstable, lifetime_capture_rules_2024, "1.76.0", None),
     /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
     (unstable, link_cfg, "1.14.0", None),
+    /// Allows using `?Trait` trait bounds in more contexts.
+    (internal, more_maybe_bounds, "CURRENT_RUSTC_VERSION", None),
     /// Allows the `multiple_supertrait_upcastable` lint.
     (unstable, multiple_supertrait_upcastable, "1.69.0", None),
     /// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 20b15499234..8c8f760bc41 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2832,7 +2832,11 @@ pub enum TyKind<'hir> {
     OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
-    TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
+    TraitObject(
+        &'hir [(PolyTraitRef<'hir>, TraitBoundModifier)],
+        &'hir Lifetime,
+        TraitObjectSyntax,
+    ),
     /// Unused for now.
     Typeof(&'hir AnonConst),
     /// `TyKind::Infer` means the type should be inferred instead of it having been
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index c202ee41e31..696f548f1ba 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -902,7 +902,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
             try_visit!(visitor.visit_array_length(length));
         }
         TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
-            walk_list!(visitor, visit_poly_trait_ref, bounds);
+            for (bound, _modifier) in bounds {
+                try_visit!(visitor.visit_poly_trait_ref(bound));
+            }
             try_visit!(visitor.visit_lifetime(lifetime));
         }
         TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 58cc0f62111..1821387e85f 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -162,6 +162,7 @@ language_item_table! {
     StructuralPeq,           sym::structural_peq,      structural_peq_trait,       Target::Trait,          GenericRequirement::None;
     Copy,                    sym::copy,                copy_trait,                 Target::Trait,          GenericRequirement::Exact(0);
     Clone,                   sym::clone,               clone_trait,                Target::Trait,          GenericRequirement::None;
+    CloneFn,                 sym::clone_fn,            clone_fn,                   Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
     Sync,                    sym::sync,                sync_trait,                 Target::Trait,          GenericRequirement::Exact(0);
     DiscriminantKind,        sym::discriminant_kind,   discriminant_kind_trait,    Target::Trait,          GenericRequirement::None;
     /// The associated item of the `DiscriminantKind` trait.
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index cc404daa51f..367f6e17e7f 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,4 +1,4 @@
-hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$ty_param_name}`
+hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$qself}`
     .label = ambiguous associated {$assoc_kind} `{$assoc_name}`
 
 hir_analysis_ambiguous_lifetime_bound =
@@ -12,16 +12,21 @@ hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private
     .label = private {$kind}
     .defined_here_label = the {$kind} is defined here
 
-hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}`
+hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$qself}`
 
 hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named ->
         [true] an
         *[false] a similarly named
     } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
 hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
-hir_analysis_assoc_item_not_found_other_sugg = `{$ty_param_name}` has the following associated {$assoc_kind}
+hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind}
+hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg =
+    consider fully qualifying{$identically_named ->
+        [true] {""}
+        *[false] {" "}and renaming
+    } the associated {$assoc_kind}
 hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
-hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name
+hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = ...and changing the associated {$assoc_kind} name
 hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
 
 hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 0316ef69bf8..456dc4e4e07 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -831,7 +831,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
 
 fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
     match ty.kind {
-        hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
+        hir::TyKind::TraitObject([(trait_ref, _)], ..) => match trait_ref.trait_ref.path.segments {
             [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
             _ => false,
         },
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 349dc9ad00e..02ea95852f0 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -652,7 +652,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 debug!(?bounds, ?lifetime, "TraitObject");
                 let scope = Scope::TraitRefBoundary { s: self.scope };
                 self.with(scope, |this| {
-                    for bound in bounds {
+                    for (bound, _) in bounds {
                         this.visit_poly_trait_ref_inner(
                             bound,
                             NonLifetimeBinderAllowed::Deny("trait object types"),
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c83788928a9..c364a561631 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -22,7 +22,7 @@ pub struct AmbiguousAssocItem<'a> {
     pub span: Span,
     pub assoc_kind: &'static str,
     pub assoc_name: Ident,
-    pub ty_param_name: &'a str,
+    pub qself: &'a str,
 }
 
 #[derive(Diagnostic)]
@@ -75,7 +75,7 @@ pub struct AssocItemNotFound<'a> {
     pub span: Span,
     pub assoc_name: Ident,
     pub assoc_kind: &'static str,
-    pub ty_param_name: &'a str,
+    pub qself: &'a str,
     #[subdiagnostic]
     pub label: Option<AssocItemNotFoundLabel<'a>>,
     #[subdiagnostic]
@@ -126,13 +126,32 @@ pub enum AssocItemNotFoundSugg<'a> {
         assoc_kind: &'static str,
         suggested_name: Symbol,
     },
-    #[suggestion(hir_analysis_assoc_item_not_found_other_sugg, code = "{suggested_name}")]
+    #[multipart_suggestion(
+        hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg,
+        style = "verbose"
+    )]
+    SimilarInOtherTraitQPath {
+        #[suggestion_part(code = "<")]
+        lo: Span,
+        #[suggestion_part(code = " as {trait_ref}>")]
+        mi: Span,
+        #[suggestion_part(code = "{suggested_name}")]
+        hi: Option<Span>,
+        trait_ref: String,
+        suggested_name: Symbol,
+        identically_named: bool,
+        #[applicability]
+        applicability: Applicability,
+    },
+    #[suggestion(
+        hir_analysis_assoc_item_not_found_other_sugg,
+        code = "{suggested_name}",
+        applicability = "maybe-incorrect"
+    )]
     Other {
         #[primary_span]
         span: Span,
-        #[applicability]
-        applicability: Applicability,
-        ty_param_name: &'a str,
+        qself: &'a str,
         assoc_kind: &'static str,
         suggested_name: Symbol,
     },
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 6f9c481650b..30c04aa47a3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -6,19 +6,17 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::bug;
-use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
-use rustc_span::{ErrorGuaranteed, Span, Symbol};
+use rustc_span::{sym, ErrorGuaranteed, Span, Symbol};
 use rustc_trait_selection::traits;
 use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use smallvec::SmallVec;
 
 use crate::bounds::Bounds;
 use crate::errors;
-use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
-
-use super::RegionInferReason;
+use crate::hir_ty_lowering::HirTyLowerer;
+use crate::hir_ty_lowering::{AssocItemQSelf, OnlySelfBounds, PredicateFilter, RegionInferReason};
 
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// Add a `Sized` bound to the `bounds` if appropriate.
@@ -75,10 +73,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
+        let mut unique_bounds = FxIndexSet::default();
+        let mut seen_repeat = false;
+        for unbound in &unbounds {
+            if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
+                seen_repeat |= !unique_bounds.insert(unbound_def_id);
+            }
+        }
         if unbounds.len() > 1 {
-            self.dcx().emit_err(errors::MultipleRelaxedDefaultBounds {
+            let err = errors::MultipleRelaxedDefaultBounds {
                 spans: unbounds.iter().map(|ptr| ptr.span).collect(),
-            });
+            };
+            if seen_repeat {
+                self.dcx().emit_err(err);
+            } else if !tcx.features().more_maybe_bounds {
+                self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
+            };
         }
 
         let mut seen_sized_unbound = false;
@@ -288,8 +298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             // one that does define it.
             self.probe_single_bound_for_assoc_item(
                 || traits::supertraits(tcx, trait_ref),
-                trait_ref.skip_binder().print_only_trait_name(),
-                None,
+                AssocItemQSelf::Trait(trait_ref.def_id()),
                 assoc_kind,
                 constraint.ident,
                 path_span,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 8ff6ced8b39..20f06d77489 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -3,7 +3,7 @@ use crate::errors::{
     ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
 };
 use crate::fluent_generated as fluent;
-use crate::hir_ty_lowering::HirTyLowerer;
+use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::unord::UnordMap;
@@ -11,9 +11,9 @@ use rustc_errors::MultiSpan;
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed,
 };
+use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, Node};
+use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::query::Key;
 use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -116,8 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     pub(super) fn complain_about_assoc_item_not_found<I>(
         &self,
         all_candidates: impl Fn() -> I,
-        ty_param_name: &str,
-        ty_param_def_id: Option<LocalDefId>,
+        qself: AssocItemQSelf,
         assoc_kind: ty::AssocKind,
         assoc_name: Ident,
         span: Span,
@@ -139,7 +138,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             );
         }
 
-        let assoc_kind_str = super::assoc_kind_str(assoc_kind);
+        let assoc_kind_str = assoc_kind_str(assoc_kind);
+        let qself_str = qself.to_string(tcx);
 
         // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
         // valid span, so we point at the whole path segment instead.
@@ -149,7 +149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             span: if is_dummy { span } else { assoc_name.span },
             assoc_name,
             assoc_kind: assoc_kind_str,
-            ty_param_name,
+            qself: &qself_str,
             label: None,
             sugg: None,
         };
@@ -219,19 +219,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     suggested_name,
                     identically_named: suggested_name == assoc_name.name,
                 });
-                let hir = tcx.hir();
-                if let Some(def_id) = ty_param_def_id
-                    && let parent = hir.get_parent_item(tcx.local_def_id_to_hir_id(def_id))
-                    && let Some(generics) = hir.get_generics(parent.def_id)
+                if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
+                    // Not using `self.item_def_id()` here as that would yield the opaque type itself if we're
+                    // inside an opaque type while we're interested in the overarching type alias (TAIT).
+                    // FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
+                    && let item_def_id =
+                        tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(ty_param_def_id))
+                    // FIXME: ...which obviously won't have any generics.
+                    && let Some(generics) = tcx.hir().get_generics(item_def_id.def_id)
                 {
-                    if generics.bounds_for_param(def_id).flat_map(|pred| pred.bounds.iter()).any(
-                        |b| match b {
+                    // FIXME: Suggest adding supertrait bounds if we have a `Self` type param.
+                    // FIXME(trait_alias): Suggest adding `Self: Trait` to
+                    // `trait Alias = where Self::Proj:;` with `trait Trait { type Proj; }`.
+                    if generics
+                        .bounds_for_param(ty_param_def_id)
+                        .flat_map(|pred| pred.bounds.iter())
+                        .any(|b| match b {
                             hir::GenericBound::Trait(t, ..) => {
                                 t.trait_ref.trait_def_id() == Some(best_trait)
                             }
                             _ => false,
-                        },
-                    ) {
+                        })
+                    {
                         // The type param already has a bound for `trait_name`, we just need to
                         // change the associated item.
                         err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
@@ -242,48 +251,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         return self.dcx().emit_err(err);
                     }
 
-                    let mut err = self.dcx().create_err(err);
-                    if suggest_constraining_type_param(
-                        tcx,
-                        generics,
-                        &mut err,
-                        &ty_param_name,
-                        &trait_name,
-                        None,
-                        None,
-                    ) && suggested_name != assoc_name.name
+                    let trait_args = &ty::GenericArgs::identity_for_item(tcx, best_trait)[1..];
+                    let mut trait_ref = trait_name.clone();
+                    let applicability = if let [arg, args @ ..] = trait_args {
+                        use std::fmt::Write;
+                        write!(trait_ref, "</* {arg}").unwrap();
+                        args.iter().try_for_each(|arg| write!(trait_ref, ", {arg}")).unwrap();
+                        trait_ref += " */>";
+                        Applicability::HasPlaceholders
+                    } else {
+                        Applicability::MaybeIncorrect
+                    };
+
+                    let identically_named = suggested_name == assoc_name.name;
+
+                    if let DefKind::TyAlias = tcx.def_kind(item_def_id)
+                        && !tcx.type_alias_is_lazy(item_def_id)
                     {
-                        // We suggested constraining a type parameter, but the associated item on it
-                        // was also not an exact match, so we also suggest changing it.
-                        err.span_suggestion_verbose(
-                            assoc_name.span,
-                            fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
+                        err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
+                            lo: ty_param_span.shrink_to_lo(),
+                            mi: ty_param_span.shrink_to_hi(),
+                            hi: (!identically_named).then_some(assoc_name.span),
+                            trait_ref,
+                            identically_named,
                             suggested_name,
-                            Applicability::MaybeIncorrect,
-                        );
+                            applicability,
+                        });
+                    } else {
+                        let mut err = self.dcx().create_err(err);
+                        if suggest_constraining_type_param(
+                            tcx, generics, &mut err, &qself_str, &trait_ref, None, None,
+                        ) && !identically_named
+                        {
+                            // We suggested constraining a type parameter, but the associated item on it
+                            // was also not an exact match, so we also suggest changing it.
+                            err.span_suggestion_verbose(
+                                assoc_name.span,
+                                fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
+                                suggested_name,
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        return err.emit();
                     }
-                    return err.emit();
                 }
                 return self.dcx().emit_err(err);
             }
         }
 
         // If we still couldn't find any associated item, and only one associated item exists,
-        // suggests using it.
+        // suggest using it.
         if let [candidate_name] = all_candidate_names.as_slice() {
-            // This should still compile, except on `#![feature(associated_type_defaults)]`
-            // where it could suggests `type A = Self::A`, thus recursing infinitely.
-            let applicability =
-                if assoc_kind == ty::AssocKind::Type && tcx.features().associated_type_defaults {
-                    Applicability::Unspecified
-                } else {
-                    Applicability::MaybeIncorrect
-                };
-
             err.sugg = Some(errors::AssocItemNotFoundSugg::Other {
                 span: assoc_name.span,
-                applicability,
-                ty_param_name,
+                qself: &qself_str,
                 assoc_kind: assoc_kind_str,
                 suggested_name: *candidate_name,
             });
@@ -349,10 +370,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         self.dcx().emit_err(errors::AssocKindMismatch {
             span,
-            expected: super::assoc_kind_str(expected),
-            got: super::assoc_kind_str(got),
+            expected: assoc_kind_str(expected),
+            got: assoc_kind_str(got),
             expected_because_label,
-            assoc_kind: super::assoc_kind_str(assoc_item.kind),
+            assoc_kind: assoc_kind_str(assoc_item.kind),
             def_span: tcx.def_span(assoc_item.def_id),
             bound_on_assoc_const_label,
             wrap_in_braces_sugg,
@@ -698,7 +719,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         &self,
         associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
         potential_assoc_types: Vec<usize>,
-        trait_bounds: &[hir::PolyTraitRef<'_>],
+        trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)],
     ) {
         if associated_types.values().all(|v| v.is_empty()) {
             return;
@@ -744,12 +765,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // related to issue #91997, turbofishes added only when in an expr or pat
         let mut in_expr_or_pat = false;
         if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
-            let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
+            let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.0.trait_ref.hir_ref_id));
             in_expr_or_pat = match grandparent {
-                Node::Expr(_) | Node::Pat(_) => true,
+                hir::Node::Expr(_) | hir::Node::Pat(_) => true,
                 _ => false,
             };
-            match bound.trait_ref.path.segments {
+            match bound.0.trait_ref.path.segments {
                 // FIXME: `trait_ref.path.span` can point to a full path with multiple
                 // segments, even though `trait_ref.path.segments` is of length `1`. Work
                 // around that bug here, even though it should be fixed elsewhere.
@@ -790,7 +811,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // and we can then use their span to indicate this to the user.
         let bound_names = trait_bounds
             .iter()
-            .filter_map(|poly_trait_ref| {
+            .filter_map(|(poly_trait_ref, _)| {
                 let path = poly_trait_ref.trait_ref.path.segments.last()?;
                 let args = path.args?;
 
@@ -1612,3 +1633,11 @@ fn generics_args_err_extend<'a>(
         _ => {}
     }
 }
+
+pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
+    match kind {
+        ty::AssocKind::Fn => "function",
+        ty::AssocKind::Const => "constant",
+        ty::AssocKind::Type => "type",
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 29c71c3fa50..e7aad0a29c5 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -34,7 +34,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 .ok()
                 .is_some_and(|s| s.trim_end().ends_with('<'));
 
-        let is_global = poly_trait_ref.trait_ref.path.is_global();
+        let is_global = poly_trait_ref.0.trait_ref.path.is_global();
 
         let mut sugg = vec![(
             self_ty.span.shrink_to_lo(),
@@ -176,7 +176,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let mut is_downgradable = true;
         let is_object_safe = match self_ty.kind {
             hir::TyKind::TraitObject(objects, ..) => {
-                objects.iter().all(|o| match o.trait_ref.path.res {
+                objects.iter().all(|(o, _)| match o.trait_ref.path.res {
                     Res::Def(DefKind::Trait, id) => {
                         if Some(id) == owner {
                             // For recursive traits, don't downgrade the error. (#119652)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index d6eb1a66902..ce298641e60 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -55,7 +55,6 @@ use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::wf::object_region_bounds;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
-use std::fmt::Display;
 use std::slice;
 
 /// A path segment that is semantically allowed to have generic arguments.
@@ -193,6 +192,25 @@ pub trait HirTyLowerer<'tcx> {
     }
 }
 
+/// The "qualified self" of an associated item path.
+///
+/// For diagnostic purposes only.
+enum AssocItemQSelf {
+    Trait(DefId),
+    TyParam(LocalDefId, Span),
+    SelfTyAlias,
+}
+
+impl AssocItemQSelf {
+    fn to_string(&self, tcx: TyCtxt<'_>) -> String {
+        match *self {
+            Self::Trait(def_id) => tcx.def_path_str(def_id),
+            Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(),
+            Self::SelfTyAlias => kw::SelfUpper.to_string(),
+        }
+    }
+}
+
 /// New-typed boolean indicating whether explicit late-bound lifetimes
 /// are present in a set of generic arguments.
 ///
@@ -802,6 +820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     fn probe_single_ty_param_bound_for_assoc_ty(
         &self,
         ty_param_def_id: LocalDefId,
+        ty_param_span: Span,
         assoc_name: Ident,
         span: Span,
     ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
@@ -811,19 +830,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name).predicates;
         debug!("predicates={:#?}", predicates);
 
-        let param_name = tcx.hir().ty_param_name(ty_param_def_id);
         self.probe_single_bound_for_assoc_item(
             || {
-                traits::transitive_bounds_that_define_assoc_item(
-                    tcx,
-                    predicates
-                        .iter()
-                        .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))),
-                    assoc_name,
-                )
+                let trait_refs = predicates
+                    .iter()
+                    .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));
+                traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
             },
-            param_name,
-            Some(ty_param_def_id),
+            AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
             ty::AssocKind::Type,
             assoc_name,
             span,
@@ -835,12 +849,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ///
     /// This fails if there is no such bound in the list of candidates or if there are multiple
     /// candidates in which case it reports ambiguity.
-    #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)]
+    #[instrument(level = "debug", skip(self, all_candidates, qself, constraint), ret)]
     fn probe_single_bound_for_assoc_item<I>(
         &self,
         all_candidates: impl Fn() -> I,
-        ty_param_name: impl Display,
-        ty_param_def_id: Option<LocalDefId>,
+        qself: AssocItemQSelf,
         assoc_kind: ty::AssocKind,
         assoc_name: Ident,
         span: Span,
@@ -858,8 +871,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let Some(bound) = matching_candidates.next() else {
             let reported = self.complain_about_assoc_item_not_found(
                 all_candidates,
-                &ty_param_name.to_string(),
-                ty_param_def_id,
+                qself,
                 assoc_kind,
                 assoc_name,
                 span,
@@ -872,13 +884,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         if let Some(bound2) = matching_candidates.next() {
             debug!(?bound2);
 
-            let assoc_kind_str = assoc_kind_str(assoc_kind);
-            let ty_param_name = &ty_param_name.to_string();
+            let assoc_kind_str = errors::assoc_kind_str(assoc_kind);
+            let qself_str = qself.to_string(tcx);
             let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem {
                 span,
                 assoc_kind: assoc_kind_str,
                 assoc_name,
-                ty_param_name,
+                qself: &qself_str,
             });
             // Provide a more specific error code index entry for equality bindings.
             err.code(
@@ -929,7 +941,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         err.span_suggestion_verbose(
                             span.with_hi(assoc_name.span.lo()),
                             "use fully-qualified syntax to disambiguate",
-                            format!("<{ty_param_name} as {}>::", bound.print_only_trait_path()),
+                            format!("<{qself_str} as {}>::", bound.print_only_trait_path()),
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -943,7 +955,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             if !where_bounds.is_empty() {
                 err.help(format!(
                     "consider introducing a new type parameter `T` and adding `where` constraints:\
-                     \n    where\n        T: {ty_param_name},\n{}",
+                     \n    where\n        T: {qself_str},\n{}",
                     where_bounds.join(",\n"),
                 ));
             }
@@ -997,11 +1009,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let tcx = self.tcx();
 
         let assoc_ident = assoc_segment.ident;
-        let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
-            path.res
-        } else {
-            Res::Err
-        };
 
         // Check if we have an enum variant or an inherent associated type.
         let mut variant_resolution = None;
@@ -1038,6 +1045,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
+        let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
+            path.res
+        } else {
+            Res::Err
+        };
+
         // Find the type of the associated item, and the trait where the associated
         // item is declared.
         let bound = match (&qself_ty.kind(), qself_res) {
@@ -1056,8 +1069,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                             ty::Binder::dummy(trait_ref.instantiate_identity()),
                         )
                     },
-                    kw::SelfUpper,
-                    None,
+                    AssocItemQSelf::SelfTyAlias,
                     ty::AssocKind::Type,
                     assoc_ident,
                     span,
@@ -1069,6 +1081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
             ) => self.probe_single_ty_param_bound_for_assoc_ty(
                 param_did.expect_local(),
+                qself.span,
                 assoc_ident,
                 span,
             )?,
@@ -2522,11 +2535,3 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         Some(r)
     }
 }
-
-fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
-    match kind {
-        ty::AssocKind::Fn => "function",
-        ty::AssocKind::Const => "constant",
-        ty::AssocKind::Type => "type",
-    }
-}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
index aafadc7f9cb..b3c7a1ff8a8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
@@ -27,7 +27,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         &self,
         span: Span,
         hir_id: hir::HirId,
-        hir_trait_bounds: &[hir::PolyTraitRef<'tcx>],
+        hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
         lifetime: &hir::Lifetime,
         borrowed: bool,
         representation: DynKind,
@@ -37,7 +37,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let mut bounds = Bounds::default();
         let mut potential_assoc_types = Vec::new();
         let dummy_self = self.tcx().types.trait_object_dummy_self;
-        for trait_bound in hir_trait_bounds.iter().rev() {
+        for (trait_bound, modifier) in hir_trait_bounds.iter().rev() {
+            if *modifier == hir::TraitBoundModifier::Maybe {
+                continue;
+            }
             if let GenericArgCountResult {
                 correct:
                     Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
@@ -249,7 +252,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let args = tcx.mk_args(&args);
 
                 let span = i.bottom().1;
-                let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
+                let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| {
                     hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
                         && hir_bound.span.contains(span)
                 });
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index a982b84e755..e25f43e169d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -300,13 +300,16 @@ impl<'a> State<'a> {
                     self.word_space("dyn");
                 }
                 let mut first = true;
-                for bound in bounds {
+                for (bound, modifier) in bounds {
                     if first {
                         first = false;
                     } else {
                         self.nbsp();
                         self.word_space("+");
                     }
+                    if *modifier == TraitBoundModifier::Maybe {
+                        self.word("?");
+                    }
                     self.print_poly_trait_ref(bound);
                 }
                 if !lifetime.is_elided() {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index a87b3c2c135..987dbf6db63 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -144,13 +144,18 @@ lint_builtin_special_module_name_used_main = found module declaration for main.r
 
 lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters
 
-lint_builtin_type_alias_bounds_help = use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
-
-lint_builtin_type_alias_generic_bounds = bounds on generic parameters are not enforced in type aliases
-    .suggestion = the bound will not be checked when the type alias is used, and should be removed
-
-lint_builtin_type_alias_where_clause = where clauses are not enforced in type aliases
-    .suggestion = the clause will not be checked when the type alias is used, and should be removed
+lint_builtin_type_alias_bounds_enable_feat_help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
+lint_builtin_type_alias_bounds_label = will not be checked at usage sites of the type alias
+lint_builtin_type_alias_bounds_limitation_note = this is a known limitation of the type checker that may be lifted in a future edition.
+    see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+lint_builtin_type_alias_bounds_param_bounds = bounds on generic parameters in type aliases are not enforced
+    .suggestion = remove {$count ->
+        [one] this bound
+        *[other] these bounds
+    }
+lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg = fully qualify this associated type
+lint_builtin_type_alias_bounds_where_clause = where clauses on type aliases are not enforced
+    .suggestion = remove this where clause
 
 lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed
 lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9ebada0fff3..ab0b47d48e5 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -31,12 +31,11 @@ use crate::{
         BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
         BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
         BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
-        BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds,
-        BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause,
+        BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
         BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
         BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe,
         BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
-        BuiltinWhileTrue, InvalidAsmLabel, SuggestChangingAssocTypes,
+        BuiltinWhileTrue, InvalidAsmLabel,
     },
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
 };
@@ -1391,64 +1390,80 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// The trait bounds in a type alias are currently ignored, and should not
-    /// be included to avoid confusion. This was previously allowed
-    /// unintentionally; this may become a hard error in the future.
+    /// Trait and lifetime bounds on generic parameters and in where clauses of
+    /// type aliases are not checked at usage sites of the type alias. Moreover,
+    /// they are not thoroughly checked for correctness at their definition site
+    /// either similar to the aliased type.
+    ///
+    /// This is a known limitation of the type checker that may be lifted in a
+    /// future edition. Permitting such bounds in light of this was unintentional.
+    ///
+    /// While these bounds may have secondary effects such as enabling the use of
+    /// "shorthand" associated type paths[^1] and affecting the default trait
+    /// object lifetime[^2] of trait object types passed to the type alias, this
+    /// should not have been allowed until the aforementioned restrictions of the
+    /// type checker have been lifted.
+    ///
+    /// Using such bounds is highly discouraged as they are actively misleading.
+    ///
+    /// [^1]: I.e., paths of the form `T::Assoc` where `T` is a type parameter
+    /// bounded by trait `Trait` which defines an associated type called `Assoc`
+    /// as opposed to a fully qualified path of the form `<T as Trait>::Assoc`.
+    /// [^2]: <https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes>
     TYPE_ALIAS_BOUNDS,
     Warn,
     "bounds in type aliases are not enforced"
 }
 
-declare_lint_pass!(
-    /// Lint for trait and lifetime bounds in type aliases being mostly ignored.
-    /// They are relevant when using associated types, but otherwise neither checked
-    /// at definition site nor enforced at use site.
-    TypeAliasBounds => [TYPE_ALIAS_BOUNDS]
-);
+declare_lint_pass!(TypeAliasBounds => [TYPE_ALIAS_BOUNDS]);
 
 impl TypeAliasBounds {
-    pub(crate) fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool {
-        match *qpath {
-            hir::QPath::TypeRelative(ty, _) => {
-                // If this is a type variable, we found a `T::Assoc`.
-                match ty.kind {
-                    hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
-                        matches!(path.res, Res::Def(DefKind::TyParam, _))
-                    }
-                    _ => false,
-                }
-            }
-            hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false,
+    pub(crate) fn affects_object_lifetime_defaults(pred: &hir::WherePredicate<'_>) -> bool {
+        // Bounds of the form `T: 'a` with `T` type param affect object lifetime defaults.
+        if let hir::WherePredicate::BoundPredicate(pred) = pred
+            && pred.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Outlives(_)))
+            && pred.bound_generic_params.is_empty() // indeed, even if absent from the RHS
+            && pred.bounded_ty.as_generic_param().is_some()
+        {
+            return true;
         }
+        false
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return };
+        let hir::ItemKind::TyAlias(hir_ty, generics) = item.kind else { return };
 
-        // Bounds of lazy type aliases and TAITs are respected.
-        if cx.tcx.type_alias_is_lazy(item.owner_id) {
+        // There must not be a where clause.
+        if generics.predicates.is_empty() {
             return;
         }
 
-        let ty = cx.tcx.type_of(item.owner_id).skip_binder();
-        if ty.has_inherent_projections() {
-            // Bounds of type aliases that contain opaque types or inherent projections are
-            // respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X =
-            // Type::Inherent;`.
+        // Bounds of lazy type aliases and TAITs are respected.
+        if cx.tcx.type_alias_is_lazy(item.owner_id) {
             return;
         }
 
-        // There must not be a where clause
-        if type_alias_generics.predicates.is_empty() {
+        // FIXME(generic_const_exprs): Revisit this before stabilization.
+        // See also `tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs`.
+        let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
+        if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION)
+            && cx.tcx.features().generic_const_exprs
+        {
             return;
         }
 
+        // NOTE(inherent_associated_types): While we currently do take some bounds in type
+        // aliases into consideration during IAT *selection*, we don't perform full use+def
+        // site wfchecking for such type aliases. Therefore TAB should still trigger.
+        // See also `tests/ui/associated-inherent-types/type-alias-bounds.rs`.
+
         let mut where_spans = Vec::new();
         let mut inline_spans = Vec::new();
         let mut inline_sugg = Vec::new();
-        for p in type_alias_generics.predicates {
+
+        for p in generics.predicates {
             let span = p.span();
             if p.in_where_clause() {
                 where_spans.push(span);
@@ -1460,37 +1475,57 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
             }
         }
 
-        let mut suggested_changing_assoc_types = false;
-        if !where_spans.is_empty() {
-            let sub = (!suggested_changing_assoc_types).then(|| {
-                suggested_changing_assoc_types = true;
-                SuggestChangingAssocTypes { ty: hir_ty }
-            });
+        let mut ty = Some(hir_ty);
+        let enable_feat_help = cx.tcx.sess.is_nightly_build();
+
+        if let [.., label_sp] = *where_spans {
             cx.emit_span_lint(
                 TYPE_ALIAS_BOUNDS,
                 where_spans,
-                BuiltinTypeAliasWhereClause {
-                    suggestion: type_alias_generics.where_clause_span,
-                    sub,
+                BuiltinTypeAliasBounds {
+                    in_where_clause: true,
+                    label: label_sp,
+                    enable_feat_help,
+                    suggestions: vec![(generics.where_clause_span, String::new())],
+                    preds: generics.predicates,
+                    ty: ty.take(),
                 },
             );
         }
-
-        if !inline_spans.is_empty() {
-            let suggestion = BuiltinTypeAliasGenericBoundsSuggestion { suggestions: inline_sugg };
-            let sub = (!suggested_changing_assoc_types).then(|| {
-                suggested_changing_assoc_types = true;
-                SuggestChangingAssocTypes { ty: hir_ty }
-            });
+        if let [.., label_sp] = *inline_spans {
             cx.emit_span_lint(
                 TYPE_ALIAS_BOUNDS,
                 inline_spans,
-                BuiltinTypeAliasGenericBounds { suggestion, sub },
+                BuiltinTypeAliasBounds {
+                    in_where_clause: false,
+                    label: label_sp,
+                    enable_feat_help,
+                    suggestions: inline_sugg,
+                    preds: generics.predicates,
+                    ty,
+                },
             );
         }
     }
 }
 
+pub(crate) struct ShorthandAssocTyCollector {
+    pub(crate) qselves: Vec<Span>,
+}
+
+impl hir::intravisit::Visitor<'_> for ShorthandAssocTyCollector {
+    fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, _: Span) {
+        // Look for "type-parameter shorthand-associated-types". I.e., paths of the
+        // form `T::Assoc` with `T` type param. These are reliant on trait bounds.
+        if let hir::QPath::TypeRelative(qself, _) = qpath
+            && qself.as_generic_param().is_some()
+        {
+            self.qselves.push(qself.span);
+        }
+        hir::intravisit::walk_qpath(self, qpath, id)
+    }
+}
+
 declare_lint! {
     /// The `trivial_bounds` lint detects trait bounds that don't depend on
     /// any type parameters.
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 1f0954c6e9f..b669a3c6288 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2,14 +2,16 @@
 #![allow(rustc::untranslatable_diagnostic)]
 use std::num::NonZero;
 
-use crate::errors::RequestedLevel;
+use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
+use crate::errors::{OverruledAttributeSub, RequestedLevel};
 use crate::fluent_generated as fluent;
+use crate::LateContext;
 use rustc_errors::{
     codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString,
     ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp,
     Subdiagnostic, SuggestionStyle,
 };
-use rustc_hir::{def::Namespace, def_id::DefId};
+use rustc_hir::{self as hir, def::Namespace, def_id::DefId};
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{
     inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
@@ -22,10 +24,6 @@ use rustc_span::{
     Span, Symbol,
 };
 
-use crate::{
-    builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext,
-};
-
 // array_into_iter.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_shadowed_into_iter)]
@@ -263,62 +261,6 @@ pub struct BuiltinUnreachablePub<'a> {
     pub help: Option<()>,
 }
 
-pub struct SuggestChangingAssocTypes<'a, 'b> {
-    pub ty: &'a rustc_hir::Ty<'b>,
-}
-
-impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        // Access to associates types should use `<T as Bound>::Assoc`, which does not need a
-        // bound. Let's see if this type does that.
-
-        // We use a HIR visitor to walk the type.
-        use rustc_hir::intravisit::{self, Visitor};
-        struct WalkAssocTypes<'a, 'b, G: EmissionGuarantee> {
-            err: &'a mut Diag<'b, G>,
-        }
-        impl<'a, 'b, G: EmissionGuarantee> Visitor<'_> for WalkAssocTypes<'a, 'b, G> {
-            fn visit_qpath(
-                &mut self,
-                qpath: &rustc_hir::QPath<'_>,
-                id: rustc_hir::HirId,
-                span: Span,
-            ) {
-                if TypeAliasBounds::is_type_variable_assoc(qpath) {
-                    self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help);
-                }
-                intravisit::walk_qpath(self, qpath, id)
-            }
-        }
-
-        // Let's go for a walk!
-        let mut visitor = WalkAssocTypes { err: diag };
-        visitor.visit_ty(self.ty);
-    }
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_builtin_type_alias_where_clause)]
-pub struct BuiltinTypeAliasWhereClause<'a, 'b> {
-    #[suggestion(code = "", applicability = "machine-applicable")]
-    pub suggestion: Span,
-    #[subdiagnostic]
-    pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(lint_builtin_type_alias_generic_bounds)]
-pub struct BuiltinTypeAliasGenericBounds<'a, 'b> {
-    #[subdiagnostic]
-    pub suggestion: BuiltinTypeAliasGenericBoundsSuggestion,
-    #[subdiagnostic]
-    pub sub: Option<SuggestChangingAssocTypes<'a, 'b>>,
-}
-
 #[derive(LintDiagnostic)]
 #[diag(lint_macro_expr_fragment_specifier_2024_migration)]
 pub struct MacroExprFragment2024 {
@@ -326,21 +268,72 @@ pub struct MacroExprFragment2024 {
     pub suggestion: Span,
 }
 
-pub struct BuiltinTypeAliasGenericBoundsSuggestion {
+pub struct BuiltinTypeAliasBounds<'a, 'hir> {
+    pub in_where_clause: bool,
+    pub label: Span,
+    pub enable_feat_help: bool,
     pub suggestions: Vec<(Span, String)>,
+    pub preds: &'hir [hir::WherePredicate<'hir>],
+    pub ty: Option<&'a hir::Ty<'hir>>,
 }
 
-impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _f: &F,
-    ) {
-        diag.multipart_suggestion(
-            fluent::lint_suggestion,
-            self.suggestions,
-            Applicability::MachineApplicable,
-        );
+impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_, '_> {
+    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
+        diag.primary_message(if self.in_where_clause {
+            fluent::lint_builtin_type_alias_bounds_where_clause
+        } else {
+            fluent::lint_builtin_type_alias_bounds_param_bounds
+        });
+        diag.span_label(self.label, fluent::lint_builtin_type_alias_bounds_label);
+        diag.note(fluent::lint_builtin_type_alias_bounds_limitation_note);
+        if self.enable_feat_help {
+            diag.help(fluent::lint_builtin_type_alias_bounds_enable_feat_help);
+        }
+
+        // We perform the walk in here instead of in `<TypeAliasBounds as LateLintPass>` to
+        // avoid doing throwaway work in case the lint ends up getting suppressed.
+        let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() };
+        if let Some(ty) = self.ty {
+            hir::intravisit::Visitor::visit_ty(&mut collector, ty);
+        }
+
+        let affect_object_lifetime_defaults = self
+            .preds
+            .iter()
+            .filter(|pred| pred.in_where_clause() == self.in_where_clause)
+            .any(|pred| TypeAliasBounds::affects_object_lifetime_defaults(pred));
+
+        // If there are any shorthand assoc tys, then the bounds can't be removed automatically.
+        // The user first needs to fully qualify the assoc tys.
+        let applicability = if !collector.qselves.is_empty() || affect_object_lifetime_defaults {
+            Applicability::MaybeIncorrect
+        } else {
+            Applicability::MachineApplicable
+        };
+
+        diag.arg("count", self.suggestions.len());
+        diag.multipart_suggestion(fluent::lint_suggestion, self.suggestions, applicability);
+
+        // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via
+        // `<T as /* Trait */>::Assoc` to remove their reliance on any type param bounds.
+        //
+        // Instead of attempting to figure out the necessary trait ref, just use a
+        // placeholder. Since we don't record type-dependent resolutions for non-body
+        // items like type aliases, we can't simply deduce the corresp. trait from
+        // the HIR path alone without rerunning parts of HIR ty lowering here
+        // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible.
+        //
+        // (We could employ some simple heuristics but that's likely not worth it).
+        for qself in collector.qselves {
+            diag.multipart_suggestion(
+                fluent::lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg,
+                vec![
+                    (qself.shrink_to_lo(), "<".into()),
+                    (qself.shrink_to_hi(), " as /* Trait */>".into()),
+                ],
+                Applicability::HasPlaceholders,
+            );
+        }
     }
 }
 
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 2f8eea6cd18..93c606a954e 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -429,7 +429,7 @@ fn ty_has_local_parent(
             path_has_local_parent(ty_path, cx, impl_parent, impl_parent_parent)
         }
         TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => path_has_local_parent(
-            principle_poly_trait_ref.trait_ref.path,
+            principle_poly_trait_ref.0.trait_ref.path,
             cx,
             impl_parent,
             impl_parent_parent,
@@ -527,7 +527,7 @@ fn self_ty_kind_for_diagnostic(ty: &rustc_hir::Ty<'_>, tcx: TyCtxt<'_>) -> (Span
                 .to_string(),
         ),
         TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
-            let path = &principle_poly_trait_ref.trait_ref.path;
+            let path = &principle_poly_trait_ref.0.trait_ref.path;
             (
                 path_span_without_args(path),
                 path.res
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index 6983e7abbd6..552245f0cdd 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -113,9 +113,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
 
     fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
         let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
-        for bound in &bounds[..] {
+        for (bound, modifier) in &bounds[..] {
             let def_id = bound.trait_ref.trait_def_id();
-            if cx.tcx.lang_items().drop_trait() == def_id {
+            if cx.tcx.lang_items().drop_trait() == def_id
+                && *modifier != hir::TraitBoundModifier::Maybe
+            {
                 let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
                 cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
             }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d2b444a066b..da98e3b9f46 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1864,9 +1864,9 @@ impl<'tcx> Ty<'tcx> {
             // Definitely absolutely not copy.
             ty::Ref(_, _, hir::Mutability::Mut) => false,
 
-            // Thin pointers & thin shared references are pure-clone-copy, but for
-            // anything with custom metadata it might be more complicated.
-            ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false,
+            // The standard library has a blanket Copy impl for shared references and raw pointers,
+            // for all unsized types.
+            ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => true,
 
             ty::Coroutine(..) | ty::CoroutineWitness(..) => false,
 
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 8209e5e2711..58fdc2d9e45 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -3,6 +3,7 @@
 use crate::simplify::simplify_duplicate_switch_targets;
 use crate::take_array;
 use rustc_ast::attr;
+use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout;
@@ -271,8 +272,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
             return;
         }
 
-        let trait_def_id = self.tcx.trait_of_item(fn_def_id);
-        if trait_def_id.is_none() || trait_def_id != self.tcx.lang_items().clone_trait() {
+        if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) {
             return;
         }
 
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 6835a39cf36..d2f50040821 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -17,7 +17,7 @@ use std::iter;
 
 use crate::{
     abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
-    mentioned_items, pass_manager as pm, remove_noop_landing_pads, simplify,
+    instsimplify, mentioned_items, pass_manager as pm, remove_noop_landing_pads, simplify,
 };
 use rustc_middle::mir::patch::MirPatch;
 use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
@@ -154,6 +154,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
             &deref_separator::Derefer,
             &remove_noop_landing_pads::RemoveNoopLandingPads,
             &simplify::SimplifyCfg::MakeShim,
+            &instsimplify::InstSimplify,
             &abort_unwinding_calls::AbortUnwindingCalls,
             &add_call_guards::CriticalCallEdges,
         ],
@@ -434,6 +435,9 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
     match self_ty.kind() {
         ty::FnDef(..) | ty::FnPtr(_) => builder.copy_shim(),
         ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
+        ty::CoroutineClosure(_, args) => {
+            builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
+        }
         ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
         ty::Coroutine(coroutine_def_id, args) => {
             assert_eq!(tcx.coroutine_movability(*coroutine_def_id), hir::Movability::Movable);
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 770ac9a929e..60beaa0df84 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -217,7 +217,10 @@ where
         // impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
         ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
 
-        ty::CoroutineClosure(..) => Err(NoSolution),
+        // impl Copy/Clone for CoroutineClosure where Self::TupledUpvars: Copy/Clone
+        ty::CoroutineClosure(_, args) => {
+            Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())])
+        }
 
         // only when `coroutine_clone` is enabled and the coroutine is movable
         // impl Copy/Clone for Coroutine where T: Copy/Clone forall T in (upvars, witnesses)
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 0b2c3044039..535b53a836e 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -457,14 +457,3 @@ impl<'a> Parser<'a> {
         Err(self.dcx().create_err(err))
     }
 }
-
-/// The attributes are complete if all attributes are either a doc comment or a
-/// builtin attribute other than `cfg_attr`.
-pub fn is_complete(attrs: &[ast::Attribute]) -> bool {
-    attrs.iter().all(|attr| {
-        attr.is_doc_comment()
-            || attr.ident().is_some_and(|ident| {
-                ident.name != sym::cfg_attr && rustc_feature::is_builtin_attr_name(ident.name)
-            })
-    })
-}
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index dc5f98f7be8..5dc49ea51d1 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -60,10 +60,6 @@ impl AttrWrapper {
     pub fn is_empty(&self) -> bool {
         self.attrs.is_empty()
     }
-
-    pub fn is_complete(&self) -> bool {
-        crate::parser::attr::is_complete(&self.attrs)
-    }
 }
 
 /// Returns `true` if `attrs` contains a `cfg` or `cfg_attr` attribute
@@ -114,17 +110,15 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
             replace_ranges.sort_by_key(|(range, _)| range.start);
 
             #[cfg(debug_assertions)]
-            {
-                for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() {
-                    assert!(
-                        range.end <= next_range.start || range.end >= next_range.end,
-                        "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
-                        range,
-                        tokens,
-                        next_range,
-                        next_tokens,
-                    );
-                }
+            for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() {
+                assert!(
+                    range.end <= next_range.start || range.end >= next_range.end,
+                    "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
+                    range,
+                    tokens,
+                    next_range,
+                    next_tokens,
+                );
             }
 
             // Process the replace ranges, starting from the highest start
@@ -137,9 +131,9 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
             // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
             //
             // By starting processing from the replace range with the greatest
-            // start position, we ensure that any replace range which encloses
-            // another replace range will capture the *replaced* tokens for the inner
-            // range, not the original tokens.
+            // start position, we ensure that any (outer) replace range which
+            // encloses another (inner) replace range will fully overwrite the
+            // inner range's replacement.
             for (range, target) in replace_ranges.into_iter().rev() {
                 assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}");
 
@@ -199,20 +193,20 @@ impl<'a> Parser<'a> {
         force_collect: ForceCollect,
         f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, bool)>,
     ) -> PResult<'a, R> {
-        // Skip collection when nothing could observe the collected tokens, i.e.
-        // all of the following conditions hold.
-        // - We are not force collecting tokens (because force collection
-        //   requires tokens by definition).
-        if matches!(force_collect, ForceCollect::No)
-            // - None of our outer attributes require tokens.
-            && attrs.is_complete()
-            // - Our target doesn't support custom inner attributes (custom
+        // We must collect if anything could observe the collected tokens, i.e.
+        // if any of the following conditions hold.
+        // - We are force collecting tokens (because force collection requires
+        //   tokens by definition).
+        let needs_collection = matches!(force_collect, ForceCollect::Yes)
+            // - Any of our outer attributes require tokens.
+            || needs_tokens(&attrs.attrs)
+            // - Our target supports custom inner attributes (custom
             //   inner attribute invocation might require token capturing).
-            && !R::SUPPORTS_CUSTOM_INNER_ATTRS
-            // - We are not in `capture_cfg` mode (which requires tokens if
+            || R::SUPPORTS_CUSTOM_INNER_ATTRS
+            // - We are in `capture_cfg` mode (which requires tokens if
             //   the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
-            && !self.capture_cfg
-        {
+            || self.capture_cfg;
+        if !needs_collection {
             return Ok(f(self, attrs.attrs)?.0);
         }
 
@@ -250,28 +244,28 @@ impl<'a> Parser<'a> {
             return Ok(ret);
         }
 
-        // This is similar to the "skip collection" check at the start of this
-        // function, but now that we've parsed an AST node we have more
+        // This is similar to the `needs_collection` check at the start of this
+        // function, but now that we've parsed an AST node we have complete
         // information available. (If we return early here that means the
         // setup, such as cloning the token cursor, was unnecessary. That's
         // hard to avoid.)
         //
-        // Skip collection when nothing could observe the collected tokens, i.e.
-        // all of the following conditions hold.
-        // - We are not force collecting tokens.
-        if matches!(force_collect, ForceCollect::No)
-            // - None of our outer *or* inner attributes require tokens.
-            //   (`attrs` was just outer attributes, but `ret.attrs()` is outer
-            //   and inner attributes. That makes this check more precise than
-            //   `attrs.is_complete()` at the start of the function, and we can
-            //   skip the subsequent check on `R::SUPPORTS_CUSTOM_INNER_ATTRS`.
-            && crate::parser::attr::is_complete(ret.attrs())
-            // - We are not in `capture_cfg` mode, or we are but there are no
-            //   `#[cfg]` or `#[cfg_attr]` attributes. (During normal
-            //   non-`capture_cfg` parsing, we don't need any special capturing
-            //   for those attributes, because they're builtin.)
-            && (!self.capture_cfg || !has_cfg_or_cfg_attr(ret.attrs()))
-        {
+        // We must collect if anything could observe the collected tokens, i.e.
+        // if any of the following conditions hold.
+        // - We are force collecting tokens.
+        let needs_collection = matches!(force_collect, ForceCollect::Yes)
+            // - Any of our outer *or* inner attributes require tokens.
+            //   (`attr.attrs` was just outer attributes, but `ret.attrs()` is
+            //   outer and inner attributes. So this check is more precise than
+            //   the earlier `needs_tokens` check, and we don't need to
+            //   check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
+            || needs_tokens(ret.attrs())
+            // - We are in `capture_cfg` mode and there are `#[cfg]` or
+            //   `#[cfg_attr]` attributes. (During normal non-`capture_cfg`
+            //   parsing, we don't need any special capturing for those
+            //   attributes, because they're builtin.)
+            || (self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs()));
+        if !needs_collection {
             return Ok(ret);
         }
 
@@ -297,11 +291,13 @@ impl<'a> Parser<'a> {
         // with `None`, which means the relevant tokens will be removed. (More
         // details below.)
         let mut inner_attr_replace_ranges = Vec::new();
-        for inner_attr in ret.attrs().iter().filter(|a| a.style == ast::AttrStyle::Inner) {
-            if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) {
-                inner_attr_replace_ranges.push((attr_range, None));
-            } else {
-                self.dcx().span_delayed_bug(inner_attr.span, "Missing token range for attribute");
+        for attr in ret.attrs() {
+            if attr.style == ast::AttrStyle::Inner {
+                if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&attr.id) {
+                    inner_attr_replace_ranges.push((attr_range, None));
+                } else {
+                    self.dcx().span_delayed_bug(attr.span, "Missing token range for attribute");
+                }
             }
         }
 
@@ -337,8 +333,7 @@ impl<'a> Parser<'a> {
         // When parsing `m`:
         // - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute).
         // - `inner_attr_replace_ranges` is empty.
-        // - `replace_range_start..replace_ranges_end` has two entries.
-        //   - One to delete the inner attribute (`17..27`), obtained when parsing `g` (see above).
+        // - `replace_range_start..replace_ranges_end` has one entry.
         //   - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`,
         //     including its outer attribute), with:
         //     - `attrs`: includes the outer and the inner attr.
@@ -369,12 +364,10 @@ impl<'a> Parser<'a> {
 
             // What is the status here when parsing the example code at the top of this method?
             //
-            // When parsing `g`, we add two entries:
+            // When parsing `g`, we add one entry:
             // - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with:
             //   - `attrs`: includes the outer and the inner attr.
             //   - `tokens`: lazy tokens for `g` (with its inner attr deleted).
-            // - `inner_attr_replace_ranges` contains the one entry to delete the inner attr's
-            //   tokens (`17..27`).
             //
             // When parsing `m`, we do nothing here.
 
@@ -384,7 +377,6 @@ impl<'a> Parser<'a> {
             let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos };
             let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
             self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target)));
-            self.capture_state.replace_ranges.extend(inner_attr_replace_ranges);
         } else if matches!(self.capture_state.capturing, Capturing::No) {
             // Only clear the ranges once we've finished capturing entirely, i.e. we've finished
             // the outermost call to this method.
@@ -461,6 +453,19 @@ fn make_attr_token_stream(
     AttrTokenStream::new(stack_top.inner)
 }
 
+/// Tokens are needed if:
+/// - any non-single-segment attributes (other than doc comments) are present; or
+/// - any `cfg_attr` attributes are present;
+/// - any single-segment, non-builtin attributes are present.
+fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
+    attrs.iter().any(|attr| match attr.ident() {
+        None => !attr.is_doc_comment(),
+        Some(ident) => {
+            ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name)
+        }
+    })
+}
+
 // Some types are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(target_pointer_width = "64")]
 mod size_asserts {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 9aaf4b99243..112855e6d1f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2483,12 +2483,15 @@ impl<'a> Parser<'a> {
     /// `check_pub` adds additional `pub` to the checks in case users place it
     /// wrongly, can be used to ensure `pub` never comes after `default`.
     pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
+        const ALL_QUALS: &[Symbol] =
+            &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern];
+
         // We use an over-approximation here.
         // `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
         // `pub` is added in case users got confused with the ordering like `async pub fn`,
         // only if it wasn't preceded by `default` as `default pub` is invalid.
         let quals: &[Symbol] = if check_pub {
-            &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
+            ALL_QUALS
         } else {
             &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
         };
@@ -2518,9 +2521,9 @@ impl<'a> Parser<'a> {
             || self.check_keyword_case(kw::Extern, case)
                 && self.look_ahead(1, |t| t.can_begin_string_literal())
                 && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) ||
-                    // this branch is only for better diagnostic in later, `pub` is not allowed here
+                    // this branch is only for better diagnostics; `pub`, `unsafe`, etc. are not allowed here
                     (self.may_recover()
-                        && self.look_ahead(2, |t| t.is_keyword(kw::Pub))
+                        && self.look_ahead(2, |t| ALL_QUALS.iter().any(|&kw| t.is_keyword(kw)))
                         && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case))))
     }
 
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 55514883cb1..239bc8e7acc 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -54,7 +54,24 @@ impl Publicness {
     }
 }
 
-fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
+fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> {
+    match ty.kind {
+        TyKind::Path(hir::QPath::Resolved(_, path)) => {
+            if let Res::Def(def_kind, def_id) = path.res
+                && let Some(local_def_id) = def_id.as_local()
+            {
+                Some((local_def_id, def_kind))
+            } else {
+                None
+            }
+        }
+        TyKind::Slice(ty) | TyKind::Array(ty, _) => adt_of(ty),
+        TyKind::Ptr(ty) | TyKind::Ref(_, ty) => adt_of(ty.ty),
+        _ => None,
+    }
+}
+
+fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool {
     // treat PhantomData and positional ZST as public,
     // we don't want to lint types which only have them,
     // cause it's a common way to use such types to check things like well-formedness
@@ -79,10 +96,7 @@ fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
 /// for enum and union, just check they are public,
 /// and doesn't solve types like &T for now, just skip them
 fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness {
-    if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
-        && let Res::Def(def_kind, def_id) = path.res
-        && def_id.is_local()
-    {
+    if let Some((def_id, def_kind)) = adt_of(ty) {
         return match def_kind {
             DefKind::Enum | DefKind::Union => {
                 let ty_is_public = tcx.visibility(def_id).is_public();
@@ -565,10 +579,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
     }
 
     fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool {
-        if let TyKind::Path(hir::QPath::Resolved(_, path)) =
-            self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
-            && let Res::Def(def_kind, def_id) = path.res
-            && let Some(local_def_id) = def_id.as_local()
+        if let Some((local_def_id, def_kind)) =
+            adt_of(self.tcx.hir().item(impl_id).expect_impl().self_ty)
             && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
         {
             if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id
@@ -915,7 +927,7 @@ fn create_and_seed_worklist(
                     match tcx.def_kind(id) {
                         DefKind::Impl { .. } => false,
                         DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
-                        DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
+                        DefKind::Struct => struct_all_fields_are_public(tcx, id) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
                         _ => true
                     })
                 .map(|id| (id, ComesFromAllowExpect::No))
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 046ae5fc593..df80f4df5b9 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1448,7 +1448,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         );
 
         if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
-            err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span });
+            let label_span = ident.span.shrink_to_hi();
+            let mut spans = MultiSpan::from_span(label_span);
+            spans.push_span_label(label_span, "put a macro name here");
+            err.subdiagnostic(MaybeMissingMacroRulesName { spans: spans });
             return;
         }
 
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 0a68231c6fe..698147765b3 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -669,7 +669,7 @@ pub(crate) struct MacroSuggMovePosition {
 #[note(resolve_missing_macro_rules_name)]
 pub(crate) struct MaybeMissingMacroRulesName {
     #[primary_span]
-    pub(crate) span: Span,
+    pub(crate) spans: MultiSpan,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2b30ca8a894..cfd263d5951 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -557,6 +557,7 @@ symbols! {
         clobber_abi,
         clone,
         clone_closures,
+        clone_fn,
         clone_from,
         closure,
         closure_lifetime_binder,
@@ -1229,6 +1230,7 @@ symbols! {
         modifiers,
         module,
         module_path,
+        more_maybe_bounds,
         more_qualified_paths,
         more_struct_aliases,
         movbe_target_feature,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
index b91b755d683..a892ce58861 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
@@ -84,7 +84,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
             }
 
             hir::TyKind::TraitObject(bounds, ..) => {
-                for bound in bounds {
+                for (bound, _) in bounds {
                     self.current_index.shift_in(1);
                     self.visit_poly_trait_ref(bound);
                     self.current_index.shift_out(1);
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index ce157ff3dc8..e5d97976534 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -607,7 +607,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
             _,
         ) = t.kind
         {
-            for ptr in poly_trait_refs {
+            for (ptr, _) in poly_trait_refs {
                 if Some(self.1) == ptr.trait_ref.trait_def_id() {
                     self.0.push(ptr.span);
                 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 87fdc5ddff8..89ae6f4ccab 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -437,7 +437,7 @@ pub fn report_object_safety_error<'tcx>(
         if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
             // Do not suggest `impl Trait` when dealing with things like super-traits.
             err.span_suggestion_verbose(
-                ty.span.until(trait_ref.span),
+                ty.span.until(trait_ref.0.span),
                 "consider using an opaque type instead",
                 "impl ",
                 Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 885216e6216..d1381d24764 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3040,11 +3040,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     match ty.kind {
                         hir::TyKind::TraitObject(traits, _, _) => {
                             let (span, kw) = match traits {
-                                [first, ..] if first.span.lo() == ty.span.lo() => {
+                                [(first, _), ..] if first.span.lo() == ty.span.lo() => {
                                     // Missing `dyn` in front of trait object.
                                     (ty.span.shrink_to_lo(), "dyn ")
                                 }
-                                [first, ..] => (ty.span.until(first.span), ""),
+                                [(first, _), ..] => (ty.span.until(first.span), ""),
                                 [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
                             };
                             let needs_parens = traits.len() != 1;
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index c007cd5314a..699c05466bd 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2262,8 +2262,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 }
             }
 
-            // FIXME(async_closures): These are never clone, for now.
-            ty::CoroutineClosure(_, _) => None,
+            ty::CoroutineClosure(_, args) => {
+                // (*) binder moved here
+                let ty = self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
+                if let ty::Infer(ty::TyVar(_)) = ty.kind() {
+                    // Not yet resolved.
+                    Ambiguous
+                } else {
+                    Where(
+                        obligation
+                            .predicate
+                            .rebind(args.as_coroutine_closure().upvar_tys().to_vec()),
+                    )
+                }
+            }
+
             // `Copy` and `Clone` are automatically implemented for an anonymous adt
             // if all of its fields are `Copy` and `Clone`
             ty::Adt(adt, args) if adt.is_anonymous() => {
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 6ec38b78fc2..d5e114b2175 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -241,10 +241,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
         self.has_type_flags(TypeFlags::HAS_ALIAS)
     }
 
-    fn has_inherent_projections(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_INHERENT)
-    }
-
     fn has_opaque_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
     }
diff --git a/config.example.toml b/config.example.toml
index 26687bcfb37..8800c85db32 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -395,7 +395,7 @@
 #metrics = false
 
 # Specify the location of the Android NDK. Used when targeting Android.
-#android-ndk = "/path/to/android-ndk-r25b"
+#android-ndk = "/path/to/android-ndk-r26d"
 
 # =============================================================================
 # General install configuration options
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 939b2be6dfa..76a89eaaff8 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -160,6 +160,9 @@ pub trait Clone: Sized {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "cloning is often expensive and is not expected to have side effects"]
+    // Clone::clone is special because the compiler generates MIR to implement it for some types.
+    // See InstanceKind::CloneShim.
+    #[cfg_attr(not(bootstrap), lang = "clone_fn")]
     fn clone(&self) -> Self;
 
     /// Performs copy-assignment from `source`.
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 36fae1c1596..794ca1851b1 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -402,6 +402,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
     }
 }
 
+/// A helper used to print list-like items with no special formatting.
 struct DebugInner<'a, 'b: 'a> {
     fmt: &'a mut fmt::Formatter<'b>,
     result: fmt::Result,
@@ -578,7 +579,8 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
+        self.inner.result = self.inner.result.and_then(|_| self.inner.fmt.write_str("}"));
+        self.inner.result
     }
 }
 
@@ -721,7 +723,8 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
+        self.inner.result = self.inner.result.and_then(|_| self.inner.fmt.write_str("]"));
+        self.inner.result
     }
 }
 
@@ -1002,11 +1005,12 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     /// ```
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        self.result.and_then(|_| {
+        self.result = self.result.and_then(|_| {
             assert!(!self.has_key, "attempted to finish a map with a partial entry");
 
             self.fmt.write_str("}")
-        })
+        });
+        self.result
     }
 
     fn is_pretty(&self) -> bool {
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 733d414d444..469097e4847 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -823,7 +823,7 @@ pub trait Iterator {
     ///
     /// Given an element the closure must return `true` or `false`. The returned
     /// iterator will yield only the elements for which the closure returns
-    /// true.
+    /// `true`.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 02cb02dce1d..9f0055d1911 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -127,7 +127,6 @@
 #![feature(const_hash)]
 #![feature(const_heap)]
 #![feature(const_index_range_slice_index)]
-#![feature(const_int_from_str)]
 #![feature(const_intrinsic_copy)]
 #![feature(const_intrinsic_forget)]
 #![feature(const_ipv4)]
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index a2d7e6f7b07..b8e22a8aef9 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -113,7 +113,7 @@ pub enum IntErrorKind {
 impl ParseIntError {
     /// Outputs the detailed cause of parsing an integer failing.
     #[must_use]
-    #[rustc_const_unstable(feature = "const_int_from_str", issue = "59133")]
+    #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
     #[stable(feature = "int_error_matching", since = "1.55.0")]
     pub const fn kind(&self) -> &IntErrorKind {
         &self.kind
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 4e8e0ecdde9..3442bb71417 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -1386,6 +1386,7 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
 #[doc(hidden)]
 #[inline(always)]
 #[unstable(issue = "none", feature = "std_internals")]
+#[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
 pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
     radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
 }
@@ -1435,7 +1436,7 @@ macro_rules! from_str_radix {
             #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")]
             /// ```
             #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_unstable(feature = "const_int_from_str", issue = "59133")]
+            #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
             pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> {
                 use self::IntErrorKind::*;
                 use self::ParseIntError as PIE;
@@ -1565,7 +1566,7 @@ macro_rules! from_str_radix_size_impl {
         #[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")]
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
-        #[rustc_const_unstable(feature = "const_int_from_str", issue = "59133")]
+        #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
         pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> {
             match <$t>::from_str_radix(src, radix) {
                 Ok(x) => Ok(x as $size),
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 04aaa3f35b7..4c225187882 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -16,7 +16,6 @@
 #![feature(const_hash)]
 #![feature(const_heap)]
 #![feature(const_intrinsic_copy)]
-#![feature(const_int_from_str)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_nonnull_new)]
 #![feature(const_pointer_is_aligned)]
diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs
index 14bce2bbeee..9a3d95bd8dd 100644
--- a/library/rtstartup/rsbegin.rs
+++ b/library/rtstartup/rsbegin.rs
@@ -29,6 +29,8 @@ trait Copy {}
 #[lang = "freeze"]
 auto trait Freeze {}
 
+impl<T: ?Sized> Copy for *mut T {}
+
 #[lang = "drop_in_place"]
 #[inline]
 #[allow(unconditional_recursion)]
diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs
index 714643c8386..2514eb00344 100644
--- a/library/rtstartup/rsend.rs
+++ b/library/rtstartup/rsend.rs
@@ -17,6 +17,8 @@ trait Copy {}
 #[lang = "freeze"]
 auto trait Freeze {}
 
+impl<T: ?Sized> Copy for *mut T {}
+
 #[lang = "drop_in_place"]
 #[inline]
 #[allow(unconditional_recursion)]
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
diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs
index d537c143d36..b650e1cee30 100644
--- a/tests/assembly/simd-intrinsic-mask-load.rs
+++ b/tests/assembly/simd-intrinsic-mask-load.rs
@@ -18,6 +18,7 @@ pub trait Sized {}
 
 #[lang = "copy"]
 trait Copy {}
+impl<T: ?Sized> Copy for *const T {}
 
 #[repr(simd)]
 pub struct i8x16([i8; 16]);
diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs
index 5d4c00c3823..95a3b28b967 100644
--- a/tests/assembly/simd-intrinsic-mask-store.rs
+++ b/tests/assembly/simd-intrinsic-mask-store.rs
@@ -18,6 +18,7 @@ pub trait Sized {}
 
 #[lang = "copy"]
 trait Copy {}
+impl<T: ?Sized> Copy for *mut T {}
 
 #[repr(simd)]
 pub struct i8x16([i8; 16]);
diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs
index 70834707564..7f9a7e6e811 100644
--- a/tests/codegen/avr/avr-func-addrspace.rs
+++ b/tests/codegen/avr/avr-func-addrspace.rs
@@ -17,6 +17,7 @@
 pub trait Sized {}
 #[lang = "copy"]
 pub trait Copy {}
+impl<T: ?Sized> Copy for *const T {}
 #[lang = "receiver"]
 pub trait Receiver {}
 #[lang = "tuple_trait"]
diff --git a/tests/codegen/clone-shims.rs b/tests/codegen/clone-shims.rs
new file mode 100644
index 00000000000..06c959f9ee7
--- /dev/null
+++ b/tests/codegen/clone-shims.rs
@@ -0,0 +1,15 @@
+// Clone shims for aggregates are generated by just calling the Clone shims for all their members.
+// Those calls generate a lot of unnecessary IR if the members are Copy. This test ensures that we
+// optimize away those inner calls without needing to inline them.
+
+//@ compile-flags: -Cno-prepopulate-passes -Csymbol-mangling-version=v0 -Zinline-mir=no
+#![crate_type = "lib"]
+
+pub type Test = (i32, i32, *const i32);
+pub static TEST: fn(&Test) -> Test = <Test as core::clone::Clone>::clone;
+
+// CHECK-NOT: call <i32 as core::clone::Clone>::clone
+// CHECK-NOT: call <*const i32 as core::clone::Clone>::clone
+// CHECK:     ; <(i32, i32, *const i32) as core::clone::Clone>::clone
+// CHECK-NOT: call <i32 as core::clone::Clone>::clone
+// CHECK-NOT: call <*const i32 as core::clone::Clone>::clone
diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs
index 6cda8c6799f..35444db9558 100644
--- a/tests/codegen/emcripten-catch-unwind.rs
+++ b/tests/codegen/emcripten-catch-unwind.rs
@@ -16,6 +16,8 @@ trait Freeze {}
 #[lang = "copy"]
 trait Copy {}
 
+impl<T> Copy for *mut T {}
+
 #[rustc_intrinsic]
 fn size_of<T>() -> usize {
     loop {}
diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
index ed0af90aaaf..520192b5d59 100644
--- a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
+++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs
@@ -18,6 +18,7 @@ impl Copy for i64 {}
 impl Copy for u64 {}
 impl Copy for f32 {}
 impl Copy for f64 {}
+impl<T> Copy for *mut T {}
 
 // CHECK: define void @f_void()
 #[no_mangle]
diff --git a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs
index fc4d570dc2e..c1967e55e75 100644
--- a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs
@@ -15,6 +15,7 @@
 trait Sized {}
 #[lang = "copy"]
 trait Copy {}
+impl<T: ?Sized> Copy for &T {}
 #[lang = "receiver"]
 trait Receiver {}
 #[lang = "dispatch_from_dyn"]
diff --git a/tests/run-make/README.md b/tests/run-make/README.md
index a6c1b4b7db7..40359903473 100644
--- a/tests/run-make/README.md
+++ b/tests/run-make/README.md
@@ -41,3 +41,8 @@ The setup for the `rmake.rs` version is a 3-stage process:
 
 [`run_make_support`]: ../../src/tools/run-make-support
 [extern_prelude]: https://doc.rust-lang.org/reference/names/preludes.html#extern-prelude
+
+### Formatting
+
+Note that files under `tests/` are not formatted by `./x fmt`,
+use `rustfmt tests/path/to/file.rs` to format a specific file if desired.
diff --git a/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile b/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile
deleted file mode 100644
index 2bb8d42495d..00000000000
--- a/tests/run-make/c-unwind-abi-catch-lib-panic/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# Exercise unwinding a panic. This catches a panic across an FFI boundary and downcasts it into an integer. The Rust code that panics is in a separate crate.
-# See https://github.com/rust-lang/rust/commit/baf227ea0c1e07fc54395a51e4b3881d701180cb
-
-# ignore-cross-compile
-# needs-unwind
-include ../tools.mk
-
-all: archive
-	# Compile `main.rs`, which will link into our library, and run it.
-	$(RUSTC) main.rs
-	$(call RUN,main)
-
-ifdef IS_MSVC
-archive: add.o panic.o
-	# Now, create an archive using these two objects.
-	$(AR) crus $(TMPDIR)/add.lib $(TMPDIR)/add.o $(TMPDIR)/panic.o
-else
-archive: add.o panic.o
-	# Now, create an archive using these two objects.
-	$(AR) crus $(TMPDIR)/libadd.a $(TMPDIR)/add.o $(TMPDIR)/panic.o
-endif
-
-# Compile `panic.rs` into an object file.
-#
-# Note that we invoke `rustc` directly, so we may emit an object rather
-# than an archive. We'll do that later.
-panic.o:
-	$(BARE_RUSTC) $(RUSTFLAGS)  \
-		--out-dir $(TMPDIR) \
-		--emit=obj panic.rs
-
-# Compile `add.c` into an object file.
-add.o:
-	$(call COMPILE_OBJ,$(TMPDIR)/add.o,add.c)
-
diff --git a/tests/run-make/c-unwind-abi-catch-lib-panic/rmake.rs b/tests/run-make/c-unwind-abi-catch-lib-panic/rmake.rs
new file mode 100644
index 00000000000..62e1748b6fb
--- /dev/null
+++ b/tests/run-make/c-unwind-abi-catch-lib-panic/rmake.rs
@@ -0,0 +1,36 @@
+// Exercise unwinding a panic. This catches a panic across an FFI (foreign function interface)
+// boundary and downcasts it into an integer.
+// The Rust code that panics is in a separate crate.
+// See https://github.com/rust-lang/rust/commit/baf227ea0c1e07fc54395a51e4b3881d701180cb
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+//@ needs-unwind
+// Reason: this test exercises unwinding a panic
+
+use run_make_support::{cc, is_msvc, llvm_ar, run, rustc, static_lib_name};
+
+fn main() {
+    // Compile `add.c` into an object file.
+    if is_msvc() {
+        cc().arg("-c").out_exe("add").input("add.c").run();
+    } else {
+        cc().arg("-v").arg("-c").out_exe("add.o").input("add.c").run();
+    };
+
+    // Compile `panic.rs` into an object file.
+    // Note that we invoke `rustc` directly, so we may emit an object rather
+    // than an archive. We'll do that later.
+    rustc().emit("obj").input("panic.rs").run();
+
+    // Now, create an archive using these two objects.
+    if is_msvc() {
+        llvm_ar().obj_to_ar().args(&[&static_lib_name("add"), "add.obj", "panic.o"]).run();
+    } else {
+        llvm_ar().obj_to_ar().args(&[&static_lib_name("add"), "add.o", "panic.o"]).run();
+    };
+
+    // Compile `main.rs`, which will link into our library, and run it.
+    rustc().input("main.rs").run();
+    run("main");
+}
diff --git a/tests/run-make/compiler-rt-works-on-mingw/Makefile b/tests/run-make/compiler-rt-works-on-mingw/Makefile
deleted file mode 100644
index 74917570a01..00000000000
--- a/tests/run-make/compiler-rt-works-on-mingw/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include ../tools.mk
-
-# only-windows-gnu
-
-all:
-	$(CXX) foo.cpp -c -o $(TMPDIR)/foo.o
-	$(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
-	$(RUSTC) foo.rs -lfoo -lstdc++
-	$(call RUN,foo)
diff --git a/tests/run-make/compiler-rt-works-on-mingw/rmake.rs b/tests/run-make/compiler-rt-works-on-mingw/rmake.rs
new file mode 100644
index 00000000000..f1b41f96312
--- /dev/null
+++ b/tests/run-make/compiler-rt-works-on-mingw/rmake.rs
@@ -0,0 +1,15 @@
+// `compiler-rt` ("runtime") is a suite of LLVM features compatible with rustc.
+// After building it was enabled on Windows-gnu in #29874, this test is a basic smoke test to
+// check if building and linking to it can work at all.
+// See https://github.com/rust-lang/rust/pull/29478
+
+//@ only-windows-gnu
+
+use run_make_support::{cxx, is_msvc, llvm_ar, run, rustc, static_lib_name};
+
+fn main() {
+    cxx().input("foo.cpp").arg("-c").out_exe("foo.o").run();
+    llvm_ar().obj_to_ar().output_input(static_lib_name("foo"), "foo.o").run();
+    rustc().input("foo.rs").arg("-lfoo").arg("-lstdc++").run();
+    run("foo");
+}
diff --git a/tests/run-make/dump-ice-to-disk/Makefile b/tests/run-make/dump-ice-to-disk/Makefile
deleted file mode 100644
index 23006fc09e2..00000000000
--- a/tests/run-make/dump-ice-to-disk/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-include ../tools.mk
-
-# ignore-windows
-
-export RUSTC := $(RUSTC_ORIGINAL)
-export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
-export TMPDIR := $(TMPDIR)
-
-all:
-	bash check.sh
diff --git a/tests/run-make/dump-ice-to-disk/check.sh b/tests/run-make/dump-ice-to-disk/check.sh
deleted file mode 100644
index ff6e4be35af..00000000000
--- a/tests/run-make/dump-ice-to-disk/check.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/sh
-
-# Default nightly behavior (write ICE to current directory)
-# FIXME(estebank): these are failing on CI, but passing locally.
-# $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default.log 2>&1
-# default=$(cat ./rustc-ice-*.txt | wc -l)
-# rm ./rustc-ice-*.txt
-
-# Explicit directory set
-export RUSTC_ICE=$TMPDIR
-$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-default-set.log 2>&1
-default_set=$(cat $TMPDIR/rustc-ice-*.txt | wc -l)
-content=$(cat $TMPDIR/rustc-ice-*.txt)
-# Ensure that the ICE dump path doesn't contain `:` because they cause problems on Windows
-windows_safe=$(echo rustc-ice-*.txt | grep ':')
-if [ ! -z "$windows_safe" ]; then
-    exit 1
-fi
-
-rm $TMPDIR/rustc-ice-*.txt
-RUST_BACKTRACE=short $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-short.log 2>&1
-short=$(cat $TMPDIR/rustc-ice-*.txt | wc -l)
-rm $TMPDIR/rustc-ice-*.txt
-RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-full.log 2>&1
-full=$(cat $TMPDIR/rustc-ice-*.txt | wc -l)
-rm $TMPDIR/rustc-ice-*.txt
-
-# Explicitly disabling ICE dump
-export RUSTC_ICE=0
-$RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-disabled.log 2>&1
-should_be_empty_tmp=$(ls -l $TMPDIR/rustc-ice-*.txt 2>/dev/null | wc -l)
-should_be_empty_dot=$(ls -l ./rustc-ice-*.txt 2>/dev/null | wc -l)
-
-echo "#### ICE Dump content:"
-echo $content
-echo "#### default length:"
-echo $default
-echo "#### short length:"
-echo $short
-echo "#### default_set length:"
-echo $default_set
-echo "#### full length:"
-echo $full
-echo "#### should_be_empty_dot length:"
-echo $should_be_empty_dot
-echo "#### should_be_empty_tmp length:"
-echo $should_be_empty_tmp
-
-## Verify that a the ICE dump file is created in the appropriate directories, that
-## their lengths are the same regardless of other backtrace configuration options,
-## that the file is not created when asked to (RUSTC_ICE=0) and that the file
-## contains at least part of the expected content.
-if [ $short -eq $default_set ] &&
-    #[ $default -eq $short ] &&
-    [ $default_set -eq $full ] &&
-    [[ $content == *"thread 'rustc' panicked at "* ]] &&
-    [[ $content == *"stack backtrace:"* ]] &&
-    #[ $default -gt 0 ] &&
-    [ $should_be_empty_dot -eq 0 ] &&
-    [ $should_be_empty_tmp -eq 0 ]; then
-    exit 0
-else
-    exit 1
-fi
diff --git a/tests/run-make/dump-ice-to-disk/src/lib.rs b/tests/run-make/dump-ice-to-disk/lib.rs
index b23b7f830d7..b23b7f830d7 100644
--- a/tests/run-make/dump-ice-to-disk/src/lib.rs
+++ b/tests/run-make/dump-ice-to-disk/lib.rs
diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs
new file mode 100644
index 00000000000..2fb5c825064
--- /dev/null
+++ b/tests/run-make/dump-ice-to-disk/rmake.rs
@@ -0,0 +1,81 @@
+// This test checks if internal compilation error (ICE) log files work as expected.
+// - Get the number of lines from the log files without any configuration options,
+// then check that the line count doesn't change if the backtrace gets configured to be short
+// or full.
+// - Check that disabling ICE logging results in zero files created.
+// - Check that the ICE files contain some of the expected strings.
+// See https://github.com/rust-lang/rust/pull/108714
+
+use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files};
+
+fn main() {
+    rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
+    let default = get_text_from_ice(".").lines().count();
+    clear_ice_files();
+
+    rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
+    let ice_text = get_text_from_ice(cwd());
+    let default_set = ice_text.lines().count();
+    let content = ice_text;
+    let ice_files = shallow_find_files(cwd(), |path| {
+        has_prefix(path, "rustc-ice") && has_extension(path, "txt")
+    });
+    assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file.
+    let ice_file_name =
+        ice_files.first().and_then(|f| f.file_name()).and_then(|n| n.to_str()).unwrap();
+    // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on Windows.
+    assert!(!ice_file_name.contains(":"), "{ice_file_name}");
+
+    clear_ice_files();
+    rustc()
+        .env("RUSTC_ICE", cwd())
+        .input("lib.rs")
+        .env("RUST_BACKTRACE", "short")
+        .arg("-Ztreat-err-as-bug=1")
+        .run_fail();
+    let short = get_text_from_ice(cwd()).lines().count();
+    clear_ice_files();
+    rustc()
+        .env("RUSTC_ICE", cwd())
+        .input("lib.rs")
+        .env("RUST_BACKTRACE", "full")
+        .arg("-Ztreat-err-as-bug=1")
+        .run_fail();
+    let full = get_text_from_ice(cwd()).lines().count();
+    clear_ice_files();
+
+    // The ICE dump is explicitly disabled. Therefore, this should produce no files.
+    rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
+    let ice_files = shallow_find_files(cwd(), |path| {
+        has_prefix(path, "rustc-ice") && has_extension(path, "txt")
+    });
+    assert!(ice_files.is_empty()); // There should be 0 ICE files.
+
+    // The line count should not change.
+    assert_eq!(short, default_set);
+    assert_eq!(short, default);
+    assert_eq!(full, default_set);
+    assert!(default > 0);
+    // Some of the expected strings in an ICE file should appear.
+    assert!(content.contains("thread 'rustc' panicked at"));
+    assert!(content.contains("stack backtrace:"));
+}
+
+fn clear_ice_files() {
+    let ice_files = shallow_find_files(cwd(), |path| {
+        has_prefix(path, "rustc-ice") && has_extension(path, "txt")
+    });
+    for file in ice_files {
+        rfs::remove_file(file);
+    }
+}
+
+#[track_caller]
+fn get_text_from_ice(dir: impl AsRef<std::path::Path>) -> String {
+    let ice_files =
+        shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt"));
+    assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file.
+    let ice_file = ice_files.get(0).unwrap();
+    let output = rfs::read_to_string(ice_file);
+    output
+}
diff --git a/tests/run-make/export-executable-symbols/Makefile b/tests/run-make/export-executable-symbols/Makefile
deleted file mode 100644
index c4d29aa2bf4..00000000000
--- a/tests/run-make/export-executable-symbols/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-include ../tools.mk
-
-# ignore-wasm32
-# ignore-wasm64
-# ignore-none no-std is not supported
-# only-linux
-
-all:
-	$(RUSTC) -Zexport-executable-symbols  main.rs --target $(TARGET) --crate-type=bin
-	nm $(TMPDIR)/main | $(CGREP) exported_symbol
-
diff --git a/tests/run-make/export-executable-symbols/rmake.rs b/tests/run-make/export-executable-symbols/rmake.rs
new file mode 100644
index 00000000000..77f968189b6
--- /dev/null
+++ b/tests/run-make/export-executable-symbols/rmake.rs
@@ -0,0 +1,25 @@
+// The unstable flag `-Z export-executable-symbols` exports symbols from executables, as if
+// they were dynamic libraries. This test is a simple smoke test to check that this feature
+// works by using it in compilation, then checking that the output binary contains the exported
+// symbol.
+// See https://github.com/rust-lang/rust/pull/85673
+
+//@ only-unix
+// Reason: the export-executable-symbols flag only works on Unix
+// due to hardcoded platform-specific implementation
+// (See #85673)
+//@ ignore-wasm32
+//@ ignore-wasm64
+//@ ignore-none
+// Reason: no-std is not supported
+
+use run_make_support::{bin_name, llvm_readobj, rustc};
+
+fn main() {
+    rustc().arg("-Zexport-executable-symbols").input("main.rs").crate_type("bin").run();
+    llvm_readobj()
+        .symbols()
+        .input(bin_name("main"))
+        .run()
+        .assert_stdout_contains("exported_symbol");
+}
diff --git a/tests/run-make/extern-flag-disambiguates/Makefile b/tests/run-make/extern-flag-disambiguates/Makefile
deleted file mode 100644
index e54a537ecd0..00000000000
--- a/tests/run-make/extern-flag-disambiguates/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Attempt to build this dependency tree:
-#
-#	A.1   A.2
-#	 |\    |
-#	 | \   |
-#        B  \  C
-#         \ | /
-#          \|/
-#           D
-#
-# Note that A.1 and A.2 are crates with the same name.
-
-all:
-	$(RUSTC) -C metadata=1 -C extra-filename=-1 a.rs
-	$(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs
-	$(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib
-	$(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib
-	@echo before
-	$(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib
-	$(call RUN,d)
-	@echo after
-	$(RUSTC) --cfg after  d.rs --extern a=$(TMPDIR)/liba-1.rlib
-	$(call RUN,d)
diff --git a/tests/run-make/extern-flag-disambiguates/rmake.rs b/tests/run-make/extern-flag-disambiguates/rmake.rs
new file mode 100644
index 00000000000..2d7d7f69f66
--- /dev/null
+++ b/tests/run-make/extern-flag-disambiguates/rmake.rs
@@ -0,0 +1,30 @@
+//@ ignore-cross-compile
+
+use run_make_support::{cwd, run, rustc};
+
+// Attempt to build this dependency tree:
+//
+//    A.1   A.2
+//     |\    |
+//     | \   |
+//     B  \  C
+//      \ | /
+//       \|/
+//        D
+//
+// Note that A.1 and A.2 are crates with the same name.
+
+// original Makefile at https://github.com/rust-lang/rust/issues/14469
+
+fn main() {
+    rustc().metadata("1").extra_filename("-1").input("a.rs").run();
+    rustc().metadata("2").extra_filename("-2").input("a.rs").run();
+    rustc().input("b.rs").extern_("a", "liba-1.rlib").run();
+    rustc().input("c.rs").extern_("a", "liba-2.rlib").run();
+    println!("before");
+    rustc().cfg("before").input("d.rs").extern_("a", "liba-1.rlib").run();
+    run("d");
+    println!("after");
+    rustc().cfg("after").input("d.rs").extern_("a", "liba-1.rlib").run();
+    run("d");
+}
diff --git a/tests/run-make/foreign-rust-exceptions/Makefile b/tests/run-make/foreign-rust-exceptions/Makefile
deleted file mode 100644
index 59cee284200..00000000000
--- a/tests/run-make/foreign-rust-exceptions/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# ignore-cross-compile
-# ignore-i686-pc-windows-gnu
-# needs-unwind
-
-# This test doesn't work on 32-bit MinGW as cdylib has its own copy of unwinder
-# so cross-DLL unwinding does not work.
-
-include ../tools.mk
-
-all:
-	$(RUSTC) bar.rs --crate-type=cdylib
-	$(RUSTC) foo.rs
-	$(call RUN,foo) 2>&1 | $(CGREP) "Rust cannot catch foreign exceptions"
diff --git a/tests/run-make/foreign-rust-exceptions/rmake.rs b/tests/run-make/foreign-rust-exceptions/rmake.rs
new file mode 100644
index 00000000000..9c917078aaa
--- /dev/null
+++ b/tests/run-make/foreign-rust-exceptions/rmake.rs
@@ -0,0 +1,23 @@
+// Rust exceptions can be foreign (from C code, in this test) or local. Foreign
+// exceptions should not be caught, as that can cause undefined behaviour. Instead
+// of catching them, #102721 made it so that the binary panics in execution with a helpful message.
+// This test checks that the correct message appears and that execution fails when trying to catch
+// a foreign exception.
+// See https://github.com/rust-lang/rust/issues/102715
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+//@ needs-unwind
+// Reason: unwinding panics is exercised in this test
+
+//@ ignore-i686-pc-windows-gnu
+// Reason: This test doesn't work on 32-bit MinGW as cdylib has its own copy of unwinder
+// so cross-DLL unwinding does not work.
+
+use run_make_support::{run_fail, rustc};
+
+fn main() {
+    rustc().input("bar.rs").crate_type("cdylib").run();
+    rustc().input("foo.rs").run();
+    run_fail("foo").assert_stderr_contains("Rust cannot catch foreign exceptions");
+}
diff --git a/tests/run-make/incr-foreign-head-span/Makefile b/tests/run-make/incr-foreign-head-span/Makefile
deleted file mode 100644
index 9be4b0f601c..00000000000
--- a/tests/run-make/incr-foreign-head-span/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-include ../tools.mk
-
-# ignore-none no-std is not supported
-# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
-
-# Ensure that modifying a crate on disk (without recompiling it)
-# does not cause ICEs in downstream crates.
-# Previously, we would call `SourceMap.guess_head_span` on a span
-# from an external crate, which would cause us to read an upstream
-# source file from disk during compilation of a downstream crate
-# See #86480 for more details
-
-INCR=$(TMPDIR)/incr
-
-all:
-	cp first_crate.rs second_crate.rs $(TMPDIR)
-	$(RUSTC) $(TMPDIR)/first_crate.rs  -C incremental=$(INCR) --target $(TARGET) --crate-type lib
-	$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET)  --extern first_crate=$(TMPDIR)/libfirst_crate.rlib --crate-type lib
-	rm $(TMPDIR)/first_crate.rs
-	$(RUSTC) $(TMPDIR)/second_crate.rs  -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
-
diff --git a/tests/run-make/incr-foreign-head-span/rmake.rs b/tests/run-make/incr-foreign-head-span/rmake.rs
new file mode 100644
index 00000000000..92e2ed5f879
--- /dev/null
+++ b/tests/run-make/incr-foreign-head-span/rmake.rs
@@ -0,0 +1,25 @@
+// Ensure that modifying a crate on disk (without recompiling it)
+// does not cause ICEs (internal compiler errors) in downstream crates.
+// Previously, we would call `SourceMap.guess_head_span` on a span
+// from an external crate, which would cause us to read an upstream
+// source file from disk during compilation of a downstream crate.
+// See https://github.com/rust-lang/rust/issues/86480
+
+//@ ignore-none
+// Reason: no-std is not supported
+//@ ignore-nvptx64-nvidia-cuda
+// Reason: can't find crate for 'std'
+
+use run_make_support::{rfs, rust_lib_name, rustc};
+
+fn main() {
+    rustc().input("first_crate.rs").incremental("incr").crate_type("lib").run();
+    rustc()
+        .input("second_crate.rs")
+        .incremental("incr")
+        .extern_("first_crate", rust_lib_name("first_crate"))
+        .crate_type("lib")
+        .run();
+    rfs::remove_file("first_crate.rs");
+    rustc().input("second_crate.rs").incremental("incr").cfg("second_run").crate_type("lib").run();
+}
diff --git a/tests/run-make/interdependent-c-libraries/Makefile b/tests/run-make/interdependent-c-libraries/Makefile
deleted file mode 100644
index 53a696d82bf..00000000000
--- a/tests/run-make/interdependent-c-libraries/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# The rust crate foo will link to the native library foo, while the rust crate
-# bar will link to the native library bar. There is also a dependency between
-# the native library bar to the natibe library foo.
-#
-# This test ensures that the ordering of -lfoo and -lbar on the command line is
-# correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo'
-# library will be stripped out, and the linkage will fail.
-
-all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar)
-	$(RUSTC) foo.rs
-	$(RUSTC) bar.rs
-	$(RUSTC) main.rs --print link-args
diff --git a/tests/run-make/interdependent-c-libraries/rmake.rs b/tests/run-make/interdependent-c-libraries/rmake.rs
new file mode 100644
index 00000000000..ee8cc76c9cc
--- /dev/null
+++ b/tests/run-make/interdependent-c-libraries/rmake.rs
@@ -0,0 +1,21 @@
+// The rust crate foo will link to the native library foo, while the rust crate
+// bar will link to the native library bar. There is also a dependency between
+// the native library bar to the natibe library foo.
+// This test ensures that the ordering of -lfoo and -lbar on the command line is
+// correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo'
+// library will be stripped out, and the linkage will fail.
+// See https://github.com/rust-lang/rust/commit/e6072fa0c4c22d62acf3dcb78c8ee260a1368bd7
+
+//@ ignore-cross-compile
+// Reason: linkage still fails as the object files produced are not in the correct
+// format in the `build_native_static_lib` step
+
+use run_make_support::{build_native_static_lib, rustc};
+
+fn main() {
+    build_native_static_lib("foo");
+    build_native_static_lib("bar");
+    rustc().input("foo.rs").run();
+    rustc().input("bar.rs").run();
+    rustc().input("main.rs").print("link-args").run();
+}
diff --git a/tests/run-make/panic-abort-eh_frame/Makefile b/tests/run-make/panic-abort-eh_frame/Makefile
deleted file mode 100644
index 7020455b742..00000000000
--- a/tests/run-make/panic-abort-eh_frame/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# only-linux
-#
-# This test ensures that `panic=abort` code (without `C-unwind`, that is) should not have any
-# unwinding related `.eh_frame` sections emitted.
-
-include ../tools.mk
-
-all:
-	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort --edition 2021 -Z validate-mir
-	objdump --dwarf=frames $(TMPDIR)/foo.o | $(CGREP) -v 'DW_CFA'
diff --git a/tests/run-make/panic-abort-eh_frame/rmake.rs b/tests/run-make/panic-abort-eh_frame/rmake.rs
new file mode 100644
index 00000000000..23d95dc5774
--- /dev/null
+++ b/tests/run-make/panic-abort-eh_frame/rmake.rs
@@ -0,0 +1,24 @@
+// An `.eh_frame` section in an object file is a symptom of an UnwindAction::Terminate
+// being inserted, useful for determining whether or not unwinding is necessary.
+// This is useless when panics would NEVER unwind due to -C panic=abort. This section should
+// therefore never appear in the emit file of a -C panic=abort compilation, and this test
+// checks that this is respected.
+// See https://github.com/rust-lang/rust/pull/112403
+
+//@ only-linux
+// FIXME(Oneirical): the DW_CFA symbol appears on Windows-gnu, because uwtable
+// is forced to true on Windows targets (see #128136).
+
+use run_make_support::{llvm_objdump, rustc};
+
+fn main() {
+    rustc()
+        .input("foo.rs")
+        .crate_type("lib")
+        .emit("obj=foo.o")
+        .panic("abort")
+        .edition("2021")
+        .arg("-Zvalidate-mir")
+        .run();
+    llvm_objdump().arg("--dwarf=frames").input("foo.o").run().assert_stdout_not_contains("DW_CFA");
+}
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
deleted file mode 100644
index 5ac7e1e58b8..00000000000
--- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ compile-flags: --crate-type=lib
-//@ check-pass
-
-#![feature(inherent_associated_types)]
-#![allow(incomplete_features)]
-
-// Bounds on the self type play a major role in the resolution of inherent associated types (*).
-// As a result of that, if a type alias contains any then its bounds have to be respected and the
-// lint `type_alias_bounds` should not fire.
-
-#![deny(type_alias_bounds)]
-
-pub type Alias<T: Bound> = (Source<T>::Assoc,);
-
-pub struct Source<T>(T);
-pub trait Bound {}
-
-impl<T: Bound> Source<T> {
-    pub type Assoc = ();
-}
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds.rs b/tests/ui/associated-inherent-types/type-alias-bounds.rs
new file mode 100644
index 00000000000..61641a83994
--- /dev/null
+++ b/tests/ui/associated-inherent-types/type-alias-bounds.rs
@@ -0,0 +1,29 @@
+//@ compile-flags: --crate-type=lib
+//@ check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// FIXME(inherent_associated_types):
+// While we currently do take some clauses of the ParamEnv into consideration
+// when performing IAT selection, we do not perform full well-formedness checking
+// for (eager) type alias definition and usage sites.
+//
+// Therefore it's *correct* for lint `type_alias_bounds` to fire here despite the
+// fact that removing `Bound` from `T` in `Alias` would lead to an error!
+//
+// Obviously, the present situation isn't ideal and we should fix it in one way
+// or another. Either we somehow delay IAT selection until after HIR ty lowering
+// to avoid the need to specify any bounds inside (eager) type aliases or we
+// force the overarching type alias to be *lazy* (similar to TAITs) which would
+// automatically lead to full wfchecking and lint TAB getting suppressed.
+
+pub type Alias<T: Bound> = (Source<T>::Assoc,);
+//~^ WARN bounds on generic parameters in type aliases are not enforced
+
+pub struct Source<T>(T);
+pub trait Bound {}
+
+impl<T: Bound> Source<T> {
+    pub type Assoc = ();
+}
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds.stderr b/tests/ui/associated-inherent-types/type-alias-bounds.stderr
new file mode 100644
index 00000000000..c56dd498f77
--- /dev/null
+++ b/tests/ui/associated-inherent-types/type-alias-bounds.stderr
@@ -0,0 +1,16 @@
+warning: bounds on generic parameters in type aliases are not enforced
+  --> $DIR/type-alias-bounds.rs:21:19
+   |
+LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
+   |                 --^^^^^
+   |                 | |
+   |                 | will not be checked at usage sites of the type alias
+   |                 help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
+   = note: `#[warn(type_alias_bounds)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/type-alias.stderr b/tests/ui/associated-type-bounds/type-alias.stderr
index 072c471467c..d59952b4a14 100644
--- a/tests/ui/associated-type-bounds/type-alias.stderr
+++ b/tests/ui/associated-type-bounds/type-alias.stderr
@@ -1,147 +1,159 @@
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias.rs:3:25
    |
 LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^
-   |
+   |                   ------^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |     |
+   |                   |     will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
    = note: `#[warn(type_alias_bounds)]` on by default
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
-LL + type _TaWhere1<T>  = T;
-   |
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias.rs:4:25
    |
 LL | type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
-LL + type _TaWhere2<T>  = T;
-   |
+   |                   ------^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |     |
+   |                   |     will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias.rs:5:25
    |
 LL | type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
-LL + type _TaWhere3<T>  = T;
-   |
+   |                   ------^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |     |
+   |                   |     will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias.rs:6:25
    |
 LL | type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + Send> = T;
-LL + type _TaWhere4<T>  = T;
-   |
+   |                   ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |     |
+   |                   |     will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias.rs:7:25
    |
 LL | type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
-LL + type _TaWhere5<T>  = T;
-   |
+   |                   ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |     |
+   |                   |     will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias.rs:8:25
    |
 LL | type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
-LL + type _TaWhere6<T>  = T;
-   |
+   |                   ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |     |
+   |                   |     will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias.rs:10:20
    |
 LL | type _TaInline1<T: Iterator<Item: Copy>> = T;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaInline1<T: Iterator<Item: Copy>> = T;
-LL + type _TaInline1<T> = T;
-   |
+   |                  --^^^^^^^^^^^^^^^^^^^^
+   |                  | |
+   |                  | will not be checked at usage sites of the type alias
+   |                  help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias.rs:11:20
    |
 LL | type _TaInline2<T: Iterator<Item: 'static>> = T;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaInline2<T: Iterator<Item: 'static>> = T;
-LL + type _TaInline2<T> = T;
-   |
+   |                  --^^^^^^^^^^^^^^^^^^^^^^^
+   |                  | |
+   |                  | will not be checked at usage sites of the type alias
+   |                  help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias.rs:12:20
    |
 LL | type _TaInline3<T: Iterator<Item: 'static>> = T;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaInline3<T: Iterator<Item: 'static>> = T;
-LL + type _TaInline3<T> = T;
-   |
+   |                  --^^^^^^^^^^^^^^^^^^^^^^^
+   |                  | |
+   |                  | will not be checked at usage sites of the type alias
+   |                  help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias.rs:13:20
    |
 LL | type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
-LL + type _TaInline4<T> = T;
-   |
+   |                  --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  | |
+   |                  | will not be checked at usage sites of the type alias
+   |                  help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias.rs:14:20
    |
 LL | type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
-LL + type _TaInline5<T> = T;
-   |
+   |                  --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  | |
+   |                  | will not be checked at usage sites of the type alias
+   |                  help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias.rs:15:20
    |
 LL | type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
-LL + type _TaInline6<T> = T;
-   |
+   |                  --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  | |
+   |                  | will not be checked at usage sites of the type alias
+   |                  help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
 warning: 12 warnings emitted
 
diff --git a/tests/ui/async-await/async-closures/clone-closure.rs b/tests/ui/async-await/async-closures/clone-closure.rs
new file mode 100644
index 00000000000..807897e3e03
--- /dev/null
+++ b/tests/ui/async-await/async-closures/clone-closure.rs
@@ -0,0 +1,24 @@
+//@ aux-build:block-on.rs
+//@ edition:2021
+//@ run-pass
+//@ check-run-results
+
+#![feature(async_closure)]
+
+extern crate block_on;
+
+async fn for_each(f: impl async FnOnce(&str) + Clone) {
+    f.clone()("world").await;
+    f.clone()("world2").await;
+}
+
+fn main() {
+    block_on::block_on(async_main());
+}
+
+async fn async_main() {
+    let x = String::from("Hello,");
+    for_each(async move |s| {
+        println!("{x} {s}");
+    }).await;
+}
diff --git a/tests/ui/async-await/async-closures/clone-closure.run.stdout b/tests/ui/async-await/async-closures/clone-closure.run.stdout
new file mode 100644
index 00000000000..0cfcf1923da
--- /dev/null
+++ b/tests/ui/async-await/async-closures/clone-closure.run.stdout
@@ -0,0 +1,2 @@
+Hello, world
+Hello, world2
diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.stderr b/tests/ui/async-await/async-closures/move-consuming-capture.stderr
index 45c1eac8f8f..4ce71ec49d6 100644
--- a/tests/ui/async-await/async-closures/move-consuming-capture.stderr
+++ b/tests/ui/async-await/async-closures/move-consuming-capture.stderr
@@ -11,6 +11,15 @@ LL |         x().await;
    |
 note: `async_call_once` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
+help: you could `clone` the value and consume it, if the `NoCopy: Clone` trait bound could be satisfied
+   |
+LL |         x.clone()().await;
+   |          ++++++++
+help: consider annotating `NoCopy` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NoCopy;
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/async-closures/not-clone-closure.rs b/tests/ui/async-await/async-closures/not-clone-closure.rs
new file mode 100644
index 00000000000..2776ce4690f
--- /dev/null
+++ b/tests/ui/async-await/async-closures/not-clone-closure.rs
@@ -0,0 +1,36 @@
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+struct NotClonableArg;
+#[derive(Default)]
+struct NotClonableReturnType;
+
+// Verify that the only components that we care about are the upvars, not the signature.
+fn we_are_okay_with_not_clonable_signature() {
+    let x = async |x: NotClonableArg| -> NotClonableReturnType { Default::default() };
+    x.clone(); // Okay
+}
+
+#[derive(Debug)]
+struct NotClonableUpvar;
+
+fn we_only_care_about_clonable_upvars() {
+    let x = NotClonableUpvar;
+    // Notably, this is clone because we capture `&x`.
+    let yes_clone = async || {
+        println!("{x:?}");
+    };
+    yes_clone.clone(); // Okay
+
+    let z = NotClonableUpvar;
+    // However, this is not because the closure captures `z` by move.
+    // (Even though the future that is lent out captures `z by ref!)
+    let not_clone = async move || {
+        println!("{z:?}");
+    };
+    not_clone.clone();
+    //~^ ERROR the trait bound `NotClonableUpvar: Clone` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-closures/not-clone-closure.stderr b/tests/ui/async-await/async-closures/not-clone-closure.stderr
new file mode 100644
index 00000000000..aea48a455c2
--- /dev/null
+++ b/tests/ui/async-await/async-closures/not-clone-closure.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `NotClonableUpvar: Clone` is not satisfied in `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`
+  --> $DIR/not-clone-closure.rs:32:15
+   |
+LL |     not_clone.clone();
+   |               ^^^^^ within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar`, which is required by `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}: Clone`
+   |
+note: required because it's used within this closure
+  --> $DIR/not-clone-closure.rs:29:21
+   |
+LL |     let not_clone = async move || {
+   |                     ^^^^^^^^^^^^^
+help: consider annotating `NotClonableUpvar` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClonableUpvar;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
index 17681161e20..18f16ca4b2d 100644
--- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
+++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
@@ -19,7 +19,7 @@ fn simple<'a>(x: &'a i32) {
 
     let c = async move || { println!("{}", *x); };
     outlives::<'a>(c()); //~ ERROR `c` does not live long enough
-    outlives::<'a>(call_once(c)); //~ ERROR cannot move out of `c`
+    outlives::<'a>(call_once(c));
 }
 
 struct S<'a>(&'a i32);
diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
index 569028934cb..1df5abdbb18 100644
--- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
+++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr
@@ -29,22 +29,6 @@ LL |     outlives::<'a>(call_once(c));
 LL | }
    | - `c` dropped here while still borrowed
 
-error[E0505]: cannot move out of `c` because it is borrowed
-  --> $DIR/without-precise-captures-we-are-powerless.rs:22:30
-   |
-LL | fn simple<'a>(x: &'a i32) {
-   |           -- lifetime `'a` defined here
-...
-LL |     let c = async move || { println!("{}", *x); };
-   |         - binding `c` declared here
-LL |     outlives::<'a>(c());
-   |                    ---
-   |                    |
-   |                    borrow of `c` occurs here
-   |                    argument requires that `c` is borrowed for `'a`
-LL |     outlives::<'a>(call_once(c));
-   |                              ^ move out of `c` occurs here
-
 error[E0597]: `x` does not live long enough
   --> $DIR/without-precise-captures-we-are-powerless.rs:28:13
    |
@@ -146,7 +130,7 @@ LL |     // outlives::<'a>(call_once(c)); // FIXME(async_closures): Figure out w
 LL | }
    | - `c` dropped here while still borrowed
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0505, E0597, E0621.
 For more information about an error, try `rustc --explain E0505`.
diff --git a/tests/ui/const-generics/generic_const_exprs/type-alias-bounds.neg.stderr b/tests/ui/const-generics/generic_const_exprs/type-alias-bounds.neg.stderr
new file mode 100644
index 00000000000..fa12dd14753
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/type-alias-bounds.neg.stderr
@@ -0,0 +1,63 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/type-alias-bounds.rs:23:12
+   |
+LL |     let _: AliasConstUnused<String>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `ct_unused_0::AliasConstUnused`
+  --> $DIR/type-alias-bounds.rs:20:30
+   |
+LL |     type AliasConstUnused<T: Copy> = (T, I32<{ DATA }>);
+   |                              ^^^^ required by this bound in `AliasConstUnused`
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/type-alias-bounds.rs:31:12
+   |
+LL |     let _: AliasConstUnused;
+   |            ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `ct_unused_1::AliasConstUnused`
+  --> $DIR/type-alias-bounds.rs:29:41
+   |
+LL |     type AliasConstUnused where String: Copy = I32<{ 0; 0 }>;
+   |                                         ^^^^ required by this bound in `AliasConstUnused`
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/type-alias-bounds.rs:39:12
+   |
+LL |     let _: AliasFnUnused<String>;
+   |            ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `AliasFnUnused`
+  --> $DIR/type-alias-bounds.rs:36:27
+   |
+LL |     type AliasFnUnused<T: Copy> = (T, I32<{ code() }>);
+   |                           ^^^^ required by this bound in `AliasFnUnused`
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/type-alias-bounds.rs:57:12
+   |
+LL |     let _: AliasAssocConstUsed<String>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `AliasAssocConstUsed`
+  --> $DIR/type-alias-bounds.rs:55:41
+   |
+LL |     type AliasAssocConstUsed<T: Trait + Copy> = I32<{ T::DATA }>;
+   |                                         ^^^^ required by this bound in `AliasAssocConstUsed`
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/type-alias-bounds.rs:65:12
+   |
+LL |     let _: AliasFnUsed<String>;
+   |            ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+note: required by a bound in `AliasFnUsed`
+  --> $DIR/type-alias-bounds.rs:62:33
+   |
+LL |     type AliasFnUsed<T: Trait + Copy> = I32<{ code::<T>() }>;
+   |                                 ^^^^ required by this bound in `AliasFnUsed`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs b/tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs
new file mode 100644
index 00000000000..f16e646129c
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs
@@ -0,0 +1,71 @@
+//@ revisions: pos neg
+//@[pos] check-pass
+
+#![feature(generic_const_exprs)]
+#![feature(trivial_bounds)] // only used in test case `ct_unused_1`
+#![allow(incomplete_features)]
+
+// FIXME(generic_const_exprs): Revisit this before stabilization.
+// Check that we don't emit the lint `type_alias_bounds` for (eager) type aliases
+// whose RHS contains a const projection (aka uneval'ed const).
+// Since anon consts inherit the parent generics and predicates and we effectively
+// check them before and after instantiaton for well-formedness, the type alias
+// bounds are in every sense "enforced".
+// Note that the test cases whose name ends in "unused" just demonstrate that this
+// holds even if the const projections don't "visibly" capture any generics and/or
+// predicates.
+#![deny(type_alias_bounds)]
+
+fn ct_unused_0() {
+    type AliasConstUnused<T: Copy> = (T, I32<{ DATA }>);
+    const DATA: i32 = 0;
+    #[cfg(neg)]
+    let _: AliasConstUnused<String>;
+    //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
+}
+
+fn ct_unused_1() {
+    #[allow(trivial_bounds)]
+    type AliasConstUnused where String: Copy = I32<{ 0; 0 }>;
+    #[cfg(neg)]
+    let _: AliasConstUnused;
+    //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
+}
+
+fn fn_unused() {
+    type AliasFnUnused<T: Copy> = (T, I32<{ code() }>);
+    const fn code() -> i32 { 0 }
+    #[cfg(neg)]
+    let _: AliasFnUnused<String>;
+    //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
+}
+
+trait Trait {
+    type Proj;
+    const DATA: i32;
+}
+
+impl Trait for String {
+    type Proj = i32;
+    const DATA: i32 = 0;
+}
+
+// Regression test for issue #94398.
+fn assoc_ct_used() {
+    type AliasAssocConstUsed<T: Trait + Copy> = I32<{ T::DATA }>;
+    #[cfg(neg)]
+    let _: AliasAssocConstUsed<String>;
+    //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
+}
+
+fn fn_used() {
+    type AliasFnUsed<T: Trait + Copy> = I32<{ code::<T>() }>;
+    const fn code<T: Trait>() -> i32 { T::DATA }
+    #[cfg(neg)]
+    let _: AliasFnUsed<String>;
+    //[neg]~^ ERROR the trait bound `String: Copy` is not satisfied
+}
+
+struct I32<const N: i32>;
+
+fn main() {}
diff --git a/tests/ui/consts/const-eval/parse_ints.rs b/tests/ui/consts/const-eval/parse_ints.rs
index ff9fc47e65c..cb9a3eb4312 100644
--- a/tests/ui/consts/const-eval/parse_ints.rs
+++ b/tests/ui/consts/const-eval/parse_ints.rs
@@ -1,5 +1,3 @@
-#![feature(const_int_from_str)]
-
 const _OK: () = match i32::from_str_radix("-1234", 10) {
     Ok(x) => assert!(x == -1234),
     Err(_) => panic!(),
diff --git a/tests/ui/consts/const-eval/parse_ints.stderr b/tests/ui/consts/const-eval/parse_ints.stderr
index 9e49fe433a1..ec9249ece8e 100644
--- a/tests/ui/consts/const-eval/parse_ints.stderr
+++ b/tests/ui/consts/const-eval/parse_ints.stderr
@@ -6,7 +6,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `core::num::<impl u64>::from_str_radix`
   --> $SRC_DIR/core/src/num/mod.rs:LL:COL
 note: inside `_TOO_LOW`
-  --> $DIR/parse_ints.rs:7:24
+  --> $DIR/parse_ints.rs:5:24
    |
 LL | const _TOO_LOW: () = { u64::from_str_radix("12345ABCD", 1); };
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `core::num::<impl u64>::from_str_radix`
   --> $SRC_DIR/core/src/num/mod.rs:LL:COL
 note: inside `_TOO_HIGH`
-  --> $DIR/parse_ints.rs:8:25
+  --> $DIR/parse_ints.rs:6:25
    |
 LL | const _TOO_HIGH: () = { u64::from_str_radix("12345ABCD", 37); };
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
new file mode 100644
index 00000000000..debe143b091
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
@@ -0,0 +1,24 @@
+#![feature(auto_traits)]
+
+trait Trait1 {}
+auto trait Trait2 {}
+trait Trait3: ?Trait1 {}
+//~^  ERROR `?Trait` is not permitted in supertraits
+trait Trait4 where Self: ?Trait1 {}
+//~^ ERROR ?Trait` bounds are only permitted at the point where a type parameter is declared
+
+fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
+//~^  ERROR `?Trait` is not permitted in trait object types
+fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
+//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+
+trait Trait {}
+// Do not suggest `#![feature(more_maybe_bounds)]` for repetitions
+fn baz<T: ?Trait + ?Trait>(_ : T) {}
+//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
new file mode 100644
index 00000000000..e6d65e05997
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
@@ -0,0 +1,71 @@
+error[E0658]: `?Trait` is not permitted in supertraits
+  --> $DIR/feature-gate-more-maybe-bounds.rs:5:15
+   |
+LL | trait Trait3: ?Trait1 {}
+   |               ^^^^^^^
+   |
+   = note: traits are `?Trait1` by default
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `?Trait` is not permitted in trait object types
+  --> $DIR/feature-gate-more-maybe-bounds.rs:10:28
+   |
+LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
+   |                            ^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
+  --> $DIR/feature-gate-more-maybe-bounds.rs:7:26
+   |
+LL | trait Trait4 where Self: ?Trait1 {}
+   |                          ^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0203]: type parameter has more than one relaxed default bound, only one is supported
+  --> $DIR/feature-gate-more-maybe-bounds.rs:12:11
+   |
+LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
+   |           ^^^^^^^   ^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/feature-gate-more-maybe-bounds.rs:12:11
+   |
+LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
+   |           ^^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/feature-gate-more-maybe-bounds.rs:12:21
+   |
+LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
+   |                     ^^^^^^^
+
+error[E0203]: type parameter has more than one relaxed default bound, only one is supported
+  --> $DIR/feature-gate-more-maybe-bounds.rs:19:11
+   |
+LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
+   |           ^^^^^^   ^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/feature-gate-more-maybe-bounds.rs:19:11
+   |
+LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
+   |           ^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/feature-gate-more-maybe-bounds.rs:19:20
+   |
+LL | fn baz<T: ?Trait + ?Trait>(_ : T) {}
+   |                    ^^^^^^
+
+error: aborting due to 5 previous errors; 4 warnings emitted
+
+Some errors have detailed explanations: E0203, E0658.
+For more information about an error, try `rustc --explain E0203`.
diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.rs b/tests/ui/lang-items/missing-clone-for-suggestion.rs
deleted file mode 100644
index e8290c0098a..00000000000
--- a/tests/ui/lang-items/missing-clone-for-suggestion.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Avoid panicking if the Clone trait is not found while building error suggestions
-// See #104870
-
-#![feature(no_core, lang_items)]
-#![no_core]
-
-#[lang = "sized"]
-trait Sized {}
-
-#[lang = "copy"]
-trait Copy {}
-
-fn g<T>(x: T) {}
-
-fn f(x: *mut u8) {
-    g(x);
-    g(x); //~ ERROR use of moved value: `x`
-}
-
-fn main() {}
diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.stderr b/tests/ui/lang-items/missing-clone-for-suggestion.stderr
deleted file mode 100644
index 0187f965b5c..00000000000
--- a/tests/ui/lang-items/missing-clone-for-suggestion.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0382]: use of moved value: `x`
-  --> $DIR/missing-clone-for-suggestion.rs:17:7
-   |
-LL | fn f(x: *mut u8) {
-   |      - move occurs because `x` has type `*mut u8`, which does not implement the `Copy` trait
-LL |     g(x);
-   |       - value moved here
-LL |     g(x);
-   |       ^ value used here after move
-   |
-note: consider changing this parameter type in function `g` to borrow instead if owning the value isn't necessary
-  --> $DIR/missing-clone-for-suggestion.rs:13:12
-   |
-LL | fn g<T>(x: T) {}
-   |    -       ^ this parameter takes ownership of the value
-   |    |
-   |    in this function
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs
new file mode 100644
index 00000000000..46065dcee81
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs
@@ -0,0 +1,45 @@
+#![deny(dead_code)]
+
+struct Foo; //~ ERROR struct `Foo` is never constructed
+
+trait Trait { //~ ERROR trait `Trait` is never used
+    fn foo(&self) {}
+}
+
+impl Trait for Foo {}
+
+impl Trait for [Foo] {}
+impl<const N: usize> Trait for [Foo; N] {}
+
+impl Trait for *const Foo {}
+impl Trait for *mut Foo {}
+
+impl Trait for &Foo {}
+impl Trait for &&Foo {}
+impl Trait for &mut Foo {}
+
+impl Trait for [&Foo] {}
+impl Trait for &[Foo] {}
+impl Trait for &*const Foo {}
+
+pub trait Trait2 {
+    fn foo(&self) {}
+}
+
+impl Trait2 for Foo {}
+
+impl Trait2 for [Foo] {}
+impl<const N: usize> Trait2 for [Foo; N] {}
+
+impl Trait2 for *const Foo {}
+impl Trait2 for *mut Foo {}
+
+impl Trait2 for &Foo {}
+impl Trait2 for &&Foo {}
+impl Trait2 for &mut Foo {}
+
+impl Trait2 for [&Foo] {}
+impl Trait2 for &[Foo] {}
+impl Trait2 for &*const Foo {}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr
new file mode 100644
index 00000000000..e61fc403e81
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr
@@ -0,0 +1,20 @@
+error: struct `Foo` is never constructed
+  --> $DIR/unused-impl-for-non-adts.rs:3:8
+   |
+LL | struct Foo;
+   |        ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-impl-for-non-adts.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: trait `Trait` is never used
+  --> $DIR/unused-impl-for-non-adts.rs:5:7
+   |
+LL | trait Trait {
+   |       ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/issue-118786.rs b/tests/ui/macros/issue-118786.rs
index 97454c9de07..a41372e4ea8 100644
--- a/tests/ui/macros/issue-118786.rs
+++ b/tests/ui/macros/issue-118786.rs
@@ -7,6 +7,7 @@ macro_rules! make_macro {
         macro_rules! $macro_name {
         //~^ ERROR macro expansion ignores token `{` and any following
         //~| ERROR cannot find macro `macro_rules` in this scope
+        //~| put a macro name here
             () => {}
         }
     }
diff --git a/tests/ui/macros/issue-118786.stderr b/tests/ui/macros/issue-118786.stderr
index 03e65c94ba7..256b742ee16 100644
--- a/tests/ui/macros/issue-118786.stderr
+++ b/tests/ui/macros/issue-118786.stderr
@@ -1,5 +1,5 @@
 error: macros that expand to items must be delimited with braces or followed by a semicolon
-  --> $DIR/issue-118786.rs:15:13
+  --> $DIR/issue-118786.rs:16:13
    |
 LL | make_macro!((meow));
    |             ^^^^^^
@@ -34,10 +34,10 @@ LL | make_macro!((meow));
    | ------------------- in this macro invocation
    |
 note: maybe you have forgotten to define a name for this `macro_rules!`
-  --> $DIR/issue-118786.rs:7:9
+  --> $DIR/issue-118786.rs:7:20
    |
 LL |         macro_rules! $macro_name {
-   |         ^^^^^^^^^^^
+   |                    ^ put a macro name here
 ...
 LL | make_macro!((meow));
    | ------------------- in this macro invocation
diff --git a/tests/ui/maybe-bounds.stderr b/tests/ui/maybe-bounds.stderr
index 1d823b6acb2..230d11fd0ae 100644
--- a/tests/ui/maybe-bounds.stderr
+++ b/tests/ui/maybe-bounds.stderr
@@ -1,22 +1,31 @@
-error: `?Trait` is not permitted in supertraits
+error[E0658]: `?Trait` is not permitted in supertraits
   --> $DIR/maybe-bounds.rs:1:11
    |
 LL | trait Tr: ?Sized {}
    |           ^^^^^^
    |
    = note: traits are `?Sized` by default
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bounds.rs:4:20
    |
 LL | type A1 = dyn Tr + (?Sized);
    |                    ^^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bounds.rs:6:28
    |
 LL | type A2 = dyn for<'a> Tr + (?Sized);
    |                            ^^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/parser/issues/issue-19398.rs b/tests/ui/parser/issues/issue-19398.rs
index 46eb320a172..358f65f1da5 100644
--- a/tests/ui/parser/issues/issue-19398.rs
+++ b/tests/ui/parser/issues/issue-19398.rs
@@ -1,6 +1,10 @@
 trait T {
     extern "Rust" unsafe fn foo();
-    //~^ ERROR expected `{`, found keyword `unsafe`
+    //~^ ERROR expected `fn`, found keyword `unsafe`
+    //~| NOTE expected `fn`
+    //~| HELP `unsafe` must come before `extern "Rust"`
+    //~| SUGGESTION unsafe extern "Rust"
+    //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
 }
 
 fn main() {}
diff --git a/tests/ui/parser/issues/issue-19398.stderr b/tests/ui/parser/issues/issue-19398.stderr
index 236fac673b6..2b97ec50c91 100644
--- a/tests/ui/parser/issues/issue-19398.stderr
+++ b/tests/ui/parser/issues/issue-19398.stderr
@@ -1,13 +1,13 @@
-error: expected `{`, found keyword `unsafe`
+error: expected `fn`, found keyword `unsafe`
   --> $DIR/issue-19398.rs:2:19
    |
-LL | trait T {
-   |         - while parsing this item list starting here
 LL |     extern "Rust" unsafe fn foo();
-   |                   ^^^^^^ expected `{`
-LL |
-LL | }
-   | - the item list ends here
+   |     --------------^^^^^^
+   |     |             |
+   |     |             expected `fn`
+   |     help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"`
+   |
+   = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.rs
new file mode 100644
index 00000000000..794ac635c76
--- /dev/null
+++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.rs
@@ -0,0 +1,16 @@
+//@ edition:2018
+
+// There is an order to respect for keywords before a function:
+// `<visibility>, const, async, unsafe, extern, "<ABI>"`
+//
+// This test ensures the compiler is helpful about them being misplaced.
+// Visibilities are tested elsewhere.
+
+extern "C" unsafe fn test() {}
+//~^ ERROR expected `fn`, found keyword `unsafe`
+//~| NOTE expected `fn`
+//~| HELP `unsafe` must come before `extern "C"`
+//~| SUGGESTION unsafe extern "C"
+//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
+
+fn main() {}
diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.stderr
new file mode 100644
index 00000000000..8ed037869c8
--- /dev/null
+++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe-abi.stderr
@@ -0,0 +1,13 @@
+error: expected `fn`, found keyword `unsafe`
+  --> $DIR/wrong-unsafe-abi.rs:9:12
+   |
+LL | extern "C" unsafe fn test() {}
+   | -----------^^^^^^
+   | |          |
+   | |          expected `fn`
+   | help: `unsafe` must come before `extern "C"`: `unsafe extern "C"`
+   |
+   = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr
index 3134746b930..ff32b173d49 100644
--- a/tests/ui/parser/trait-object-trait-parens.stderr
+++ b/tests/ui/parser/trait-object-trait-parens.stderr
@@ -1,20 +1,29 @@
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/trait-object-trait-parens.rs:8:24
    |
 LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
    |                        ^^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/trait-object-trait-parens.rs:13:16
    |
 LL |     let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
    |                ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/trait-object-trait-parens.rs:18:44
    |
 LL |     let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
    |                                            ^^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/trait-object-trait-parens.rs:8:16
@@ -91,4 +100,5 @@ LL |     let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
 
 error: aborting due to 6 previous errors; 3 warnings emitted
 
-For more information about this error, try `rustc --explain E0225`.
+Some errors have detailed explanations: E0225, E0658.
+For more information about an error, try `rustc --explain E0225`.
diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs
index 99d318e36be..746b98fbd07 100644
--- a/tests/ui/privacy/private-in-public-warn.rs
+++ b/tests/ui/privacy/private-in-public-warn.rs
@@ -39,7 +39,7 @@ mod traits {
     pub trait PubTr {}
 
     pub type Alias<T: PrivTr> = T; //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Alias`
-    //~^ WARNING bounds on generic parameters are not enforced in type aliases
+    //~^ WARNING bounds on generic parameters in type aliases are not enforced
     pub trait Tr1: PrivTr {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr1`
     pub trait Tr2<T: PrivTr> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr2`
     pub trait Tr3 {
@@ -58,7 +58,7 @@ mod traits_where {
 
     pub type Alias<T> where T: PrivTr = T;
         //~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Alias`
-        //~| WARNING where clauses are not enforced in type aliases
+        //~| WARNING where clauses on type aliases are not enforced
     pub trait Tr2<T> where T: PrivTr {}
         //~^ ERROR trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2`
     pub trait Tr3 {
diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr
index ac7e5547de9..3f7b8c281e7 100644
--- a/tests/ui/privacy/private-in-public-warn.stderr
+++ b/tests/ui/privacy/private-in-public-warn.stderr
@@ -395,30 +395,32 @@ note: but type `Priv2` is only usable at visibility `pub(self)`
 LL |     struct Priv2;
    |     ^^^^^^^^^^^^
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/private-in-public-warn.rs:41:23
    |
 LL |     pub type Alias<T: PrivTr> = T;
-   |                       ^^^^^^
-   |
+   |                     --^^^^^^
+   |                     | |
+   |                     | will not be checked at usage sites of the type alias
+   |                     help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
    = note: `#[warn(type_alias_bounds)]` on by default
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL -     pub type Alias<T: PrivTr> = T;
-LL +     pub type Alias<T> = T;
-   |
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/private-in-public-warn.rs:59:29
    |
 LL |     pub type Alias<T> where T: PrivTr = T;
-   |                             ^^^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL -     pub type Alias<T> where T: PrivTr = T;
-LL +     pub type Alias<T>  = T;
-   |
+   |                       ------^^^^^^^^^
+   |                       |     |
+   |                       |     will not be checked at usage sites of the type alias
+   |                       help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
 error: aborting due to 34 previous errors; 2 warnings emitted
 
diff --git a/tests/ui/resolve/issue-118295.rs b/tests/ui/resolve/issue-118295.rs
index b97681d9563..37a49baee80 100644
--- a/tests/ui/resolve/issue-118295.rs
+++ b/tests/ui/resolve/issue-118295.rs
@@ -1,5 +1,11 @@
 macro_rules! {}
 //~^ ERROR cannot find macro `macro_rules` in this scope
 //~| NOTE maybe you have forgotten to define a name for this `macro_rules!`
+//~| put a macro name here
+
+macro_rules!{}
+//~^ ERROR cannot find macro `macro_rules` in this scope
+//~| NOTE maybe you have forgotten to define a name for this `macro_rules!`
+//~| put a macro name here
 
 fn main() {}
diff --git a/tests/ui/resolve/issue-118295.stderr b/tests/ui/resolve/issue-118295.stderr
index d60d7d9185d..06a37e81d6c 100644
--- a/tests/ui/resolve/issue-118295.stderr
+++ b/tests/ui/resolve/issue-118295.stderr
@@ -1,14 +1,26 @@
 error: cannot find macro `macro_rules` in this scope
-  --> $DIR/issue-118295.rs:1:1
+  --> $DIR/issue-118295.rs:6:1
    |
-LL | macro_rules! {}
+LL | macro_rules!{}
    | ^^^^^^^^^^^
    |
 note: maybe you have forgotten to define a name for this `macro_rules!`
+  --> $DIR/issue-118295.rs:6:12
+   |
+LL | macro_rules!{}
+   |            ^ put a macro name here
+
+error: cannot find macro `macro_rules` in this scope
   --> $DIR/issue-118295.rs:1:1
    |
 LL | macro_rules! {}
    | ^^^^^^^^^^^
+   |
+note: maybe you have forgotten to define a name for this `macro_rules!`
+  --> $DIR/issue-118295.rs:1:12
+   |
+LL | macro_rules! {}
+   |            ^ put a macro name here
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/resolve/issue-55673.stderr b/tests/ui/resolve/issue-55673.stderr
index ffc3252230a..4069b35a998 100644
--- a/tests/ui/resolve/issue-55673.stderr
+++ b/tests/ui/resolve/issue-55673.stderr
@@ -19,7 +19,7 @@ help: consider further restricting type parameter `T`
    |
 LL |     T::Baa: std::fmt::Debug, T: Foo
    |                            ~~~~~~~~
-help: and also change the associated type name
+help: ...and changing the associated type name
    |
 LL |     T::Bar: std::fmt::Debug,
    |        ~~~
diff --git a/tests/ui/traits/maybe-polarity-pass.rs b/tests/ui/traits/maybe-polarity-pass.rs
new file mode 100644
index 00000000000..075a0d8dcac
--- /dev/null
+++ b/tests/ui/traits/maybe-polarity-pass.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(auto_traits)]
+#![feature(more_maybe_bounds)]
+#![feature(negative_impls)]
+
+trait Trait1 {}
+auto trait Trait2 {}
+
+trait Trait3 : ?Trait1 {}
+trait Trait4 where Self: Trait1 {}
+
+fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
+fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+//~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+
+struct S;
+impl !Trait2 for S {}
+impl Trait1 for S {}
+impl Trait3 for S {}
+
+fn main() {
+    foo(Box::new(S));
+    bar(&S);
+}
diff --git a/tests/ui/traits/maybe-polarity-pass.stderr b/tests/ui/traits/maybe-polarity-pass.stderr
new file mode 100644
index 00000000000..09ed52f5b0d
--- /dev/null
+++ b/tests/ui/traits/maybe-polarity-pass.stderr
@@ -0,0 +1,20 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-polarity-pass.rs:14:20
+   |
+LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+   |                    ^^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-polarity-pass.rs:14:30
+   |
+LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+   |                              ^^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-polarity-pass.rs:14:40
+   |
+LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
+   |                                        ^^^^^^^
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/traits/maybe-polarity-repeated.rs b/tests/ui/traits/maybe-polarity-repeated.rs
new file mode 100644
index 00000000000..4b5ec83fffa
--- /dev/null
+++ b/tests/ui/traits/maybe-polarity-repeated.rs
@@ -0,0 +1,9 @@
+#![feature(more_maybe_bounds)]
+
+trait Trait {}
+fn foo<T: ?Trait + ?Trait>(_: T) {}
+//~^ ERROR type parameter has more than one relaxed default bound, only one is supported
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+//~| WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+
+fn main() {}
diff --git a/tests/ui/traits/maybe-polarity-repeated.stderr b/tests/ui/traits/maybe-polarity-repeated.stderr
new file mode 100644
index 00000000000..610c484fbec
--- /dev/null
+++ b/tests/ui/traits/maybe-polarity-repeated.stderr
@@ -0,0 +1,21 @@
+error[E0203]: type parameter has more than one relaxed default bound, only one is supported
+  --> $DIR/maybe-polarity-repeated.rs:4:11
+   |
+LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
+   |           ^^^^^^   ^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-polarity-repeated.rs:4:11
+   |
+LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
+   |           ^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-polarity-repeated.rs:4:20
+   |
+LL | fn foo<T: ?Trait + ?Trait>(_: T) {}
+   |                    ^^^^^^
+
+error: aborting due to 1 previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0203`.
diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr
index 2fe3f0fc39f..be7afabd0d0 100644
--- a/tests/ui/traits/wf-object/maybe-bound.stderr
+++ b/tests/ui/traits/wf-object/maybe-bound.stderr
@@ -1,32 +1,48 @@
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bound.rs:5:15
    |
 LL | type _0 = dyn ?Sized + Foo;
    |               ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bound.rs:8:21
    |
 LL | type _1 = dyn Foo + ?Sized;
    |                     ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bound.rs:11:21
    |
 LL | type _2 = dyn Foo + ?Sized + ?Sized;
    |                     ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bound.rs:11:30
    |
 LL | type _2 = dyn Foo + ?Sized + ?Sized;
    |                              ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/maybe-bound.rs:15:15
    |
 LL | type _3 = dyn ?Sized + Foo;
    |               ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr
index cbc41feec1e..26269476eaa 100644
--- a/tests/ui/traits/wf-object/only-maybe-bound.stderr
+++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr
@@ -1,8 +1,11 @@
-error: `?Trait` is not permitted in trait object types
+error[E0658]: `?Trait` is not permitted in trait object types
   --> $DIR/only-maybe-bound.rs:3:15
    |
 LL | type _0 = dyn ?Sized;
    |               ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0224]: at least one trait is required for an object type
   --> $DIR/only-maybe-bound.rs:3:11
@@ -12,4 +15,5 @@ LL | type _0 = dyn ?Sized;
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0224`.
+Some errors have detailed explanations: E0224, E0658.
+For more information about an error, try `rustc --explain E0224`.
diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr
index d66e468873b..0eae68bfcf0 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr
+++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr
@@ -24,18 +24,19 @@ warning: trait bound i32: Foo does not depend on any type or lifetime parameters
 LL | union U where i32: Foo { f: i32 }
    |                    ^^^
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/trivial-bounds-inconsistent.rs:22:14
    |
 LL | type Y where i32: Foo = ();
-   |              ^^^^^^^^
-   |
+   |        ------^^^^^^^^
+   |        |     |
+   |        |     will not be checked at usage sites of the type alias
+   |        help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
    = note: `#[warn(type_alias_bounds)]` on by default
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type Y where i32: Foo = ();
-LL + type Y  = ();
-   |
 
 warning: trait bound i32: Foo does not depend on any type or lifetime parameters
   --> $DIR/trivial-bounds-inconsistent.rs:22:19
diff --git a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.eager.stderr b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.eager.stderr
new file mode 100644
index 00000000000..e891ff10fda
--- /dev/null
+++ b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.eager.stderr
@@ -0,0 +1,36 @@
+error[E0220]: associated type `Assoc` not found for `T`
+  --> $DIR/unresolved-assoc-ty-suggest-trait.rs:9:22
+   |
+LL | type AssocOf<T> = T::Assoc;
+   |                      ^^^^^ there is an associated type `Assoc` in the trait `Trait`
+   |
+help: consider fully qualifying the associated type
+   |
+LL | type AssocOf<T> = <T as Trait>::Assoc;
+   |                   +  +++++++++
+
+error[E0220]: associated type `Assok` not found for `T`
+  --> $DIR/unresolved-assoc-ty-suggest-trait.rs:13:22
+   |
+LL | type AssokOf<T> = T::Assok;
+   |                      ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
+   |
+help: consider fully qualifying and renaming the associated type
+   |
+LL | type AssokOf<T> = <T as Trait>::Assoc;
+   |                   +  +++++++++  ~~~~~
+
+error[E0220]: associated type `Proj` not found for `T`
+  --> $DIR/unresolved-assoc-ty-suggest-trait.rs:22:21
+   |
+LL | type ProjOf<T> = T::Proj;
+   |                     ^^^^ there is an associated type `Proj` in the trait `Parametrized`
+   |
+help: consider fully qualifying the associated type
+   |
+LL | type ProjOf<T> = <T as Parametrized</* 'a, T, N */>>::Proj;
+   |                  +  ++++++++++++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr
new file mode 100644
index 00000000000..96179a7b484
--- /dev/null
+++ b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr
@@ -0,0 +1,40 @@
+error[E0220]: associated type `Assoc` not found for `T`
+  --> $DIR/unresolved-assoc-ty-suggest-trait.rs:9:22
+   |
+LL | type AssocOf<T> = T::Assoc;
+   |                      ^^^^^ there is an associated type `Assoc` in the trait `Trait`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type AssocOf<T: Trait> = T::Assoc;
+   |               +++++++
+
+error[E0220]: associated type `Assok` not found for `T`
+  --> $DIR/unresolved-assoc-ty-suggest-trait.rs:13:22
+   |
+LL | type AssokOf<T> = T::Assok;
+   |                      ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type AssokOf<T: Trait> = T::Assok;
+   |               +++++++
+help: ...and changing the associated type name
+   |
+LL | type AssokOf<T> = T::Assoc;
+   |                      ~~~~~
+
+error[E0220]: associated type `Proj` not found for `T`
+  --> $DIR/unresolved-assoc-ty-suggest-trait.rs:22:21
+   |
+LL | type ProjOf<T> = T::Proj;
+   |                     ^^^^ there is an associated type `Proj` in the trait `Parametrized`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type ProjOf<T: Parametrized</* 'a, T, N */>> = T::Proj;
+   |              ++++++++++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs
new file mode 100644
index 00000000000..2c8d448f308
--- /dev/null
+++ b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs
@@ -0,0 +1,26 @@
+// Ensure that we don't suggest *type alias bounds* for **eager** type aliases.
+// issue: rust-lang/rust#125789
+
+//@ revisions: eager lazy
+#![cfg_attr(lazy, feature(lazy_type_alias), allow(incomplete_features))]
+
+trait Trait { type Assoc; }
+
+type AssocOf<T> = T::Assoc; //~ ERROR associated type `Assoc` not found for `T`
+//[eager]~^ HELP consider fully qualifying the associated type
+//[lazy]~| HELP consider restricting type parameter `T`
+
+type AssokOf<T> = T::Assok; //~ ERROR associated type `Assok` not found for `T`
+//[eager]~^ HELP consider fully qualifying and renaming the associated type
+//[lazy]~| HELP consider restricting type parameter `T`
+//[lazy]~| HELP and changing the associated type name
+
+trait Parametrized<'a, T, const N: usize> {
+    type Proj;
+}
+
+type ProjOf<T> = T::Proj; //~ ERROR associated type `Proj` not found for `T`
+//[eager]~^ HELP consider fully qualifying the associated type
+//[lazy]~| HELP consider restricting type parameter `T`
+
+fn main() {}
diff --git a/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs
index 5ee3c027f40..52e0887175d 100644
--- a/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs
+++ b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs
@@ -3,6 +3,6 @@
 
 //@ check-pass
 pub type T<P: Send + Send + Send> = P;
-//~^ WARN bounds on generic parameters are not enforced in type aliases
+//~^ WARN bounds on generic parameters in type aliases are not enforced
 
 fn main() {}
diff --git a/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr
index 125ffbbb417..9fd0fe4913b 100644
--- a/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr
+++ b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr
@@ -1,15 +1,16 @@
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15
    |
 LL | pub type T<P: Send + Send + Send> = P;
-   |               ^^^^   ^^^^   ^^^^
+   |             --^^^^---^^^^---^^^^
+   |             |               |
+   |             |               will not be checked at usage sites of the type alias
+   |             help: remove this bound
    |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
    = note: `#[warn(type_alias_bounds)]` on by default
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - pub type T<P: Send + Send + Send> = P;
-LL + pub type T<P> = P;
-   |
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/type/type-alias-bounds.rs b/tests/ui/type/type-alias-bounds.rs
index 6d63c0c7e1b..37c073fe1f9 100644
--- a/tests/ui/type/type-alias-bounds.rs
+++ b/tests/ui/type/type-alias-bounds.rs
@@ -6,15 +6,15 @@
 use std::rc::Rc;
 
 type SVec<T: Send + Send> = Vec<T>;
-//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
+//~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds]
 type S2Vec<T> where T: Send = Vec<T>;
-//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds]
+//~^ WARN where clauses on type aliases are not enforced [type_alias_bounds]
 type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
-//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
+//~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds]
 type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
-//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds]
+//~^ WARN bounds on generic parameters in type aliases are not enforced [type_alias_bounds]
 type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
-//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds]
+//~^ WARN where clauses on type aliases are not enforced [type_alias_bounds]
 
 static STATIC: u32 = 0;
 
@@ -42,10 +42,11 @@ fn foo<'a>(y: &'a i32) {
 struct Sendable<T: Send>(T);
 type MySendable<T> = Sendable<T>; // no error here!
 
-// However, bounds *are* taken into account when accessing associated types
+// Bounds on type params do enable shorthand type alias paths.
+// However, that doesn't actually mean that they are properly enforced.
 trait Bound { type Assoc; }
-type T1<U: Bound> = U::Assoc; //~ WARN not enforced in type aliases
-type T2<U> where U: Bound = U::Assoc;  //~ WARN not enforced in type aliases
+type T1<U: Bound> = U::Assoc; //~ WARN are not enforced
+type T2<U> where U: Bound = U::Assoc;  //~ WARN are not enforced
 
 // This errors:
 // `type T3<U> = U::Assoc;`
@@ -53,7 +54,7 @@ type T2<U> where U: Bound = U::Assoc;  //~ WARN not enforced in type aliases
 type T4<U> = <U as Bound>::Assoc;
 
 // Make sure the help about associated types is not shown incorrectly
-type T5<U: Bound> = <U as Bound>::Assoc;  //~ WARN not enforced in type aliases
-type T6<U: Bound> = ::std::vec::Vec<U>;  //~ WARN not enforced in type aliases
+type T5<U: Bound> = <U as Bound>::Assoc;  //~ WARN are not enforced
+type T6<U: Bound> = ::std::vec::Vec<U>;  //~ WARN are not enforced
 
 fn main() {}
diff --git a/tests/ui/type/type-alias-bounds.stderr b/tests/ui/type/type-alias-bounds.stderr
index 92e573393c9..15c00901066 100644
--- a/tests/ui/type/type-alias-bounds.stderr
+++ b/tests/ui/type/type-alias-bounds.stderr
@@ -1,121 +1,132 @@
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias-bounds.rs:8:14
    |
 LL | type SVec<T: Send + Send> = Vec<T>;
-   |              ^^^^   ^^^^
-   |
+   |            --^^^^---^^^^
+   |            |        |
+   |            |        will not be checked at usage sites of the type alias
+   |            help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
    = note: `#[warn(type_alias_bounds)]` on by default
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type SVec<T: Send + Send> = Vec<T>;
-LL + type SVec<T> = Vec<T>;
-   |
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias-bounds.rs:10:21
    |
 LL | type S2Vec<T> where T: Send = Vec<T>;
-   |                     ^^^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type S2Vec<T> where T: Send = Vec<T>;
-LL + type S2Vec<T>  = Vec<T>;
-   |
+   |               ------^^^^^^^
+   |               |     |
+   |               |     will not be checked at usage sites of the type alias
+   |               help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias-bounds.rs:12:19
    |
 LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
-   |                   ^^   ^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
-LL + type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>);
-   |
+   |                 --^^---^^
+   |                 |      |
+   |                 |      will not be checked at usage sites of the type alias
+   |                 help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
+warning: bounds on generic parameters in type aliases are not enforced
   --> $DIR/type-alias-bounds.rs:14:18
    |
 LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
-   |                  ^^   ^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
-LL + type WVec<'b, T> = (&'b u32, Vec<T>);
-   |
+   |                --^^---^^
+   |                |      |
+   |                |      will not be checked at usage sites of the type alias
+   |                help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: where clauses are not enforced in type aliases
+warning: where clauses on type aliases are not enforced
   --> $DIR/type-alias-bounds.rs:16:25
    |
 LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
-   |                         ^^^^^  ^^^^^
-   |
-help: the clause will not be checked when the type alias is used, and should be removed
-   |
-LL - type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec<T>);
-LL + type W2Vec<'b, T>  = (&'b u32, Vec<T>);
-   |
+   |                   ------^^^^^--^^^^^
+   |                   |            |
+   |                   |            will not be checked at usage sites of the type alias
+   |                   help: remove this where clause
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
-  --> $DIR/type-alias-bounds.rs:47:12
+warning: bounds on generic parameters in type aliases are not enforced
+  --> $DIR/type-alias-bounds.rs:48:12
    |
 LL | type T1<U: Bound> = U::Assoc;
-   |            ^^^^^
+   |            ^^^^^ will not be checked at usage sites of the type alias
    |
-help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
-  --> $DIR/type-alias-bounds.rs:47:21
-   |
-LL | type T1<U: Bound> = U::Assoc;
-   |                     ^^^^^^^^
-help: the bound will not be checked when the type alias is used, and should be removed
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
+help: remove this bound
    |
 LL - type T1<U: Bound> = U::Assoc;
 LL + type T1<U> = U::Assoc;
    |
+help: fully qualify this associated type
+   |
+LL | type T1<U: Bound> = <U as /* Trait */>::Assoc;
+   |                     +  +++++++++++++++
 
-warning: where clauses are not enforced in type aliases
-  --> $DIR/type-alias-bounds.rs:48:18
+warning: where clauses on type aliases are not enforced
+  --> $DIR/type-alias-bounds.rs:49:18
    |
 LL | type T2<U> where U: Bound = U::Assoc;
-   |                  ^^^^^^^^
+   |                  ^^^^^^^^ will not be checked at usage sites of the type alias
    |
-help: use fully disambiguated paths (i.e., `<T as Trait>::Assoc`) to refer to associated types in type aliases
-  --> $DIR/type-alias-bounds.rs:48:29
-   |
-LL | type T2<U> where U: Bound = U::Assoc;
-   |                             ^^^^^^^^
-help: the clause will not be checked when the type alias is used, and should be removed
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
+help: remove this where clause
    |
 LL - type T2<U> where U: Bound = U::Assoc;
 LL + type T2<U>  = U::Assoc;
    |
+help: fully qualify this associated type
+   |
+LL | type T2<U> where U: Bound = <U as /* Trait */>::Assoc;
+   |                             +  +++++++++++++++
 
-warning: bounds on generic parameters are not enforced in type aliases
-  --> $DIR/type-alias-bounds.rs:56:12
+warning: bounds on generic parameters in type aliases are not enforced
+  --> $DIR/type-alias-bounds.rs:57:12
    |
 LL | type T5<U: Bound> = <U as Bound>::Assoc;
-   |            ^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type T5<U: Bound> = <U as Bound>::Assoc;
-LL + type T5<U> = <U as Bound>::Assoc;
-   |
+   |          --^^^^^
+   |          | |
+   |          | will not be checked at usage sites of the type alias
+   |          help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
-warning: bounds on generic parameters are not enforced in type aliases
-  --> $DIR/type-alias-bounds.rs:57:12
+warning: bounds on generic parameters in type aliases are not enforced
+  --> $DIR/type-alias-bounds.rs:58:12
    |
 LL | type T6<U: Bound> = ::std::vec::Vec<U>;
-   |            ^^^^^
-   |
-help: the bound will not be checked when the type alias is used, and should be removed
-   |
-LL - type T6<U: Bound> = ::std::vec::Vec<U>;
-LL + type T6<U> = ::std::vec::Vec<U>;
-   |
+   |          --^^^^^
+   |          | |
+   |          | will not be checked at usage sites of the type alias
+   |          help: remove this bound
+   |
+   = note: this is a known limitation of the type checker that may be lifted in a future edition.
+           see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics
 
 warning: 9 warnings emitted
 
diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/maybe-bounds-where.stderr
index 683bd387bb2..f7851261667 100644
--- a/tests/ui/unsized/maybe-bounds-where.stderr
+++ b/tests/ui/unsized/maybe-bounds-where.stderr
@@ -1,32 +1,47 @@
-error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
   --> $DIR/maybe-bounds-where.rs:1:28
    |
 LL | struct S1<T>(T) where (T): ?Sized;
    |                            ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
   --> $DIR/maybe-bounds-where.rs:4:27
    |
 LL | struct S2<T>(T) where u8: ?Sized;
    |                           ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
   --> $DIR/maybe-bounds-where.rs:7:35
    |
 LL | struct S3<T>(T) where &'static T: ?Sized;
    |                                   ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
   --> $DIR/maybe-bounds-where.rs:12:34
    |
 LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
    |                                  ^^^^^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: `?Trait` bounds are only permitted at the point where a type parameter is declared
+error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared
   --> $DIR/maybe-bounds-where.rs:21:21
    |
 LL |     fn f() where T: ?Sized {}
    |                     ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
   --> $DIR/maybe-bounds-where.rs:12:34
@@ -39,6 +54,9 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
    |                                 ^^^^^^^^^^^^^^^   ^^^^^^
+   |
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
   --> $DIR/maybe-bounds-where.rs:16:33
@@ -48,4 +66,5 @@ LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
 
 error: aborting due to 6 previous errors; 2 warnings emitted
 
-For more information about this error, try `rustc --explain E0203`.
+Some errors have detailed explanations: E0203, E0658.
+For more information about an error, try `rustc --explain E0203`.