about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/pull_request_template.md10
-rw-r--r--compiler/rustc_ast_passes/messages.ftl5
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs23
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs2
-rw-r--r--compiler/rustc_attr/src/builtin.rs10
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl2
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/util.rs4
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_expand/src/base.rs21
-rw-r--r--compiler/rustc_expand/src/config.rs9
-rw-r--r--compiler/rustc_expand/src/expand.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs24
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs6
-rw-r--r--compiler/rustc_interface/src/util.rs28
-rw-r--r--compiler/rustc_lint/messages.ftl235
-rw-r--r--compiler/rustc_lint/src/builtin.rs21
-rw-r--r--compiler/rustc_lint/src/context.rs22
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs601
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs311
-rw-r--r--compiler/rustc_lint/src/early.rs12
-rw-r--r--compiler/rustc_lint/src/lints.rs850
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs116
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs16
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs12
-rw-r--r--compiler/rustc_macros/src/lib.rs6
-rw-r--r--compiler/rustc_metadata/messages.ftl2
-rw-r--r--compiler/rustc_metadata/src/creader.rs21
-rw-r--r--compiler/rustc_middle/messages.ftl14
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs183
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs8
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs3
-rw-r--r--compiler/rustc_parse/src/parser/item.rs12
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs32
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs74
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs12
-rw-r--r--compiler/rustc_resolve/src/ident.rs15
-rw-r--r--compiler/rustc_resolve/src/imports.rs22
-rw-r--r--compiler/rustc_resolve/src/late.rs20
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs109
-rw-r--r--compiler/rustc_resolve/src/lib.rs10
-rw-r--r--compiler/rustc_resolve/src/macros.rs59
-rw-r--r--compiler/rustc_session/src/parse.rs20
-rw-r--r--compiler/rustc_session/src/version.rs13
-rw-r--r--src/bootstrap/src/core/build_steps/synthetic_targets.rs5
-rwxr-xr-xsrc/tools/clippy/.github/driver.sh19
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml6
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml4
-rw-r--r--src/tools/clippy/CHANGELOG.md7
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md42
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs31
-rw-r--r--src/tools/clippy/clippy_config/src/msrvs.rs3
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml3
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs570
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs14
-rw-r--r--src/tools/clippy/clippy_dev/src/serve.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/assigning_clones.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs49
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs95
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs129
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs110
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_float.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs256
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs82
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_filter.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_unimplemented.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs78
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs82
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs15
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs10
-rw-r--r--src/tools/clippy/lintcheck/Cargo.toml2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr30
-rw-r--r--src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml8
-rw-r--r--src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs260
-rw-r--r--src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr187
-rw-r--r--src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs15
-rw-r--r--src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr17
-rw-r--r--src/tools/clippy/tests/ui-toml/panic/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/panic/panic.rs54
-rw-r--r--src/tools/clippy/tests/ui-toml/panic/panic.stderr11
-rw-r--r--src/tools/clippy/tests/ui-toml/renamed_function_params/default/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/renamed_function_params/extend/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr46
-rw-r--r--src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr34
-rw-r--r--src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.rs110
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs6
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr9
-rw-r--r--src/tools/clippy/tests/ui/assigning_clones.fixed26
-rw-r--r--src/tools/clippy/tests/ui/assigning_clones.rs26
-rw-r--r--src/tools/clippy/tests/ui/assigning_clones.stderr46
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.fixed47
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.rs47
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.stderr76
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed77
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_list.rs77
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr136
-rw-r--r--src/tools/clippy/tests/ui/duplicated_attributes.rs6
-rw-r--r--src/tools/clippy/tests/ui/from_str_radix_10.fixed11
-rw-r--r--src/tools/clippy/tests/ui/from_str_radix_10.rs11
-rw-r--r--src/tools/clippy/tests/ui/from_str_radix_10.stderr16
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.stderr122
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.fixed241
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs5
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr257
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.fixed61
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs1
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr18
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs18
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs28
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr30
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.rs8
-rw-r--r--src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed42
-rw-r--r--src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs36
-rw-r--r--src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.stderr177
-rw-r--r--src/tools/clippy/tests/ui/no_effect.rs13
-rw-r--r--src/tools/clippy/tests/ui/no_effect.stderr68
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs56
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr28
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed32
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs32
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr4
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.fixed43
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.rs43
-rw-r--r--src/tools/clippy/tests/ui/while_float.rs14
-rw-r--r--src/tools/clippy/tests/ui/while_float.stderr20
-rw-r--r--src/tools/clippy/util/gh-pages/script.js2
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt1
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/Makefile5
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk21
-rw-r--r--tests/ui/asm/empty_global_asm.rs (renamed from tests/ui/empty_global_asm.rs)0
-rw-r--r--tests/ui/asm/simple_global_asm.rs (renamed from tests/ui/simple_global_asm.rs)0
-rw-r--r--tests/ui/backtrace/apple-no-dsymutil.rs (renamed from tests/ui/backtrace-apple-no-dsymutil.rs)0
-rw-r--r--tests/ui/backtrace/auxiliary/dylib-dep-helper-aux.rs (renamed from tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs)0
-rw-r--r--tests/ui/backtrace/auxiliary/dylib-dep-helper.rs (renamed from tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs)0
-rw-r--r--tests/ui/backtrace/auxiliary/line-tables-only-helper.rs (renamed from tests/ui/debuginfo/auxiliary/line-tables-only-helper.rs)0
-rw-r--r--tests/ui/backtrace/backtrace.rs (renamed from tests/ui/backtrace.rs)0
-rw-r--r--tests/ui/backtrace/dylib-dep.rs (renamed from tests/ui/debuginfo/backtrace-dylib-dep.rs)0
-rw-r--r--tests/ui/backtrace/line-tables-only.rs (renamed from tests/ui/debuginfo/backtrace-line-tables-only.rs)0
-rw-r--r--tests/ui/backtrace/std-backtrace.rs (renamed from tests/ui/std-backtrace.rs)0
-rw-r--r--tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr8
-rw-r--r--tests/ui/check-cfg/allow-same-level.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-feature.none.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-feature.some.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr2
-rw-r--r--tests/ui/check-cfg/cfg-value-for-cfg-name.stderr2
-rw-r--r--tests/ui/check-cfg/compact-names.stderr2
-rw-r--r--tests/ui/check-cfg/compact-values.stderr2
-rw-r--r--tests/ui/check-cfg/concat-values.stderr4
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names.stderr2
-rw-r--r--tests/ui/check-cfg/mix.stderr4
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.stderr2
-rw-r--r--tests/ui/check-cfg/unexpected-cfg-value.stderr4
-rw-r--r--tests/ui/check-cfg/well-known-names.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr32
-rw-r--r--tests/ui/coherence/auxiliary/orphan-check-diagnostics.rs (renamed from tests/ui/auxiliary/orphan-check-diagnostics.rs)0
-rw-r--r--tests/ui/coherence/orphan-check-diagnostics.rs (renamed from tests/ui/orphan-check-diagnostics.rs)0
-rw-r--r--tests/ui/coherence/orphan-check-diagnostics.stderr (renamed from tests/ui/orphan-check-diagnostics.stderr)0
-rw-r--r--tests/ui/cross-crate/address-insignificant.rs (renamed from tests/ui/cross-crate/xcrate-address-insignificant.rs)0
-rw-r--r--tests/ui/cross-crate/associated-type-defaults.rs (renamed from tests/ui/cross-crate/xcrate-associated-type-defaults.rs)0
-rw-r--r--tests/ui/cross-crate/auxiliary/static_priv_by_default.rs (renamed from tests/ui/xcrate/auxiliary/static_priv_by_default.rs)0
-rw-r--r--tests/ui/cross-crate/auxiliary/xcrate_unit_struct.rs (renamed from tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs)0
-rw-r--r--tests/ui/cross-crate/generic_fn_nested_return.rs (renamed from tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs)0
-rw-r--r--tests/ui/cross-crate/private-by-default.rs (renamed from tests/ui/xcrate/xcrate-private-by-default.rs)0
-rw-r--r--tests/ui/cross-crate/private-by-default.stderr (renamed from tests/ui/xcrate/xcrate-private-by-default.stderr)20
-rw-r--r--tests/ui/cross-crate/static-addresses.rs (renamed from tests/ui/cross-crate/xcrate-static-addresses.rs)0
-rw-r--r--tests/ui/cross-crate/trait-lifetime-param.rs (renamed from tests/ui/cross-crate/xcrate-trait-lifetime-param.rs)0
-rw-r--r--tests/ui/cross-crate/unit-struct-2.rs (renamed from tests/ui/xcrate/xcrate-unit-struct-2.rs)0
-rw-r--r--tests/ui/cross-crate/unit-struct.rs (renamed from tests/ui/xcrate/xcrate-unit-struct.rs)0
-rw-r--r--tests/ui/cross-crate/unit-struct.stderr (renamed from tests/ui/xcrate/xcrate-unit-struct.stderr)4
-rw-r--r--tests/ui/expr/block-fn.rs (renamed from tests/ui/expr-block-fn.rs)0
-rw-r--r--tests/ui/expr/block-generic.rs (renamed from tests/ui/expr-block-generic.rs)0
-rw-r--r--tests/ui/expr/block.rs (renamed from tests/ui/expr-block.rs)0
-rw-r--r--tests/ui/expr/copy.rs (renamed from tests/ui/expr-copy.rs)0
-rw-r--r--tests/ui/expr/if-generic.rs (renamed from tests/ui/expr-if-generic.rs)0
-rw-r--r--tests/ui/expr/if-panic-all.rs (renamed from tests/ui/expr-if-panic-all.rs)0
-rw-r--r--tests/ui/expr/scope.rs (renamed from tests/ui/expr-scope.rs)0
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs2
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr2
-rw-r--r--tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs (renamed from tests/ui/stmt_expr_attrs_no_feature.rs)0
-rw-r--r--tests/ui/feature-gates/stmt_expr_attrs_no_feature.stderr (renamed from tests/ui/stmt_expr_attrs_no_feature.stderr)0
-rw-r--r--tests/ui/ffi-attrs/ffi_const.rs (renamed from tests/ui/ffi_const.rs)0
-rw-r--r--tests/ui/ffi-attrs/ffi_const.stderr (renamed from tests/ui/ffi_const.stderr)0
-rw-r--r--tests/ui/ffi-attrs/ffi_const2.rs (renamed from tests/ui/ffi_const2.rs)0
-rw-r--r--tests/ui/ffi-attrs/ffi_const2.stderr (renamed from tests/ui/ffi_const2.stderr)0
-rw-r--r--tests/ui/ffi-attrs/ffi_pure.rs (renamed from tests/ui/ffi_pure.rs)0
-rw-r--r--tests/ui/ffi-attrs/ffi_pure.stderr (renamed from tests/ui/ffi_pure.stderr)0
-rw-r--r--tests/ui/fn-main/wrong-location.rs (renamed from tests/ui/main-wrong-location.rs)0
-rw-r--r--tests/ui/fn-main/wrong-location.stderr (renamed from tests/ui/main-wrong-location.stderr)8
-rw-r--r--tests/ui/fn-main/wrong-type.rs (renamed from tests/ui/main-wrong-type.rs)0
-rw-r--r--tests/ui/fn-main/wrong-type.stderr (renamed from tests/ui/main-wrong-type.stderr)2
-rw-r--r--tests/ui/foreign/foreign-fn-return-lifetime.rs (renamed from tests/ui/foreign-fn-return-lifetime.rs)0
-rw-r--r--tests/ui/foreign/foreign-fn-return-lifetime.stderr (renamed from tests/ui/foreign-fn-return-lifetime.stderr)0
-rw-r--r--tests/ui/fuel/optimization-fuel-0.rs (renamed from tests/ui/optimization-fuel-0.rs)0
-rw-r--r--tests/ui/fuel/optimization-fuel-0.stderr (renamed from tests/ui/optimization-fuel-0.stderr)0
-rw-r--r--tests/ui/fuel/optimization-fuel-1.rs (renamed from tests/ui/optimization-fuel-1.rs)0
-rw-r--r--tests/ui/fuel/optimization-fuel-1.stderr (renamed from tests/ui/optimization-fuel-1.stderr)0
-rw-r--r--tests/ui/fuel/print-fuel.rs (renamed from tests/ui/print-fuel/print-fuel.rs)0
-rw-r--r--tests/ui/fuel/print-fuel.stderr (renamed from tests/ui/print-fuel/print-fuel.stderr)0
-rw-r--r--tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.rs28
-rw-r--r--tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.stderr92
-rw-r--r--tests/ui/inference/infer-fn-tail-expr.rs (renamed from tests/ui/infer-fn-tail-expr.rs)0
-rw-r--r--tests/ui/inference/lambda-infer-unresolved.rs (renamed from tests/ui/lambda-infer-unresolved.rs)0
-rw-r--r--tests/ui/inference/order-dependent-cast-inference.rs (renamed from tests/ui/order-dependent-cast-inference.rs)0
-rw-r--r--tests/ui/inference/order-dependent-cast-inference.stderr (renamed from tests/ui/order-dependent-cast-inference.stderr)0
-rw-r--r--tests/ui/intrinsics/always-extern.rs (renamed from tests/ui/intrinsics-always-extern.rs)0
-rw-r--r--tests/ui/intrinsics/always-extern.stderr (renamed from tests/ui/intrinsics-always-extern.stderr)8
-rw-r--r--tests/ui/intrinsics/reify-intrinsic.rs (renamed from tests/ui/reify-intrinsic.rs)0
-rw-r--r--tests/ui/intrinsics/reify-intrinsic.stderr (renamed from tests/ui/reify-intrinsic.stderr)0
-rw-r--r--tests/ui/lint/anonymous-reexport.stderr2
-rw-r--r--tests/ui/lint/group-denied-lint-allowed.rs (renamed from tests/ui/lint-group-denied-lint-allowed.rs)0
-rw-r--r--tests/ui/lint/group-forbid-always-trumps-cli.rs (renamed from tests/ui/lint-group-forbid-always-trumps-cli.rs)0
-rw-r--r--tests/ui/lint/group-forbid-always-trumps-cli.stderr (renamed from tests/ui/lint-group-forbid-always-trumps-cli.stderr)2
-rw-r--r--tests/ui/lint/unknown-lints-at-crate-level.rs (renamed from tests/ui/lint-unknown-lints-at-crate-level.rs)0
-rw-r--r--tests/ui/lint/unused/import_remove_line.stderr2
-rw-r--r--tests/ui/lint/unused/lint-unused-imports.rs2
-rw-r--r--tests/ui/lint/unused/lint-unused-imports.stderr2
-rw-r--r--tests/ui/macros/compile_error_macro.rs (renamed from tests/ui/compile_error_macro.rs)0
-rw-r--r--tests/ui/macros/compile_error_macro.stderr (renamed from tests/ui/compile_error_macro.stderr)0
-rw-r--r--tests/ui/macros/module-macro_use-arguments.rs (renamed from tests/ui/module-macro_use-arguments.rs)0
-rw-r--r--tests/ui/macros/module-macro_use-arguments.stderr (renamed from tests/ui/module-macro_use-arguments.stderr)0
-rw-r--r--tests/ui/macros/no-patterns-in-args-macro.rs (renamed from tests/ui/no-patterns-in-args-macro.rs)0
-rw-r--r--tests/ui/macros/no-patterns-in-args-macro.stderr (renamed from tests/ui/no-patterns-in-args-macro.stderr)0
-rw-r--r--tests/ui/malformed/malformed-regressions.rs6
-rw-r--r--tests/ui/malformed/malformed-regressions.stderr6
-rw-r--r--tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.rs6
-rw-r--r--tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.stderr8
-rw-r--r--tests/ui/parser/issues/issue-49040.rs2
-rw-r--r--tests/ui/parser/issues/issue-49040.stderr6
-rw-r--r--tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.rs5
-rw-r--r--tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.stderr10
-rw-r--r--tests/ui/parser/super-fast-paren-parsing.rs (renamed from tests/ui/super-fast-paren-parsing.rs)5
-rw-r--r--tests/ui/pattern/by-move-pattern-binding.rs (renamed from tests/ui/by-move-pattern-binding.rs)0
-rw-r--r--tests/ui/pattern/by-move-pattern-binding.stderr (renamed from tests/ui/by-move-pattern-binding.stderr)0
-rw-r--r--tests/ui/pattern/fn-in-pat.rs (renamed from tests/ui/fn-in-pat.rs)0
-rw-r--r--tests/ui/pattern/fn-in-pat.stderr (renamed from tests/ui/fn-in-pat.stderr)0
-rw-r--r--tests/ui/pattern/inc-range-pat.rs (renamed from tests/ui/inc-range-pat.rs)0
-rw-r--r--tests/ui/pattern/no-patterns-in-args-2.rs (renamed from tests/ui/no-patterns-in-args-2.rs)0
-rw-r--r--tests/ui/pattern/no-patterns-in-args-2.stderr (renamed from tests/ui/no-patterns-in-args-2.stderr)0
-rw-r--r--tests/ui/pattern/no-patterns-in-args.rs (renamed from tests/ui/no-patterns-in-args.rs)0
-rw-r--r--tests/ui/pattern/no-patterns-in-args.stderr (renamed from tests/ui/no-patterns-in-args.stderr)0
-rw-r--r--tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs2
-rw-r--r--tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr2
-rw-r--r--tests/ui/process/env-args-reverse-iterator.rs (renamed from tests/ui/env-args-reverse-iterator.rs)0
-rw-r--r--tests/ui/process/env-funky-keys.rs (renamed from tests/ui/env-funky-keys.rs)0
-rw-r--r--tests/ui/process/env-null-vars.rs (renamed from tests/ui/env-null-vars.rs)0
-rw-r--r--tests/ui/process/env-vars.rs (renamed from tests/ui/env-vars.rs)0
-rw-r--r--tests/ui/process/exec-env.rs (renamed from tests/ui/exec-env.rs)0
-rw-r--r--tests/ui/process/inherit-env.rs (renamed from tests/ui/inherit-env.rs)0
-rw-r--r--tests/ui/range/impossible_range.fixed (renamed from tests/ui/impossible_range.fixed)0
-rw-r--r--tests/ui/range/impossible_range.rs (renamed from tests/ui/impossible_range.rs)0
-rw-r--r--tests/ui/range/impossible_range.stderr (renamed from tests/ui/impossible_range.stderr)0
-rw-r--r--tests/ui/range/range_inclusive.rs (renamed from tests/ui/range_inclusive.rs)0
-rw-r--r--tests/ui/repr/conflicting-repr-hints.rs (renamed from tests/ui/conflicting-repr-hints.rs)0
-rw-r--r--tests/ui/repr/conflicting-repr-hints.stderr (renamed from tests/ui/conflicting-repr-hints.stderr)0
-rw-r--r--tests/ui/return/ret-bang.rs (renamed from tests/ui/ret-bang.rs)0
-rw-r--r--tests/ui/return/ret-non-nil.rs (renamed from tests/ui/ret-non-nil.rs)0
-rw-r--r--tests/ui/return/ret-non-nil.stderr (renamed from tests/ui/ret-non-nil.stderr)0
-rw-r--r--tests/ui/return/return-disjoint-regions.rs (renamed from tests/ui/return-disjoint-regions.rs)0
-rw-r--r--tests/ui/return/return-disjoint-regions.stderr (renamed from tests/ui/return-disjoint-regions.stderr)0
-rw-r--r--tests/ui/return/return-nil.rs (renamed from tests/ui/return-nil.rs)0
-rw-r--r--tests/ui/span/multispan-import-lint.stderr2
-rw-r--r--tests/ui/statics/auxiliary/check_static_recursion_foreign_helper.rs (renamed from tests/ui/auxiliary/check_static_recursion_foreign_helper.rs)0
-rw-r--r--tests/ui/statics/check-immutable-mut-slices.rs (renamed from tests/ui/check-static-immutable-mut-slices.rs)0
-rw-r--r--tests/ui/statics/check-immutable-mut-slices.stderr (renamed from tests/ui/check-static-immutable-mut-slices.stderr)2
-rw-r--r--tests/ui/statics/check-recursion-foreign.rs (renamed from tests/ui/check-static-recursion-foreign.rs)0
-rw-r--r--tests/ui/statics/check-values-constraints.rs (renamed from tests/ui/check-static-values-constraints.rs)0
-rw-r--r--tests/ui/statics/check-values-constraints.stderr (renamed from tests/ui/check-static-values-constraints.stderr)34
-rw-r--r--tests/ui/suggestions/dont-suggest-private-trait-method.rs (renamed from tests/ui/dont-suggest-private-trait-method.rs)0
-rw-r--r--tests/ui/suggestions/dont-suggest-private-trait-method.stderr (renamed from tests/ui/dont-suggest-private-trait-method.stderr)0
-rw-r--r--tests/ui/suggestions/suggest-null-ptr.fixed (renamed from tests/ui/suggest-null-ptr.fixed)0
-rw-r--r--tests/ui/suggestions/suggest-null-ptr.rs (renamed from tests/ui/suggest-null-ptr.rs)0
-rw-r--r--tests/ui/suggestions/suggest-null-ptr.stderr (renamed from tests/ui/suggest-null-ptr.stderr)0
-rw-r--r--tests/ui/suggestions/trait-impl-bound-suggestions.fixed (renamed from tests/ui/trait-impl-bound-suggestions.fixed)0
-rw-r--r--tests/ui/suggestions/trait-impl-bound-suggestions.rs (renamed from tests/ui/trait-impl-bound-suggestions.rs)0
-rw-r--r--tests/ui/suggestions/trait-impl-bound-suggestions.stderr (renamed from tests/ui/trait-impl-bound-suggestions.stderr)0
-rw-r--r--tests/ui/suggestions/unused-imports.stderr4
-rw-r--r--tests/ui/tool-attributes/tool_lints-fail.rs (renamed from tests/ui/tool_lints-fail.rs)0
-rw-r--r--tests/ui/tool-attributes/tool_lints-fail.stderr (renamed from tests/ui/tool_lints-fail.stderr)0
-rw-r--r--tests/ui/tool-attributes/tool_lints-rpass.rs (renamed from tests/ui/tool_lints-rpass.rs)0
-rw-r--r--tests/ui/tool-attributes/tool_lints.rs (renamed from tests/ui/tool_lints.rs)0
-rw-r--r--tests/ui/tool-attributes/tool_lints.stderr (renamed from tests/ui/tool_lints.stderr)0
-rw-r--r--tests/ui/tool-attributes/tool_lints_2018_preview.rs (renamed from tests/ui/tool_lints_2018_preview.rs)0
-rw-r--r--tests/ui/tool-attributes/unknown-lint-tool-name.rs (renamed from tests/ui/unknown-lint-tool-name.rs)0
-rw-r--r--tests/ui/tool-attributes/unknown-lint-tool-name.stderr (renamed from tests/ui/unknown-lint-tool-name.stderr)0
-rw-r--r--tests/ui/tool-attributes/unknown-tool-name.rs (renamed from tests/ui/unknown-tool-name.rs)0
-rw-r--r--tests/ui/tool-attributes/unknown-tool-name.stderr (renamed from tests/ui/unknown-tool-name.stderr)0
-rw-r--r--tests/ui/unop/unop-move-semantics.rs (renamed from tests/ui/unop-move-semantics.rs)0
-rw-r--r--tests/ui/unop/unop-move-semantics.stderr (renamed from tests/ui/unop-move-semantics.stderr)0
-rw-r--r--tests/ui/unop/unop-neg-bool.rs (renamed from tests/ui/unop-neg-bool.rs)0
-rw-r--r--tests/ui/unop/unop-neg-bool.stderr (renamed from tests/ui/unop-neg-bool.stderr)0
-rw-r--r--tests/ui/use/use-nested-groups-unused-imports.rs2
-rw-r--r--tests/ui/use/use-nested-groups-unused-imports.stderr2
346 files changed, 6440 insertions, 2117 deletions
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000000..ca704082a3f
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,10 @@
+<!--
+If this PR is related to an unstable feature or an otherwise tracked effort,
+please link to the relevant tracking issue here. If you don't know of a related
+tracking issue or there are none, feel free to ignore this.
+
+This PR will get automatically assigned to a reviewer. In case you would like
+a specific user to review your work, you can assign it to them by using
+
+    r​? <reviewer name>
+-->
\ No newline at end of file
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index a3731e94276..31a184fe921 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -55,9 +55,6 @@ ast_passes_const_without_body =
 ast_passes_constraint_on_negative_bound =
     associated type constraints not allowed on negative bounds
 
-ast_passes_deprecated_where_clause_location =
-    where clause not allowed here
-
 ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
     .label = not supported
     .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
@@ -80,8 +77,6 @@ ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$de
     .suggestion = remove the {$remove_descr}
     .label = `extern` block begins here
 
-ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
-
 ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
     .suggestion = remove the attribute
     .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 9d07683f8d6..c57be3cdf35 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -27,7 +27,6 @@ use std::ops::{Deref, DerefMut};
 use thin_vec::thin_vec;
 
 use crate::errors;
-use crate::fluent_generated as fluent;
 
 /// Is `self` allowed semantically as the first parameter in an `FnDecl`?
 enum SelfSemantic {
@@ -766,11 +765,10 @@ impl<'a> AstValidator<'a> {
             .span_to_snippet(span)
             .is_ok_and(|snippet| !snippet.starts_with("#["))
         {
-            self.lint_buffer.buffer_lint_with_diagnostic(
+            self.lint_buffer.buffer_lint(
                 MISSING_ABI,
                 id,
                 span,
-                fluent::ast_passes_extern_without_abi,
                 BuiltinLintDiag::MissingAbi(span, abi::Abi::FALLBACK),
             )
         }
@@ -1428,17 +1426,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
                     if let Some(ident) = ident {
-                        let msg = match ctxt {
-                            FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign,
-                            _ => fluent::ast_passes_pattern_in_bodiless,
-                        };
-                        let diag = BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident);
-                        self.lint_buffer.buffer_lint_with_diagnostic(
+                        self.lint_buffer.buffer_lint(
                             PATTERNS_IN_FNS_WITHOUT_BODY,
                             id,
                             span,
-                            msg,
-                            diag,
+                            BuiltinLintDiag::PatternsInFnsWithoutBody {
+                                span,
+                                ident,
+                                is_foreign: matches!(ctxt, FnCtxt::Foreign),
+                            },
                         )
                     }
                 } else {
@@ -1510,12 +1506,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     Some((right, snippet))
                 }
             };
-            self.lint_buffer.buffer_lint_with_diagnostic(
+            self.lint_buffer.buffer_lint(
                 DEPRECATED_WHERE_CLAUSE_LOCATION,
                 item.id,
                 err.span,
-                fluent::ast_passes_deprecated_where_clause_location,
-                BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg),
+                BuiltinLintDiag::DeprecatedWhereclauseLocation(err.span, sugg),
             );
         }
 
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 25a125f8393..a95a7bdaf6d 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -669,6 +669,7 @@ pub struct ConstAndCVariadic {
 
 #[derive(Diagnostic)]
 #[diag(ast_passes_pattern_in_foreign, code = E0130)]
+// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)
 pub struct PatternInForeign {
     #[primary_span]
     #[label]
@@ -677,6 +678,7 @@ pub struct PatternInForeign {
 
 #[derive(Diagnostic)]
 #[diag(ast_passes_pattern_in_bodiless, code = E0642)]
+// FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`)
 pub struct PatternInBodiless {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index c08bf287733..5113c5adc8f 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -528,15 +528,10 @@ pub fn cfg_matches(
         try_gate_cfg(cfg.name, cfg.span, sess, features);
         match sess.psess.check_config.expecteds.get(&cfg.name) {
             Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
-                sess.psess.buffer_lint_with_diagnostic(
+                sess.psess.buffer_lint(
                     UNEXPECTED_CFGS,
                     cfg.span,
                     lint_node_id,
-                    if let Some(value) = cfg.value {
-                        format!("unexpected `cfg` condition value: `{value}`")
-                    } else {
-                        format!("unexpected `cfg` condition value: (none)")
-                    },
                     BuiltinLintDiag::UnexpectedCfgValue(
                         (cfg.name, cfg.name_span),
                         cfg.value.map(|v| (v, cfg.value_span.unwrap())),
@@ -544,11 +539,10 @@ pub fn cfg_matches(
                 );
             }
             None if sess.psess.check_config.exhaustive_names => {
-                sess.psess.buffer_lint_with_diagnostic(
+                sess.psess.buffer_lint(
                     UNEXPECTED_CFGS,
                     cfg.span,
                     lint_node_id,
-                    format!("unexpected `cfg` condition name: `{}`", cfg.name),
                     BuiltinLintDiag::UnexpectedCfgName(
                         (cfg.name, cfg.name_span),
                         cfg.value.map(|v| (v, cfg.value_span.unwrap())),
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 0f158990319..a3d6a1c7360 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -247,5 +247,3 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
     .label = not a trait
     .str_lit = try using `#[derive({$sym})]`
     .other = for example, write `#[derive(Debug)]` for `Debug`
-
-builtin_macros_unnameable_test_items = cannot test inner items
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 49b1b8cf992..1a7961bf70c 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -1,6 +1,7 @@
 use crate::errors;
 use crate::util::expr_to_spanned_string;
 use ast::token::IdentIsRaw;
+use lint::BuiltinLintDiag;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
@@ -513,7 +514,7 @@ fn expand_preparsed_asm(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".intel_syntax"),
                     ecx.current_expansion.lint_node_id,
-                    "avoid using `.intel_syntax`, Intel syntax is the default",
+                    BuiltinLintDiag::AvoidUsingIntelSyntax,
                 );
             }
             if template_str.contains(".att_syntax") {
@@ -521,7 +522,7 @@ fn expand_preparsed_asm(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".att_syntax"),
                     ecx.current_expansion.lint_node_id,
-                    "avoid using `.att_syntax`, prefer using `options(att_syntax)` instead",
+                    BuiltinLintDiag::AvoidUsingAttSyntax,
                 );
             }
         }
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 46949f731aa..217fa5ff9f1 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1621,14 +1621,13 @@ impl<'a> TraitDef<'a> {
                         };
 
                         if let Some(ty) = exception {
-                            cx.sess.psess.buffer_lint_with_diagnostic(
+                            cx.sess.psess.buffer_lint(
                                 BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
                                 sp,
                                 ast::CRATE_NODE_ID,
-                                format!(
-                                    "{ty} slice in a packed struct that derives a built-in trait"
-                                ),
-                                rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive,
+                                rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive {
+                                    ty: ty.to_string(),
+                                },
                             );
                         } else {
                             // Wrap the expression in `{...}`, causing a copy.
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index a5fc74f1d66..5cb0407bd59 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -556,7 +556,6 @@ fn make_format_args(
             let arg_name = args.explicit_args()[index].kind.ident().unwrap();
             ecx.buffered_early_lint.push(BufferedEarlyLint {
                 span: arg_name.span.into(),
-                msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
                 node_id: rustc_ast::CRATE_NODE_ID,
                 lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY),
                 diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally {
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 47b2ee975ca..29e991525a9 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -11,6 +11,7 @@ use rustc_expand::base::{
     resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult,
 };
 use rustc_expand::module::DirOwnership;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::new_parser_from_file;
 use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
@@ -147,7 +148,7 @@ pub(crate) fn expand_include<'cx>(
                     INCOMPLETE_INCLUDE,
                     self.p.token.span,
                     self.node_id,
-                    "include macro expected single expression in source",
+                    BuiltinLintDiag::IncompleteInclude,
                 );
             }
             Some(expr)
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 8cf431482ff..38ac2f15fe7 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -9,6 +9,7 @@ use rustc_ast::{attr, ModKind};
 use rustc_expand::base::{ExtCtxt, ResolverExpand};
 use rustc_expand::expand::{AstFragment, ExpansionConfig};
 use rustc_feature::Features;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
 use rustc_session::Session;
 use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
@@ -163,7 +164,7 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
                 UNNAMEABLE_TEST_ITEMS,
                 attr.span,
                 i.id,
-                crate::fluent_generated::builtin_macros_unnameable_test_items,
+                BuiltinLintDiag::UnnameableTestItems,
             );
         }
     }
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index 8dc7bc14ec3..652e34268ea 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -5,7 +5,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
 use rustc_expand::expand::AstFragment;
 use rustc_feature::AttributeTemplate;
-use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
+use rustc_lint_defs::{builtin::DUPLICATE_MACRO_ATTRIBUTES, BuiltinLintDiag};
 use rustc_parse::{parser, validate_attr};
 use rustc_session::errors::report_lit_error;
 use rustc_span::{BytePos, Span, Symbol};
@@ -46,7 +46,7 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable,
                 DUPLICATE_MACRO_ATTRIBUTES,
                 attr.span,
                 ecx.current_expansion.lint_node_id,
-                "duplicated attribute",
+                BuiltinLintDiag::DuplicateMacroAttribute,
             );
         }
     }
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 4bf7dccab92..662c8a7b8be 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -282,6 +282,12 @@ impl IntoDiagArg for ClosureKind {
     }
 }
 
+impl IntoDiagArg for hir::def::Namespace {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Str(Cow::Borrowed(self.descr()))
+    }
+}
+
 #[derive(Clone)]
 pub struct DiagSymbolList(Vec<Symbol>);
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 12868a66605..91af8758e51 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1364,18 +1364,15 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
                             };
 
                             if crate_matches {
-                                // FIXME: make this translatable
-                                #[allow(rustc::untranslatable_diagnostic)]
-                                sess.psess.buffer_lint_with_diagnostic(
-                                        PROC_MACRO_BACK_COMPAT,
-                                        item.ident.span,
-                                        ast::CRATE_NODE_ID,
-                                        "using an old version of `rental`",
-                                        BuiltinLintDiag::ProcMacroBackCompat(
-                                        "older versions of the `rental` crate will stop compiling in future versions of Rust; \
-                                        please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string()
-                                        )
-                                    );
+                                sess.psess.buffer_lint(
+                                    PROC_MACRO_BACK_COMPAT,
+                                    item.ident.span,
+                                    ast::CRATE_NODE_ID,
+                                    BuiltinLintDiag::ProcMacroBackCompat {
+                                        crate_name: "rental".to_string(),
+                                        fixed_version: "0.5.6".to_string(),
+                                    },
+                                );
                                 return true;
                             }
                         }
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 35f0d8abffc..badfa6d3aa3 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -14,6 +14,7 @@ use rustc_attr as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_feature::Features;
 use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES};
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::validate_attr;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -248,7 +249,6 @@ impl<'a> StripUnconfigured<'a> {
     /// Gives a compiler warning when the `cfg_attr` contains no attributes and
     /// is in the original source file. Gives a compiler error if the syntax of
     /// the attribute is incorrect.
-    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec<Attribute> {
         let Some((cfg_predicate, expanded_attrs)) =
             rustc_parse::parse_cfg_attr(attr, &self.sess.psess)
@@ -262,7 +262,7 @@ impl<'a> StripUnconfigured<'a> {
                 rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
                 attr.span,
                 ast::CRATE_NODE_ID,
-                "`#[cfg_attr]` does not expand to any attributes",
+                BuiltinLintDiag::CfgAttrNoAttributes,
             );
         }
 
@@ -283,7 +283,6 @@ impl<'a> StripUnconfigured<'a> {
         }
     }
 
-    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn expand_cfg_attr_item(
         &self,
         attr: &Attribute,
@@ -346,7 +345,7 @@ impl<'a> StripUnconfigured<'a> {
                 rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
                 attr.span,
                 ast::CRATE_NODE_ID,
-                "`crate_type` within an `#![cfg_attr] attribute is deprecated`",
+                BuiltinLintDiag::CrateTypeInCfgAttr,
             );
         }
         if attr.has_name(sym::crate_name) {
@@ -354,7 +353,7 @@ impl<'a> StripUnconfigured<'a> {
                 rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
                 attr.span,
                 ast::CRATE_NODE_ID,
-                "`crate_name` within an `#![cfg_attr] attribute is deprecated`",
+                BuiltinLintDiag::CrateNameInCfgAttr,
             );
         }
         attr
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index a049ac251e1..d8f0f221189 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1799,11 +1799,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
             }
 
             if attr.is_doc_comment() {
-                self.cx.sess.psess.buffer_lint_with_diagnostic(
+                self.cx.sess.psess.buffer_lint(
                     UNUSED_DOC_COMMENTS,
                     current_span,
                     self.cx.current_expansion.lint_node_id,
-                    "unused doc comment",
                     BuiltinLintDiag::UnusedDocComment(attr.span),
                 );
             } else if rustc_attr::is_builtin_attr(attr) {
@@ -1811,11 +1810,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 // `#[cfg]` and `#[cfg_attr]` are special - they are
                 // eagerly evaluated.
                 if attr_name != sym::cfg && attr_name != sym::cfg_attr {
-                    self.cx.sess.psess.buffer_lint_with_diagnostic(
+                    self.cx.sess.psess.buffer_lint(
                         UNUSED_ATTRIBUTES,
                         attr.span,
                         self.cx.current_expansion.lint_node_id,
-                        format!("unused attribute `{attr_name}`"),
                         BuiltinLintDiag::UnusedBuiltinAttribute {
                             attr_name,
                             macro_name: pprust::path_to_string(&call.path),
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index dce8e0c36ed..72dbbde54b3 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -110,7 +110,8 @@ use crate::mbe::{KleeneToken, TokenTree};
 use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{DiagMessage, MultiSpan};
+use rustc_errors::MultiSpan;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
@@ -252,7 +253,7 @@ fn check_binders(
                 // 1. The meta-variable is already bound in the current LHS: This is an error.
                 let mut span = MultiSpan::from_span(span);
                 span.push_span_label(prev_info.span, "previous declaration");
-                buffer_lint(psess, span, node_id, "duplicate matcher binding");
+                buffer_lint(psess, span, node_id, BuiltinLintDiag::DuplicateMatcherBinding);
             } else if get_binder_info(macros, binders, name).is_none() {
                 // 2. The meta-variable is free: This is a binder.
                 binders.insert(name, BinderInfo { span, ops: ops.into() });
@@ -271,7 +272,7 @@ fn check_binders(
                     MISSING_FRAGMENT_SPECIFIER,
                     span,
                     node_id,
-                    "missing fragment specifier",
+                    BuiltinLintDiag::MissingFragmentSpecifier,
                 );
             }
             if !macros.is_empty() {
@@ -595,7 +596,7 @@ fn check_ops_is_prefix(
             return;
         }
     }
-    buffer_lint(psess, span.into(), node_id, format!("unknown macro variable `{name}`"));
+    buffer_lint(psess, span.into(), node_id, BuiltinLintDiag::UnknownMacroVariable(name));
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -628,8 +629,7 @@ fn ops_is_prefix(
         if i >= occurrence_ops.len() {
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
-            let message = format!("variable '{name}' is still repeating at this depth");
-            buffer_lint(psess, span, node_id, message);
+            buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableStillRepeating(name));
             return;
         }
         let occurrence = &occurrence_ops[i];
@@ -637,21 +637,15 @@ fn ops_is_prefix(
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
             span.push_span_label(occurrence.span, "conflicting repetition");
-            let message = "meta-variable repeats with different Kleene operator";
-            buffer_lint(psess, span, node_id, message);
+            buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableWrongOperator);
             return;
         }
     }
 }
 
-fn buffer_lint(
-    psess: &ParseSess,
-    span: MultiSpan,
-    node_id: NodeId,
-    message: impl Into<DiagMessage>,
-) {
+fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
-        psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message);
+        psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, diag);
     }
 }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 8f18055f838..d99ecb61085 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -79,11 +79,10 @@ impl<'a> ParserAnyMacro<'a> {
         // but `m!()` is allowed in expression positions (cf. issue #34706).
         if kind == AstFragmentKind::Expr && parser.token == token::Semi {
             if is_local {
-                parser.psess.buffer_lint_with_diagnostic(
+                parser.psess.buffer_lint(
                     SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
                     parser.token.span,
                     lint_node_id,
-                    "trailing semicolon in macro used in expression position",
                     BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident),
                 );
             }
@@ -1154,11 +1153,10 @@ fn check_matcher_core<'tt>(
                             name,
                             Some(NonterminalKind::PatParam { inferred: false }),
                         ));
-                        sess.psess.buffer_lint_with_diagnostic(
+                        sess.psess.buffer_lint(
                             RUST_2021_INCOMPATIBLE_OR_PATTERNS,
                             span,
                             ast::CRATE_NODE_ID,
-                            "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",
                             BuiltinLintDiag::OrPatternsBackCompat(span, suggestion),
                         );
                     }
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index ce2382b9501..987e48a1a76 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -399,31 +399,17 @@ pub(crate) fn check_attr_crate_type(
 
                 if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() {
                     let span = spanned.span;
-                    let lev_candidate = find_best_match_for_name(
+                    let candidate = find_best_match_for_name(
                         &CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(),
                         n,
                         None,
                     );
-                    if let Some(candidate) = lev_candidate {
-                        lint_buffer.buffer_lint_with_diagnostic(
-                            lint::builtin::UNKNOWN_CRATE_TYPES,
-                            ast::CRATE_NODE_ID,
-                            span,
-                            "invalid `crate_type` value",
-                            BuiltinLintDiag::UnknownCrateTypes(
-                                span,
-                                "did you mean".to_string(),
-                                format!("\"{candidate}\""),
-                            ),
-                        );
-                    } else {
-                        lint_buffer.buffer_lint(
-                            lint::builtin::UNKNOWN_CRATE_TYPES,
-                            ast::CRATE_NODE_ID,
-                            span,
-                            "invalid `crate_type` value",
-                        );
-                    }
+                    lint_buffer.buffer_lint(
+                        lint::builtin::UNKNOWN_CRATE_TYPES,
+                        ast::CRATE_NODE_ID,
+                        span,
+                        BuiltinLintDiag::UnknownCrateTypes { span, candidate },
+                    );
                 }
             } else {
                 // This is here mainly to check for using a macro, such as
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index cf9d089ff62..6f6480a4964 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -1,7 +1,20 @@
+lint_abs_path_with_module = absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+    .suggestion = use `crate`
+
+lint_ambiguous_glob_reexport = ambiguous glob re-exports
+    .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here
+    .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here
+
 lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
     .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
     .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
 
+lint_associated_const_elided_lifetime = {$elided ->
+        [true] `&` without an explicit lifetime name cannot be used here
+        *[false] `'_` cannot be used here
+    }
+    .suggestion = use the `'static` lifetime
+
 lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
     .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
     .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change
@@ -19,10 +32,19 @@ lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` order
 lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
     .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
 
+lint_avoid_att_syntax =
+    avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+
+lint_avoid_intel_syntax =
+    avoid using `.intel_syntax`, Intel syntax is the default
+
 lint_bad_attribute_argument = bad attribute argument
 
 lint_bad_opt_access = {$msg}
 
+lint_break_with_label_and_loop = this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression
+    .suggestion = wrap this expression in parentheses
+
 lint_builtin_allow_internal_unsafe =
     `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site
 
@@ -30,6 +52,8 @@ lint_builtin_anonymous_params = anonymous parameters are deprecated and will be
     .suggestion = try naming the parameter or explicitly ignoring it
 
 lint_builtin_asm_labels = avoid using named labels in inline assembly
+    .help = only local labels of the form `<number>:` should be used in inline asm
+    .note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
 
@@ -154,6 +178,12 @@ lint_builtin_unused_doc_comment = unused doc comment
 lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
     .suggestion = use `loop`
 
+lint_byte_slice_in_packed_struct_with_derive = {$ty} slice in a packed struct that derives a built-in trait
+    .help = consider implementing the trait by hand, or remove the `packed` attribute
+
+lint_cfg_attr_no_attributes =
+    `#[cfg_attr]` does not expand to any attributes
+
 lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
 
 lint_command_line_source = `forbid` lint level was set on command line
@@ -162,12 +192,20 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i
     .current_use = this identifier can be confused with `{$existing_sym}`
     .other_use = other identifier used here
 
+lint_crate_name_in_cfg_attr_deprecated =
+    `crate_name` within an `#![cfg_attr]` attribute is deprecated
+
+lint_crate_type_in_cfg_attr_deprecated =
+    `crate_type` within an `#![cfg_attr]` attribute is deprecated
+
 lint_cstring_ptr = getting the inner pointer of a temporary `CString`
     .as_ptr_label = this pointer will be invalid
     .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
     .note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
     .help = for more information, see https://doc.rust-lang.org/reference/destructors.html
 
+lint_custom_inner_attribute_unstable = custom inner attributes are unstable
+
 lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
     .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary
 
@@ -178,6 +216,11 @@ lint_deprecated_lint_name =
     .suggestion = change it to
     .help = change it to {$replace}
 
+lint_deprecated_where_clause_location = where clause not allowed here
+    .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+    .suggestion_move_to_end = move it to the end of the type declaration
+    .suggestion_remove_where = remove this `where`
+
 lint_diag_out_of_impl =
     diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
 
@@ -195,6 +238,11 @@ lint_dropping_references = calls to `std::mem::drop` with a reference instead of
     .label = argument has type `{$arg_ty}`
     .note = use `let _ = ...` to ignore the expression or result
 
+lint_duplicate_macro_attribute =
+    duplicated attribute
+
+lint_duplicate_matcher_binding = duplicate matcher binding
+
 lint_enum_intrinsics_mem_discriminant =
     the return value of `mem::discriminant` is unspecified when called with a non-enum type
     .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum.
@@ -207,6 +255,13 @@ lint_expectation = this lint expectation is unfulfilled
     .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
     .rationale = {$rationale}
 
+lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition
+    .suggestion = convert it to a `use`
+
+lint_extern_without_abi = extern declarations without an explicit ABI are deprecated
+    .label = ABI should be specified here
+    .help = the default ABI is {$default_abi}
+
 lint_for_loops_over_fallibles =
     for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
     .suggestion = consider using `if let` to clear intent
@@ -221,6 +276,12 @@ lint_forgetting_references = calls to `std::mem::forget` with a reference instea
     .label = argument has type `{$arg_ty}`
     .note = use `let _ = ...` to ignore the expression or result
 
+lint_hidden_glob_reexport = private item shadows public glob re-export
+    .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here
+    .note_private_item = but the private item here shadows it
+
+lint_hidden_lifetime_parameters = hidden lifetime parameters in types are deprecated
+
 lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label}
     .label = this {$label} contains {$count ->
         [one] an invisible
@@ -262,6 +323,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
 
 lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
 
+lint_ill_formed_attribute_input = {$num_suggestions ->
+        [1] attribute must be of the form {$suggestions}
+        *[other] valid forms for the attribute are {$suggestions}
+    }
+
 lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024
     .note = specifically, {$num_captured ->
         [one] this lifetime is
@@ -332,6 +398,14 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
 lint_improper_ctypes_union_layout_reason = this union has unspecified layout
 lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
 
+lint_incomplete_include =
+    include macro expected single expression in source
+
+lint_inner_macro_attribute_unstable = inner macro attributes are unstable
+
+lint_invalid_crate_type_value = invalid `crate_type` value
+    .suggestion = did you mean
+
 # FIXME: we should ordinalize $valid_up_to when we add support for doing so
 lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error
     .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
@@ -360,9 +434,22 @@ lint_invalid_reference_casting_note_book = for more information, visit <https://
 
 lint_invalid_reference_casting_note_ty_has_interior_mutability = even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
 
+lint_legacy_derive_helpers = derive helper attribute is used before it is introduced
+    .label = the attribute is introduced here
+
 lint_lintpass_by_hand = implementing `LintPass` by hand
     .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
+lint_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
+    .note = the macro is defined here
+
+lint_macro_is_private = macro `{$ident}` is private
+
+lint_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used
+
+lint_macro_use_deprecated =
+    deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
+
 lint_malformed_attribute = malformed lint attribute input
 
 lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
@@ -372,6 +459,12 @@ lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
     .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
     .suggestion = you might have meant to use `Iterator::for_each`
 
+lint_metavariable_still_repeating = variable '{$name}' is still repeating at this depth
+
+lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator
+
+lint_missing_fragment_specifier = missing fragment specifier
+
 lint_mixed_script_confusables =
     the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
     .includes_note = the usage includes {$includes}
@@ -379,6 +472,11 @@ lint_mixed_script_confusables =
 
 lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
 
+lint_named_argument_used_positionally = named argument `{$named_arg_name}` is not used by name
+    .label_named_arg = this named argument is referred to by position in formatting string
+    .label_position_arg = this formatting argument uses named argument `{$named_arg_name}` by position
+    .suggestion = use the named argument by name to avoid ambiguity
+
 lint_node_source = `forbid` level set here
     .note = {$reason}
 
@@ -490,6 +588,9 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
 
 lint_opaque_hidden_inferred_bound_sugg = add this bound
 
+lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+    .suggestion = use pat_param to preserve semantics
+
 lint_overflowing_bin_hex = literal out of range for `{$ty}`
     .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`
     .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
@@ -519,6 +620,21 @@ lint_path_statement_drop = path statement drops value
 
 lint_path_statement_no_effect = path statement with no effect
 
+lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies
+    .label = pattern not allowed in function without body
+
+lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations
+    .label = pattern not allowed in foreign function
+
+lint_private_extern_crate_reexport =
+    extern crate `{$ident}` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+
+lint_proc_macro_back_compat = using an old version of `{$crate_name}`
+    .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
+
+lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope
+    .label = names from parent modules are not accessible without an explicit import
+
 lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false
     .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
     .label = expression has type `{$orig_ty}`
@@ -540,6 +656,16 @@ lint_reason_must_be_string_literal = reason must be a string literal
 
 lint_reason_must_come_last = reason in lint attribute must come last
 
+lint_redundant_import = the item `{$ident}` is imported redundantly
+    .label_imported_here = the item `{ident}` is already imported here
+    .label_defined_here = the item `{ident}` is already defined here
+    .label_imported_prelude = the item `{ident}` is already imported by the extern prelude
+    .label_defined_prelude = the item `{ident}` is already defined by the extern prelude
+
+lint_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough
+    .note = the most public imported item is `{$max_vis}`
+    .help = reduce the glob import's visibility or increase visibility of imported items
+
 lint_redundant_semicolons =
     unnecessary trailing {$multiple ->
         [true] semicolons
@@ -550,6 +676,8 @@ lint_redundant_semicolons =
         *[false] this semicolon
     }
 
+lint_remove_mut_from_pattern = remove `mut` from the parameter
+
 lint_removed_lint = lint `{$name}` has been removed: {$reason}
 
 lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
@@ -558,6 +686,10 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
 
 lint_requested_level = requested on the command line with `{$level} {$lint_name}`
 
+lint_reserved_prefix = prefix `{$prefix}` is unknown
+    .label = unknown prefix
+    .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021
+
 lint_shadowed_into_iter =
     this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}
     .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity
@@ -565,6 +697,11 @@ lint_shadowed_into_iter =
     .use_explicit_into_iter_suggestion =
         or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
 
+lint_single_use_lifetime = lifetime parameter `{$ident}` only used once
+    .label_param = this lifetime...
+    .label_use = ...is used only here
+    .suggestion = elide the single-use lifetime
+
 lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
 
 lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion
@@ -578,6 +715,10 @@ lint_suspicious_double_ref_clone =
 lint_suspicious_double_ref_deref =
     using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
 
+lint_trailing_semi_macro = trailing semicolon in macro used in expression position
+    .note1 = macro invocations at the end of a block are treated as expressions
+    .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
+
 lint_ty_qualified = usage of qualified `ty::{$ty}`
     .suggestion = try importing it and using it unqualified
 
@@ -591,12 +732,64 @@ lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::Manual
     .label = argument has type `{$arg_ty}`
     .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
 
+lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs`
+lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead
+lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}
+lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}`
+lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml`
+lint_unexpected_cfg_doc_cargo = see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+lint_unexpected_cfg_doc_rustc = see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}`
+lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more ->
+        [0] {""}
+        *[other] {" "}and {$and_more} more
+    }
+lint_unexpected_cfg_name_expected_values = expected values for `{$best_match}` are: {$possibilities}
+lint_unexpected_cfg_name_similar_name = there is a config with a similar name
+lint_unexpected_cfg_name_similar_name_different_values = there is a config with a similar name and different values
+lint_unexpected_cfg_name_similar_name_no_value = there is a config with a similar name and no value
+lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value
+lint_unexpected_cfg_name_with_similar_value = found config with similar value
+
+lint_unexpected_cfg_value = unexpected `cfg` condition value: {$has_value ->
+        [true] `{$value}`
+        *[false] (none)
+    }
+lint_unexpected_cfg_value_add_feature = consider adding `{$value}` as a feature in `Cargo.toml`
+lint_unexpected_cfg_value_expected_values = expected values for `{$name}` are: {$have_none_possibility ->
+        [true] {"(none), "}
+        *[false] {""}
+    }{$possibilities}{$and_more ->
+        [0] {""}
+        *[other] {" "}and {$and_more} more
+    }
+lint_unexpected_cfg_value_no_expected_value = no expected value for `{$name}`
+lint_unexpected_cfg_value_no_expected_values = no expected values for `{$name}`
+lint_unexpected_cfg_value_remove_condition = remove the condition
+lint_unexpected_cfg_value_remove_value = remove the value
+lint_unexpected_cfg_value_similar_name = there is a expected value with a similar name
+lint_unexpected_cfg_value_specify_value = specify a config value
+
 lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
      .label = this function will not propagate the caller location
 
+lint_unicode_text_flow = unicode codepoint changing visible direction of text present in comment
+    .label = {$num_codepoints ->
+            [1] this comment contains an invisible unicode text flow control codepoint
+            *[other] this comment contains invisible unicode text flow control codepoints
+        }
+    .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+    .suggestion = if their presence wasn't intentional, you can remove them
+    .label_comment_char = {$c_debug}
+
+
 lint_unit_bindings = binding has unit type `()`
     .label = this pattern is inferred to be the unit type `()`
 
+lint_unknown_diagnostic_attribute = unknown diagnostic attribute
+lint_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar name exists
+
 lint_unknown_gated_lint =
     unknown lint: `{$name}`
     .note = the `{$name}` lint is unstable
@@ -612,9 +805,16 @@ lint_unknown_lint =
         *[false] did you mean: `{$replace}`
     }
 
+lint_unknown_macro_variable = unknown macro variable `{$name}`
+
 lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
     .help = add `#![register_tool({$tool_name})]` to the crate root
 
+lint_unnameable_test_items = cannot test inner items
+
+lint_unnecessary_qualification = unnecessary qualification
+    .suggestion = remove the unnecessary path segments
+
 lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
 
 lint_untranslatable_diag = diagnostics should be created using translatable messages
@@ -622,6 +822,9 @@ lint_untranslatable_diag = diagnostics should be created using translatable mess
 lint_unused_allocation = unnecessary allocation, use `&` instead
 lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
 
+lint_unused_builtin_attribute = unused attribute `{$attr_name}`
+    .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`
+
 lint_unused_closure =
     unused {$pre}{$count ->
         [one] closure
@@ -638,14 +841,43 @@ lint_unused_coroutine =
     }{$post} that must be used
     .note = coroutines are lazy and do nothing unless resumed
 
+lint_unused_crate_dependency = external crate `{$extern_crate}` unused in `{$local_crate}`: remove the dependency or add `use {$extern_crate} as _;`
+
 lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
     .suggestion = use `let _ = ...` to ignore the resulting value
 
 lint_unused_delim = unnecessary {$delim} around {$item}
     .suggestion = remove these {$delim}
 
+lint_unused_doc_comment = unused doc comment
+    .label = rustdoc does not generate documentation for macro invocations
+    .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
+lint_unused_extern_crate = unused extern crate
+    .suggestion = remove it
+
 lint_unused_import_braces = braces around {$node} is unnecessary
 
+lint_unused_imports = {$num_snippets ->
+        [one] unused import: {$span_snippets}
+        *[other] unused imports: {$span_snippets}
+    }
+    .suggestion_remove_whole_use = remove the whole `use` item
+    .suggestion_remove_imports = {$num_to_remove ->
+            [one] remove the unused import
+            *[other] remove the unused imports
+        }
+    .help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module
+
+lint_unused_label = unused label
+
+lint_unused_lifetime = lifetime parameter `{$ident}` never used
+    .suggestion = elide the unused lifetime
+
+lint_unused_macro_definition = unused macro definition: `{$name}`
+
+lint_unused_macro_use = unused `#[macro_use]` import
+
 lint_unused_op = unused {$op} that must be used
     .label = the {$op} produces a value
     .suggestion = use `let _ = ...` to ignore the resulting value
@@ -654,3 +886,6 @@ lint_unused_result = unused result of type `{$ty}`
 
 lint_variant_size_differences =
     enum variant is more than three times larger ({$largest} bytes) than the next largest
+
+lint_wasm_c_abi =
+    older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 6b9f9d1531e..0f059bceae7 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -30,10 +30,10 @@ use crate::{
         BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
         BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
         BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
-        BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
-        BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds,
-        BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause,
-        BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
+        BuiltinMutablesTransmutes, BuiltinNamedAsmLabel, BuiltinNoMangleGeneric,
+        BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds,
+        BuiltinTypeAliasGenericBounds, BuiltinTypeAliasGenericBoundsSuggestion,
+        BuiltinTypeAliasWhereClause, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
         BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe,
         BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
         BuiltinWhileTrue, SuggestChangingAssocTypes,
@@ -60,7 +60,7 @@ use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::Upcast;
 use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
-use rustc_session::lint::{BuiltinLintDiag, FutureIncompatibilityReason};
+use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
@@ -2882,16 +2882,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                     let target_spans: MultiSpan =
                         if spans.len() > 0 { spans.into() } else { (*template_span).into() };
 
-                    cx.span_lint_with_diagnostics(
-                            NAMED_ASM_LABELS,
-                            Some(target_spans),
-                            fluent::lint_builtin_asm_labels,
-                            |_| {},
-                            BuiltinLintDiag::NamedAsmLabel(
-                                "only local labels of the form `<number>:` should be used in inline asm"
-                                    .to_string(),
-                            ),
-                        );
+                    cx.emit_span_lint(NAMED_ASM_LABELS, target_spans, BuiltinNamedAsmLabel);
                 }
             }
         }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 62ba9ef5c11..deeb3ae090c 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -527,30 +527,24 @@ pub struct EarlyContext<'a> {
     pub buffered: LintBuffer,
 }
 
-pub trait LintContext {
-    fn sess(&self) -> &Session;
-
+impl EarlyContext<'_> {
     /// Emit a lint at the appropriate level, with an optional associated span and an existing
     /// diagnostic.
     ///
     /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
     #[rustc_lint_diagnostics]
-    fn span_lint_with_diagnostics(
+    pub fn span_lint_with_diagnostics(
         &self,
         lint: &'static Lint,
-        span: Option<impl Into<MultiSpan>>,
-        msg: impl Into<DiagMessage>,
-        decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
+        span: MultiSpan,
         diagnostic: BuiltinLintDiag,
     ) {
-        // We first generate a blank diagnostic.
-        self.opt_span_lint(lint, span, msg, |db| {
-            // Now, set up surrounding context.
-            diagnostics::builtin(self.sess(), diagnostic, db);
-            // Rewrap `db`, and pass control to the user.
-            decorate(db)
-        });
+        diagnostics::emit_buffered_lint(self, lint, span, diagnostic)
     }
+}
+
+pub trait LintContext {
+    fn sess(&self) -> &Session;
 
     // FIXME: These methods should not take an Into<MultiSpan> -- instead, callers should need to
     // set the span in their `decorate` function (preferably using set_span).
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 5ad3ff71a6d..236eeee6152 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -1,58 +1,57 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 
+use std::borrow::Cow;
+
 use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
-use rustc_errors::{elided_lifetime_in_path_suggestion, Diag};
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
+use rustc_errors::{elided_lifetime_in_path_suggestion, DiagArgValue, MultiSpan};
 use rustc_middle::middle::stability;
-use rustc_session::lint::BuiltinLintDiag;
-use rustc_session::Session;
+use rustc_session::lint::{BuiltinLintDiag, Lint};
 use rustc_span::BytePos;
 
+use crate::{lints, EarlyContext, LintContext as _};
+
 mod check_cfg;
 
-pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
+pub(super) fn emit_buffered_lint(
+    ctx: &EarlyContext<'_>,
+    lint: &'static Lint,
+    span: MultiSpan,
+    diagnostic: BuiltinLintDiag,
+) {
+    let sess = ctx.sess();
     match diagnostic {
-        BuiltinLintDiag::UnicodeTextFlow(span, content) => {
+        BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => {
             let spans: Vec<_> = content
                 .char_indices()
                 .filter_map(|(i, c)| {
                     TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
-                        let lo = span.lo() + BytePos(2 + i as u32);
-                        (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+                        let lo = comment_span.lo() + BytePos(2 + i as u32);
+                        (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
                     })
                 })
                 .collect();
-            let (an, s) = match spans.len() {
-                1 => ("an ", ""),
-                _ => ("", "s"),
-            };
-            diag.span_label(
+            let characters = spans
+                .iter()
+                .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") })
+                .collect();
+            let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion {
+                spans: spans.iter().map(|(_c, span)| *span).collect(),
+            });
+            ctx.emit_span_lint(
+                lint,
                 span,
-                format!(
-                    "this comment contains {an}invisible unicode text flow control codepoint{s}",
-                ),
-            );
-            for (c, span) in &spans {
-                diag.span_label(*span, format!("{c:?}"));
-            }
-            diag.note(
-                "these kind of unicode codepoints change the way text flows on \
-                         applications that support them, but can cause confusion because they \
-                         change the order of characters on the screen",
-            );
-            if !spans.is_empty() {
-                diag.multipart_suggestion_with_style(
-                    "if their presence wasn't intentional, you can remove them",
-                    spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(),
-                    Applicability::MachineApplicable,
-                    SuggestionStyle::HideCodeAlways,
-                );
-            }
-        }
-        BuiltinLintDiag::Normal => (),
-        BuiltinLintDiag::AbsPathWithModule(span) => {
-            let (sugg, app) = match sess.source_map().span_to_snippet(span) {
+                lints::UnicodeTextFlow {
+                    comment_span,
+                    characters,
+                    suggestions,
+                    num_codepoints: spans.len(),
+                },
+            )
+        }
+        BuiltinLintDiag::AbsPathWithModule(mod_span) => {
+            let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) {
                 Ok(ref s) => {
                     // FIXME(Manishearth) ideally the emitting code
                     // can tell us whether or not this is global
@@ -62,160 +61,207 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                 }
                 Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
             };
-            diag.span_suggestion(span, "use `crate`", sugg, app);
-        }
-        BuiltinLintDiag::ProcMacroDeriveResolutionFallback(span) => {
-            diag.span_label(
+            ctx.emit_span_lint(
+                lint,
                 span,
-                "names from parent modules are not accessible without an explicit import",
+                lints::AbsPathWithModule {
+                    sugg: lints::AbsPathWithModuleSugg {
+                        span: mod_span,
+                        applicability,
+                        replacement,
+                    },
+                },
             );
         }
-        BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
-            diag.span_note(span_def, "the macro is defined here");
-        }
+        BuiltinLintDiag::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident } => ctx
+            .emit_span_lint(
+                lint,
+                span,
+                lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns, ident },
+            ),
+        BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => ctx
+            .emit_span_lint(
+                lint,
+                span,
+                lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
+            ),
         BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
-            diag.subdiagnostic(
-                sess.dcx(),
-                elided_lifetime_in_path_suggestion(
-                    sess.source_map(),
-                    n,
-                    path_span,
-                    incl_angl_brckt,
-                    insertion_span,
-                ),
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::ElidedLifetimesInPaths {
+                    subdiag: elided_lifetime_in_path_suggestion(
+                        sess.source_map(),
+                        n,
+                        path_span,
+                        incl_angl_brckt,
+                        insertion_span,
+                    ),
+                },
             );
         }
-        BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => {
-            diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect);
-        }
-        BuiltinLintDiag::UnusedImports(message, replaces, in_test_module) => {
-            if !replaces.is_empty() {
-                diag.tool_only_multipart_suggestion(
-                    message,
-                    replaces,
-                    Applicability::MachineApplicable,
-                );
-            }
+        BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
+            let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate });
+            ctx.emit_span_lint(lint, span, lints::UnknownCrateTypes { sugg });
+        }
+        BuiltinLintDiag::UnusedImports {
+            remove_whole_use,
+            num_to_remove,
+            remove_spans,
+            test_module_span,
+            span_snippets,
+        } => {
+            let sugg = if remove_whole_use {
+                lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] }
+            } else {
+                lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove }
+            };
+            let test_module_span =
+                test_module_span.map(|span| sess.source_map().guess_head_span(span));
 
-            if let Some(span) = in_test_module {
-                diag.span_help(
-                    sess.source_map().guess_head_span(span),
-                    "if this is a test module, consider adding a `#[cfg(test)]` to the containing module",
-                );
-            }
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::UnusedImports {
+                    sugg,
+                    test_module_span,
+                    num_snippets: span_snippets.len(),
+                    span_snippets: DiagArgValue::StrListSepByAnd(
+                        span_snippets.into_iter().map(Cow::Owned).collect(),
+                    ),
+                },
+            );
         }
         BuiltinLintDiag::RedundantImport(spans, ident) => {
-            for (span, is_imported) in spans {
-                let introduced = if is_imported { "imported" } else { "defined" };
-                let span_msg = if span.is_dummy() { "by the extern prelude" } else { "here" };
-                diag.span_label(
-                    span,
-                    format!("the item `{ident}` is already {introduced} {span_msg}"),
-                );
-            }
-        }
-        BuiltinLintDiag::DeprecatedMacro(suggestion, span) => {
-            stability::deprecation_suggestion(diag, "macro", suggestion, span)
-        }
-        BuiltinLintDiag::UnusedDocComment(span) => {
-            diag.span_label(span, "rustdoc does not generate documentation for macro invocations");
-            diag.help("to document an item produced by a macro, \
-                                  the macro must produce the documentation as part of its expansion");
-        }
-        BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident) => {
-            diag.span_suggestion(
+            let subs = spans
+                .into_iter()
+                .map(|(span, is_imported)| {
+                    (match (span.is_dummy(), is_imported) {
+                        (false, true) => lints::RedundantImportSub::ImportedHere,
+                        (false, false) => lints::RedundantImportSub::DefinedHere,
+                        (true, true) => lints::RedundantImportSub::ImportedPrelude,
+                        (true, false) => lints::RedundantImportSub::DefinedPrelude,
+                    })(span)
+                })
+                .collect();
+            ctx.emit_span_lint(lint, span, lints::RedundantImport { subs, ident });
+        }
+        BuiltinLintDiag::DeprecatedMacro {
+            suggestion,
+            suggestion_span,
+            note,
+            path,
+            since_kind,
+        } => {
+            let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion {
+                span: suggestion_span,
+                kind: "macro".to_owned(),
+                suggestion,
+            });
+            ctx.emit_span_lint(
+                lint,
                 span,
-                "remove `mut` from the parameter",
-                ident,
-                Applicability::MachineApplicable,
+                stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind },
             );
         }
-        BuiltinLintDiag::MissingAbi(span, default_abi) => {
-            diag.span_label(span, "ABI should be specified here");
-            diag.help(format!("the default ABI is {}", default_abi.name()));
+        BuiltinLintDiag::UnusedDocComment(attr_span) => {
+            ctx.emit_span_lint(lint, span, lints::UnusedDocComment { span: attr_span });
         }
-        BuiltinLintDiag::LegacyDeriveHelpers(span) => {
-            diag.span_label(span, "the attribute is introduced here");
+        BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
+            let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
+
+            ctx.emit_span_lint(
+                lint,
+                span,
+                if is_foreign {
+                    lints::PatternsInFnsWithoutBody::Foreign { sub }
+                } else {
+                    lints::PatternsInFnsWithoutBody::Bodiless { sub }
+                },
+            );
         }
-        BuiltinLintDiag::ProcMacroBackCompat(note) => {
-            diag.note(note);
+        BuiltinLintDiag::MissingAbi(label_span, default_abi) => {
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::MissingAbi { span: label_span, default_abi: default_abi.name() },
+            );
         }
-        BuiltinLintDiag::OrPatternsBackCompat(span, suggestion) => {
-            diag.span_suggestion(
+        BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
+            ctx.emit_span_lint(lint, span, lints::LegacyDeriveHelpers { span: label_span });
+        }
+        BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => {
+            ctx.emit_span_lint(
+                lint,
                 span,
-                "use pat_param to preserve semantics",
-                suggestion,
-                Applicability::MachineApplicable,
+                lints::ProcMacroBackCompat { crate_name, fixed_version },
+            );
+        }
+        BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::OrPatternsBackCompat { span: suggestion_span, suggestion },
             );
         }
-        BuiltinLintDiag::ReservedPrefix(span) => {
-            diag.span_label(span, "unknown prefix");
-            diag.span_suggestion_verbose(
-                span.shrink_to_hi(),
-                "insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
-                " ",
-                Applicability::MachineApplicable,
+        BuiltinLintDiag::ReservedPrefix(label_span, prefix) => {
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::ReservedPrefix {
+                    label: label_span,
+                    suggestion: label_span.shrink_to_hi(),
+                    prefix,
+                },
             );
         }
         BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
-            diag.span_note(
-                        invoc_span,
-                        format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`")
-                    );
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name },
+            );
         }
         BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
-            if is_trailing {
-                diag.note("macro invocations at the end of a block are treated as expressions");
-                diag.note(format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`"));
-            }
-        }
-        BuiltinLintDiag::BreakWithLabelAndLoop(span) => {
-            diag.multipart_suggestion(
-                "wrap this expression in parentheses",
-                vec![
-                    (span.shrink_to_lo(), "(".to_string()),
-                    (span.shrink_to_hi(), ")".to_string()),
-                ],
-                Applicability::MachineApplicable,
-            );
+            ctx.emit_span_lint(lint, span, lints::TrailingMacro { is_trailing, name });
         }
-        BuiltinLintDiag::NamedAsmLabel(help) => {
-            diag.help(help);
-            diag.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
+        BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => {
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::BreakWithLabelAndLoop {
+                    sub: lints::BreakWithLabelAndLoopSub {
+                        left: sugg_span.shrink_to_lo(),
+                        right: sugg_span.shrink_to_hi(),
+                    },
+                },
+            );
         }
         BuiltinLintDiag::UnexpectedCfgName(name, value) => {
-            check_cfg::unexpected_cfg_name(sess, diag, name, value)
+            ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_name(sess, name, value));
         }
         BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
-            check_cfg::unexpected_cfg_value(sess, diag, name, value)
-        }
-        BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => {
-            let left_sp = diag.span.primary_span().unwrap();
-            match sugg {
-                Some((right_sp, sugg)) => diag.multipart_suggestion(
-                    "move it to the end of the type declaration",
-                    vec![(left_sp, String::new()), (right_sp, sugg)],
-                    Applicability::MachineApplicable,
-                ),
-                None => diag.span_suggestion(
-                    left_sp,
-                    "remove this `where`",
-                    "",
-                    Applicability::MachineApplicable,
-                ),
+            ctx.emit_span_lint(lint, span, check_cfg::unexpected_cfg_value(sess, name, value));
+        }
+        BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
+            let suggestion = match sugg {
+                Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd {
+                    left: left_sp,
+                    right: right_sp,
+                    sugg,
+                },
+                None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp },
             };
-            diag.note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information");
+            ctx.emit_span_lint(lint, span, lints::DeprecatedWhereClauseLocation { suggestion });
         }
         BuiltinLintDiag::SingleUseLifetime {
             param_span,
             use_span: Some((use_span, elide)),
             deletion_span,
+            ident,
         } => {
             debug!(?param_span, ?use_span, ?deletion_span);
-            diag.span_label(param_span, "this lifetime...");
-            diag.span_label(use_span, "...is used only here");
-            if let Some(deletion_span) = deletion_span {
-                let msg = "elide the single-use lifetime";
+            let suggestion = if let Some(deletion_span) = deletion_span {
                 let (use_span, replace_lt) = if elide {
                     let use_span = sess.source_map().span_extend_while_whitespace(use_span);
                     (use_span, String::new())
@@ -226,24 +272,22 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
 
                 // issue 107998 for the case such as a wrong function pointer type
                 // `deletion_span` is empty and there is no need to report lifetime uses here
-                let suggestions = if deletion_span.is_empty() {
-                    vec![(use_span, replace_lt)]
-                } else {
-                    vec![(deletion_span, String::new()), (use_span, replace_lt)]
-                };
-                diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable);
-            }
+                let deletion_span =
+                    if deletion_span.is_empty() { None } else { Some(deletion_span) };
+                Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt })
+            } else {
+                None
+            };
+
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::SingleUseLifetime { suggestion, param_span, use_span, ident },
+            );
         }
-        BuiltinLintDiag::SingleUseLifetime { param_span: _, use_span: None, deletion_span } => {
+        BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
             debug!(?deletion_span);
-            if let Some(deletion_span) = deletion_span {
-                diag.span_suggestion(
-                    deletion_span,
-                    "elide the unused lifetime",
-                    "",
-                    Applicability::MachineApplicable,
-                );
-            }
+            ctx.emit_span_lint(lint, span, lints::UnusedLifetime { deletion_span, ident });
         }
         BuiltinLintDiag::NamedArgumentUsedPositionally {
             position_sp_to_replace,
@@ -252,19 +296,12 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
             named_arg_name,
             is_formatting_arg,
         } => {
-            diag.span_label(
-                named_arg_sp,
-                "this named argument is referred to by position in formatting string",
-            );
-            if let Some(positional_arg_for_msg) = position_sp_for_msg {
-                let msg = format!(
-                    "this formatting argument uses named argument `{named_arg_name}` by position"
-                );
-                diag.span_label(positional_arg_for_msg, msg);
-            }
-
-            if let Some(positional_arg_to_replace) = position_sp_to_replace {
-                let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name };
+            let (suggestion, name) = if let Some(positional_arg_to_replace) = position_sp_to_replace
+            {
+                let mut name = named_arg_name.clone();
+                if is_formatting_arg {
+                    name.push('$')
+                };
                 let span_to_replace = if let Ok(positional_arg_content) =
                     sess.source_map().span_to_snippet(positional_arg_to_replace)
                     && positional_arg_content.starts_with(':')
@@ -273,31 +310,40 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                 } else {
                     positional_arg_to_replace
                 };
-                diag.span_suggestion_verbose(
-                    span_to_replace,
-                    "use the named argument by name to avoid ambiguity",
+                (Some(span_to_replace), name)
+            } else {
+                (None, String::new())
+            };
+
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::NamedArgumentUsedPositionally {
+                    named_arg_sp,
+                    position_label_sp: position_sp_for_msg,
+                    suggestion,
                     name,
-                    Applicability::MaybeIncorrect,
-                );
-            }
+                    named_arg_name,
+                },
+            )
         }
-        BuiltinLintDiag::ByteSliceInPackedStructWithDerive => {
-            diag.help("consider implementing the trait by hand, or remove the `packed` attribute");
+        BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
+            ctx.emit_span_lint(lint, span, lints::ByteSliceInPackedStructWithDerive { ty })
         }
         BuiltinLintDiag::UnusedExternCrate { removal_span } => {
-            diag.span_suggestion(removal_span, "remove it", "", Applicability::MachineApplicable);
+            ctx.emit_span_lint(lint, span, lints::UnusedExternCrate { removal_span })
         }
         BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
             let suggestion_span = vis_span.between(ident_span);
-            diag.span_suggestion_verbose(
-                suggestion_span,
-                "convert it to a `use`",
-                if vis_span.is_empty() { "use " } else { " use " },
-                Applicability::MachineApplicable,
+            let code = if vis_span.is_empty() { "use " } else { " use " };
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::ExternCrateNotIdiomatic { span: suggestion_span, code },
             );
         }
         BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
-            rustc_errors::report_ambiguity_error(diag, ambiguity);
+            ctx.emit_span_lint(lint, span, lints::AmbiguousGlobImports { ambiguity });
         }
         BuiltinLintDiag::AmbiguousGlobReexports {
             name,
@@ -305,15 +351,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
             first_reexport_span,
             duplicate_reexport_span,
         } => {
-            diag.span_label(
-                first_reexport_span,
-                format!("the name `{name}` in the {namespace} namespace is first re-exported here"),
-            );
-            diag.span_label(
-                duplicate_reexport_span,
-                format!(
-                    "but the name `{name}` in the {namespace} namespace is also re-exported here"
-                ),
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::AmbiguousGlobReexports {
+                    first_reexport: first_reexport_span,
+                    duplicate_reexport: duplicate_reexport_span,
+                    name,
+                    namespace,
+                },
             );
         }
         BuiltinLintDiag::HiddenGlobReexports {
@@ -322,38 +368,127 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
             glob_reexport_span,
             private_item_span,
         } => {
-            diag.span_note(glob_reexport_span, format!("the name `{name}` in the {namespace} namespace is supposed to be publicly re-exported here"));
-            diag.span_note(private_item_span, "but the private item here shadows it".to_owned());
-        }
-        BuiltinLintDiag::UnusedQualifications { removal_span } => {
-            diag.span_suggestion_verbose(
-                removal_span,
-                "remove the unnecessary path segments",
-                "",
-                Applicability::MachineApplicable,
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::HiddenGlobReexports {
+                    glob_reexport: glob_reexport_span,
+                    private_item: private_item_span,
+
+                    name,
+                    namespace,
+                },
             );
         }
-        BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => {
-            diag.span_suggestion_verbose(
-                if elided { span.shrink_to_hi() } else { span },
-                "use the `'static` lifetime",
-                if elided { "'static " } else { "'static" },
-                Applicability::MachineApplicable,
-            );
+        BuiltinLintDiag::UnusedQualifications { removal_span } => {
+            ctx.emit_span_lint(lint, span, lints::UnusedQualifications { removal_span });
         }
-        BuiltinLintDiag::RedundantImportVisibility { max_vis, span } => {
-            diag.span_note(span, format!("the most public imported item is `{max_vis}`"));
-            diag.help(
-                "reduce the glob import's visibility or increase visibility of imported items",
+        BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => {
+            let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
+            let code = if elided { "'static " } else { "'static" };
+            ctx.emit_span_lint(
+                lint,
+                span,
+                lints::AssociatedConstElidedLifetime { span: lt_span, code, elided },
             );
         }
-        BuiltinLintDiag::MaybeTypo { span, name } => {
-            diag.span_suggestion_verbose(
+        BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => {
+            ctx.emit_span_lint(
+                lint,
                 span,
-                "an attribute with a similar name exists",
-                name,
-                Applicability::MachineApplicable,
+                lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis },
             );
         }
+        BuiltinLintDiag::UnknownDiagnosticAttribute { span: typo_span, typo_name } => {
+            let typo = typo_name.map(|typo_name| lints::UnknownDiagnosticAttributeTypoSugg {
+                span: typo_span,
+                typo_name,
+            });
+            ctx.emit_span_lint(lint, span, lints::UnknownDiagnosticAttribute { typo });
+        }
+        BuiltinLintDiag::MacroUseDeprecated => {
+            ctx.emit_span_lint(lint, span, lints::MacroUseDeprecated)
+        }
+        BuiltinLintDiag::UnusedMacroUse => ctx.emit_span_lint(lint, span, lints::UnusedMacroUse),
+        BuiltinLintDiag::PrivateExternCrateReexport(ident) => {
+            ctx.emit_span_lint(lint, span, lints::PrivateExternCrateReexport { ident })
+        }
+        BuiltinLintDiag::UnusedLabel => ctx.emit_span_lint(lint, span, lints::UnusedLabel),
+        BuiltinLintDiag::MacroIsPrivate(ident) => {
+            ctx.emit_span_lint(lint, span, lints::MacroIsPrivate { ident })
+        }
+        BuiltinLintDiag::UnusedMacroDefinition(name) => {
+            ctx.emit_span_lint(lint, span, lints::UnusedMacroDefinition { name })
+        }
+        BuiltinLintDiag::MacroRuleNeverUsed(n, name) => {
+            ctx.emit_span_lint(lint, span, lints::MacroRuleNeverUsed { n: n + 1, name })
+        }
+        BuiltinLintDiag::UnstableFeature(msg) => {
+            ctx.emit_span_lint(lint, span, lints::UnstableFeature { msg })
+        }
+        BuiltinLintDiag::AvoidUsingIntelSyntax => {
+            ctx.emit_span_lint(lint, span, lints::AvoidIntelSyntax)
+        }
+        BuiltinLintDiag::AvoidUsingAttSyntax => {
+            ctx.emit_span_lint(lint, span, lints::AvoidAttSyntax)
+        }
+        BuiltinLintDiag::IncompleteInclude => {
+            ctx.emit_span_lint(lint, span, lints::IncompleteInclude)
+        }
+        BuiltinLintDiag::UnnameableTestItems => {
+            ctx.emit_span_lint(lint, span, lints::UnnameableTestItems)
+        }
+        BuiltinLintDiag::DuplicateMacroAttribute => {
+            ctx.emit_span_lint(lint, span, lints::DuplicateMacroAttribute)
+        }
+        BuiltinLintDiag::CfgAttrNoAttributes => {
+            ctx.emit_span_lint(lint, span, lints::CfgAttrNoAttributes)
+        }
+        BuiltinLintDiag::CrateTypeInCfgAttr => {
+            ctx.emit_span_lint(lint, span, lints::CrateTypeInCfgAttr)
+        }
+        BuiltinLintDiag::CrateNameInCfgAttr => {
+            ctx.emit_span_lint(lint, span, lints::CrateNameInCfgAttr)
+        }
+        BuiltinLintDiag::MissingFragmentSpecifier => {
+            ctx.emit_span_lint(lint, span, lints::MissingFragmentSpecifier)
+        }
+        BuiltinLintDiag::MetaVariableStillRepeating(name) => {
+            ctx.emit_span_lint(lint, span, lints::MetaVariableStillRepeating { name })
+        }
+        BuiltinLintDiag::MetaVariableWrongOperator => {
+            ctx.emit_span_lint(lint, span, lints::MetaVariableWrongOperator)
+        }
+        BuiltinLintDiag::DuplicateMatcherBinding => {
+            ctx.emit_span_lint(lint, span, lints::DuplicateMatcherBinding)
+        }
+        BuiltinLintDiag::UnknownMacroVariable(name) => {
+            ctx.emit_span_lint(lint, span, lints::UnknownMacroVariable { name })
+        }
+        BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => ctx.emit_span_lint(
+            lint,
+            span,
+            lints::UnusedCrateDependency { extern_crate, local_crate },
+        ),
+        BuiltinLintDiag::WasmCAbi => ctx.emit_span_lint(lint, span, lints::WasmCAbi),
+        BuiltinLintDiag::IllFormedAttributeInput { suggestions } => ctx.emit_span_lint(
+            lint,
+            span,
+            lints::IllFormedAttributeInput {
+                num_suggestions: suggestions.len(),
+                suggestions: DiagArgValue::StrListSepByAnd(
+                    suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
+                ),
+            },
+        ),
+        BuiltinLintDiag::InnerAttributeUnstable { is_macro } => ctx.emit_span_lint(
+            lint,
+            span,
+            if is_macro {
+                lints::InnerAttributeUnstable::InnerMacroAttribute
+            } else {
+                lints::InnerAttributeUnstable::CustomInnerAttribute
+            },
+        ),
     }
 }
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index 3fa04ab75f8..020ca1753cf 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -1,44 +1,27 @@
-use rustc_errors::{Applicability, Diag};
 use rustc_middle::bug;
 use rustc_session::{config::ExpectedValues, Session};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::{sym, Span, Symbol};
 
+use crate::lints;
+
 const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35;
 
-fn check_cfg_expected_note(
+fn sort_and_truncate_possibilities(
     sess: &Session,
-    possibilities: &[Symbol],
-    type_: &str,
-    name: Option<Symbol>,
-    suffix: &str,
-) -> String {
-    use std::fmt::Write;
-
+    mut possibilities: Vec<Symbol>,
+) -> (Vec<Symbol>, usize) {
     let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected {
         possibilities.len()
     } else {
         std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES)
     };
 
-    let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-    possibilities.sort();
+    possibilities.sort_by(|s1, s2| s1.as_str().cmp(s2.as_str()));
 
     let and_more = possibilities.len().saturating_sub(n_possibilities);
-    let possibilities = possibilities[..n_possibilities].join("`, `");
-
-    let mut note = String::with_capacity(50 + possibilities.len());
-
-    write!(&mut note, "expected {type_}").unwrap();
-    if let Some(name) = name {
-        write!(&mut note, " for `{name}`").unwrap();
-    }
-    write!(&mut note, " are: {suffix}`{possibilities}`").unwrap();
-    if and_more > 0 {
-        write!(&mut note, " and {and_more} more").unwrap();
-    }
-
-    note
+    possibilities.truncate(n_possibilities);
+    (possibilities, and_more)
 }
 
 enum EscapeQuotes {
@@ -61,10 +44,9 @@ fn to_check_cfg_arg(name: Symbol, value: Option<Symbol>, quotes: EscapeQuotes) -
 
 pub(super) fn unexpected_cfg_name(
     sess: &Session,
-    diag: &mut Diag<'_, ()>,
     (name, name_span): (Symbol, Span),
     value: Option<(Symbol, Span)>,
-) {
+) -> lints::UnexpectedCfgName {
     #[allow(rustc::potential_query_instability)]
     let possibilities: Vec<Symbol> = sess.psess.check_config.expecteds.keys().copied().collect();
 
@@ -87,114 +69,122 @@ pub(super) fn unexpected_cfg_name(
     let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
     let mut is_feature_cfg = name == sym::feature;
 
-    if is_feature_cfg && is_from_cargo {
-        diag.help("consider defining some features in `Cargo.toml`");
+    let code_sugg = if is_feature_cfg && is_from_cargo {
+        lints::unexpected_cfg_name::CodeSuggestion::DefineFeatures
     // Suggest the most probable if we found one
     } else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
+        is_feature_cfg |= best_match == sym::feature;
+
         if let Some(ExpectedValues::Some(best_match_values)) =
             sess.psess.check_config.expecteds.get(&best_match)
         {
             // We will soon sort, so the initial order does not matter.
             #[allow(rustc::potential_query_instability)]
-            let mut possibilities =
-                best_match_values.iter().flatten().map(Symbol::as_str).collect::<Vec<_>>();
-            possibilities.sort();
+            let mut possibilities = best_match_values.iter().flatten().collect::<Vec<_>>();
+            possibilities.sort_by_key(|s| s.as_str());
+
+            let get_possibilities_sub = || {
+                if !possibilities.is_empty() {
+                    let possibilities =
+                        possibilities.iter().copied().cloned().collect::<Vec<_>>().into();
+                    Some(lints::unexpected_cfg_name::ExpectedValues { best_match, possibilities })
+                } else {
+                    None
+                }
+            };
 
-            let mut should_print_possibilities = true;
             if let Some((value, value_span)) = value {
                 if best_match_values.contains(&Some(value)) {
-                    diag.span_suggestion(
-                        name_span,
-                        "there is a config with a similar name and value",
-                        best_match,
-                        Applicability::MaybeIncorrect,
-                    );
-                    should_print_possibilities = false;
+                    lints::unexpected_cfg_name::CodeSuggestion::SimilarNameAndValue {
+                        span: name_span,
+                        code: best_match.to_string(),
+                    }
                 } else if best_match_values.contains(&None) {
-                    diag.span_suggestion(
-                        name_span.to(value_span),
-                        "there is a config with a similar name and no value",
-                        best_match,
-                        Applicability::MaybeIncorrect,
-                    );
-                    should_print_possibilities = false;
+                    lints::unexpected_cfg_name::CodeSuggestion::SimilarNameNoValue {
+                        span: name_span.to(value_span),
+                        code: best_match.to_string(),
+                    }
                 } else if let Some(first_value) = possibilities.first() {
-                    diag.span_suggestion(
-                        name_span.to(value_span),
-                        "there is a config with a similar name and different values",
-                        format!("{best_match} = \"{first_value}\""),
-                        Applicability::MaybeIncorrect,
-                    );
+                    lints::unexpected_cfg_name::CodeSuggestion::SimilarNameDifferentValues {
+                        span: name_span.to(value_span),
+                        code: format!("{best_match} = \"{first_value}\""),
+                        expected: get_possibilities_sub(),
+                    }
                 } else {
-                    diag.span_suggestion(
-                        name_span.to(value_span),
-                        "there is a config with a similar name and different values",
-                        best_match,
-                        Applicability::MaybeIncorrect,
-                    );
-                };
+                    lints::unexpected_cfg_name::CodeSuggestion::SimilarNameDifferentValues {
+                        span: name_span.to(value_span),
+                        code: best_match.to_string(),
+                        expected: get_possibilities_sub(),
+                    }
+                }
             } else {
-                diag.span_suggestion(
-                    name_span,
-                    "there is a config with a similar name",
-                    best_match,
-                    Applicability::MaybeIncorrect,
-                );
-            }
-
-            if !possibilities.is_empty() && should_print_possibilities {
-                let possibilities = possibilities.join("`, `");
-                diag.help(format!("expected values for `{best_match}` are: `{possibilities}`"));
+                lints::unexpected_cfg_name::CodeSuggestion::SimilarName {
+                    span: name_span,
+                    code: best_match.to_string(),
+                    expected: get_possibilities_sub(),
+                }
             }
         } else {
-            diag.span_suggestion(
-                name_span,
-                "there is a config with a similar name",
-                best_match,
-                Applicability::MaybeIncorrect,
-            );
+            lints::unexpected_cfg_name::CodeSuggestion::SimilarName {
+                span: name_span,
+                code: best_match.to_string(),
+                expected: None,
+            }
         }
-
-        is_feature_cfg |= best_match == sym::feature;
     } else {
-        if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
+        let similar_values = if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
             names_possibilities.sort();
-            for cfg_name in names_possibilities.iter() {
-                diag.span_suggestion(
-                    name_span,
-                    "found config with similar value",
-                    format!("{cfg_name} = \"{name}\""),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-        }
-        if !possibilities.is_empty() {
-            diag.help_once(check_cfg_expected_note(sess, &possibilities, "names", None, ""));
+            names_possibilities
+                .iter()
+                .map(|cfg_name| lints::unexpected_cfg_name::FoundWithSimilarValue {
+                    span: name_span,
+                    code: format!("{cfg_name} = \"{name}\""),
+                })
+                .collect()
+        } else {
+            vec![]
+        };
+        let expected_names = if !possibilities.is_empty() {
+            let (possibilities, and_more) = sort_and_truncate_possibilities(sess, possibilities);
+            Some(lints::unexpected_cfg_name::ExpectedNames {
+                possibilities: possibilities.into(),
+                and_more,
+            })
+        } else {
+            None
+        };
+        lints::unexpected_cfg_name::CodeSuggestion::SimilarValues {
+            with_similar_values: similar_values,
+            expected_names,
         }
-    }
+    };
 
     let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
 
-    if is_from_cargo {
-        if !is_feature_cfg {
-            diag.help(format!("consider using a Cargo feature instead"));
-            diag.help(format!("or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{}'] }}", inst(EscapeQuotes::No)));
-            diag.help(format!("or consider adding `println!(\"cargo::rustc-check-cfg={}\");` to the top of the `build.rs`", inst(EscapeQuotes::Yes)));
-        }
-        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration");
+    let invocation_help = if is_from_cargo {
+        let sub = if !is_feature_cfg {
+            Some(lints::UnexpectedCfgCargoHelp::new(
+                &inst(EscapeQuotes::No),
+                &inst(EscapeQuotes::Yes),
+            ))
+        } else {
+            None
+        };
+        lints::unexpected_cfg_name::InvocationHelp::Cargo { sub }
     } else {
-        let inst = inst(EscapeQuotes::No);
-        diag.help(format!("to expect this configuration use `--check-cfg={inst}`",));
-        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
-    }
+        lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new(
+            &inst(EscapeQuotes::No),
+        ))
+    };
+
+    lints::UnexpectedCfgName { code_sugg, invocation_help, name }
 }
 
 pub(super) fn unexpected_cfg_value(
     sess: &Session,
-    diag: &mut Diag<'_, ()>,
     (name, name_span): (Symbol, Span),
     value: Option<(Symbol, Span)>,
-) {
+) -> lints::UnexpectedCfgValue {
     let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name) else {
         bug!(
             "it shouldn't be possible to have a diagnostic on a value whose name is not in values"
@@ -214,53 +204,53 @@ pub(super) fn unexpected_cfg_value(
 
     // Show the full list if all possible values for a given name, but don't do it
     // for names as the possibilities could be very long
-    if !possibilities.is_empty() {
-        diag.note(check_cfg_expected_note(
-            sess,
-            &possibilities,
-            "values",
-            Some(name),
-            if have_none_possibility { "(none), " } else { "" },
-        ));
+    let code_sugg = if !possibilities.is_empty() {
+        let expected_values = {
+            let (possibilities, and_more) =
+                sort_and_truncate_possibilities(sess, possibilities.clone());
+            lints::unexpected_cfg_value::ExpectedValues {
+                name,
+                have_none_possibility,
+                possibilities: possibilities.into(),
+                and_more,
+            }
+        };
 
-        if let Some((value, value_span)) = value {
+        let suggestion = if let Some((value, value_span)) = value {
             // Suggest the most probable if we found one
             if let Some(best_match) = find_best_match_for_name(&possibilities, value, None) {
-                diag.span_suggestion(
-                    value_span,
-                    "there is a expected value with a similar name",
-                    format!("\"{best_match}\""),
-                    Applicability::MaybeIncorrect,
-                );
+                Some(lints::unexpected_cfg_value::ChangeValueSuggestion::SimilarName {
+                    span: value_span,
+                    best_match,
+                })
+            } else {
+                None
             }
         } else if let &[first_possibility] = &possibilities[..] {
-            diag.span_suggestion(
-                name_span.shrink_to_hi(),
-                "specify a config value",
-                format!(" = \"{first_possibility}\""),
-                Applicability::MaybeIncorrect,
-            );
-        }
+            Some(lints::unexpected_cfg_value::ChangeValueSuggestion::SpecifyValue {
+                span: name_span.shrink_to_hi(),
+                first_possibility,
+            })
+        } else {
+            None
+        };
+
+        lints::unexpected_cfg_value::CodeSuggestion::ChangeValue { expected_values, suggestion }
     } else if have_none_possibility {
-        diag.note(format!("no expected value for `{name}`"));
-        if let Some((_value, value_span)) = value {
-            diag.span_suggestion(
-                name_span.shrink_to_hi().to(value_span),
-                "remove the value",
-                "",
-                Applicability::MaybeIncorrect,
-            );
-        }
+        let suggestion =
+            value.map(|(_value, value_span)| lints::unexpected_cfg_value::RemoveValueSuggestion {
+                span: name_span.shrink_to_hi().to(value_span),
+            });
+        lints::unexpected_cfg_value::CodeSuggestion::RemoveValue { suggestion, name }
     } else {
-        diag.note(format!("no expected values for `{name}`"));
-
-        let sp = if let Some((_value, value_span)) = value {
+        let span = if let Some((_value, value_span)) = value {
             name_span.to(value_span)
         } else {
             name_span
         };
-        diag.span_suggestion(sp, "remove the condition", "", Applicability::MaybeIncorrect);
-    }
+        let suggestion = lints::unexpected_cfg_value::RemoveConditionSuggestion { span };
+        lints::unexpected_cfg_value::CodeSuggestion::RemoveCondition { suggestion, name }
+    };
 
     // We don't want to suggest adding values to well known names
     // since those are defined by rustc it-self. Users can still
@@ -269,24 +259,35 @@ pub(super) fn unexpected_cfg_value(
 
     let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
 
-    if is_from_cargo {
-        if name == sym::feature {
+    let invocation_help = if is_from_cargo {
+        let help = if name == sym::feature {
             if let Some((value, _value_span)) = value {
-                diag.help(format!("consider adding `{value}` as a feature in `Cargo.toml`"));
+                Some(lints::unexpected_cfg_value::CargoHelp::AddFeature { value })
             } else {
-                diag.help("consider defining some features in `Cargo.toml`");
+                Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures)
             }
         } else if !is_cfg_a_well_know_name {
-            diag.help(format!("consider using a Cargo feature instead"));
-            diag.help(format!("or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{}'] }}", inst(EscapeQuotes::No)));
-            diag.help(format!("or consider adding `println!(\"cargo::rustc-check-cfg={}\");` to the top of the `build.rs`", inst(EscapeQuotes::Yes)));
-        }
-        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration");
+            Some(lints::unexpected_cfg_value::CargoHelp::Other(lints::UnexpectedCfgCargoHelp::new(
+                &inst(EscapeQuotes::No),
+                &inst(EscapeQuotes::Yes),
+            )))
+        } else {
+            None
+        };
+        lints::unexpected_cfg_value::InvocationHelp::Cargo(help)
     } else {
-        if !is_cfg_a_well_know_name {
-            let inst = inst(EscapeQuotes::No);
-            diag.help(format!("to expect this configuration use `--check-cfg={inst}`",));
-        }
-        diag.note("see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration");
+        let help = if !is_cfg_a_well_know_name {
+            Some(lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No)))
+        } else {
+            None
+        };
+        lints::unexpected_cfg_value::InvocationHelp::Rustc(help)
+    };
+
+    lints::UnexpectedCfgValue {
+        code_sugg,
+        invocation_help,
+        has_value: value.is_some(),
+        value: value.map_or_else(String::new, |(v, _span)| v.to_string()),
     }
 }
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 3f627baf770..736c7a11069 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -14,7 +14,7 @@
 //! upon. As the ast is traversed, this keeps track of the current lint level
 //! for all lint attributes.
 
-use crate::context::{EarlyContext, LintContext, LintStore};
+use crate::context::{EarlyContext, LintStore};
 use crate::passes::{EarlyLintPass, EarlyLintPassObject};
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self as ast_visit, walk_list, Visitor};
@@ -44,14 +44,8 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
     #[allow(rustc::diagnostic_outside_of_impl)]
     fn inlined_check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.context.buffered.take(id) {
-            let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
-            self.context.span_lint_with_diagnostics(
-                lint_id.lint,
-                Some(span),
-                msg,
-                |_| {},
-                diagnostic,
-            );
+            let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint;
+            self.context.span_lint_with_diagnostics(lint_id.lint, span, diagnostic);
         }
     }
 
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index bc0c8cf85d8..3bd6faca379 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -5,16 +5,22 @@ use std::num::NonZero;
 use crate::errors::RequestedLevel;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee,
-    LintDiagnostic, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
+    codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString,
+    ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, SubdiagMessageOp,
+    Subdiagnostic, SuggestionStyle,
 };
-use rustc_hir::def_id::DefId;
+use rustc_hir::{def::Namespace, def_id::DefId};
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{
     inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
 };
-use rustc_session::Session;
-use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
+use rustc_session::{lint::AmbiguityErrorDiag, Session};
+use rustc_span::{
+    edition::Edition,
+    sym,
+    symbol::{Ident, MacroRulesNormalizedIdent},
+    Span, Symbol,
+};
 
 use crate::{
     builtin::InitError, builtin::TypeAliasBounds, errors::OverruledAttributeSub, LateContext,
@@ -1947,3 +1953,837 @@ pub struct UnitBindingsDiag {
     #[label]
     pub label: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(lint_builtin_asm_labels)]
+#[help]
+#[note]
+pub struct BuiltinNamedAsmLabel;
+
+#[derive(Subdiagnostic)]
+#[help(lint_unexpected_cfg_add_cargo_feature)]
+#[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
+#[help(lint_unexpected_cfg_add_build_rs_println)]
+pub struct UnexpectedCfgCargoHelp {
+    pub build_rs_println: String,
+    pub cargo_toml_lint_cfg: String,
+}
+
+impl UnexpectedCfgCargoHelp {
+    pub fn new(unescaped: &str, escaped: &str) -> Self {
+        Self {
+            cargo_toml_lint_cfg: format!(
+                "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}",
+            ),
+            build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");",),
+        }
+    }
+}
+
+#[derive(Subdiagnostic)]
+#[help(lint_unexpected_cfg_add_cmdline_arg)]
+pub struct UnexpectedCfgRustcHelp {
+    pub cmdline_arg: String,
+}
+
+impl UnexpectedCfgRustcHelp {
+    pub fn new(unescaped: &str) -> Self {
+        Self { cmdline_arg: format!("--check-cfg={unescaped}") }
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unexpected_cfg_name)]
+pub struct UnexpectedCfgName {
+    #[subdiagnostic]
+    pub code_sugg: unexpected_cfg_name::CodeSuggestion,
+    #[subdiagnostic]
+    pub invocation_help: unexpected_cfg_name::InvocationHelp,
+
+    pub name: Symbol,
+}
+
+pub mod unexpected_cfg_name {
+    use rustc_errors::DiagSymbolList;
+    use rustc_macros::Subdiagnostic;
+    use rustc_span::{Span, Symbol};
+
+    #[derive(Subdiagnostic)]
+    pub enum CodeSuggestion {
+        #[help(lint_unexpected_cfg_define_features)]
+        DefineFeatures,
+        #[suggestion(
+            lint_unexpected_cfg_name_similar_name_value,
+            applicability = "maybe-incorrect",
+            code = "{code}"
+        )]
+        SimilarNameAndValue {
+            #[primary_span]
+            span: Span,
+            code: String,
+        },
+        #[suggestion(
+            lint_unexpected_cfg_name_similar_name_no_value,
+            applicability = "maybe-incorrect",
+            code = "{code}"
+        )]
+        SimilarNameNoValue {
+            #[primary_span]
+            span: Span,
+            code: String,
+        },
+        #[suggestion(
+            lint_unexpected_cfg_name_similar_name_different_values,
+            applicability = "maybe-incorrect",
+            code = "{code}"
+        )]
+        SimilarNameDifferentValues {
+            #[primary_span]
+            span: Span,
+            code: String,
+            #[subdiagnostic]
+            expected: Option<ExpectedValues>,
+        },
+        #[suggestion(
+            lint_unexpected_cfg_name_similar_name,
+            applicability = "maybe-incorrect",
+            code = "{code}"
+        )]
+        SimilarName {
+            #[primary_span]
+            span: Span,
+            code: String,
+            #[subdiagnostic]
+            expected: Option<ExpectedValues>,
+        },
+        SimilarValues {
+            #[subdiagnostic]
+            with_similar_values: Vec<FoundWithSimilarValue>,
+            #[subdiagnostic]
+            expected_names: Option<ExpectedNames>,
+        },
+    }
+
+    #[derive(Subdiagnostic)]
+    #[help(lint_unexpected_cfg_name_expected_values)]
+    pub struct ExpectedValues {
+        pub best_match: Symbol,
+        pub possibilities: DiagSymbolList,
+    }
+
+    #[derive(Subdiagnostic)]
+    #[suggestion(
+        lint_unexpected_cfg_name_with_similar_value,
+        applicability = "maybe-incorrect",
+        code = "{code}"
+    )]
+    pub struct FoundWithSimilarValue {
+        #[primary_span]
+        pub span: Span,
+        pub code: String,
+    }
+
+    #[derive(Subdiagnostic)]
+    #[help_once(lint_unexpected_cfg_name_expected_names)]
+    pub struct ExpectedNames {
+        pub possibilities: DiagSymbolList,
+        pub and_more: usize,
+    }
+
+    #[derive(Subdiagnostic)]
+    pub enum InvocationHelp {
+        #[note(lint_unexpected_cfg_doc_cargo)]
+        Cargo {
+            #[subdiagnostic]
+            sub: Option<super::UnexpectedCfgCargoHelp>,
+        },
+        #[note(lint_unexpected_cfg_doc_rustc)]
+        Rustc(#[subdiagnostic] super::UnexpectedCfgRustcHelp),
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unexpected_cfg_value)]
+pub struct UnexpectedCfgValue {
+    #[subdiagnostic]
+    pub code_sugg: unexpected_cfg_value::CodeSuggestion,
+    #[subdiagnostic]
+    pub invocation_help: unexpected_cfg_value::InvocationHelp,
+
+    pub has_value: bool,
+    pub value: String,
+}
+
+pub mod unexpected_cfg_value {
+    use rustc_errors::DiagSymbolList;
+    use rustc_macros::Subdiagnostic;
+    use rustc_span::{Span, Symbol};
+
+    #[derive(Subdiagnostic)]
+    pub enum CodeSuggestion {
+        ChangeValue {
+            #[subdiagnostic]
+            expected_values: ExpectedValues,
+            #[subdiagnostic]
+            suggestion: Option<ChangeValueSuggestion>,
+        },
+        #[note(lint_unexpected_cfg_value_no_expected_value)]
+        RemoveValue {
+            #[subdiagnostic]
+            suggestion: Option<RemoveValueSuggestion>,
+
+            name: Symbol,
+        },
+        #[note(lint_unexpected_cfg_value_no_expected_values)]
+        RemoveCondition {
+            #[subdiagnostic]
+            suggestion: RemoveConditionSuggestion,
+
+            name: Symbol,
+        },
+    }
+
+    #[derive(Subdiagnostic)]
+    pub enum ChangeValueSuggestion {
+        #[suggestion(
+            lint_unexpected_cfg_value_similar_name,
+            code = r#""{best_match}""#,
+            applicability = "maybe-incorrect"
+        )]
+        SimilarName {
+            #[primary_span]
+            span: Span,
+            best_match: Symbol,
+        },
+        #[suggestion(
+            lint_unexpected_cfg_value_specify_value,
+            code = r#" = "{first_possibility}""#,
+            applicability = "maybe-incorrect"
+        )]
+        SpecifyValue {
+            #[primary_span]
+            span: Span,
+            first_possibility: Symbol,
+        },
+    }
+
+    #[derive(Subdiagnostic)]
+    #[suggestion(
+        lint_unexpected_cfg_value_remove_value,
+        code = "",
+        applicability = "maybe-incorrect"
+    )]
+    pub struct RemoveValueSuggestion {
+        #[primary_span]
+        pub span: Span,
+    }
+
+    #[derive(Subdiagnostic)]
+    #[suggestion(
+        lint_unexpected_cfg_value_remove_condition,
+        code = "",
+        applicability = "maybe-incorrect"
+    )]
+    pub struct RemoveConditionSuggestion {
+        #[primary_span]
+        pub span: Span,
+    }
+
+    #[derive(Subdiagnostic)]
+    #[note(lint_unexpected_cfg_value_expected_values)]
+    pub struct ExpectedValues {
+        pub name: Symbol,
+        pub have_none_possibility: bool,
+        pub possibilities: DiagSymbolList,
+        pub and_more: usize,
+    }
+
+    #[derive(Subdiagnostic)]
+    pub enum InvocationHelp {
+        #[note(lint_unexpected_cfg_doc_cargo)]
+        Cargo(#[subdiagnostic] Option<CargoHelp>),
+        #[note(lint_unexpected_cfg_doc_rustc)]
+        Rustc(#[subdiagnostic] Option<super::UnexpectedCfgRustcHelp>),
+    }
+
+    #[derive(Subdiagnostic)]
+    pub enum CargoHelp {
+        #[help(lint_unexpected_cfg_value_add_feature)]
+        AddFeature {
+            value: Symbol,
+        },
+        #[help(lint_unexpected_cfg_define_features)]
+        DefineFeatures,
+        Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp),
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_macro_use_deprecated)]
+pub struct MacroUseDeprecated;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_macro_use)]
+pub struct UnusedMacroUse;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_private_extern_crate_reexport)]
+pub struct PrivateExternCrateReexport {
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_label)]
+pub struct UnusedLabel;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_macro_is_private)]
+pub struct MacroIsPrivate {
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_macro_definition)]
+pub struct UnusedMacroDefinition {
+    pub name: Symbol,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_macro_rule_never_used)]
+pub struct MacroRuleNeverUsed {
+    pub n: usize,
+    pub name: Symbol,
+}
+
+pub struct UnstableFeature {
+    pub msg: DiagMessage,
+}
+
+impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
+    fn decorate_lint<'b>(self, _diag: &'b mut Diag<'a, ()>) {}
+
+    fn msg(&self) -> DiagMessage {
+        self.msg.clone()
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_avoid_intel_syntax)]
+pub struct AvoidIntelSyntax;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_avoid_att_syntax)]
+pub struct AvoidAttSyntax;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_incomplete_include)]
+pub struct IncompleteInclude;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unnameable_test_items)]
+pub struct UnnameableTestItems;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_duplicate_macro_attribute)]
+pub struct DuplicateMacroAttribute;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_cfg_attr_no_attributes)]
+pub struct CfgAttrNoAttributes;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_crate_type_in_cfg_attr_deprecated)]
+pub struct CrateTypeInCfgAttr;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_crate_name_in_cfg_attr_deprecated)]
+pub struct CrateNameInCfgAttr;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_missing_fragment_specifier)]
+pub struct MissingFragmentSpecifier;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_metavariable_still_repeating)]
+pub struct MetaVariableStillRepeating {
+    pub name: MacroRulesNormalizedIdent,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_metavariable_wrong_operator)]
+pub struct MetaVariableWrongOperator;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_duplicate_matcher_binding)]
+pub struct DuplicateMatcherBinding;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unknown_macro_variable)]
+pub struct UnknownMacroVariable {
+    pub name: MacroRulesNormalizedIdent,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_crate_dependency)]
+pub struct UnusedCrateDependency {
+    pub extern_crate: Symbol,
+    pub local_crate: Symbol,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_wasm_c_abi)]
+pub struct WasmCAbi;
+
+#[derive(LintDiagnostic)]
+#[diag(lint_ill_formed_attribute_input)]
+pub struct IllFormedAttributeInput {
+    pub num_suggestions: usize,
+    pub suggestions: DiagArgValue,
+}
+
+#[derive(LintDiagnostic)]
+pub enum InnerAttributeUnstable {
+    #[diag(lint_inner_macro_attribute_unstable)]
+    InnerMacroAttribute,
+    #[diag(lint_custom_inner_attribute_unstable)]
+    CustomInnerAttribute,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unknown_diagnostic_attribute)]
+pub struct UnknownDiagnosticAttribute {
+    #[subdiagnostic]
+    pub typo: Option<UnknownDiagnosticAttributeTypoSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    lint_unknown_diagnostic_attribute_typo_sugg,
+    style = "verbose",
+    code = "{typo_name}",
+    applicability = "machine-applicable"
+)]
+pub struct UnknownDiagnosticAttributeTypoSugg {
+    #[primary_span]
+    pub span: Span,
+    pub typo_name: Symbol,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unicode_text_flow)]
+#[note]
+pub struct UnicodeTextFlow {
+    #[label]
+    pub comment_span: Span,
+    #[subdiagnostic]
+    pub characters: Vec<UnicodeCharNoteSub>,
+    #[subdiagnostic]
+    pub suggestions: Option<UnicodeTextFlowSuggestion>,
+
+    pub num_codepoints: usize,
+}
+
+#[derive(Subdiagnostic)]
+#[label(lint_label_comment_char)]
+pub struct UnicodeCharNoteSub {
+    #[primary_span]
+    pub span: Span,
+    pub c_debug: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")]
+pub struct UnicodeTextFlowSuggestion {
+    #[suggestion_part(code = "")]
+    pub spans: Vec<Span>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_abs_path_with_module)]
+pub struct AbsPathWithModule {
+    #[subdiagnostic]
+    pub sugg: AbsPathWithModuleSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(lint_suggestion, code = "{replacement}")]
+pub struct AbsPathWithModuleSugg {
+    #[primary_span]
+    pub span: Span,
+    #[applicability]
+    pub applicability: Applicability,
+    pub replacement: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_proc_macro_derive_resolution_fallback)]
+pub struct ProcMacroDeriveResolutionFallback {
+    #[label]
+    pub span: Span,
+    pub ns: Namespace,
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)]
+pub struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
+    #[note]
+    pub definition: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_hidden_lifetime_parameters)]
+pub struct ElidedLifetimesInPaths {
+    #[subdiagnostic]
+    pub subdiag: ElidedLifetimeInPathSubdiag,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_invalid_crate_type_value)]
+pub struct UnknownCrateTypes {
+    #[subdiagnostic]
+    pub sugg: Option<UnknownCrateTypesSub>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")]
+pub struct UnknownCrateTypesSub {
+    #[primary_span]
+    pub span: Span,
+    pub candidate: Symbol,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_imports)]
+pub struct UnusedImports {
+    #[subdiagnostic]
+    pub sugg: UnusedImportsSugg,
+    #[help]
+    pub test_module_span: Option<Span>,
+
+    pub span_snippets: DiagArgValue,
+    pub num_snippets: usize,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedImportsSugg {
+    #[suggestion(
+        lint_suggestion_remove_whole_use,
+        applicability = "machine-applicable",
+        code = "",
+        style = "tool-only"
+    )]
+    RemoveWholeUse {
+        #[primary_span]
+        span: Span,
+    },
+    #[multipart_suggestion(
+        lint_suggestion_remove_imports,
+        applicability = "machine-applicable",
+        style = "tool-only"
+    )]
+    RemoveImports {
+        #[suggestion_part(code = "")]
+        remove_spans: Vec<Span>,
+        num_to_remove: usize,
+    },
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_redundant_import)]
+pub struct RedundantImport {
+    #[subdiagnostic]
+    pub subs: Vec<RedundantImportSub>,
+
+    pub ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+pub enum RedundantImportSub {
+    #[label(lint_label_imported_here)]
+    ImportedHere(#[primary_span] Span),
+    #[label(lint_label_defined_here)]
+    DefinedHere(#[primary_span] Span),
+    #[label(lint_label_imported_prelude)]
+    ImportedPrelude(#[primary_span] Span),
+    #[label(lint_label_defined_prelude)]
+    DefinedPrelude(#[primary_span] Span),
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_doc_comment)]
+#[help]
+pub struct UnusedDocComment {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+pub enum PatternsInFnsWithoutBody {
+    #[diag(lint_pattern_in_foreign)]
+    Foreign {
+        #[subdiagnostic]
+        sub: PatternsInFnsWithoutBodySub,
+    },
+    #[diag(lint_pattern_in_bodiless)]
+    Bodiless {
+        #[subdiagnostic]
+        sub: PatternsInFnsWithoutBodySub,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")]
+pub struct PatternsInFnsWithoutBodySub {
+    #[primary_span]
+    pub span: Span,
+
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_extern_without_abi)]
+#[help]
+pub struct MissingAbi {
+    #[label]
+    pub span: Span,
+
+    pub default_abi: &'static str,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_legacy_derive_helpers)]
+pub struct LegacyDeriveHelpers {
+    #[label]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_proc_macro_back_compat)]
+#[note]
+pub struct ProcMacroBackCompat {
+    pub crate_name: String,
+    pub fixed_version: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_or_patterns_back_compat)]
+pub struct OrPatternsBackCompat {
+    #[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
+    pub span: Span,
+    pub suggestion: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_reserved_prefix)]
+pub struct ReservedPrefix {
+    #[label]
+    pub label: Span,
+    #[suggestion(code = " ", applicability = "machine-applicable")]
+    pub suggestion: Span,
+
+    pub prefix: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_builtin_attribute)]
+pub struct UnusedBuiltinAttribute {
+    #[note]
+    pub invoc_span: Span,
+
+    pub attr_name: Symbol,
+    pub macro_name: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_trailing_semi_macro)]
+pub struct TrailingMacro {
+    #[note(lint_note1)]
+    #[note(lint_note2)]
+    pub is_trailing: bool,
+
+    pub name: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_break_with_label_and_loop)]
+pub struct BreakWithLabelAndLoop {
+    #[subdiagnostic]
+    pub sub: BreakWithLabelAndLoopSub,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
+pub struct BreakWithLabelAndLoopSub {
+    #[suggestion_part(code = "(")]
+    pub left: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_deprecated_where_clause_location)]
+#[note]
+pub struct DeprecatedWhereClauseLocation {
+    #[subdiagnostic]
+    pub suggestion: DeprecatedWhereClauseLocationSugg,
+}
+
+#[derive(Subdiagnostic)]
+pub enum DeprecatedWhereClauseLocationSugg {
+    #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")]
+    MoveToEnd {
+        #[suggestion_part(code = "")]
+        left: Span,
+        #[suggestion_part(code = "{sugg}")]
+        right: Span,
+
+        sugg: String,
+    },
+    #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")]
+    RemoveWhere {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_single_use_lifetime)]
+pub struct SingleUseLifetime {
+    #[label(lint_label_param)]
+    pub param_span: Span,
+    #[label(lint_label_use)]
+    pub use_span: Span,
+    #[subdiagnostic]
+    pub suggestion: Option<SingleUseLifetimeSugg>,
+
+    pub ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
+pub struct SingleUseLifetimeSugg {
+    #[suggestion_part(code = "")]
+    pub deletion_span: Option<Span>,
+    #[suggestion_part(code = "{replace_lt}")]
+    pub use_span: Span,
+
+    pub replace_lt: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_lifetime)]
+pub struct UnusedLifetime {
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    pub deletion_span: Option<Span>,
+
+    pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_named_argument_used_positionally)]
+pub struct NamedArgumentUsedPositionally {
+    #[label(lint_label_named_arg)]
+    pub named_arg_sp: Span,
+    #[label(lint_label_position_arg)]
+    pub position_label_sp: Option<Span>,
+    #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")]
+    pub suggestion: Option<Span>,
+
+    pub name: String,
+    pub named_arg_name: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_byte_slice_in_packed_struct_with_derive)]
+#[help]
+pub struct ByteSliceInPackedStructWithDerive {
+    // FIXME: make this translatable
+    pub ty: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unused_extern_crate)]
+pub struct UnusedExternCrate {
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    pub removal_span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_extern_crate_not_idiomatic)]
+pub struct ExternCrateNotIdiomatic {
+    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
+    pub span: Span,
+
+    pub code: &'static str,
+}
+
+// FIXME: make this translatable
+pub struct AmbiguousGlobImports {
+    pub ambiguity: AmbiguityErrorDiag,
+}
+
+impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports {
+    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
+        rustc_errors::report_ambiguity_error(diag, self.ambiguity);
+    }
+
+    fn msg(&self) -> DiagMessage {
+        DiagMessage::Str(self.ambiguity.msg.clone().into())
+    }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_ambiguous_glob_reexport)]
+pub struct AmbiguousGlobReexports {
+    #[label(lint_label_first_reexport)]
+    pub first_reexport: Span,
+    #[label(lint_label_duplicate_reexport)]
+    pub duplicate_reexport: Span,
+
+    pub name: String,
+    // FIXME: make this translatable
+    pub namespace: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_hidden_glob_reexport)]
+pub struct HiddenGlobReexports {
+    #[note(lint_note_glob_reexport)]
+    pub glob_reexport: Span,
+    #[note(lint_note_private_item)]
+    pub private_item: Span,
+
+    pub name: String,
+    // FIXME: make this translatable
+    pub namespace: String,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unnecessary_qualification)]
+pub struct UnusedQualifications {
+    #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
+    pub removal_span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_associated_const_elided_lifetime)]
+pub struct AssociatedConstElidedLifetime {
+    #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")]
+    pub span: Span,
+
+    pub code: &'static str,
+    pub elided: bool,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_redundant_import_visibility)]
+pub struct RedundantImportVisibility {
+    #[note]
+    pub span: Span,
+    #[help]
+    pub help: (),
+
+    pub import_vis: String,
+    pub max_vis: String,
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index e06e3e9b805..1941b0b1264 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -6,10 +6,12 @@ use rustc_data_structures::stable_hasher::{
     HashStable, StableCompare, StableHasher, ToStableHashKey,
 };
 use rustc_error_messages::{DiagMessage, MultiSpan};
+use rustc_hir::def::Namespace;
 use rustc_hir::HashStableContext;
 use rustc_hir::HirId;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::edition::Edition;
+use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::{sym, symbol::Ident, Span, Symbol};
 use rustc_target::spec::abi::Abi;
 
@@ -565,19 +567,44 @@ pub struct AmbiguityErrorDiag {
     pub b2_help_msgs: Vec<String>,
 }
 
+#[derive(Debug, Clone)]
+pub enum DeprecatedSinceKind {
+    InEffect,
+    InFuture,
+    InVersion(String),
+}
+
 // This could be a closure, but then implementing derive trait
 // becomes hacky (and it gets allocated).
 #[derive(Debug)]
 pub enum BuiltinLintDiag {
-    Normal,
     AbsPathWithModule(Span),
-    ProcMacroDeriveResolutionFallback(Span),
+    ProcMacroDeriveResolutionFallback {
+        span: Span,
+        ns: Namespace,
+        ident: Ident,
+    },
     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
     ElidedLifetimesInPaths(usize, Span, bool, Span),
-    UnknownCrateTypes(Span, String, String),
-    UnusedImports(String, Vec<(Span, String)>, Option<Span>),
+    UnknownCrateTypes {
+        span: Span,
+        candidate: Option<Symbol>,
+    },
+    UnusedImports {
+        remove_whole_use: bool,
+        num_to_remove: usize,
+        remove_spans: Vec<Span>,
+        test_module_span: Option<Span>,
+        span_snippets: Vec<String>,
+    },
     RedundantImport(Vec<(Span, bool)>, Ident),
-    DeprecatedMacro(Option<Symbol>, Span),
+    DeprecatedMacro {
+        suggestion: Option<Symbol>,
+        suggestion_span: Span,
+        note: Option<Symbol>,
+        path: String,
+        since_kind: DeprecatedSinceKind,
+    },
     MissingAbi(Span, Abi),
     UnusedDocComment(Span),
     UnusedBuiltinAttribute {
@@ -585,18 +612,24 @@ pub enum BuiltinLintDiag {
         macro_name: String,
         invoc_span: Span,
     },
-    PatternsInFnsWithoutBody(Span, Ident),
+    PatternsInFnsWithoutBody {
+        span: Span,
+        ident: Ident,
+        is_foreign: bool,
+    },
     LegacyDeriveHelpers(Span),
-    ProcMacroBackCompat(String),
+    ProcMacroBackCompat {
+        crate_name: String,
+        fixed_version: String,
+    },
     OrPatternsBackCompat(Span, String),
-    ReservedPrefix(Span),
+    ReservedPrefix(Span, String),
     TrailingMacro(bool, Ident),
     BreakWithLabelAndLoop(Span),
-    NamedAsmLabel(String),
     UnicodeTextFlow(Span, String),
     UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
     UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
-    DeprecatedWhereclauseLocation(Option<(Span, String)>),
+    DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
     SingleUseLifetime {
         /// Span of the parameter which declares this lifetime.
         param_span: Span,
@@ -606,6 +639,7 @@ pub enum BuiltinLintDiag {
         /// Span of the single use, or None if the lifetime is never used.
         /// If true, the lifetime will be fully elided.
         use_span: Option<(Span, bool)>,
+        ident: Ident,
     },
     NamedArgumentUsedPositionally {
         /// Span where the named argument is used by position and will be replaced with the named
@@ -620,7 +654,10 @@ pub enum BuiltinLintDiag {
         /// Indicates if the named argument is used as a width/precision for formatting
         is_formatting_arg: bool,
     },
-    ByteSliceInPackedStructWithDerive,
+    ByteSliceInPackedStructWithDerive {
+        // FIXME: enum of byte/string
+        ty: String,
+    },
     UnusedExternCrate {
         removal_span: Span,
     },
@@ -662,10 +699,43 @@ pub enum BuiltinLintDiag {
     RedundantImportVisibility {
         span: Span,
         max_vis: String,
+        import_vis: String,
     },
-    MaybeTypo {
+    UnknownDiagnosticAttribute {
         span: Span,
-        name: Symbol,
+        typo_name: Option<Symbol>,
+    },
+    MacroUseDeprecated,
+    UnusedMacroUse,
+    PrivateExternCrateReexport(Ident),
+    UnusedLabel,
+    MacroIsPrivate(Ident),
+    UnusedMacroDefinition(Symbol),
+    MacroRuleNeverUsed(usize, Symbol),
+    UnstableFeature(DiagMessage),
+    AvoidUsingIntelSyntax,
+    AvoidUsingAttSyntax,
+    IncompleteInclude,
+    UnnameableTestItems,
+    DuplicateMacroAttribute,
+    CfgAttrNoAttributes,
+    CrateTypeInCfgAttr,
+    CrateNameInCfgAttr,
+    MissingFragmentSpecifier,
+    MetaVariableStillRepeating(MacroRulesNormalizedIdent),
+    MetaVariableWrongOperator,
+    DuplicateMatcherBinding,
+    UnknownMacroVariable(MacroRulesNormalizedIdent),
+    UnusedCrateDependency {
+        extern_crate: Symbol,
+        local_crate: Symbol,
+    },
+    WasmCAbi,
+    IllFormedAttributeInput {
+        suggestions: Vec<String>,
+    },
+    InnerAttributeUnstable {
+        is_macro: bool,
     },
 }
 
@@ -676,9 +746,6 @@ pub struct BufferedEarlyLint {
     /// The span of code that we are linting on.
     pub span: MultiSpan,
 
-    /// The lint message.
-    pub msg: DiagMessage,
-
     /// The `NodeId` of the AST node that generated the lint.
     pub node_id: NodeId,
 
@@ -706,12 +773,10 @@ impl LintBuffer {
         lint: &'static Lint,
         node_id: NodeId,
         span: MultiSpan,
-        msg: impl Into<DiagMessage>,
         diagnostic: BuiltinLintDiag,
     ) {
         let lint_id = LintId::of(lint);
-        let msg = msg.into();
-        self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
+        self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, diagnostic });
     }
 
     pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
@@ -724,20 +789,9 @@ impl LintBuffer {
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagMessage>,
-    ) {
-        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiag::Normal)
-    }
-
-    pub fn buffer_lint_with_diagnostic(
-        &mut self,
-        lint: &'static Lint,
-        id: NodeId,
-        sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagMessage>,
         diagnostic: BuiltinLintDiag,
     ) {
-        self.add_lint(lint, id, sp.into(), msg, diagnostic)
+        self.add_lint(lint, id, sp.into(), diagnostic)
     }
 }
 
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index ae481efb263..38d4a5ee61c 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -158,7 +158,9 @@ impl DiagnosticDeriveVariantBuilder {
         let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind {
             SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
             SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
+            SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once },
             SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
+            SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once },
             SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn },
             SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion },
             SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
@@ -233,9 +235,11 @@ impl DiagnosticDeriveVariantBuilder {
         };
         let fn_ident = format_ident!("{}", subdiag);
         match subdiag {
-            SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
-                Ok(self.add_subdiagnostic(&fn_ident, slug))
-            }
+            SubdiagnosticKind::Note
+            | SubdiagnosticKind::NoteOnce
+            | SubdiagnosticKind::Help
+            | SubdiagnosticKind::HelpOnce
+            | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug)),
             SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
                 throw_invalid_attr!(attr, |diag| diag
                     .help("`#[label]` and `#[suggestion]` can only be applied to fields"));
@@ -347,7 +351,11 @@ impl DiagnosticDeriveVariantBuilder {
                 report_error_if_not_applied_to_span(attr, &info)?;
                 Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
             }
-            SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
+            SubdiagnosticKind::Note
+            | SubdiagnosticKind::NoteOnce
+            | SubdiagnosticKind::Help
+            | SubdiagnosticKind::HelpOnce
+            | SubdiagnosticKind::Warn => {
                 let inner = info.ty.inner_type();
                 if type_matches_path(inner, &["rustc_span", "Span"])
                     || type_matches_path(inner, &["rustc_span", "MultiSpan"])
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 45236771bce..69014f39925 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -510,11 +510,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             .map(|binding| self.generate_field_attr_code(binding, kind_stats))
             .collect();
 
-        if kind_slugs.is_empty() {
+        if kind_slugs.is_empty() && !self.has_subdiagnostic {
             if self.is_enum {
                 // It's okay for a variant to not be a subdiagnostic at all..
                 return Ok(quote! {});
-            } else if !self.has_subdiagnostic {
+            } else {
                 // ..but structs should always be _something_.
                 throw_span_err!(
                     self.variant.ast().ident.span().unwrap(),
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 4684306e235..05a5a32514b 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -575,8 +575,12 @@ pub(super) enum SubdiagnosticKind {
     Label,
     /// `#[note(...)]`
     Note,
+    /// `#[note_once(...)]`
+    NoteOnce,
     /// `#[help(...)]`
     Help,
+    /// `#[help_once(...)]`
+    HelpOnce,
     /// `#[warning(...)]`
     Warn,
     /// `#[suggestion{,_short,_hidden,_verbose}]`
@@ -624,7 +628,9 @@ impl SubdiagnosticVariant {
         let mut kind = match name {
             "label" => SubdiagnosticKind::Label,
             "note" => SubdiagnosticKind::Note,
+            "note_once" => SubdiagnosticKind::NoteOnce,
             "help" => SubdiagnosticKind::Help,
+            "help_once" => SubdiagnosticKind::HelpOnce,
             "warning" => SubdiagnosticKind::Warn,
             _ => {
                 // Recover old `#[(multipart_)suggestion_*]` syntaxes
@@ -682,7 +688,9 @@ impl SubdiagnosticVariant {
                 match kind {
                     SubdiagnosticKind::Label
                     | SubdiagnosticKind::Note
+                    | SubdiagnosticKind::NoteOnce
                     | SubdiagnosticKind::Help
+                    | SubdiagnosticKind::HelpOnce
                     | SubdiagnosticKind::Warn
                     | SubdiagnosticKind::MultipartSuggestion { .. } => {
                         return Ok(Some(SubdiagnosticVariant { kind, slug: None, no_span: false }));
@@ -836,7 +844,9 @@ impl SubdiagnosticVariant {
             }
             SubdiagnosticKind::Label
             | SubdiagnosticKind::Note
+            | SubdiagnosticKind::NoteOnce
             | SubdiagnosticKind::Help
+            | SubdiagnosticKind::HelpOnce
             | SubdiagnosticKind::Warn => {}
         }
 
@@ -849,7 +859,9 @@ impl quote::IdentFragment for SubdiagnosticKind {
         match self {
             SubdiagnosticKind::Label => write!(f, "label"),
             SubdiagnosticKind::Note => write!(f, "note"),
+            SubdiagnosticKind::NoteOnce => write!(f, "note_once"),
             SubdiagnosticKind::Help => write!(f, "help"),
+            SubdiagnosticKind::HelpOnce => write!(f, "help_once"),
             SubdiagnosticKind::Warn => write!(f, "warn"),
             SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"),
             SubdiagnosticKind::MultipartSuggestion { .. } => {
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index c7b7eadbd9d..de9c916b4f0 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -108,7 +108,9 @@ decl_derive!(
         // struct attributes
         diag,
         help,
+        help_once,
         note,
+        note_once,
         warning,
         // field attributes
         skip_arg,
@@ -125,7 +127,9 @@ decl_derive!(
         // struct attributes
         diag,
         help,
+        help_once,
         note,
+        note_once,
         warning,
         // field attributes
         skip_arg,
@@ -142,7 +146,9 @@ decl_derive!(
         // struct/variant attributes
         label,
         help,
+        help_once,
         note,
+        note_once,
         warning,
         subdiagnostic,
         suggestion,
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 3d0846ae6de..2f5dfad265c 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -284,8 +284,6 @@ metadata_unsupported_abi =
 metadata_unsupported_abi_i686 =
     ABI not supported by `#[link(kind = "raw-dylib")]` on i686
 
-metadata_wasm_c_abi =
-    older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88
 metadata_wasm_import_form =
     wasm import module must be of the form `wasm_import_module = "string"`
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e3205fc1d30..be1a73ef0a7 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -20,7 +20,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
 use rustc_session::config::{self, CrateType, ExternLocation};
 use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
-use rustc_session::lint;
+use rustc_session::lint::{self, BuiltinLintDiag};
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
 use rustc_span::edition::Edition;
@@ -975,15 +975,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
             }
 
             self.sess.psess.buffer_lint(
-                    lint::builtin::UNUSED_CRATE_DEPENDENCIES,
-                    span,
-                    ast::CRATE_NODE_ID,
-                    format!(
-                        "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
-                        name,
-                        self.tcx.crate_name(LOCAL_CRATE),
-                        name),
-                );
+                lint::builtin::UNUSED_CRATE_DEPENDENCIES,
+                span,
+                ast::CRATE_NODE_ID,
+                BuiltinLintDiag::UnusedCrateDependency {
+                    extern_crate: name_interned,
+                    local_crate: self.tcx.crate_name(LOCAL_CRATE),
+                },
+            );
         }
     }
 
@@ -1020,7 +1019,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 lint::builtin::WASM_C_ABI,
                 span,
                 ast::CRATE_NODE_ID,
-                crate::fluent_generated::metadata_wasm_c_abi,
+                BuiltinLintDiag::WasmCAbi,
             );
         }
     }
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 27d555d7e26..f4d619329eb 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -50,6 +50,20 @@ middle_const_not_used_in_type_alias =
 middle_cycle =
     a cycle occurred during layout computation
 
+middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note ->
+        [true] : {$note}
+        *[other] {""}
+    }
+middle_deprecated_in_future = use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note ->
+        [true] : {$note}
+        *[other] {""}
+    }
+middle_deprecated_in_version = use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note ->
+        [true] : {$note}
+        *[other] {""}
+    }
+middle_deprecated_suggestion = replace the use of the deprecated {$kind}
+
 middle_drop_check_overflow =
     overflow while adding drop-check rules for {$ty}
     .note = overflowed on {$overflow_ty}
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 67bd53f53da..e5df05763b0 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -9,15 +9,15 @@ use rustc_attr::{
     self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
 };
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{Applicability, Diag};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee};
 use rustc_feature::GateIssue;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::{self as hir, HirId};
-use rustc_macros::{Decodable, Encodable, HashStable};
+use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
-use rustc_session::lint::{BuiltinLintDiag, Level, Lint, LintBuffer};
+use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
@@ -125,90 +125,107 @@ pub fn report_unstable(
     }
 }
 
-pub fn deprecation_suggestion(
-    diag: &mut Diag<'_, ()>,
-    kind: &str,
-    suggestion: Option<Symbol>,
-    span: Span,
-) {
-    if let Some(suggestion) = suggestion {
-        diag.span_suggestion_verbose(
-            span,
-            format!("replace the use of the deprecated {kind}"),
-            suggestion,
-            Applicability::MachineApplicable,
-        );
-    }
-}
-
 fn deprecation_lint(is_in_effect: bool) -> &'static Lint {
     if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE }
 }
 
-fn deprecation_message(
-    is_in_effect: bool,
-    since: DeprecatedSince,
-    note: Option<Symbol>,
-    kind: &str,
-    path: &str,
-) -> String {
-    let message = if is_in_effect {
-        format!("use of deprecated {kind} `{path}`")
+#[derive(Subdiagnostic)]
+#[suggestion(
+    middle_deprecated_suggestion,
+    code = "{suggestion}",
+    style = "verbose",
+    applicability = "machine-applicable"
+)]
+pub struct DeprecationSuggestion {
+    #[primary_span]
+    pub span: Span,
+
+    pub kind: String,
+    pub suggestion: Symbol,
+}
+
+pub struct Deprecated {
+    pub sub: Option<DeprecationSuggestion>,
+
+    // FIXME: make this translatable
+    pub kind: String,
+    pub path: String,
+    pub note: Option<Symbol>,
+    pub since_kind: DeprecatedSinceKind,
+}
+
+impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated {
+    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
+        diag.arg("kind", self.kind);
+        diag.arg("path", self.path);
+        if let DeprecatedSinceKind::InVersion(version) = self.since_kind {
+            diag.arg("version", version);
+        }
+        if let Some(note) = self.note {
+            diag.arg("has_note", true);
+            diag.arg("note", note);
+        } else {
+            diag.arg("has_note", false);
+        }
+        if let Some(sub) = self.sub {
+            diag.subdiagnostic(diag.dcx, sub);
+        }
+    }
+
+    fn msg(&self) -> rustc_errors::DiagMessage {
+        match &self.since_kind {
+            DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated,
+            DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future,
+            DeprecatedSinceKind::InVersion(_) => {
+                crate::fluent_generated::middle_deprecated_in_version
+            }
+        }
+    }
+}
+
+fn deprecated_since_kind(is_in_effect: bool, since: DeprecatedSince) -> DeprecatedSinceKind {
+    if is_in_effect {
+        DeprecatedSinceKind::InEffect
     } else {
         match since {
-            DeprecatedSince::RustcVersion(version) => format!(
-                "use of {kind} `{path}` that will be deprecated in future version {version}"
-            ),
-            DeprecatedSince::Future => {
-                format!("use of {kind} `{path}` that will be deprecated in a future Rust version")
+            DeprecatedSince::RustcVersion(version) => {
+                DeprecatedSinceKind::InVersion(version.to_string())
             }
+            DeprecatedSince::Future => DeprecatedSinceKind::InFuture,
             DeprecatedSince::NonStandard(_)
             | DeprecatedSince::Unspecified
             | DeprecatedSince::Err => {
                 unreachable!("this deprecation is always in effect; {since:?}")
             }
         }
-    };
-
-    match note {
-        Some(reason) => format!("{message}: {reason}"),
-        None => message,
     }
 }
 
-pub fn deprecation_message_and_lint(
-    depr: &Deprecation,
-    kind: &str,
-    path: &str,
-) -> (String, &'static Lint) {
-    let is_in_effect = depr.is_in_effect();
-    (
-        deprecation_message(is_in_effect, depr.since, depr.note, kind, path),
-        deprecation_lint(is_in_effect),
-    )
-}
-
-pub fn early_report_deprecation(
+pub fn early_report_macro_deprecation(
     lint_buffer: &mut LintBuffer,
-    message: String,
-    suggestion: Option<Symbol>,
-    lint: &'static Lint,
+    depr: &Deprecation,
     span: Span,
     node_id: NodeId,
+    path: String,
 ) {
     if span.in_derive_expansion() {
         return;
     }
 
-    let diag = BuiltinLintDiag::DeprecatedMacro(suggestion, span);
-    lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, message, diag);
+    let is_in_effect = depr.is_in_effect();
+    let diag = BuiltinLintDiag::DeprecatedMacro {
+        suggestion: depr.suggestion,
+        suggestion_span: span,
+        note: depr.note,
+        path,
+        since_kind: deprecated_since_kind(is_in_effect, depr.since.clone()),
+    };
+    lint_buffer.buffer_lint(deprecation_lint(is_in_effect), node_id, span, diag);
 }
 
 fn late_report_deprecation(
     tcx: TyCtxt<'_>,
-    message: String,
-    suggestion: Option<Symbol>,
-    lint: &'static Lint,
+    depr: &Deprecation,
     span: Span,
     method_span: Option<Span>,
     hir_id: HirId,
@@ -217,13 +234,26 @@ fn late_report_deprecation(
     if span.in_derive_expansion() {
         return;
     }
+
+    let def_path = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+    let def_kind = tcx.def_descr(def_id);
+    let is_in_effect = depr.is_in_effect();
+
     let method_span = method_span.unwrap_or(span);
-    tcx.node_span_lint(lint, hir_id, method_span, message, |diag| {
-        if let hir::Node::Expr(_) = tcx.hir_node(hir_id) {
-            let kind = tcx.def_descr(def_id);
-            deprecation_suggestion(diag, kind, suggestion, method_span);
-        }
-    });
+    let suggestion =
+        if let hir::Node::Expr(_) = tcx.hir_node(hir_id) { depr.suggestion } else { None };
+    let diag = Deprecated {
+        sub: suggestion.map(|suggestion| DeprecationSuggestion {
+            span: method_span,
+            kind: def_kind.to_owned(),
+            suggestion,
+        }),
+        kind: def_kind.to_owned(),
+        path: def_path,
+        note: depr.note,
+        since_kind: deprecated_since_kind(is_in_effect, depr.since),
+    };
+    tcx.emit_node_span_lint(deprecation_lint(is_in_effect), hir_id, method_span, diag);
 }
 
 /// Result of `TyCtxt::eval_stability`.
@@ -352,28 +382,9 @@ impl<'tcx> TyCtxt<'tcx> {
                     // Calculating message for lint involves calling `self.def_path_str`.
                     // Which by default to calculate visible path will invoke expensive `visible_parent_map` query.
                     // So we skip message calculation altogether, if lint is allowed.
-                    let is_in_effect = depr_attr.is_in_effect();
-                    let lint = deprecation_lint(is_in_effect);
+                    let lint = deprecation_lint(depr_attr.is_in_effect());
                     if self.lint_level_at_node(lint, id).0 != Level::Allow {
-                        let def_path = with_no_trimmed_paths!(self.def_path_str(def_id));
-                        let def_kind = self.def_descr(def_id);
-
-                        late_report_deprecation(
-                            self,
-                            deprecation_message(
-                                is_in_effect,
-                                depr_attr.since,
-                                depr_attr.note,
-                                def_kind,
-                                &def_path,
-                            ),
-                            depr_attr.suggestion,
-                            lint,
-                            span,
-                            method_span,
-                            id,
-                            def_id,
-                        );
+                        late_report_deprecation(self, depr_attr, span, method_span, id, def_id);
                     }
                 }
             };
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index d2d200a91af..6eb8bed6a8c 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -370,11 +370,10 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
         let content = self.str_from(content_start);
         if contains_text_flow_control_chars(content) {
             let span = self.mk_sp(start, self.pos);
-            self.psess.buffer_lint_with_diagnostic(
+            self.psess.buffer_lint(
                 TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
                 span,
                 ast::CRATE_NODE_ID,
-                "unicode codepoint changing visible direction of text present in comment",
                 BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()),
             );
         }
@@ -723,12 +722,11 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
             self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg });
         } else {
             // Before Rust 2021, only emit a lint for migration.
-            self.psess.buffer_lint_with_diagnostic(
+            self.psess.buffer_lint(
                 RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
-                format!("prefix `{prefix}` is unknown"),
-                BuiltinLintDiag::ReservedPrefix(prefix_span),
+                BuiltinLintDiag::ReservedPrefix(prefix_span, prefix.to_string()),
             );
         }
     }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index d2d21624150..fd3f63a04de 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1913,11 +1913,10 @@ impl<'a> Parser<'a> {
                             | ExprKind::Block(_, None)
                     )
                 {
-                    self.psess.buffer_lint_with_diagnostic(
+                    self.psess.buffer_lint(
                         BREAK_WITH_LABEL_AND_LOOP,
                         lo.to(expr.span),
                         ast::CRATE_NODE_ID,
-                        "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression",
                         BuiltinLintDiag::BreakWithLabelAndLoop(expr.span),
                     );
                 }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index a46c104b6d9..f43ddadc2ea 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -58,9 +58,15 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_inner_attributes()?;
 
         let post_attr_lo = self.token.span;
-        let mut items = ThinVec::new();
-        while let Some(item) = self.parse_item(ForceCollect::No)? {
-            self.maybe_consume_incorrect_semicolon(Some(&item));
+        let mut items: ThinVec<P<_>> = ThinVec::new();
+
+        // There shouldn't be any stray semicolons before or after items.
+        // `parse_item` consumes the appropriate semicolons so any leftover is an error.
+        loop {
+            while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons
+            let Some(item) = self.parse_item(ForceCollect::No)? else {
+                break;
+            };
             items.push(item);
         }
 
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index f88edf29dce..b91ef1ae1f3 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -10,6 +10,7 @@ use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_session::errors::report_lit_error;
 use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, Symbol};
 
@@ -176,37 +177,26 @@ fn emit_malformed_attribute(
     };
 
     let error_msg = format!("malformed `{name}` attribute input");
-    let mut msg = "attribute must be of the form ".to_owned();
     let mut suggestions = vec![];
-    let mut first = true;
     let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
     if template.word {
-        first = false;
-        let code = format!("#{inner}[{name}]");
-        msg.push_str(&format!("`{code}`"));
-        suggestions.push(code);
+        suggestions.push(format!("#{inner}[{name}]"));
     }
     if let Some(descr) = template.list {
-        if !first {
-            msg.push_str(" or ");
-        }
-        first = false;
-        let code = format!("#{inner}[{name}({descr})]");
-        msg.push_str(&format!("`{code}`"));
-        suggestions.push(code);
+        suggestions.push(format!("#{inner}[{name}({descr})]"));
     }
     if let Some(descr) = template.name_value_str {
-        if !first {
-            msg.push_str(" or ");
-        }
-        let code = format!("#{inner}[{name} = \"{descr}\"]");
-        msg.push_str(&format!("`{code}`"));
-        suggestions.push(code);
+        suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
     }
-    suggestions.sort();
     if should_warn(name) {
-        psess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
+        psess.buffer_lint(
+            ILL_FORMED_ATTRIBUTE_INPUT,
+            span,
+            ast::CRATE_NODE_ID,
+            BuiltinLintDiag::IllFormedAttributeInput { suggestions: suggestions.clone() },
+        );
     } else {
+        suggestions.sort();
         psess
             .dcx
             .struct_span_err(span, error_msg)
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 180e7f6def3..fc3669fecc2 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -32,7 +32,7 @@ use rustc_ast as ast;
 use rustc_ast::visit::{self, Visitor};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{pluralize, MultiSpan};
+use rustc_errors::MultiSpan;
 use rustc_hir::def::{DefKind, Res};
 use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES};
 use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS};
@@ -151,11 +151,10 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
             // We do this in any edition.
             if warn_if_unused {
                 if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
-                    self.r.lint_buffer.buffer_lint_with_diagnostic(
+                    self.r.lint_buffer.buffer_lint(
                         UNUSED_EXTERN_CRATES,
                         extern_crate.id,
                         span,
-                        "unused extern crate",
                         BuiltinLintDiag::UnusedExternCrate {
                             removal_span: extern_crate.span_with_attributes,
                         },
@@ -204,11 +203,10 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
                 .span
                 .find_ancestor_inside(extern_crate.span)
                 .unwrap_or(extern_crate.ident.span);
-            self.r.lint_buffer.buffer_lint_with_diagnostic(
+            self.r.lint_buffer.buffer_lint(
                 UNUSED_EXTERN_CRATES,
                 extern_crate.id,
                 extern_crate.span,
-                "`extern crate` is not idiomatic in the new edition",
                 BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span },
             );
         }
@@ -394,10 +392,7 @@ impl Resolver<'_, '_> {
                                 MACRO_USE_EXTERN_CRATE,
                                 import.root_id,
                                 import.span,
-                                "deprecated `#[macro_use]` attribute used to \
-                                import macros should be replaced at use sites \
-                                with a `use` item to import the macro \
-                                instead",
+                                BuiltinLintDiag::MacroUseDeprecated,
                             );
                         }
                     }
@@ -414,8 +409,12 @@ impl Resolver<'_, '_> {
                     }
                 }
                 ImportKind::MacroUse { .. } => {
-                    let msg = "unused `#[macro_use]` import";
-                    self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
+                    self.lint_buffer.buffer_lint(
+                        UNUSED_IMPORTS,
+                        import.root_id,
+                        import.span,
+                        BuiltinLintDiag::UnusedMacroUse,
+                    );
                 }
                 _ => {}
             }
@@ -434,20 +433,12 @@ impl Resolver<'_, '_> {
         visitor.report_unused_extern_crate_items(maybe_unused_extern_crates);
 
         for unused in visitor.unused_imports.values() {
-            let mut fixes = Vec::new();
-            let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
-                UnusedSpanResult::Used => continue,
-                UnusedSpanResult::Unused { spans, remove } => {
-                    fixes.push((remove, String::new()));
-                    spans
-                }
-                UnusedSpanResult::PartialUnused { spans, remove } => {
-                    for fix in &remove {
-                        fixes.push((*fix, String::new()));
-                    }
-                    spans
-                }
-            };
+            let (spans, remove_spans) =
+                match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
+                    UnusedSpanResult::Used => continue,
+                    UnusedSpanResult::Unused { spans, remove } => (spans, vec![remove]),
+                    UnusedSpanResult::PartialUnused { spans, remove } => (spans, remove),
+                };
 
             let ms = MultiSpan::from_spans(spans);
 
@@ -459,23 +450,8 @@ impl Resolver<'_, '_> {
                 .collect::<Vec<String>>();
             span_snippets.sort();
 
-            let msg = format!(
-                "unused import{}{}",
-                pluralize!(ms.primary_spans().len()),
-                if !span_snippets.is_empty() {
-                    format!(": {}", span_snippets.join(", "))
-                } else {
-                    String::new()
-                }
-            );
-
-            let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
-                "remove the whole `use` item"
-            } else if ms.primary_spans().len() > 1 {
-                "remove the unused imports"
-            } else {
-                "remove the unused import"
-            };
+            let remove_whole_use = remove_spans.len() == 1 && remove_spans[0] == unused.item_span;
+            let num_to_remove = ms.primary_spans().len();
 
             // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]`
             // attribute; however, if not, suggest adding the attribute. There is no way to
@@ -501,12 +477,17 @@ impl Resolver<'_, '_> {
                 }
             };
 
-            visitor.r.lint_buffer.buffer_lint_with_diagnostic(
+            visitor.r.lint_buffer.buffer_lint(
                 UNUSED_IMPORTS,
                 unused.use_tree_id,
                 ms,
-                msg,
-                BuiltinLintDiag::UnusedImports(fix_msg.into(), fixes, test_module_span),
+                BuiltinLintDiag::UnusedImports {
+                    remove_whole_use,
+                    num_to_remove,
+                    remove_spans,
+                    test_module_span,
+                    span_snippets,
+                },
             );
         }
 
@@ -552,11 +533,10 @@ impl Resolver<'_, '_> {
                 continue;
             }
 
-            self.lint_buffer.buffer_lint_with_diagnostic(
+            self.lint_buffer.buffer_lint(
                 UNUSED_QUALIFICATIONS,
                 unn_qua.node_id,
                 unn_qua.path_span,
-                "unnecessary qualification",
                 BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span },
             );
         }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index b28312fa473..856cfbc01e8 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -128,13 +128,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self.report_with_use_injections(krate);
 
         for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
-            let msg = "macro-expanded `macro_export` macros from the current crate \
-                       cannot be referred to by absolute paths";
-            self.lint_buffer.buffer_lint_with_diagnostic(
+            self.lint_buffer.buffer_lint(
                 MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
                 CRATE_NODE_ID,
                 span_use,
-                msg,
                 BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
             );
         }
@@ -145,11 +142,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 let NameBindingKind::Import { import, .. } = ambiguity_error.b1.0.kind else {
                     unreachable!()
                 };
-                self.lint_buffer.buffer_lint_with_diagnostic(
+                self.lint_buffer.buffer_lint(
                     AMBIGUOUS_GLOB_IMPORTS,
                     import.root_id,
                     ambiguity_error.ident.span,
-                    diag.msg.to_string(),
                     BuiltinLintDiag::AmbiguousGlobImports { diag },
                 );
             } else {
@@ -526,12 +522,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let diag = BuiltinLintDiag::AbsPathWithModule(root_span);
-        self.lint_buffer.buffer_lint_with_diagnostic(
+        self.lint_buffer.buffer_lint(
             ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             node_id,
             root_span,
-            "absolute paths must start with `self`, `super`, \
-             `crate`, or an external crate name in the 2018 edition",
             diag,
         );
     }
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index f88725830f1..57db765c07e 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -524,18 +524,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         match binding {
                             Ok(binding) => {
                                 if let Some(lint_id) = derive_fallback_lint_id {
-                                    this.lint_buffer.buffer_lint_with_diagnostic(
+                                    this.lint_buffer.buffer_lint(
                                         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
                                         lint_id,
                                         orig_ident.span,
-                                        format!(
-                                            "cannot find {} `{}` in this scope",
-                                            ns.descr(),
-                                            ident
-                                        ),
-                                        BuiltinLintDiag::ProcMacroDeriveResolutionFallback(
-                                            orig_ident.span,
-                                        ),
+                                        BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
+                                            span: orig_ident.span,
+                                            ns,
+                                            ident,
+                                        },
                                     );
                                 }
                                 let misc_flags = if module == this.graph_root {
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f53bcb0e9d0..51b87c5a9b0 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -619,11 +619,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         && binding.res() != Res::Err
                         && exported_ambiguities.contains(&binding)
                     {
-                        self.lint_buffer.buffer_lint_with_diagnostic(
+                        self.lint_buffer.buffer_lint(
                             AMBIGUOUS_GLOB_REEXPORTS,
                             import.root_id,
                             import.root_span,
-                            "ambiguous glob re-exports",
                             BuiltinLintDiag::AmbiguousGlobReexports {
                                 name: key.ident.to_string(),
                                 namespace: key.ns.descr().to_string(),
@@ -655,11 +654,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             && glob_binding.vis.is_public()
                             && !binding.vis.is_public()
                         {
-                            self.lint_buffer.buffer_lint_with_diagnostic(
+                            self.lint_buffer.buffer_lint(
                                 HIDDEN_GLOB_REEXPORTS,
                                 binding_id,
                                 binding.span,
-                                "private item shadows public glob re-export",
                                 BuiltinLintDiag::HiddenGlobReexports {
                                     name: key.ident.name.to_string(),
                                     namespace: key.ns.descr().to_owned(),
@@ -1015,17 +1013,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         && !max_vis.is_at_least(import_vis, self.tcx)
                     {
                         let def_id = self.local_def_id(id);
-                        let msg = format!(
-                            "glob import doesn't reexport anything with visibility `{}` because no imported item is public enough",
-                            import_vis.to_string(def_id, self.tcx)
-                        );
-                        self.lint_buffer.buffer_lint_with_diagnostic(
+                        self.lint_buffer.buffer_lint(
                             UNUSED_IMPORTS,
                             id,
                             import.span,
-                            msg,
                             BuiltinLintDiag::RedundantImportVisibility {
                                 max_vis: max_vis.to_string(def_id, self.tcx),
+                                import_vis: import_vis.to_string(def_id, self.tcx),
                                 span: import.span,
                             },
                         );
@@ -1252,16 +1246,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         if !any_successful_reexport {
             let (ns, binding) = reexport_error.unwrap();
             if pub_use_of_private_extern_crate_hack(import, binding) {
-                let msg = format!(
-                    "extern crate `{ident}` is private, and cannot be \
-                                   re-exported (error E0365), consider declaring with \
-                                   `pub`"
-                );
                 self.lint_buffer.buffer_lint(
                     PUB_USE_OF_PRIVATE_EXTERN_CRATE,
                     import_id,
                     import.span,
-                    msg,
+                    BuiltinLintDiag::PrivateExternCrateReexport(ident),
                 );
             } else {
                 if ns == TypeNS {
@@ -1397,7 +1386,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 UNUSED_IMPORTS,
                 id,
                 import.span,
-                format!("the item `{source}` is imported redundantly"),
                 BuiltinLintDiag::RedundantImport(redundant_spans, source),
             );
             */
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 0f585aafdd5..d1d0e336cfe 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -24,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::ty::DelegationFnSig;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
-use rustc_session::lint;
+use rustc_session::lint::{self, BuiltinLintDiag};
 use rustc_session::parse::feature_err;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1675,16 +1675,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     return;
                 }
                 LifetimeRibKind::AnonymousWarn(node_id) => {
-                    let msg = if elided {
-                        "`&` without an explicit lifetime name cannot be used here"
-                    } else {
-                        "`'_` cannot be used here"
-                    };
-                    self.r.lint_buffer.buffer_lint_with_diagnostic(
+                    self.r.lint_buffer.buffer_lint(
                         lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
                         node_id,
                         lifetime.ident.span,
-                        msg,
                         lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
                             elided,
                             span: lifetime.ident.span,
@@ -1966,11 +1960,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             if should_lint {
-                self.r.lint_buffer.buffer_lint_with_diagnostic(
+                self.r.lint_buffer.buffer_lint(
                     lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
                     segment_id,
                     elided_lifetime_span,
-                    "hidden lifetime parameters in types are deprecated",
                     lint::BuiltinLintDiag::ElidedLifetimesInPaths(
                         expected_lifetimes,
                         path_span,
@@ -4822,7 +4815,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
         visit::walk_crate(&mut late_resolution_visitor, krate);
         for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
-            self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
+            self.lint_buffer.buffer_lint(
+                lint::builtin::UNUSED_LABELS,
+                *id,
+                *span,
+                BuiltinLintDiag::UnusedLabel,
+            );
         }
     }
 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 1958fdf1cbc..9daa22f89d2 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -17,6 +17,7 @@ use rustc_ast::{
 };
 use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
     SuggestionStyle,
@@ -31,7 +32,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 
 use rustc_middle::ty;
 
@@ -2651,15 +2652,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     let deletion_span =
                         if param.bounds.is_empty() { deletion_span() } else { None };
 
-                    self.r.lint_buffer.buffer_lint_with_diagnostic(
+                    self.r.lint_buffer.buffer_lint(
                         lint::builtin::SINGLE_USE_LIFETIMES,
                         param.id,
                         param.ident.span,
-                        format!("lifetime parameter `{}` only used once", param.ident),
                         lint::BuiltinLintDiag::SingleUseLifetime {
                             param_span: param.ident.span,
                             use_span: Some((use_span, elidable)),
                             deletion_span,
+                            ident: param.ident,
                         },
                     );
                 }
@@ -2669,15 +2670,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
 
                     // if the lifetime originates from expanded code, we won't be able to remove it #104432
                     if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) {
-                        self.r.lint_buffer.buffer_lint_with_diagnostic(
+                        self.r.lint_buffer.buffer_lint(
                             lint::builtin::UNUSED_LIFETIMES,
                             param.id,
                             param.ident.span,
-                            format!("lifetime parameter `{}` never used", param.ident),
                             lint::BuiltinLintDiag::SingleUseLifetime {
                                 param_span: param.ident.span,
                                 use_span: None,
                                 deletion_span,
+                                ident: param.ident,
                             },
                         );
                     }
@@ -2714,8 +2715,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         self.suggest_introducing_lifetime(
             &mut err,
             Some(lifetime_ref.ident.name.as_str()),
-            |err, _, span, message, suggestion| {
-                err.span_suggestion(span, message, suggestion, Applicability::MaybeIncorrect);
+            |err, _, span, message, suggestion, span_suggs| {
+                err.multipart_suggestion_with_style(
+                    message,
+                    std::iter::once((span, suggestion)).chain(span_suggs.clone()).collect(),
+                    Applicability::MaybeIncorrect,
+                    if span_suggs.is_empty() {
+                        SuggestionStyle::ShowCode
+                    } else {
+                        SuggestionStyle::ShowAlways
+                    },
+                );
                 true
             },
         );
@@ -2726,13 +2736,20 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         &self,
         err: &mut Diag<'_>,
         name: Option<&str>,
-        suggest: impl Fn(&mut Diag<'_>, bool, Span, Cow<'static, str>, String) -> bool,
+        suggest: impl Fn(
+            &mut Diag<'_>,
+            bool,
+            Span,
+            Cow<'static, str>,
+            String,
+            Vec<(Span, String)>,
+        ) -> bool,
     ) {
         let mut suggest_note = true;
         for rib in self.lifetime_ribs.iter().rev() {
             let mut should_continue = true;
             match rib.kind {
-                LifetimeRibKind::Generics { binder: _, span, kind } => {
+                LifetimeRibKind::Generics { binder, span, kind } => {
                     // Avoid suggesting placing lifetime parameters on constant items unless the relevant
                     // feature is enabled. Suggest the parent item as a possible location if applicable.
                     if let LifetimeBinderKind::ConstItem = kind
@@ -2761,11 +2778,53 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             | LifetimeBinderKind::PolyTrait
                             | LifetimeBinderKind::WhereBound
                     );
+
+                    let mut rm_inner_binders: FxIndexSet<Span> = Default::default();
                     let (span, sugg) = if span.is_empty() {
+                        let mut binder_idents: FxIndexSet<Ident> = Default::default();
+                        binder_idents.insert(Ident::from_str(name.unwrap_or("'a")));
+
+                        // We need to special case binders in the following situation:
+                        // Change `T: for<'a> Trait<T> + 'b` to `for<'a, 'b> T: Trait<T> + 'b`
+                        // T: for<'a> Trait<T> + 'b
+                        //    ^^^^^^^  remove existing inner binder `for<'a>`
+                        // for<'a, 'b> T: Trait<T> + 'b
+                        // ^^^^^^^^^^^  suggest outer binder `for<'a, 'b>`
+                        if let LifetimeBinderKind::WhereBound = kind
+                            && let Some(ast::WherePredicate::BoundPredicate(
+                                ast::WhereBoundPredicate { bounded_ty, bounds, .. },
+                            )) = self.diag_metadata.current_where_predicate
+                            && bounded_ty.id == binder
+                        {
+                            for bound in bounds {
+                                if let ast::GenericBound::Trait(poly_trait_ref, _) = bound
+                                    && let span = poly_trait_ref
+                                        .span
+                                        .with_hi(poly_trait_ref.trait_ref.path.span.lo())
+                                    && !span.is_empty()
+                                {
+                                    rm_inner_binders.insert(span);
+                                    poly_trait_ref.bound_generic_params.iter().for_each(|v| {
+                                        binder_idents.insert(v.ident);
+                                    });
+                                }
+                            }
+                        }
+
+                        let binders_sugg = binder_idents.into_iter().enumerate().fold(
+                            "".to_string(),
+                            |mut binders, (i, x)| {
+                                if i != 0 {
+                                    binders += ", ";
+                                }
+                                binders += x.as_str();
+                                binders
+                            },
+                        );
                         let sugg = format!(
                             "{}<{}>{}",
                             if higher_ranked { "for" } else { "" },
-                            name.unwrap_or("'a"),
+                            binders_sugg,
                             if higher_ranked { " " } else { "" },
                         );
                         (span, sugg)
@@ -2780,13 +2839,28 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         let sugg = format!("{}, ", name.unwrap_or("'a"));
                         (span, sugg)
                     };
+
                     if higher_ranked {
                         let message = Cow::from(format!(
                             "consider making the {} lifetime-generic with a new `{}` lifetime",
                             kind.descr(),
                             name.unwrap_or("'a"),
                         ));
-                        should_continue = suggest(err, true, span, message, sugg);
+                        should_continue = suggest(
+                            err,
+                            true,
+                            span,
+                            message,
+                            sugg,
+                            if !rm_inner_binders.is_empty() {
+                                rm_inner_binders
+                                    .into_iter()
+                                    .map(|v| (v, "".to_string()))
+                                    .collect::<Vec<_>>()
+                            } else {
+                                vec![]
+                            },
+                        );
                         err.note_once(
                             "for more information on higher-ranked polymorphism, visit \
                              https://doc.rust-lang.org/nomicon/hrtb.html",
@@ -2794,10 +2868,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     } else if let Some(name) = name {
                         let message =
                             Cow::from(format!("consider introducing lifetime `{name}` here"));
-                        should_continue = suggest(err, false, span, message, sugg);
+                        should_continue = suggest(err, false, span, message, sugg, vec![]);
                     } else {
                         let message = Cow::from("consider introducing a named lifetime parameter");
-                        should_continue = suggest(err, false, span, message, sugg);
+                        should_continue = suggest(err, false, span, message, sugg, vec![]);
                     }
                 }
                 LifetimeRibKind::Item | LifetimeRibKind::ConstParamTy => break,
@@ -3033,11 +3107,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 self.suggest_introducing_lifetime(
                     err,
                     None,
-                    |err, higher_ranked, span, message, intro_sugg| {
+                    |err, higher_ranked, span, message, intro_sugg, _| {
                         err.multipart_suggestion_verbose(
                             message,
                             std::iter::once((span, intro_sugg))
-                                .chain(spans_suggs.iter().cloned())
+                                .chain(spans_suggs.clone())
                                 .collect(),
                             Applicability::MaybeIncorrect,
                         );
@@ -3161,11 +3235,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             self.suggest_introducing_lifetime(
                                 err,
                                 None,
-                                |err, higher_ranked, span, message, intro_sugg| {
+                                |err, higher_ranked, span, message, intro_sugg, _| {
                                     err.multipart_suggestion_verbose(
                                         message,
                                         std::iter::once((span, intro_sugg))
-                                            .chain(spans_suggs.iter().cloned())
+                                            .chain(spans_suggs.clone())
                                             .collect(),
                                         Applicability::MaybeIncorrect,
                                     );
@@ -3309,7 +3383,6 @@ fn mk_where_bound_predicate(
     poly_trait_ref: &ast::PolyTraitRef,
     ty: &Ty,
 ) -> Option<ast::WhereBoundPredicate> {
-    use rustc_span::DUMMY_SP;
     let modified_segments = {
         let mut segments = path.segments.clone();
         let [preceding @ .., second_last, last] = segments.as_mut_slice() else {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 01bcfec4bdc..f4c5ad8f672 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -51,7 +51,7 @@ use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTo
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
-use rustc_session::lint::LintBuffer;
+use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -1860,8 +1860,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
         if let NameBindingKind::Import { import, binding } = used_binding.kind {
             if let ImportKind::MacroUse { warn_private: true } = import.kind {
-                let msg = format!("macro `{ident}` is private");
-                self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg);
+                self.lint_buffer().buffer_lint(
+                    PRIVATE_MACRO_USE,
+                    import.root_id,
+                    ident.span,
+                    BuiltinLintDiag::MacroIsPrivate(ident),
+                );
             }
             // Avoid marking `extern crate` items that refer to a name from extern prelude,
             // but not introduce it, as used if they are accessed from lexical scope.
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index f8d245f94e5..092eb1ce2ee 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -315,7 +315,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
                 UNUSED_MACROS,
                 node_id,
                 ident.span,
-                format!("unused macro definition: `{}`", ident.name),
+                BuiltinLintDiag::UnusedMacroDefinition(ident.name),
             );
         }
         for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() {
@@ -328,7 +328,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
                 UNUSED_MACRO_RULES,
                 node_id,
                 rule_span,
-                format!("rule #{} of macro `{}` is never used", arm_i + 1, ident.name),
+                BuiltinLintDiag::MacroRuleNeverUsed(arm_i, ident.name),
             );
         }
     }
@@ -552,14 +552,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         // We are trying to avoid reporting this error if other related errors were reported.
         if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes {
-            let msg = match res {
-                Res::Def(..) => "inner macro attributes are unstable",
-                Res::NonMacroAttr(..) => "custom inner attributes are unstable",
+            let is_macro = match res {
+                Res::Def(..) => true,
+                Res::NonMacroAttr(..) => false,
                 _ => unreachable!(),
             };
             if soft_custom_inner_attributes_gate {
-                self.tcx.sess.psess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
+                self.tcx.sess.psess.buffer_lint(
+                    SOFT_UNSTABLE,
+                    path.span,
+                    node_id,
+                    BuiltinLintDiag::InnerAttributeUnstable { is_macro },
+                );
             } else {
+                // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::InnerAttributeUnstable`)
+                let msg = if is_macro {
+                    "inner macro attributes are unstable"
+                } else {
+                    "custom inner attributes are unstable"
+                };
                 feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
             }
         }
@@ -572,17 +583,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let distance =
                 edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
 
-            let help = if distance.is_some() {
-                BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented }
-            } else {
-                BuiltinLintDiag::Normal
-            };
-            self.tcx.sess.psess.buffer_lint_with_diagnostic(
+            let typo_name = distance.map(|_| sym::on_unimplemented);
+
+            self.tcx.sess.psess.buffer_lint(
                 UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
                 attribute.span(),
                 node_id,
-                "unknown diagnostic attribute",
-                help,
+                BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name },
             );
         }
 
@@ -782,11 +789,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             .invocation_parents
                             .get(&parent_scope.expansion)
                             .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]);
-                        self.lint_buffer.buffer_lint_with_diagnostic(
+                        self.lint_buffer.buffer_lint(
                             LEGACY_DERIVE_HELPERS,
                             node_id,
                             ident.span,
-                            "derive helper attribute is used before it is introduced",
                             BuiltinLintDiag::LegacyDeriveHelpers(binding.span),
                         );
                     }
@@ -836,8 +842,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
                 if !is_allowed(feature) && !allowed_by_implication {
                     let lint_buffer = &mut self.lint_buffer;
-                    let soft_handler =
-                        |lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg);
+                    let soft_handler = |lint, span, msg: String| {
+                        lint_buffer.buffer_lint(
+                            lint,
+                            node_id,
+                            span,
+                            BuiltinLintDiag::UnstableFeature(
+                                // FIXME make this translatable
+                                msg.into(),
+                            ),
+                        )
+                    };
                     stability::report_unstable(
                         self.tcx.sess,
                         feature,
@@ -853,14 +868,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
         if let Some(depr) = &ext.deprecation {
             let path = pprust::path_to_string(path);
-            let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
-            stability::early_report_deprecation(
+            stability::early_report_macro_deprecation(
                 &mut self.lint_buffer,
-                message,
-                depr.suggestion,
-                lint,
+                depr,
                 span,
                 node_id,
+                path,
             );
         }
     }
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index f6053f43fbd..df07f81bc45 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -305,32 +305,12 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: impl Into<DiagMessage>,
-    ) {
-        self.buffered_lints.with_lock(|buffered_lints| {
-            buffered_lints.push(BufferedEarlyLint {
-                span: span.into(),
-                node_id,
-                msg: msg.into(),
-                lint_id: LintId::of(lint),
-                diagnostic: BuiltinLintDiag::Normal,
-            });
-        });
-    }
-
-    pub fn buffer_lint_with_diagnostic(
-        &self,
-        lint: &'static Lint,
-        span: impl Into<MultiSpan>,
-        node_id: NodeId,
-        msg: impl Into<DiagMessage>,
         diagnostic: BuiltinLintDiag,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
                 span: span.into(),
                 node_id,
-                msg: msg.into(),
                 lint_id: LintId::of(lint),
                 diagnostic,
             });
diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs
index 39e4541349e..e244c77f7f9 100644
--- a/compiler/rustc_session/src/version.rs
+++ b/compiler/rustc_session/src/version.rs
@@ -1,5 +1,10 @@
 use rustc_macros::{current_rustc_version, Decodable, Encodable, HashStable_Generic};
-use std::fmt::{self, Display};
+use std::{
+    borrow::Cow,
+    fmt::{self, Display},
+};
+
+use rustc_errors::IntoDiagArg;
 
 #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[derive(HashStable_Generic)]
@@ -18,3 +23,9 @@ impl Display for RustcVersion {
         write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
     }
 }
+
+impl IntoDiagArg for RustcVersion {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        rustc_errors::DiagArgValue::Str(Cow::Owned(self.to_string()))
+    }
+}
diff --git a/src/bootstrap/src/core/build_steps/synthetic_targets.rs b/src/bootstrap/src/core/build_steps/synthetic_targets.rs
index 89d50b5ffff..281a9b093b9 100644
--- a/src/bootstrap/src/core/build_steps/synthetic_targets.rs
+++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs
@@ -80,8 +80,5 @@ fn create_synthetic_target(
     customize(spec_map);
 
     std::fs::write(&path, serde_json::to_vec_pretty(&spec).unwrap()).unwrap();
-    let target = TargetSelection::create_synthetic(&name, path.to_str().unwrap());
-    crate::utils::cc_detect::find_target(builder, target);
-
-    target
+    TargetSelection::create_synthetic(&name, path.to_str().unwrap())
 }
diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh
index 2eafdd0fbc8..09202b1878b 100755
--- a/src/tools/clippy/.github/driver.sh
+++ b/src/tools/clippy/.github/driver.sh
@@ -2,15 +2,18 @@
 
 set -ex
 
+sysroot="$(rustc --print sysroot)"
+case $OS in
+    Linux) export LD_LIBRARY_PATH="$sysroot/lib" ;;
+    macOS) export DYLD_FALLBACK_LIBRARY_PATH="$sysroot/lib" ;;
+    Windows) export PATH="$(cygpath "$sysroot")/bin:$PATH" ;;
+    *) exit 1
+esac
+
 # Check sysroot handling
-sysroot=$(./target/debug/clippy-driver --print sysroot)
-test "$sysroot" = "$(rustc --print sysroot)"
-
-if [[ ${OS} == "Windows" ]]; then
-	desired_sysroot=C:/tmp
-else
-	desired_sysroot=/tmp
-fi
+test "$(./target/debug/clippy-driver --print sysroot)" = "$sysroot"
+
+desired_sysroot="target/sysroot"
 # Set --sysroot in command line
 sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot)
 test "$sysroot" = $desired_sysroot
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 8179e3e65b5..06bf3b6fdbf 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -69,6 +69,6 @@ jobs:
       working-directory: clippy_dev
 
     - name: Test clippy-driver
-      run: |
-        TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
-        rustup run $TOOLCHAIN bash .github/driver.sh
+      run: .github/driver.sh
+      env:
+        OS: ${{ runner.os }}
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 94515987eba..1f4bec92918 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -116,9 +116,7 @@ jobs:
       working-directory: clippy_dev
 
     - name: Test clippy-driver
-      run: |
-        TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
-        rustup run $TOOLCHAIN bash .github/driver.sh
+      run: .github/driver.sh
       env:
         OS: ${{ runner.os }}
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 9c9ea114081..d5115f70f66 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5249,6 +5249,7 @@ Released 2018-09-13
 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
 [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
+[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation
 [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
 [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
 [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
@@ -5447,6 +5448,7 @@ Released 2018-09-13
 [`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes
 [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
+[`macro_metavars_in_unsafe`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe
 [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
 [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
 [`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
@@ -5702,6 +5704,7 @@ Released 2018-09-13
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
 [`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns
 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
+[`renamed_function_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params
 [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
 [`repeat_vec_with_capacity`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity
 [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
@@ -5908,6 +5911,7 @@ Released 2018-09-13
 [`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads
 [`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
 [`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/master/index.html#waker_clone_wake
+[`while_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_float
 [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
 [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
 [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
@@ -5939,8 +5943,10 @@ Released 2018-09-13
 [`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests
 [`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args
 [`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
+[`allow-panic-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-panic-in-tests
 [`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests
 [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception
+[`allow-renamed-params-for`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-renamed-params-for
 [`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests
 [`allow-useless-vec-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-useless-vec-in-tests
 [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
@@ -6002,4 +6008,5 @@ Released 2018-09-13
 [`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold
 [`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold
 [`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports
+[`warn-unsafe-macro-metavars-in-private-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-unsafe-macro-metavars-in-private-macros
 <!-- end autogenerated links to configuration documentation -->
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index f6af9810ca1..c8223007df7 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -101,6 +101,16 @@ Whether to allow `r#""#` when `r""` can be used
 * [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes)
 
 
+## `allow-panic-in-tests`
+Whether `panic` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`panic`](https://rust-lang.github.io/rust-clippy/master/index.html#panic)
+
+
 ## `allow-print-in-tests`
 Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
 
@@ -122,6 +132,28 @@ Whether to allow module inception if it's not public.
 * [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception)
 
 
+## `allow-renamed-params-for`
+List of trait paths to ignore when checking renamed function parameters.
+
+#### Example
+
+```toml
+allow-renamed-params-for = [ "std::convert::From" ]
+```
+
+#### Noteworthy
+
+- By default, the following traits are ignored: `From`, `TryFrom`, `FromStr`
+- `".."` can be used as part of the list to indicate that the configured values should be appended to the
+default configuration of Clippy. By default, any configuration will replace the default value.
+
+**Default Value:** `["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"]`
+
+---
+**Affected lints:**
+* [`renamed_function_params`](https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params)
+
+
 ## `allow-unwrap-in-tests`
 Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
 
@@ -900,3 +932,13 @@ Whether to allow certain wildcard imports (prelude, super in tests).
 * [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
 
 
+## `warn-unsafe-macro-metavars-in-private-macros`
+Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe)
+
+
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 5cfcbdb57d7..cfdf620b7d0 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -40,6 +40,8 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
 const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
 const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
 const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"];
+const DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS: &[&str] =
+    &["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"];
 
 /// Conf with parse errors
 #[derive(Default)]
@@ -455,6 +457,10 @@ define_Conf! {
     ///
     /// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
     (allow_unwrap_in_tests: bool = false),
+    /// Lint: PANIC.
+    ///
+    /// Whether `panic` should be allowed in test functions or `#[cfg(test)]`
+    (allow_panic_in_tests: bool = false),
     /// Lint: DBG_MACRO.
     ///
     /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
@@ -613,6 +619,27 @@ define_Conf! {
     /// - Use `".."` as part of the list to indicate that the configured values should be appended to the
     /// default configuration of Clippy. By default, any configuration will replace the default value
     (allowed_prefixes: Vec<String> = DEFAULT_ALLOWED_PREFIXES.iter().map(ToString::to_string).collect()),
+    /// Lint: RENAMED_FUNCTION_PARAMS.
+    ///
+    /// List of trait paths to ignore when checking renamed function parameters.
+    ///
+    /// #### Example
+    ///
+    /// ```toml
+    /// allow-renamed-params-for = [ "std::convert::From" ]
+    /// ```
+    ///
+    /// #### Noteworthy
+    ///
+    /// - By default, the following traits are ignored: `From`, `TryFrom`, `FromStr`
+    /// - `".."` can be used as part of the list to indicate that the configured values should be appended to the
+    /// default configuration of Clippy. By default, any configuration will replace the default value.
+    (allow_renamed_params_for: Vec<String> =
+        DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS.iter().map(ToString::to_string).collect()),
+    /// Lint: MACRO_METAVARS_IN_UNSAFE.
+    ///
+    /// Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros.
+    (warn_unsafe_macro_metavars_in_private_macros: bool = false),
 }
 
 /// Search for the configuration file.
@@ -674,6 +701,10 @@ fn deserialize(file: &SourceFile) -> TryConf {
             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(
+                &mut conf.conf.allow_renamed_params_for,
+                DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS,
+            );
             // TODO: THIS SHOULD BE TESTED, this comment will be gone soon
             if conf.conf.allowed_idents_below_min_chars.contains("..") {
                 conf.conf
diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs
index 14808440d48..a3e7d0c3fa5 100644
--- a/src/tools/clippy/clippy_config/src/msrvs.rs
+++ b/src/tools/clippy/clippy_config/src/msrvs.rs
@@ -26,7 +26,8 @@ msrv_aliases! {
     1,63,0 { CLONE_INTO }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
     1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST }
-    1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
+    1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
+    1,56,0 { CONST_FN_UNION }
     1,55,0 { SEEK_REWIND }
     1,54,0 { INTO_KEYS }
     1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index 42a953039b1..4104e7d94f1 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -1,11 +1,12 @@
 [package]
 name = "clippy_dev"
+description = "Clippy developer tooling"
 version = "0.0.1"
 edition = "2021"
 
 [dependencies]
 aho-corasick = "1.0"
-clap = "4.1.4"
+clap = { version = "4.4", features = ["derive"] }
 indoc = "1.0"
 itertools = "0.12"
 opener = "0.6"
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index 397a0e99082..366b52b25df 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -2,350 +2,292 @@
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use clap::{Arg, ArgAction, ArgMatches, Command};
+use clap::{Args, Parser, Subcommand};
 use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints};
-use indoc::indoc;
 use std::convert::Infallible;
 
 fn main() {
-    let matches = get_clap_config();
+    let dev = Dev::parse();
 
-    match matches.subcommand() {
-        Some(("bless", _)) => {
+    match dev.command {
+        DevCommand::Bless => {
             eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run");
         },
-        Some(("dogfood", matches)) => {
-            dogfood::dogfood(
-                matches.get_flag("fix"),
-                matches.get_flag("allow-dirty"),
-                matches.get_flag("allow-staged"),
-            );
-        },
-        Some(("fmt", matches)) => {
-            fmt::run(matches.get_flag("check"), matches.get_flag("verbose"));
-        },
-        Some(("update_lints", matches)) => {
-            if matches.get_flag("print-only") {
+        DevCommand::Dogfood {
+            fix,
+            allow_dirty,
+            allow_staged,
+        } => dogfood::dogfood(fix, allow_dirty, allow_staged),
+        DevCommand::Fmt { check, verbose } => fmt::run(check, verbose),
+        DevCommand::UpdateLints { print_only, check } => {
+            if print_only {
                 update_lints::print_lints();
-            } else if matches.get_flag("check") {
+            } else if check {
                 update_lints::update(update_lints::UpdateMode::Check);
             } else {
                 update_lints::update(update_lints::UpdateMode::Change);
             }
         },
-        Some(("new_lint", matches)) => {
-            match new_lint::create(
-                matches.get_one::<String>("pass").unwrap(),
-                matches.get_one::<String>("name"),
-                matches.get_one::<String>("category").map(String::as_str),
-                matches.get_one::<String>("type").map(String::as_str),
-                matches.get_flag("msrv"),
-            ) {
-                Ok(()) => update_lints::update(update_lints::UpdateMode::Change),
-                Err(e) => eprintln!("Unable to create lint: {e}"),
-            }
+        DevCommand::NewLint {
+            pass,
+            name,
+            category,
+            r#type,
+            msrv,
+        } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) {
+            Ok(()) => update_lints::update(update_lints::UpdateMode::Change),
+            Err(e) => eprintln!("Unable to create lint: {e}"),
         },
-        Some(("setup", sub_command)) => match sub_command.subcommand() {
-            Some(("git-hook", matches)) => {
-                if matches.get_flag("remove") {
-                    setup::git_hook::remove_hook();
+        DevCommand::Setup(SetupCommand { subcommand }) => match subcommand {
+            SetupSubcommand::Intellij { remove, repo_path } => {
+                if remove {
+                    setup::intellij::remove_rustc_src();
                 } else {
-                    setup::git_hook::install_hook(matches.get_flag("force-override"));
+                    setup::intellij::setup_rustc_src(&repo_path);
                 }
             },
-            Some(("intellij", matches)) => {
-                if matches.get_flag("remove") {
-                    setup::intellij::remove_rustc_src();
+            SetupSubcommand::GitHook { remove, force_override } => {
+                if remove {
+                    setup::git_hook::remove_hook();
                 } else {
-                    setup::intellij::setup_rustc_src(
-                        matches
-                            .get_one::<String>("rustc-repo-path")
-                            .expect("this field is mandatory and therefore always valid"),
-                    );
+                    setup::git_hook::install_hook(force_override);
                 }
             },
-            Some(("toolchain", matches)) => {
-                setup::toolchain::create(
-                    matches.get_flag("force"),
-                    matches.get_flag("release"),
-                    matches.get_one::<String>("name").unwrap(),
-                );
-            },
-            Some(("vscode-tasks", matches)) => {
-                if matches.get_flag("remove") {
+            SetupSubcommand::Toolchain { force, release, name } => setup::toolchain::create(force, release, &name),
+            SetupSubcommand::VscodeTasks { remove, force_override } => {
+                if remove {
                     setup::vscode::remove_tasks();
                 } else {
-                    setup::vscode::install_tasks(matches.get_flag("force-override"));
+                    setup::vscode::install_tasks(force_override);
                 }
             },
-            _ => {},
-        },
-        Some(("remove", sub_command)) => match sub_command.subcommand() {
-            Some(("git-hook", _)) => setup::git_hook::remove_hook(),
-            Some(("intellij", _)) => setup::intellij::remove_rustc_src(),
-            Some(("vscode-tasks", _)) => setup::vscode::remove_tasks(),
-            _ => {},
-        },
-        Some(("serve", matches)) => {
-            let port = *matches.get_one::<u16>("port").unwrap();
-            let lint = matches.get_one::<String>("lint");
-            serve::run(port, lint);
         },
-        Some(("lint", matches)) => {
-            let path = matches.get_one::<String>("path").unwrap();
-            let args = matches.get_many::<String>("args").into_iter().flatten();
-            lint::run(path, args);
+        DevCommand::Remove(RemoveCommand { subcommand }) => match subcommand {
+            RemoveSubcommand::Intellij => setup::intellij::remove_rustc_src(),
+            RemoveSubcommand::GitHook => setup::git_hook::remove_hook(),
+            RemoveSubcommand::VscodeTasks => setup::vscode::remove_tasks(),
         },
-        Some(("rename_lint", matches)) => {
-            let old_name = matches.get_one::<String>("old_name").unwrap();
-            let new_name = matches.get_one::<String>("new_name").unwrap_or(old_name);
-            let uplift = matches.get_flag("uplift");
-            update_lints::rename(old_name, new_name, uplift);
-        },
-        Some(("deprecate", matches)) => {
-            let name = matches.get_one::<String>("name").unwrap();
-            let reason = matches.get_one("reason");
-            update_lints::deprecate(name, reason);
-        },
-        _ => {},
+        DevCommand::Serve { port, lint } => serve::run(port, lint),
+        DevCommand::Lint { path, args } => lint::run(&path, args.iter()),
+        DevCommand::RenameLint {
+            old_name,
+            new_name,
+            uplift,
+        } => update_lints::rename(&old_name, new_name.as_ref().unwrap_or(&old_name), uplift),
+        DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, reason.as_deref()),
     }
 }
 
-fn get_clap_config() -> ArgMatches {
-    Command::new("Clippy developer tooling")
-        .arg_required_else_help(true)
-        .subcommands([
-            Command::new("bless").about("bless the test output changes").arg(
-                Arg::new("ignore-timestamp")
-                    .long("ignore-timestamp")
-                    .action(ArgAction::SetTrue)
-                    .help("Include files updated before clippy was built"),
-            ),
-            Command::new("dogfood").about("Runs the dogfood test").args([
-                Arg::new("fix")
-                    .long("fix")
-                    .action(ArgAction::SetTrue)
-                    .help("Apply the suggestions when possible"),
-                Arg::new("allow-dirty")
-                    .long("allow-dirty")
-                    .action(ArgAction::SetTrue)
-                    .help("Fix code even if the working directory has changes")
-                    .requires("fix"),
-                Arg::new("allow-staged")
-                    .long("allow-staged")
-                    .action(ArgAction::SetTrue)
-                    .help("Fix code even if the working directory has staged changes")
-                    .requires("fix"),
-            ]),
-            Command::new("fmt")
-                .about("Run rustfmt on all projects and tests")
-                .args([
-                    Arg::new("check")
-                        .long("check")
-                        .action(ArgAction::SetTrue)
-                        .help("Use the rustfmt --check option"),
-                    Arg::new("verbose")
-                        .short('v')
-                        .long("verbose")
-                        .action(ArgAction::SetTrue)
-                        .help("Echo commands run"),
-                ]),
-            Command::new("update_lints")
-                .about("Updates lint registration and information from the source code")
-                .long_about(
-                    "Makes sure that:\n \
-                    * the lint count in README.md is correct\n \
-                    * the changelog contains markdown link references at the bottom\n \
-                    * all lint groups include the correct lints\n \
-                    * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \
-                    * all lints are registered in the lint store",
-                )
-                .args([
-                    Arg::new("print-only")
-                        .long("print-only")
-                        .action(ArgAction::SetTrue)
-                        .help(
-                            "Print a table of lints to STDOUT. \
-                            This does not include deprecated and internal lints. \
-                            (Does not modify any files)",
-                        ),
-                    Arg::new("check")
-                        .long("check")
-                        .action(ArgAction::SetTrue)
-                        .help("Checks that `cargo dev update_lints` has been run. Used on CI."),
-                ]),
-            Command::new("new_lint")
-                .about("Create new lint and run `cargo dev update_lints`")
-                .args([
-                    Arg::new("pass")
-                        .short('p')
-                        .long("pass")
-                        .help("Specify whether the lint runs during the early or late pass")
-                        .value_parser(["early", "late"])
-                        .conflicts_with("type")
-                        .default_value("late"),
-                    Arg::new("name")
-                        .short('n')
-                        .long("name")
-                        .help("Name of the new lint in snake case, ex: fn_too_long")
-                        .required(true)
-                        .value_parser(|name: &str| Ok::<_, Infallible>(name.replace('-', "_"))),
-                    Arg::new("category")
-                        .short('c')
-                        .long("category")
-                        .help("What category the lint belongs to")
-                        .default_value("nursery")
-                        .value_parser([
-                            "style",
-                            "correctness",
-                            "suspicious",
-                            "complexity",
-                            "perf",
-                            "pedantic",
-                            "restriction",
-                            "cargo",
-                            "nursery",
-                            "internal",
-                        ]),
-                    Arg::new("type").long("type").help("What directory the lint belongs in"),
-                    Arg::new("msrv")
-                        .long("msrv")
-                        .action(ArgAction::SetTrue)
-                        .help("Add MSRV config code to the lint"),
-                ]),
-            Command::new("setup")
-                .about("Support for setting up your personal development environment")
-                .arg_required_else_help(true)
-                .subcommands([
-                    Command::new("git-hook")
-                        .about("Add a pre-commit git hook that formats your code to make it look pretty")
-                        .args([
-                            Arg::new("remove")
-                                .long("remove")
-                                .action(ArgAction::SetTrue)
-                                .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
-                            Arg::new("force-override")
-                                .long("force-override")
-                                .short('f')
-                                .action(ArgAction::SetTrue)
-                                .help("Forces the override of an existing git pre-commit hook"),
-                        ]),
-                    Command::new("intellij")
-                        .about("Alter dependencies so Intellij Rust can find rustc internals")
-                        .args([
-                            Arg::new("remove")
-                                .long("remove")
-                                .action(ArgAction::SetTrue)
-                                .help("Remove the dependencies added with 'cargo dev setup intellij'"),
-                            Arg::new("rustc-repo-path")
-                                .long("repo-path")
-                                .short('r')
-                                .help("The path to a rustc repo that will be used for setting the dependencies")
-                                .value_name("path")
-                                .conflicts_with("remove")
-                                .required(true),
-                        ]),
-                    Command::new("toolchain")
-                        .about("Install a rustup toolchain pointing to the local clippy build")
-                        .args([
-                            Arg::new("force")
-                                .long("force")
-                                .short('f')
-                                .action(ArgAction::SetTrue)
-                                .help("Override an existing toolchain"),
-                            Arg::new("release")
-                                .long("release")
-                                .short('r')
-                                .action(ArgAction::SetTrue)
-                                .help("Point to --release clippy binaries"),
-                            Arg::new("name")
-                                .long("name")
-                                .default_value("clippy")
-                                .help("The name of the created toolchain"),
-                        ]),
-                    Command::new("vscode-tasks")
-                        .about("Add several tasks to vscode for formatting, validation and testing")
-                        .args([
-                            Arg::new("remove")
-                                .long("remove")
-                                .action(ArgAction::SetTrue)
-                                .help("Remove the tasks added with 'cargo dev setup vscode-tasks'"),
-                            Arg::new("force-override")
-                                .long("force-override")
-                                .short('f')
-                                .action(ArgAction::SetTrue)
-                                .help("Forces the override of existing vscode tasks"),
-                        ]),
-                ]),
-            Command::new("remove")
-                .about("Support for undoing changes done by the setup command")
-                .arg_required_else_help(true)
-                .subcommands([
-                    Command::new("git-hook").about("Remove any existing pre-commit git hook"),
-                    Command::new("vscode-tasks").about("Remove any existing vscode tasks"),
-                    Command::new("intellij").about("Removes rustc source paths added via `cargo dev setup intellij`"),
-                ]),
-            Command::new("serve")
-                .about("Launch a local 'ALL the Clippy Lints' website in a browser")
-                .args([
-                    Arg::new("port")
-                        .long("port")
-                        .short('p')
-                        .help("Local port for the http server")
-                        .default_value("8000")
-                        .value_parser(clap::value_parser!(u16)),
-                    Arg::new("lint").help("Which lint's page to load initially (optional)"),
-                ]),
-            Command::new("lint")
-                .about("Manually run clippy on a file or package")
-                .after_help(indoc! {"
-                    EXAMPLES
-                        Lint a single file:
-                            cargo dev lint tests/ui/attrs.rs
+#[derive(Parser)]
+#[command(name = "dev", about)]
+struct Dev {
+    #[command(subcommand)]
+    command: DevCommand,
+}
 
-                        Lint a package directory:
-                            cargo dev lint tests/ui-cargo/wildcard_dependencies/fail
-                            cargo dev lint ~/my-project
+#[derive(Subcommand)]
+enum DevCommand {
+    /// Bless the test output changes
+    Bless,
+    /// Runs the dogfood test
+    Dogfood {
+        #[arg(long)]
+        /// Apply the suggestions when possible
+        fix: bool,
+        #[arg(long, requires = "fix")]
+        /// Fix code even if the working directory has changes
+        allow_dirty: bool,
+        #[arg(long, requires = "fix")]
+        /// Fix code even if the working directory has staged changes
+        allow_staged: bool,
+    },
+    /// Run rustfmt on all projects and tests
+    Fmt {
+        #[arg(long)]
+        /// Use the rustfmt --check option
+        check: bool,
+        #[arg(short, long)]
+        /// Echo commands run
+        verbose: bool,
+    },
+    #[command(name = "update_lints")]
+    /// Updates lint registration and information from the source code
+    ///
+    /// Makes sure that: {n}
+    /// * the lint count in README.md is correct {n}
+    /// * the changelog contains markdown link references at the bottom {n}
+    /// * all lint groups include the correct lints {n}
+    /// * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod` {n}
+    /// * all lints are registered in the lint store
+    UpdateLints {
+        #[arg(long)]
+        /// Print a table of lints to STDOUT
+        ///
+        /// This does not include deprecated and internal lints. (Does not modify any files)
+        print_only: bool,
+        #[arg(long)]
+        /// Checks that `cargo dev update_lints` has been run. Used on CI.
+        check: bool,
+    },
+    #[command(name = "new_lint")]
+    /// Create a new lint and run `cargo dev update_lints`
+    NewLint {
+        #[arg(short, long, value_parser = ["early", "late"], conflicts_with = "type", default_value = "late")]
+        /// Specify whether the lint runs during the early or late pass
+        pass: String,
+        #[arg(
+            short,
+            long,
+            value_parser = |name: &str| Ok::<_, Infallible>(name.replace('-', "_")),
+        )]
+        /// Name of the new lint in snake case, ex: `fn_too_long`
+        name: String,
+        #[arg(
+            short,
+            long,
+            value_parser = [
+                "style",
+                "correctness",
+                "suspicious",
+                "complexity",
+                "perf",
+                "pedantic",
+                "restriction",
+                "cargo",
+                "nursery",
+                "internal",
+            ],
+            default_value = "nursery",
+        )]
+        /// What category the lint belongs to
+        category: String,
+        #[arg(long)]
+        /// What directory the lint belongs in
+        r#type: Option<String>,
+        #[arg(long)]
+        /// Add MSRV config code to the lint
+        msrv: bool,
+    },
+    /// Support for setting up your personal development environment
+    Setup(SetupCommand),
+    /// Support for removing changes done by the setup command
+    Remove(RemoveCommand),
+    /// Launch a local 'ALL the Clippy Lints' website in a browser
+    Serve {
+        #[arg(short, long, default_value = "8000")]
+        /// Local port for the http server
+        port: u16,
+        #[arg(long)]
+        /// Which lint's page to load initially (optional)
+        lint: Option<String>,
+    },
+    #[allow(clippy::doc_markdown)]
+    /// Manually run clippy on a file or package
+    ///
+    /// ## Examples
+    ///
+    /// Lint a single file: {n}
+    ///     cargo dev lint tests/ui/attrs.rs
+    ///
+    /// Lint a package directory: {n}
+    ///     cargo dev lint tests/ui-cargo/wildcard_dependencies/fail {n}
+    ///     cargo dev lint ~/my-project
+    ///
+    /// Run rustfix: {n}
+    ///     cargo dev lint ~/my-project -- --fix
+    ///
+    /// Set lint levels: {n}
+    ///     cargo dev lint file.rs -- -W clippy::pedantic {n}
+    ///     cargo dev lint ~/my-project -- -- -W clippy::pedantic
+    Lint {
+        /// The path to a file or package directory to lint
+        path: String,
+        /// Pass extra arguments to cargo/clippy-driver
+        args: Vec<String>,
+    },
+    #[command(name = "rename_lint")]
+    /// Rename a lint
+    RenameLint {
+        /// The name of the lint to rename
+        old_name: String,
+        #[arg(required_unless_present = "uplift")]
+        /// The new name of the lint
+        new_name: Option<String>,
+        #[arg(long)]
+        /// This lint will be uplifted into rustc
+        uplift: bool,
+    },
+    /// Deprecate the given lint
+    Deprecate {
+        /// The name of the lint to deprecate
+        name: String,
+        #[arg(long, short)]
+        /// The reason for deprecation
+        reason: Option<String>,
+    },
+}
 
-                        Run rustfix:
-                            cargo dev lint ~/my-project -- --fix
+#[derive(Args)]
+struct SetupCommand {
+    #[command(subcommand)]
+    subcommand: SetupSubcommand,
+}
+
+#[derive(Subcommand)]
+enum SetupSubcommand {
+    /// Alter dependencies so Intellij Rust can find rustc internals
+    Intellij {
+        #[arg(long)]
+        /// Remove the dependencies added with 'cargo dev setup intellij'
+        remove: bool,
+        #[arg(long, short, conflicts_with = "remove")]
+        /// The path to a rustc repo that will be used for setting the dependencies
+        repo_path: String,
+    },
+    /// Add a pre-commit git hook that formats your code to make it look pretty
+    GitHook {
+        #[arg(long)]
+        /// Remove the pre-commit hook added with 'cargo dev setup git-hook'
+        remove: bool,
+        #[arg(long, short)]
+        /// Forces the override of an existing git pre-commit hook
+        force_override: bool,
+    },
+    /// Install a rustup toolchain pointing to the local clippy build
+    Toolchain {
+        #[arg(long, short)]
+        /// Override an existing toolchain
+        force: bool,
+        #[arg(long, short)]
+        /// Point to --release clippy binary
+        release: bool,
+        #[arg(long, default_value = "clippy")]
+        /// Name of the toolchain
+        name: String,
+    },
+    /// Add several tasks to vscode for formatting, validation and testing
+    VscodeTasks {
+        #[arg(long)]
+        /// Remove the tasks added with 'cargo dev setup vscode-tasks'
+        remove: bool,
+        #[arg(long, short)]
+        /// Forces the override of existing vscode tasks
+        force_override: bool,
+    },
+}
+
+#[derive(Args)]
+struct RemoveCommand {
+    #[command(subcommand)]
+    subcommand: RemoveSubcommand,
+}
 
-                        Set lint levels:
-                            cargo dev lint file.rs -- -W clippy::pedantic
-                            cargo dev lint ~/my-project -- -- -W clippy::pedantic
-                "})
-                .args([
-                    Arg::new("path")
-                        .required(true)
-                        .help("The path to a file or package directory to lint"),
-                    Arg::new("args")
-                        .action(ArgAction::Append)
-                        .help("Pass extra arguments to cargo/clippy-driver"),
-                ]),
-            Command::new("rename_lint").about("Renames the given lint").args([
-                Arg::new("old_name")
-                    .index(1)
-                    .required(true)
-                    .help("The name of the lint to rename"),
-                Arg::new("new_name")
-                    .index(2)
-                    .required_unless_present("uplift")
-                    .help("The new name of the lint"),
-                Arg::new("uplift")
-                    .long("uplift")
-                    .action(ArgAction::SetTrue)
-                    .help("This lint will be uplifted into rustc"),
-            ]),
-            Command::new("deprecate").about("Deprecates the given lint").args([
-                Arg::new("name")
-                    .index(1)
-                    .required(true)
-                    .help("The name of the lint to deprecate"),
-                Arg::new("reason")
-                    .long("reason")
-                    .short('r')
-                    .help("The reason for deprecation"),
-            ]),
-        ])
-        .get_matches()
+#[derive(Subcommand)]
+enum RemoveSubcommand {
+    /// Remove the dependencies added with 'cargo dev setup intellij'
+    Intellij,
+    /// Remove the pre-commit git hook
+    GitHook,
+    /// Remove the tasks added with 'cargo dev setup vscode-tasks'
+    VscodeTasks,
 }
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 2940d56350f..b6481dde4dd 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -36,22 +36,16 @@ impl<T> Context for io::Result<T> {
 /// # Errors
 ///
 /// This function errors out if the files couldn't be created or written to.
-pub fn create(
-    pass: &String,
-    lint_name: Option<&String>,
-    category: Option<&str>,
-    mut ty: Option<&str>,
-    msrv: bool,
-) -> io::Result<()> {
-    if category == Some("cargo") && ty.is_none() {
+pub fn create(pass: &str, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> {
+    if category == "cargo" && ty.is_none() {
         // `cargo` is a special category, these lints should always be in `clippy_lints/src/cargo`
         ty = Some("cargo");
     }
 
     let lint = LintData {
         pass,
-        name: lint_name.expect("`name` argument is validated by clap"),
-        category: category.expect("`category` argument is validated by clap"),
+        name,
+        category,
         ty,
         project_root: clippy_project_root(),
     };
diff --git a/src/tools/clippy/clippy_dev/src/serve.rs b/src/tools/clippy/clippy_dev/src/serve.rs
index ea925f6709f..4a4261d1a1e 100644
--- a/src/tools/clippy/clippy_dev/src/serve.rs
+++ b/src/tools/clippy/clippy_dev/src/serve.rs
@@ -8,7 +8,7 @@ use std::{env, thread};
 /// # Panics
 ///
 /// Panics if the python commands could not be spawned
-pub fn run(port: u16, lint: Option<&String>) -> ! {
+pub fn run(port: u16, lint: Option<String>) -> ! {
     let mut url = Some(match lint {
         None => format!("http://localhost:{port}"),
         Some(lint) => format!("http://localhost:{port}/#{lint}"),
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 625b1339591..45353901c98 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -314,7 +314,7 @@ const DEFAULT_DEPRECATION_REASON: &str = "default deprecation note";
 /// # Panics
 ///
 /// If a file path could not read from or written to
-pub fn deprecate(name: &str, reason: Option<&String>) {
+pub fn deprecate(name: &str, reason: Option<&str>) {
     fn finish(
         (lints, mut deprecated_lints, renamed_lints): (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>),
         name: &str,
@@ -335,7 +335,7 @@ pub fn deprecate(name: &str, reason: Option<&String>) {
         println!("note: you must run `cargo uitest` to update the test results");
     }
 
-    let reason = reason.map_or(DEFAULT_DEPRECATION_REASON, String::as_str);
+    let reason = reason.unwrap_or(DEFAULT_DEPRECATION_REASON);
     let name_lower = name.to_lowercase();
     let name_upper = name.to_uppercase();
 
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index f0dafb1ae0d..e94a6f3e3fc 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -2,15 +2,15 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::HirNode;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{is_trait_method, path_to_local};
+use clippy_utils::{is_trait_method, local_is_initialized, path_to_local};
 use rustc_errors::Applicability;
-use rustc_hir::{self as hir, Expr, ExprKind, Node};
+use rustc_hir::{self as hir, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Instance, Mutability};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::sym;
-use rustc_span::ExpnKind;
+use rustc_span::{ExpnKind, SyntaxContext};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -36,6 +36,7 @@ declare_clippy_lint! {
     /// Use instead:
     /// ```rust
     /// struct Thing;
+    ///
     /// impl Clone for Thing {
     ///     fn clone(&self) -> Self { todo!() }
     ///     fn clone_from(&mut self, other: &Self) { todo!() }
@@ -47,7 +48,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.78.0"]
     pub ASSIGNING_CLONES,
-    perf,
+    pedantic,
     "assigning the result of cloning may be inefficient"
 }
 
@@ -67,7 +68,8 @@ impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]);
 impl<'tcx> LateLintPass<'tcx> for AssigningClones {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx Expr<'_>) {
         // Do not fire the lint in macros
-        let expn_data = assign_expr.span().ctxt().outer_expn_data();
+        let ctxt = assign_expr.span().ctxt();
+        let expn_data = ctxt.outer_expn_data();
         match expn_data.kind {
             ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) | ExpnKind::Macro(..) => return,
             ExpnKind::Root => {},
@@ -82,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
         };
 
         if is_ok_to_suggest(cx, lhs, &call, &self.msrv) {
-            suggest(cx, assign_expr, lhs, &call);
+            suggest(cx, ctxt, assign_expr, lhs, &call);
         }
     }
 
@@ -163,9 +165,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
         // TODO: This check currently bails if the local variable has no initializer.
         // That is overly conservative - the lint should fire even if there was no initializer,
         // but the variable has been initialized before `lhs` was evaluated.
-        if let Some(Node::LetStmt(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p))
-            && local.init.is_none()
-        {
+        if !local_is_initialized(cx, local) {
             return false;
         }
     }
@@ -222,14 +222,20 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
     implemented_fns.contains_key(&provided_fn.def_id)
 }
 
-fn suggest<'tcx>(cx: &LateContext<'tcx>, assign_expr: &Expr<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) {
+fn suggest<'tcx>(
+    cx: &LateContext<'tcx>,
+    ctxt: SyntaxContext,
+    assign_expr: &Expr<'tcx>,
+    lhs: &Expr<'tcx>,
+    call: &CallCandidate<'tcx>,
+) {
     span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| {
         let mut applicability = Applicability::Unspecified;
 
         diag.span_suggestion(
             assign_expr.span,
             call.suggestion_msg(),
-            call.suggested_replacement(cx, lhs, &mut applicability),
+            call.suggested_replacement(cx, ctxt, lhs, &mut applicability),
             applicability,
         );
     });
@@ -275,6 +281,7 @@ impl<'tcx> CallCandidate<'tcx> {
     fn suggested_replacement(
         &self,
         cx: &LateContext<'tcx>,
+        ctxt: SyntaxContext,
         lhs: &Expr<'tcx>,
         applicability: &mut Applicability,
     ) -> String {
@@ -294,7 +301,7 @@ impl<'tcx> CallCandidate<'tcx> {
                         // Determine whether we need to reference the argument to clone_from().
                         let clone_receiver_type = cx.typeck_results().expr_ty(receiver);
                         let clone_receiver_adj_type = cx.typeck_results().expr_ty_adjusted(receiver);
-                        let mut arg_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability);
+                        let mut arg_sugg = Sugg::hir_with_context(cx, receiver, ctxt, "_", applicability);
                         if clone_receiver_type != clone_receiver_adj_type {
                             // The receiver may have been a value type, so we need to add an `&` to
                             // be sure the argument to clone_from will be a reference.
@@ -312,7 +319,7 @@ impl<'tcx> CallCandidate<'tcx> {
                             Sugg::hir_with_applicability(cx, lhs, "_", applicability).mut_addr()
                         };
                         // The RHS had to be exactly correct before the call, there is no auto-deref for function calls.
-                        let rhs_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability);
+                        let rhs_sugg = Sugg::hir_with_context(cx, self_arg, ctxt, "_", applicability);
 
                         format!("Clone::clone_from({self_sugg}, {rhs_sugg})")
                     },
@@ -341,11 +348,11 @@ impl<'tcx> CallCandidate<'tcx> {
 
                 match self.kind {
                     CallKind::MethodCall { receiver } => {
-                        let receiver_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability);
+                        let receiver_sugg = Sugg::hir_with_context(cx, receiver, ctxt, "_", applicability);
                         format!("{receiver_sugg}.clone_into({rhs_sugg})")
                     },
                     CallKind::FunctionCall { self_arg, .. } => {
-                        let self_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability);
+                        let self_sugg = Sugg::hir_with_context(cx, self_arg, ctxt, "_", applicability);
                         format!("ToOwned::clone_into({self_sugg}, {rhs_sugg})")
                     },
                 }
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index 736ee48641d..40a1c4e2884 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -36,9 +36,10 @@ fn check_duplicated_attr(
     }
     let Some(ident) = attr.ident() else { return };
     let name = ident.name;
-    if name == sym::doc || name == sym::cfg_attr {
+    if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented {
         // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
         // conditions are the same.
+        // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
         return;
     }
     if let Some(direct_parent) = parent.last()
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index 8f47bc7653b..39f40607799 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -61,11 +61,21 @@ declare_clippy_lint! {
     ///
     /// This lint permits lint attributes for lints emitted on the items themself.
     /// For `use` items these lints are:
+    /// * ambiguous_glob_reexports
+    /// * dead_code
     /// * deprecated
+    /// * hidden_glob_reexports
     /// * unreachable_pub
-    /// * unused_imports
+    /// * unused
+    /// * unused_braces
+    /// * unused_import_braces
+    /// * clippy::disallowed_types
     /// * clippy::enum_glob_use
     /// * clippy::macro_use_imports
+    /// * clippy::module_name_repetitions
+    /// * clippy::redundant_pub_crate
+    /// * clippy::single_component_path_imports
+    /// * clippy::unsafe_removed_from_name
     /// * clippy::wildcard_imports
     ///
     /// For `extern crate` items these lints are:
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index 7575f502a7c..f0868231d01 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -2,6 +2,7 @@ use super::utils::{extract_clippy_lint, is_lint_level, is_word};
 use super::{Attribute, USELESS_ATTRIBUTE};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{first_line_of_span, snippet_opt};
+use rustc_ast::NestedMetaItem;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LintContext};
@@ -20,26 +21,40 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute])
                 for lint in lint_list {
                     match item.kind {
                         ItemKind::Use(..) => {
-                            if is_word(lint, sym::unused_imports)
-                                || is_word(lint, sym::deprecated)
-                                || is_word(lint, sym!(unreachable_pub))
-                                || is_word(lint, sym!(unused))
-                                || is_word(lint, sym!(unused_import_braces))
-                                || extract_clippy_lint(lint).map_or(false, |s| {
-                                    matches!(
-                                        s.as_str(),
-                                        "wildcard_imports"
-                                            | "enum_glob_use"
-                                            | "redundant_pub_crate"
-                                            | "macro_use_imports"
-                                            | "unsafe_removed_from_name"
-                                            | "module_name_repetitions"
-                                            | "single_component_path_imports"
-                                    )
-                                })
+                            if let NestedMetaItem::MetaItem(meta_item) = lint
+                                && meta_item.is_word()
+                                && let Some(ident) = meta_item.ident()
+                                && matches!(
+                                    ident.name.as_str(),
+                                    "ambiguous_glob_reexports"
+                                        | "dead_code"
+                                        | "deprecated"
+                                        | "hidden_glob_reexports"
+                                        | "unreachable_pub"
+                                        | "unused"
+                                        | "unused_braces"
+                                        | "unused_import_braces"
+                                        | "unused_imports"
+                                )
                             {
                                 return;
                             }
+
+                            if extract_clippy_lint(lint).is_some_and(|symbol| {
+                                matches!(
+                                    symbol.as_str(),
+                                    "wildcard_imports"
+                                        | "enum_glob_use"
+                                        | "redundant_pub_crate"
+                                        | "macro_use_imports"
+                                        | "unsafe_removed_from_name"
+                                        | "module_name_repetitions"
+                                        | "single_component_path_imports"
+                                        | "disallowed_types"
+                                )
+                            }) {
+                                return;
+                            }
                         },
                         ItemKind::ExternCrate(..) => {
                             if is_word(lint, sym::unused_imports) && skip_unused_imports {
diff --git a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
index a3291c9da10..0d9eaac882f 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
@@ -49,7 +49,7 @@ impl LintConfig {
 
 type LintTable = BTreeMap<Spanned<String>, Spanned<LintConfig>>;
 
-#[derive(Deserialize, Debug)]
+#[derive(Deserialize, Debug, Default)]
 struct Lints {
     #[serde(default)]
     rust: LintTable,
@@ -57,9 +57,18 @@ struct Lints {
     clippy: LintTable,
 }
 
+#[derive(Deserialize, Debug, Default)]
+struct Workspace {
+    #[serde(default)]
+    lints: Lints,
+}
+
 #[derive(Deserialize, Debug)]
 struct CargoToml {
+    #[serde(default)]
     lints: Lints,
+    #[serde(default)]
+    workspace: Workspace,
 }
 
 #[derive(Default, Debug)]
@@ -164,5 +173,7 @@ pub fn check(cx: &LateContext<'_>) {
 
         check_table(cx, cargo_toml.lints.rust, &rustc_groups, &file);
         check_table(cx, cargo_toml.lints.clippy, &clippy_groups, &file);
+        check_table(cx, cargo_toml.workspace.lints.rust, &rustc_groups, &file);
+        check_table(cx, cargo_toml.workspace.lints.clippy, &clippy_groups, &file);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 2b6e17dc103..864489ee3fc 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -255,8 +255,10 @@ fn expr_add_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign {
 
 /// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`],
 /// where the result depends on:
+///
 /// - the number of negative values in the entire expression, or
 /// - the number of negative values on the left hand side of the expression.
+///
 /// Ignores overflow.
 ///
 ///
@@ -303,8 +305,10 @@ fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> {
 }
 
 /// Peels binary operators such as [`BinOpKind::Add`], where the result depends on:
+///
 /// - all the expressions being positive, or
 /// - all the expressions being negative.
+///
 /// Ignores overflow.
 ///
 /// Expressions using other operators are preserved, so we can try to evaluate them later.
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 5ff7d8e5134..df2ef465700 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -140,6 +140,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::disallowed_names::DISALLOWED_NAMES_INFO,
     crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
     crate::disallowed_types::DISALLOWED_TYPES_INFO,
+    crate::doc::DOC_LAZY_CONTINUATION_INFO,
     crate::doc::DOC_LINK_WITH_QUOTES_INFO,
     crate::doc::DOC_MARKDOWN_INFO,
     crate::doc::EMPTY_DOCS_INFO,
@@ -205,6 +206,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::functions::MUST_USE_CANDIDATE_INFO,
     crate::functions::MUST_USE_UNIT_INFO,
     crate::functions::NOT_UNSAFE_PTR_ARG_DEREF_INFO,
+    crate::functions::RENAMED_FUNCTION_PARAMS_INFO,
     crate::functions::RESULT_LARGE_ERR_INFO,
     crate::functions::RESULT_UNIT_ERR_INFO,
     crate::functions::TOO_MANY_ARGUMENTS_INFO,
@@ -291,9 +293,11 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::loops::SAME_ITEM_PUSH_INFO,
     crate::loops::SINGLE_ELEMENT_LOOP_INFO,
     crate::loops::UNUSED_ENUMERATE_INDEX_INFO,
+    crate::loops::WHILE_FLOAT_INFO,
     crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
     crate::loops::WHILE_LET_LOOP_INFO,
     crate::loops::WHILE_LET_ON_ITERATOR_INFO,
+    crate::macro_metavars_in_unsafe::MACRO_METAVARS_IN_UNSAFE_INFO,
     crate::macro_use::MACRO_USE_IMPORTS_INFO,
     crate::main_recursion::MAIN_RECURSION_INFO,
     crate::manual_assert::MANUAL_ASSERT_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
new file mode 100644
index 00000000000..38bc58a5501
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
@@ -0,0 +1,95 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use itertools::Itertools;
+use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_lint::LateContext;
+use rustc_span::{BytePos, Span};
+use std::ops::Range;
+
+use super::DOC_LAZY_CONTINUATION;
+
+fn map_container_to_text(c: &super::Container) -> &'static str {
+    match c {
+        super::Container::Blockquote => "> ",
+        // numbered list can have up to nine digits, plus the dot, plus four spaces on either side
+        super::Container::List(indent) => &"                  "[0..*indent],
+    }
+}
+
+// TODO: Adjust the parameters as necessary
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    doc: &str,
+    range: Range<usize>,
+    mut span: Span,
+    containers: &[super::Container],
+) {
+    if doc[range.clone()].contains('\t') {
+        // We don't do tab stops correctly.
+        return;
+    }
+
+    let ccount = doc[range.clone()].chars().filter(|c| *c == '>').count();
+    let blockquote_level = containers
+        .iter()
+        .filter(|c| matches!(c, super::Container::Blockquote))
+        .count();
+    let lcount = doc[range.clone()].chars().filter(|c| *c == ' ').count();
+    let list_indentation = containers
+        .iter()
+        .map(|c| {
+            if let super::Container::List(indent) = c {
+                *indent
+            } else {
+                0
+            }
+        })
+        .sum();
+    if ccount < blockquote_level || lcount < list_indentation {
+        let msg = if ccount < blockquote_level {
+            "doc quote missing `>` marker"
+        } else {
+            "doc list item missing indentation"
+        };
+        span_lint_and_then(cx, DOC_LAZY_CONTINUATION, span, msg, |diag| {
+            if ccount == 0 && blockquote_level == 0 {
+                // simpler suggestion style for indentation
+                let indent = list_indentation - lcount;
+                diag.span_suggestion_with_style(
+                    span.shrink_to_hi(),
+                    "indent this line",
+                    std::iter::repeat(" ").take(indent).join(""),
+                    Applicability::MaybeIncorrect,
+                    SuggestionStyle::ShowAlways,
+                );
+                diag.help("if this is supposed to be its own paragraph, add a blank line");
+                return;
+            }
+            let mut doc_start_range = &doc[range];
+            let mut suggested = String::new();
+            for c in containers {
+                let text = map_container_to_text(c);
+                if doc_start_range.starts_with(text) {
+                    doc_start_range = &doc_start_range[text.len()..];
+                    span = span
+                        .with_lo(span.lo() + BytePos(u32::try_from(text.len()).expect("text is not 2**32 or bigger")));
+                } else if matches!(c, super::Container::Blockquote)
+                    && let Some(i) = doc_start_range.find('>')
+                {
+                    doc_start_range = &doc_start_range[i + 1..];
+                    span =
+                        span.with_lo(span.lo() + BytePos(u32::try_from(i).expect("text is not 2**32 or bigger") + 1));
+                } else {
+                    suggested.push_str(text);
+                }
+            }
+            diag.span_suggestion_with_style(
+                span,
+                "add markers to start of line",
+                suggested,
+                Applicability::MachineApplicable,
+                SuggestionStyle::ShowAlways,
+            );
+            diag.help("if this not intended to be a quote at all, escape it with `\\>`");
+        });
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index 36ba19698c7..010fab803d9 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -1,3 +1,4 @@
+use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{is_doc_hidden, return_ty};
@@ -6,15 +7,13 @@ use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::{sym, Span};
 
-use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC};
-
 pub fn check(
     cx: &LateContext<'_>,
     owner_id: OwnerId,
     sig: FnSig<'_>,
     headers: DocHeaders,
     body_id: Option<BodyId>,
-    panic_span: Option<Span>,
+    panic_info: Option<(Span, bool)>,
     check_private_items: bool,
 ) {
     if !check_private_items && !cx.effective_visibilities.is_exported(owner_id.def_id) {
@@ -48,13 +47,13 @@ pub fn check(
         ),
         _ => (),
     }
-    if !headers.panics && panic_span.is_some() {
+    if !headers.panics && panic_info.map_or(false, |el| !el.1) {
         span_lint_and_note(
             cx,
             MISSING_PANICS_DOC,
             span,
             "docs for function which may panic missing `# Panics` section",
-            panic_span,
+            panic_info.map(|el| el.0),
             "first possible panic found here",
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 7fdb582e640..9f08973948a 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -1,13 +1,14 @@
+mod lazy_continuation;
 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};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::Visitable;
-use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
+use clippy_utils::{in_constant, is_entrypoint_fn, is_trait_impl_item, method_chain_args};
 use pulldown_cmark::Event::{
     Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
 };
-use pulldown_cmark::Tag::{BlockQuote, CodeBlock, Heading, Item, Link, Paragraph};
+use pulldown_cmark::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, Item, Link, Paragraph};
 use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
 use rustc_ast::ast::Attribute;
 use rustc_data_structures::fx::FxHashSet;
@@ -362,6 +363,63 @@ declare_clippy_lint! {
     "docstrings exist but documentation is empty"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// In CommonMark Markdown, the language used to write doc comments, a
+    /// paragraph nested within a list or block quote does not need any line
+    /// after the first one to be indented or marked. The specification calls
+    /// this a "lazy paragraph continuation."
+    ///
+    /// ### Why is this bad?
+    ///
+    /// This is easy to write but hard to read. Lazy continuations makes
+    /// unintended markers hard to see, and make it harder to deduce the
+    /// document's intended structure.
+    ///
+    /// ### Example
+    ///
+    /// This table is probably intended to have two rows,
+    /// but it does not. It has zero rows, and is followed by
+    /// a block quote.
+    /// ```no_run
+    /// /// Range | Description
+    /// /// ----- | -----------
+    /// /// >= 1  | fully opaque
+    /// /// < 1   | partially see-through
+    /// fn set_opacity(opacity: f32) {}
+    /// ```
+    ///
+    /// Fix it by escaping the marker:
+    /// ```no_run
+    /// /// Range | Description
+    /// /// ----- | -----------
+    /// /// \>= 1 | fully opaque
+    /// /// < 1   | partially see-through
+    /// fn set_opacity(opacity: f32) {}
+    /// ```
+    ///
+    /// This example is actually intended to be a list:
+    /// ```no_run
+    /// /// * Do nothing.
+    /// /// * Then do something. Whatever it is needs done,
+    /// /// it should be done right now.
+    /// # fn do_stuff() {}
+    /// ```
+    ///
+    /// Fix it by indenting the list contents:
+    /// ```no_run
+    /// /// * Do nothing.
+    /// /// * Then do something. Whatever it is needs done,
+    /// ///   it should be done right now.
+    /// # fn do_stuff() {}
+    /// ```
+    #[clippy::version = "1.80.0"]
+    pub DOC_LAZY_CONTINUATION,
+    style,
+    "require every line of a paragraph to be indented and marked"
+}
+
 #[derive(Clone)]
 pub struct Documentation {
     valid_idents: FxHashSet<String>,
@@ -388,6 +446,7 @@ impl_lint_pass!(Documentation => [
     UNNECESSARY_SAFETY_DOC,
     SUSPICIOUS_DOC_COMMENTS,
     EMPTY_DOCS,
+    DOC_LAZY_CONTINUATION,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Documentation {
@@ -402,14 +461,14 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                     if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
                         let body = cx.tcx.hir().body(body_id);
 
-                        let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
+                        let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
                         missing_headers::check(
                             cx,
                             item.owner_id,
                             sig,
                             headers,
                             Some(body_id),
-                            panic_span,
+                            panic_info,
                             self.check_private_items,
                         );
                     }
@@ -551,6 +610,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
         cx,
         valid_idents,
         parser.into_offset_iter(),
+        &doc,
         Fragments {
             fragments: &fragments,
             doc: &doc,
@@ -560,6 +620,11 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
 
 const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"];
 
+enum Container {
+    Blockquote,
+    List(usize),
+}
+
 /// Checks parsed documentation.
 /// This walks the "events" (think sections of markdown) produced by `pulldown_cmark`,
 /// so lints here will generally access that information.
@@ -569,6 +634,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     cx: &LateContext<'_>,
     valid_idents: &FxHashSet<String>,
     events: Events,
+    doc: &str,
     fragments: Fragments<'_>,
 ) -> DocHeaders {
     // true if a safety header was found
@@ -576,6 +642,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut in_code = false;
     let mut in_link = None;
     let mut in_heading = false;
+    let mut in_footnote_definition = false;
     let mut is_rust = false;
     let mut no_test = false;
     let mut ignore = false;
@@ -586,7 +653,11 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut code_level = 0;
     let mut blockquote_level = 0;
 
-    for (event, range) in events {
+    let mut containers = Vec::new();
+
+    let mut events = events.peekable();
+
+    while let Some((event, range)) = events.next() {
         match event {
             Html(tag) => {
                 if tag.starts_with("<code") {
@@ -599,8 +670,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     blockquote_level -= 1;
                 }
             },
-            Start(BlockQuote) => blockquote_level += 1,
-            End(BlockQuote) => blockquote_level -= 1,
+            Start(BlockQuote) => {
+                blockquote_level += 1;
+                containers.push(Container::Blockquote);
+            },
+            End(BlockQuote) => {
+                blockquote_level -= 1;
+                containers.pop();
+            },
             Start(CodeBlock(ref kind)) => {
                 in_code = true;
                 if let CodeBlockKind::Fenced(lang) = kind {
@@ -633,6 +710,13 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 if let Start(Heading(_, _, _)) = event {
                     in_heading = true;
                 }
+                if let Start(Item) = event {
+                    if let Some((_next_event, next_range)) = events.peek() {
+                        containers.push(Container::List(next_range.start - range.start));
+                    } else {
+                        containers.push(Container::List(0));
+                    }
+                }
                 ticks_unbalanced = false;
                 paragraph_range = range;
             },
@@ -640,6 +724,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 if let End(Heading(_, _, _)) = event {
                     in_heading = false;
                 }
+                if let End(Item) = event {
+                    containers.pop();
+                }
                 if ticks_unbalanced && let Some(span) = fragments.span(cx, paragraph_range.clone()) {
                     span_lint_and_help(
                         cx,
@@ -658,8 +745,27 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 }
                 text_to_check = Vec::new();
             },
+            Start(FootnoteDefinition(..)) => in_footnote_definition = true,
+            End(FootnoteDefinition(..)) => in_footnote_definition = false,
             Start(_tag) | End(_tag) => (), // We don't care about other tags
-            SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (),
+            SoftBreak | HardBreak => {
+                if !containers.is_empty()
+                    && let Some((next_event, next_range)) = events.peek()
+                    && let Some(next_span) = fragments.span(cx, next_range.clone())
+                    && let Some(span) = fragments.span(cx, range.clone())
+                    && !in_footnote_definition
+                    && !matches!(next_event, End(_))
+                {
+                    lazy_continuation::check(
+                        cx,
+                        doc,
+                        range.end..next_range.start,
+                        Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
+                        &containers[..],
+                    );
+                }
+            },
+            TaskListMarker(_) | Code(_) | Rule => (),
             FootnoteReference(text) | Text(text) => {
                 paragraph_range.end = range.end;
                 ticks_unbalanced |= text.contains('`') && !in_code;
@@ -701,6 +807,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
 
 struct FindPanicUnwrap<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
+    is_const: bool,
     panic_span: Option<Span>,
     typeck_results: &'tcx ty::TypeckResults<'tcx>,
 }
@@ -710,14 +817,15 @@ impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> {
         cx: &'a LateContext<'tcx>,
         typeck_results: &'tcx ty::TypeckResults<'tcx>,
         body: impl Visitable<'tcx>,
-    ) -> Option<Span> {
+    ) -> Option<(Span, bool)> {
         let mut vis = Self {
             cx,
+            is_const: false,
             panic_span: None,
             typeck_results,
         };
         body.visit(&mut vis);
-        vis.panic_span
+        vis.panic_span.map(|el| (el, vis.is_const))
     }
 }
 
@@ -736,6 +844,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
                     "assert" | "assert_eq" | "assert_ne"
                 )
             {
+                self.is_const = in_constant(self.cx, expr.hir_id);
                 self.panic_span = Some(macro_call.span);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 6715de52649..8d6e27700d8 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -104,7 +104,9 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
             too_large_for_stack: self.too_large_for_stack,
         };
 
-        ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v).consume_body(body).into_ok();
+        ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v)
+            .consume_body(body)
+            .into_ok();
 
         for node in v.set {
             span_lint_hir(
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index 724e1843359..3c4a043a732 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{find_format_args, format_args_inputs_span};
+use clippy_utils::macros::{format_args_inputs_span, FormatArgsStorage};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_expn_of, path_def_id};
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{BindingMode, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
 use rustc_span::{sym, ExpnId};
 
 declare_clippy_lint! {
@@ -38,7 +38,17 @@ declare_clippy_lint! {
     "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work"
 }
 
-declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]);
+pub struct ExplicitWrite {
+    format_args: FormatArgsStorage,
+}
+
+impl ExplicitWrite {
+    pub fn new(format_args: FormatArgsStorage) -> Self {
+        Self { format_args }
+    }
+}
+
+impl_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]);
 
 impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
@@ -57,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                 Some(sym::io_stderr) => ("stderr", "e"),
                 _ => return,
             };
-            let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else {
+            let Some(format_args) = self.format_args.get(cx, write_arg, ExpnId::root()) else {
                 return;
             };
 
@@ -83,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
             };
             let mut applicability = Applicability::MachineApplicable;
             let inputs_snippet =
-                snippet_with_applicability(cx, format_args_inputs_span(&format_args), "..", &mut applicability);
+                snippet_with_applicability(cx, format_args_inputs_span(format_args), "..", &mut applicability);
             span_lint_and_sugg(
                 cx,
                 EXPLICIT_WRITE,
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index 8a0cd155d21..0b248f784b7 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node};
+use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
 use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
 use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
@@ -39,13 +39,24 @@ declare_clippy_lint! {
     "useless use of `format!`"
 }
 
-declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
+#[allow(clippy::module_name_repetitions)]
+pub struct UselessFormat {
+    format_args: FormatArgsStorage,
+}
+
+impl UselessFormat {
+    pub fn new(format_args: FormatArgsStorage) -> Self {
+        Self { format_args }
+    }
+}
+
+impl_lint_pass!(UselessFormat => [USELESS_FORMAT]);
 
 impl<'tcx> LateLintPass<'tcx> for UselessFormat {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if let Some(macro_call) = root_macro_call_first_node(cx, expr)
             && cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id)
-            && let Some(format_args) = find_format_args(cx, expr, macro_call.expn)
+            && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn)
         {
             let mut applicability = Applicability::MachineApplicable;
             let call_site = macro_call.span;
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 003a9995c15..86115807aa4 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -3,8 +3,8 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::is_diag_trait_item;
 use clippy_utils::macros::{
-    find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro,
-    is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, FormatParamUsage, MacroCall,
+    find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
+    is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
 };
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{implements_trait, is_type_lang_item};
@@ -167,15 +167,18 @@ impl_lint_pass!(FormatArgs => [
     UNUSED_FORMAT_SPECS,
 ]);
 
+#[allow(clippy::struct_field_names)]
 pub struct FormatArgs {
+    format_args: FormatArgsStorage,
     msrv: Msrv,
     ignore_mixed: bool,
 }
 
 impl FormatArgs {
     #[must_use]
-    pub fn new(msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self {
+    pub fn new(format_args: FormatArgsStorage, msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self {
         Self {
+            format_args,
             msrv,
             ignore_mixed: allow_mixed_uninlined_format_args,
         }
@@ -186,13 +189,13 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let Some(macro_call) = root_macro_call_first_node(cx, expr)
             && is_format_macro(cx, macro_call.def_id)
-            && let Some(format_args) = find_format_args(cx, expr, macro_call.expn)
+            && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn)
         {
             let linter = FormatArgsExpr {
                 cx,
                 expr,
                 macro_call: &macro_call,
-                format_args: &format_args,
+                format_args,
                 ignore_mixed: self.ignore_mixed,
             };
 
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index 0a52347940a..09be7237b5c 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node};
+use clippy_utils::macros::{find_format_arg_expr, is_format_macro, root_macro_call_first_node, FormatArgsStorage};
 use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
 use rustc_ast::{FormatArgsPiece, FormatTrait};
 use rustc_errors::Applicability;
@@ -99,13 +99,15 @@ struct FormatTraitNames {
 
 #[derive(Default)]
 pub struct FormatImpl {
+    format_args: FormatArgsStorage,
     // Whether we are inside Display or Debug trait impl - None for neither
     format_trait_impl: Option<FormatTraitNames>,
 }
 
 impl FormatImpl {
-    pub fn new() -> Self {
+    pub fn new(format_args: FormatArgsStorage) -> Self {
         Self {
+            format_args,
             format_trait_impl: None,
         }
     }
@@ -129,6 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl {
         if let Some(format_trait_impl) = self.format_trait_impl {
             let linter = FormatImplExpr {
                 cx,
+                format_args: &self.format_args,
                 expr,
                 format_trait_impl,
             };
@@ -141,6 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl {
 
 struct FormatImplExpr<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
+    format_args: &'a FormatArgsStorage,
     expr: &'tcx Expr<'tcx>,
     format_trait_impl: FormatTraitNames,
 }
@@ -175,7 +179,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
         if let Some(outer_macro) = root_macro_call_first_node(self.cx, self.expr)
             && let macro_def_id = outer_macro.def_id
             && is_format_macro(self.cx, macro_def_id)
-            && let Some(format_args) = find_format_args(self.cx, self.expr, outer_macro.expn)
+            && let Some(format_args) = self.format_args.get(self.cx, self.expr, outer_macro.expn)
         {
             for piece in &format_args.template {
                 if let FormatArgsPiece::Placeholder(placeholder) = piece
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 633ed96d6a6..82ce501bac5 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_integer_literal;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
+use clippy_utils::{in_constant, is_integer_literal};
 use rustc_errors::Applicability;
 use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -47,6 +47,9 @@ 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 first part of the path is some integer primitive
             && let TyKind::Path(ty_qpath) = &ty.kind
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 9cc51fa8cd5..dfcaac9abef 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -2,15 +2,17 @@ mod impl_trait_in_params;
 mod misnamed_getters;
 mod must_use;
 mod not_unsafe_ptr_arg_deref;
+mod renamed_function_params;
 mod result;
 mod too_many_arguments;
 mod too_many_lines;
 
+use clippy_utils::def_path_def_ids;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{DefIdSet, LocalDefId};
 use rustc_span::Span;
 
 declare_clippy_lint! {
@@ -359,13 +361,51 @@ declare_clippy_lint! {
     "`impl Trait` is used in the function's parameters"
 }
 
-#[derive(Copy, Clone)]
-#[allow(clippy::struct_field_names)]
+declare_clippy_lint! {
+    /// ### What it does
+    /// Lints when the name of function parameters from trait impl is
+    /// different than its default implementation.
+    ///
+    /// ### Why is this bad?
+    /// Using the default name for parameters of a trait method is often
+    /// more desirable for consistency's sake.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct A(u32);
+    ///
+    /// impl PartialEq for A {
+    ///     fn eq(&self, b: &Self) -> bool {
+    ///         self.0 == b.0
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct A(u32);
+    ///
+    /// impl PartialEq for A {
+    ///     fn eq(&self, other: &Self) -> bool {
+    ///         self.0 == other.0
+    ///     }
+    /// }
+    /// ```
+    #[clippy::version = "1.74.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 {
@@ -374,12 +414,15 @@ impl Functions {
         too_many_lines_threshold: u64,
         large_error_threshold: u64,
         avoid_breaking_exported_api: bool,
+        allow_renamed_params_for: Vec<String>,
     ) -> 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(),
         }
     }
 }
@@ -395,6 +438,7 @@ impl_lint_pass!(Functions => [
     RESULT_LARGE_ERR,
     MISNAMED_GETTERS,
     IMPL_TRAIT_IN_PARAMS,
+    RENAMED_FUNCTION_PARAMS,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Functions {
@@ -424,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
         must_use::check_impl_item(cx, item);
         result::check_impl_item(cx, item, self.large_error_threshold);
         impl_trait_in_params::check_impl_item(cx, item);
+        renamed_function_params::check_impl_item(cx, item, &self.trait_ids);
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
@@ -433,4 +478,12 @@ 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/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
new file mode 100644
index 00000000000..c7de0385c02
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
@@ -0,0 +1,110 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_errors::{Applicability, MultiSpan};
+use rustc_hir::def_id::{DefId, DefIdSet};
+use rustc_hir::hir_id::OwnerId;
+use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef};
+use rustc_lint::LateContext;
+use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::Span;
+
+use super::RENAMED_FUNCTION_PARAMS;
+
+pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored_traits: &DefIdSet) {
+    if !item.span.from_expansion()
+        && let ImplItemKind::Fn(_, body_id) = item.kind
+        && let parent_node = cx.tcx.parent_hir_node(item.hir_id())
+        && let Node::Item(parent_item) = parent_node
+        && let ItemKind::Impl(Impl {
+            items,
+            of_trait: Some(trait_ref),
+            ..
+        }) = &parent_item.kind
+        && let Some(did) = trait_item_def_id_of_impl(items, item.owner_id)
+        && !is_from_ignored_trait(trait_ref, ignored_traits)
+    {
+        let mut param_idents_iter = cx.tcx.hir().body_param_names(body_id);
+        let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied();
+
+        let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter);
+        if !renames.0.is_empty() {
+            let multi_span = renames.multi_span();
+            let plural = if renames.0.len() == 1 { "" } else { "s" };
+            span_lint_and_then(
+                cx,
+                RENAMED_FUNCTION_PARAMS,
+                multi_span,
+                format!("renamed function parameter{plural} of trait impl"),
+                |diag| {
+                    diag.multipart_suggestion(
+                        format!("consider using the default name{plural}"),
+                        renames.0,
+                        Applicability::Unspecified,
+                    );
+                },
+            );
+        }
+    }
+}
+
+struct RenamedFnArgs(Vec<(Span, String)>);
+
+impl RenamedFnArgs {
+    /// Comparing between an iterator of default names and one with current names,
+    /// then collect the ones that got renamed.
+    fn new<I, T>(default_names: &mut I, current_names: &mut T) -> Self
+    where
+        I: Iterator<Item = Ident>,
+        T: Iterator<Item = Ident>,
+    {
+        let mut renamed: Vec<(Span, String)> = vec![];
+
+        debug_assert!(default_names.size_hint() == current_names.size_hint());
+        while let (Some(def_name), Some(cur_name)) = (default_names.next(), current_names.next()) {
+            let current_name = cur_name.name;
+            let default_name = def_name.name;
+            if is_unused_or_empty_symbol(current_name) || is_unused_or_empty_symbol(default_name) {
+                continue;
+            }
+            if current_name != default_name {
+                renamed.push((cur_name.span, default_name.to_string()));
+            }
+        }
+
+        Self(renamed)
+    }
+
+    fn multi_span(&self) -> MultiSpan {
+        self.0
+            .iter()
+            .map(|(span, _)| span)
+            .copied()
+            .collect::<Vec<Span>>()
+            .into()
+    }
+}
+
+fn is_unused_or_empty_symbol(symbol: Symbol) -> bool {
+    // FIXME: `body_param_names` currently returning empty symbols for `wild` as well,
+    // so we need to check if the symbol is empty first.
+    // Therefore the check of whether it's equal to [`kw::Underscore`] has no use for now,
+    // but it would be nice to keep it here just to be future-proof.
+    symbol.is_empty() || symbol == kw::Underscore || symbol.as_str().starts_with('_')
+}
+
+/// Get the [`trait_item_def_id`](ImplItemRef::trait_item_def_id) of a relevant impl item.
+fn trait_item_def_id_of_impl(items: &[ImplItemRef], target: OwnerId) -> Option<DefId> {
+    items.iter().find_map(|item| {
+        if item.id.owner_id == target {
+            item.trait_item_def_id
+        } else {
+            None
+        }
+    })
+}
+
+fn is_from_ignored_trait(of_trait: &TraitRef<'_>, ignored_traits: &DefIdSet) -> bool {
+    let Some(trait_did) = of_trait.trait_def_id() else {
+        return false;
+    };
+    ignored_traits.contains(&trait_did)
+}
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 2c2daac0234..192fb611c2d 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,8 +4,8 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
 use rustc_middle::ty::print::PrintTraitRefExt;
+use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index a8bfbbdd9ec..3328d642bd8 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -61,11 +61,6 @@ extern crate clippy_utils;
 #[macro_use]
 extern crate declare_clippy_lint;
 
-use std::collections::BTreeMap;
-
-use rustc_data_structures::fx::FxHashSet;
-use rustc_lint::{Lint, LintId};
-
 #[cfg(feature = "internal")]
 pub mod deprecated_lints;
 #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
@@ -199,6 +194,7 @@ mod lifetimes;
 mod lines_filter_map_ok;
 mod literal_representation;
 mod loops;
+mod macro_metavars_in_unsafe;
 mod macro_use;
 mod main_recursion;
 mod manual_assert;
@@ -385,6 +381,10 @@ mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
 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
 ///
@@ -533,6 +533,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         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,
@@ -597,9 +598,11 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         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();
 
@@ -616,6 +619,14 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         }
     }
 
+    let format_args_storage = FormatArgsStorage::default();
+    let format_args = format_args_storage.clone();
+    store.register_early_pass(move || {
+        Box::new(utils::format_args_collector::FormatArgsCollector::new(
+            format_args.clone(),
+        ))
+    });
+
     // all the internal lints
     #[cfg(feature = "internal")]
     {
@@ -656,7 +667,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
                 .collect(),
         ))
     });
-    store.register_early_pass(|| Box::<utils::format_args_collector::FormatArgsCollector>::default());
     store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
     store.register_late_pass(|_| Box::new(utils::author::Author));
     store.register_late_pass(move |_| {
@@ -698,6 +708,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     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())));
+    let format_args = format_args_storage.clone();
     store.register_late_pass(move |_| {
         Box::new(methods::Methods::new(
             avoid_breaking_exported_api,
@@ -705,6 +716,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             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())));
@@ -759,7 +771,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             allow_in_test: allow_useless_vec_in_tests,
         })
     });
-    store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
+    store.register_late_pass(move |_| Box::new(panic_unimplemented::PanicUnimplemented { allow_panic_in_tests }));
     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())));
@@ -769,7 +781,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     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(|_| Box::new(copy_iterator::CopyIterator));
-    store.register_late_pass(|_| Box::new(format::UselessFormat));
+    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(overflow_check_conditional::OverflowCheckConditional));
     store.register_late_pass(|_| Box::<new_without_default::NewWithoutDefault>::default());
@@ -780,6 +793,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             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)));
@@ -793,7 +807,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     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(|_| Box::new(explicit_write::ExplicitWrite));
+    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(
@@ -835,7 +850,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
     store.register_early_pass(|| Box::new(reference::DerefAddrOf));
     store.register_early_pass(|| Box::new(double_parens::DoubleParens));
-    store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new()));
+    let format_args = format_args_storage.clone();
+    store.register_late_pass(move |_| Box::new(format_impl::FormatImpl::new(format_args.clone())));
     store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
     store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
     store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
@@ -961,8 +977,14 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             accept_comment_above_attributes,
         ))
     });
-    store
-        .register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined_format_args)));
+    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(|_| 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));
@@ -973,7 +995,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static 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(write::Write::new(allow_print_in_tests)));
+    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,
@@ -1136,6 +1159,12 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static 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()
+        })
+    });
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index b5e39b33c6a..3dcb050d77e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -17,6 +17,7 @@ mod same_item_push;
 mod single_element_loop;
 mod unused_enumerate_index;
 mod utils;
+mod while_float;
 mod while_immutable_condition;
 mod while_let_loop;
 mod while_let_on_iterator;
@@ -418,6 +419,39 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for while loops comparing floating point values.
+    ///
+    /// ### Why is this bad?
+    /// If you increment floating point values, errors can compound,
+    /// so, use integers instead if possible.
+    ///
+    /// ### Known problems
+    /// The lint will catch all while loops comparing floating point
+    /// values without regarding the increment.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let mut x = 0.0;
+    /// while x < 42.0 {
+    ///     x += 1.0;
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// let mut x = 0;
+    /// while x < 42 {
+    ///     x += 1;
+    /// }
+    /// ```
+    #[clippy::version = "1.80.0"]
+    pub WHILE_FLOAT,
+    nursery,
+    "while loops comaparing floating point values"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks whether a for loop is being used to push a constant
     /// value into a Vec.
     ///
@@ -706,6 +740,7 @@ impl_lint_pass!(Loops => [
     NEVER_LOOP,
     MUT_RANGE_BOUND,
     WHILE_IMMUTABLE_CONDITION,
+    WHILE_FLOAT,
     SAME_ITEM_PUSH,
     SINGLE_ELEMENT_LOOP,
     MISSING_SPIN_LOOP,
@@ -762,6 +797,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
 
         if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) {
             while_immutable_condition::check(cx, condition, body);
+            while_float::check(cx, condition);
             missing_spin_loop::check(cx, condition, body);
             manual_while_let_some::check(cx, condition, body, span);
         }
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 6b9ecf5f141..6c6a9a1a2e0 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
@@ -60,12 +60,9 @@ fn check_for_mutation(
         span_low: None,
         span_high: None,
     };
-    ExprUseVisitor::for_clippy(
-        cx,
-        body.hir_id.owner.def_id,
-        &mut delegate,
-    )
-    .walk_expr(body).into_ok();
+    ExprUseVisitor::for_clippy(cx, body.hir_id.owner.def_id, &mut delegate)
+        .walk_expr(body)
+        .into_ok();
 
     delegate.mutation_span()
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_float.rs b/src/tools/clippy/clippy_lints/src/loops/while_float.rs
new file mode 100644
index 00000000000..cf62ce29f0c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/loops/while_float.rs
@@ -0,0 +1,20 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_hir::ExprKind;
+
+pub(super) fn check(cx: &rustc_lint::LateContext<'_>, condition: &rustc_hir::Expr<'_>) {
+    if let ExprKind::Binary(_op, left, right) = condition.kind
+        && is_float_type(cx, left)
+        && is_float_type(cx, right)
+    {
+        span_lint(
+            cx,
+            super::WHILE_FLOAT,
+            condition.span,
+            "while condition comparing floats",
+        );
+    }
+}
+
+fn is_float_type(cx: &rustc_lint::LateContext<'_>, expr: &rustc_hir::Expr<'_>) -> bool {
+    cx.typeck_results().expr_ty(expr).is_floating_point()
+}
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
new file mode 100644
index 00000000000..aea3d26e187
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -0,0 +1,256 @@
+use std::collections::btree_map::Entry;
+use std::collections::BTreeMap;
+
+use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::is_lint_allowed;
+use itertools::Itertools;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
+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};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Looks for macros that expand metavariables in an unsafe block.
+    ///
+    /// ### Why is this bad?
+    /// This hides an unsafe block and allows the user of the macro to write unsafe code without an explicit
+    /// unsafe block at callsite, making it possible to perform unsafe operations in seemingly safe code.
+    ///
+    /// The macro should be restructured so that these metavariables are referenced outside of unsafe blocks
+    /// and that the usual unsafety checks apply to the macro argument.
+    ///
+    /// This is usually done by binding it to a variable outside of the unsafe block
+    /// and then using that variable inside of the block as shown in the example, or by referencing it a second time
+    /// in a safe context, e.g. `if false { $expr }`.
+    ///
+    /// ### Known limitations
+    /// Due to how macros are represented in the compiler at the time Clippy runs its lints,
+    /// it's not possible to look for metavariables in macro definitions directly.
+    ///
+    /// Instead, this lint looks at expansions of macros.
+    /// This leads to false negatives for macros that are never actually invoked.
+    ///
+    /// By default, this lint is rather conservative and will only emit warnings on publicly-exported
+    /// macros from the same crate, because oftentimes private internal macros are one-off macros where
+    /// this lint would just be noise (e.g. macros that generate `impl` blocks).
+    /// The default behavior should help with preventing a high number of such false positives,
+    /// however it can be configured to also emit warnings in private macros if desired.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// /// Gets the first element of a slice
+    /// macro_rules! first {
+    ///     ($slice:expr) => {
+    ///         unsafe {
+    ///             let slice = $slice; // ⚠️ expansion inside of `unsafe {}`
+    ///
+    ///             assert!(!slice.is_empty());
+    ///             // SAFETY: slice is checked to have at least one element
+    ///             slice.first().unwrap_unchecked()
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(*first!(&[1i32]), 1);
+    ///
+    /// // This will compile as a consequence (note the lack of `unsafe {}`)
+    /// assert_eq!(*first!(std::hint::unreachable_unchecked() as &[i32]), 1);
+    /// ```
+    /// Use instead:
+    /// ```compile_fail
+    /// macro_rules! first {
+    ///     ($slice:expr) => {{
+    ///         let slice = $slice; // ✅ outside of `unsafe {}`
+    ///         unsafe {
+    ///             assert!(!slice.is_empty());
+    ///             // SAFETY: slice is checked to have at least one element
+    ///             slice.first().unwrap_unchecked()
+    ///         }
+    ///     }}
+    /// }
+    ///
+    /// assert_eq!(*first!(&[1]), 1);
+    ///
+    /// // This won't compile:
+    /// assert_eq!(*first!(std::hint::unreachable_unchecked() as &[i32]), 1);
+    /// ```
+    #[clippy::version = "1.80.0"]
+    pub MACRO_METAVARS_IN_UNSAFE,
+    suspicious,
+    "expanding macro metavariables in an unsafe block"
+}
+impl_lint_pass!(ExprMetavarsInUnsafe => [MACRO_METAVARS_IN_UNSAFE]);
+
+#[derive(Clone, Debug)]
+pub enum MetavarState {
+    ReferencedInUnsafe { unsafe_blocks: Vec<HirId> },
+    ReferencedInSafe,
+}
+
+#[derive(Default)]
+pub struct ExprMetavarsInUnsafe {
+    pub 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:
+    ///
+    /// ```ignore
+    /// macro_rules! x {
+    ///     ($v:expr) => {
+    ///         unsafe { $v; } // unsafe context, it might be possible to emit a warning here, so add it to the map
+    ///
+    ///         $v;            // `$v` expanded another time but in a safe context, set to ReferencedInSafe to suppress
+    ///     }
+    /// }
+    /// ```
+    pub metavar_expns: BTreeMap<Span, MetavarState>,
+}
+
+struct BodyVisitor<'a, 'tcx> {
+    /// Stack of unsafe blocks -- the top item always represents the last seen unsafe block from
+    /// within a relevant macro.
+    macro_unsafe_blocks: Vec<HirId>,
+    /// When this is >0, it means that the node currently being visited is "within" a
+    /// macro definition. This is not necessary for correctness, it merely helps reduce the number
+    /// of spans we need to insert into the map, since only spans from macros are relevant.
+    expn_depth: u32,
+    cx: &'a LateContext<'tcx>,
+    lint: &'a mut ExprMetavarsInUnsafe,
+}
+
+fn is_public_macro(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
+    (cx.effective_visibilities.is_exported(def_id) || cx.tcx.has_attr(def_id, sym::macro_export))
+        && !cx.tcx.is_doc_hidden(def_id)
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> {
+    fn visit_stmt(&mut self, s: &'tcx Stmt<'tcx>) {
+        let from_expn = s.span.from_expansion();
+        if from_expn {
+            self.expn_depth += 1;
+        }
+        walk_stmt(self, s);
+        if from_expn {
+            self.expn_depth -= 1;
+        }
+    }
+
+    fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+        let ctxt = e.span.ctxt();
+
+        if let ExprKind::Block(block, _) = e.kind
+            && let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules
+            && !ctxt.is_root()
+            && let Some(macro_def_id) = ctxt.outer_expn_data().macro_def_id
+            && let Some(macro_def_id) = macro_def_id.as_local()
+            && (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id))
+        {
+            self.macro_unsafe_blocks.push(block.hir_id);
+            walk_block(self, block);
+            self.macro_unsafe_blocks.pop();
+        } else if ctxt.is_root() && self.expn_depth > 0 {
+            let unsafe_block = self.macro_unsafe_blocks.last().copied();
+
+            match (self.lint.metavar_expns.entry(e.span), unsafe_block) {
+                (Entry::Vacant(e), None) => {
+                    e.insert(MetavarState::ReferencedInSafe);
+                },
+                (Entry::Vacant(e), Some(unsafe_block)) => {
+                    e.insert(MetavarState::ReferencedInUnsafe {
+                        unsafe_blocks: vec![unsafe_block],
+                    });
+                },
+                (Entry::Occupied(mut e), None) => {
+                    if let MetavarState::ReferencedInUnsafe { .. } = *e.get() {
+                        e.insert(MetavarState::ReferencedInSafe);
+                    }
+                },
+                (Entry::Occupied(mut e), Some(unsafe_block)) => {
+                    if let MetavarState::ReferencedInUnsafe { unsafe_blocks } = e.get_mut()
+                        && !unsafe_blocks.contains(&unsafe_block)
+                    {
+                        unsafe_blocks.push(unsafe_block);
+                    }
+                },
+            }
+
+            // NB: No need to visit descendant nodes. They're guaranteed to represent the same
+            // metavariable
+        } else {
+            walk_expr(self, e);
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe {
+    fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx rustc_hir::Body<'tcx>) {
+        if is_lint_allowed(cx, MACRO_METAVARS_IN_UNSAFE, body.value.hir_id) {
+            return;
+        }
+
+        // This BodyVisitor is separate and not part of the lint pass because there is no
+        // `check_stmt_post` on `(Late)LintPass`, which we'd need to detect when we're leaving a macro span
+
+        let mut vis = BodyVisitor {
+            #[expect(clippy::bool_to_int_with_if)] // obfuscates the meaning
+            expn_depth: if body.value.span.from_expansion() { 1 } else { 0 },
+            macro_unsafe_blocks: Vec::new(),
+            lint: self,
+            cx
+        };
+        vis.visit_body(body);
+    }
+
+    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
+        // Aggregate all unsafe blocks from all spans:
+        // ```
+        // macro_rules! x {
+        //   ($w:expr, $x:expr, $y:expr) => { $w; unsafe { $w; $x; }; unsafe { $x; $y; }; }
+        // }
+        // $w: []  (unsafe#0 is never added because it was referenced in a safe context)
+        // $x: [unsafe#0, unsafe#1]
+        // $y: [unsafe#1]
+        // ```
+        // We want to lint unsafe blocks #0 and #1
+        let bad_unsafe_blocks = self
+            .metavar_expns
+            .iter()
+            .filter_map(|(_, state)| match state {
+                MetavarState::ReferencedInUnsafe { unsafe_blocks } => Some(unsafe_blocks.as_slice()),
+                MetavarState::ReferencedInSafe => None,
+            })
+            .flatten()
+            .copied()
+            .map(|id| {
+                // Remove the syntax context to hide "in this macro invocation" in the diagnostic.
+                // The invocation doesn't matter. Also we want to dedupe by the unsafe block and not by anything
+                // related to the callsite.
+                let span = cx.tcx.hir().span(id);
+
+                (id, Span::new(span.lo(), span.hi(), SyntaxContext::root(), None))
+            })
+            .dedup_by(|&(_, a), &(_, b)| a == b);
+
+        for (id, span) in bad_unsafe_blocks {
+            span_lint_hir_and_then(
+                cx,
+                MACRO_METAVARS_IN_UNSAFE,
+                id,
+                span,
+                "this macro expands metavariables in an unsafe block",
+                |diag| {
+                    diag.note("this allows the user of the macro to write unsafe code outside of an unsafe block");
+                    diag.help(
+                            "consider expanding any metavariables outside of this block, e.g. by storing them in a variable",
+                        );
+                    diag.help(
+                            "... or also expand referenced metavariables in a safe context to require an unsafe block at callsite",
+                        );
+                },
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index 1eadc200bed..e2ab4415518 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -611,15 +611,22 @@ impl<'tcx> BinaryOp<'tcx> {
 
 /// The clamp meta pattern is a pattern shared between many (but not all) patterns.
 /// In summary, this pattern consists of two if statements that meet many criteria,
+///
 /// - binary operators that are one of [`>`, `<`, `>=`, `<=`].
+///
 /// - Both binary statements must have a shared argument
+///
 ///     - Which can appear on the left or right side of either statement
+///
 ///     - The binary operators must define a finite range for the shared argument. To put this in
 ///       the terms of Rust `std` library, the following ranges are acceptable
+///
 ///         - `Range`
 ///         - `RangeInclusive`
+///
 ///       And all other range types are not accepted. For the purposes of `clamp` it's irrelevant
 ///       whether the range is inclusive or not, the output is the same.
+///
 /// - The result of each if statement must be equal to the argument unique to that if statement. The
 ///   result can not be the shared argument in either case.
 fn is_clamp_meta_pattern<'tcx>(
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index cd61e733694..da8c918a62b 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::snippet;
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash};
 use core::cmp::Ordering;
 use core::{iter, slice};
@@ -9,9 +9,9 @@ use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
 use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
-use rustc_lint::LateContext;
+use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
-use rustc_span::{ErrorGuaranteed, Symbol};
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
 use super::MATCH_SAME_ARMS;
 
@@ -110,20 +110,22 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
             && check_same_body()
     };
 
+    let mut appl = Applicability::MaybeIncorrect;
     let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
     for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) {
         if matches!(arm2.pat.kind, PatKind::Wild) {
             if !cx.tcx.features().non_exhaustive_omitted_patterns_lint
                 || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id)
             {
+                let arm_span = adjusted_arm_span(cx, arm1.span);
                 span_lint_hir_and_then(
                     cx,
                     MATCH_SAME_ARMS,
                     arm1.hir_id,
-                    arm1.span,
+                    arm_span,
                     "this match arm has an identical body to the `_` wildcard arm",
                     |diag| {
-                        diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect)
+                        diag.span_suggestion(arm_span, "try removing the arm", "", appl)
                             .help("or try changing either arm body")
                             .span_note(arm2.span, "`_` wildcard arm here");
                     },
@@ -144,23 +146,36 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                 keep_arm.span,
                 "this match arm has an identical body to another arm",
                 |diag| {
-                    let move_pat_snip = snippet(cx, move_arm.pat.span, "<pat2>");
-                    let keep_pat_snip = snippet(cx, keep_arm.pat.span, "<pat1>");
+                    let move_pat_snip = snippet_with_applicability(cx, move_arm.pat.span, "<pat2>", &mut appl);
+                    let keep_pat_snip = snippet_with_applicability(cx, keep_arm.pat.span, "<pat1>", &mut appl);
 
                     diag.span_suggestion(
                         keep_arm.pat.span,
-                        "try merging the arm patterns",
+                        "or try merging the arm patterns",
                         format!("{keep_pat_snip} | {move_pat_snip}"),
-                        Applicability::MaybeIncorrect,
+                        appl,
                     )
-                    .help("or try changing either arm body")
-                    .span_note(move_arm.span, "other arm here");
+                    .span_suggestion(
+                        adjusted_arm_span(cx, move_arm.span),
+                        "and remove this obsolete arm",
+                        "",
+                        appl,
+                    )
+                    .help("try changing either arm body");
                 },
             );
         }
     }
 }
 
+/// Extend arm's span to include the comma and whitespaces after it.
+fn adjusted_arm_span(cx: &LateContext<'_>, span: Span) -> Span {
+    let source_map = cx.sess().source_map();
+    source_map
+        .span_extend_while(span, |c| c == ',' || c.is_ascii_whitespace())
+        .unwrap_or(span)
+}
+
 #[derive(Clone, Copy)]
 enum NormalizedPat<'a> {
     Wild,
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 f775ea072e1..6ac0705abb2 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
@@ -115,45 +115,60 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
         }
     }
 
-    fn get_type(&self, ex: &'tcx Expr<'_>) -> Ty<'tcx> {
-        self.cx.typeck_results().expr_ty(ex)
+    fn is_sig_drop_expr(&mut self, ex: &'tcx Expr<'_>) -> bool {
+        !ex.is_syntactic_place_expr() && self.has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex))
     }
 
-    fn has_seen_type(&mut self, ty: Ty<'tcx>) -> bool {
-        !self.seen_types.insert(ty)
+    fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+        self.seen_types.clear();
+        self.has_sig_drop_attr_impl(ty)
     }
 
-    fn has_sig_drop_attr(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    fn has_sig_drop_attr_impl(&mut self, ty: Ty<'tcx>) -> bool {
         if let Some(adt) = ty.ty_adt_def() {
-            if get_attr(cx.sess(), cx.tcx.get_attrs_unchecked(adt.did()), "has_significant_drop").count() > 0 {
+            if get_attr(
+                self.cx.sess(),
+                self.cx.tcx.get_attrs_unchecked(adt.did()),
+                "has_significant_drop",
+            )
+            .count()
+                > 0
+            {
                 return true;
             }
         }
 
-        match ty.kind() {
-            rustc_middle::ty::Adt(a, b) => {
-                for f in a.all_fields() {
-                    let ty = f.ty(cx.tcx, b);
-                    if !self.has_seen_type(ty) && self.has_sig_drop_attr(cx, ty) {
-                        return true;
-                    }
-                }
+        if !self.seen_types.insert(ty) {
+            return false;
+        }
 
-                for generic_arg in *b {
-                    if let GenericArgKind::Type(ty) = generic_arg.unpack() {
-                        if self.has_sig_drop_attr(cx, ty) {
-                            return true;
-                        }
-                    }
-                }
-                false
+        let result = match ty.kind() {
+            rustc_middle::ty::Adt(adt, args) => {
+                // if some field has significant drop,
+                adt.all_fields()
+                    .map(|field| field.ty(self.cx.tcx, args))
+                    .any(|ty| self.has_sig_drop_attr_impl(ty))
+                    // or if there is no generic lifetime and..
+                    // (to avoid false positive on `Ref<'a, MutexGuard<Foo>>`)
+                    || (args
+                        .iter()
+                        .all(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+                        // some generic parameter has significant drop
+                        // (to avoid false negative on `Box<MutexGuard<Foo>>`)
+                        && args
+                            .iter()
+                            .filter_map(|arg| match arg.unpack() {
+                                GenericArgKind::Type(ty) => Some(ty),
+                                _ => None,
+                            })
+                            .any(|ty| self.has_sig_drop_attr_impl(ty)))
             },
-            rustc_middle::ty::Array(ty, _)
-            | rustc_middle::ty::RawPtr(ty, _)
-            | rustc_middle::ty::Ref(_, ty, _)
-            | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(cx, *ty),
+            rustc_middle::ty::Tuple(tys) => tys.iter().any(|ty| self.has_sig_drop_attr_impl(ty)),
+            rustc_middle::ty::Array(ty, _) | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr_impl(*ty),
             _ => false,
-        }
+        };
+
+        result
     }
 }
 
@@ -232,7 +247,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
         if self.current_sig_drop.is_some() {
             return;
         }
-        let ty = self.sig_drop_checker.get_type(expr);
+        let ty = self.cx.typeck_results().expr_ty(expr);
         if ty.is_ref() {
             // We checked that the type was ref, so builtin_deref will return Some,
             // but let's avoid any chance of an ICE.
@@ -279,11 +294,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
-        if !self.is_chain_end
-            && self
-                .sig_drop_checker
-                .has_sig_drop_attr(self.cx, self.sig_drop_checker.get_type(ex))
-        {
+        if !self.is_chain_end && self.sig_drop_checker.is_sig_drop_expr(ex) {
             self.has_significant_drop = true;
             return;
         }
@@ -387,10 +398,7 @@ fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'
 
 impl<'a, 'tcx> Visitor<'tcx> for ArmSigDropHelper<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
-        if self
-            .sig_drop_checker
-            .has_sig_drop_attr(self.sig_drop_checker.cx, self.sig_drop_checker.get_type(ex))
-        {
+        if self.sig_drop_checker.is_sig_drop_expr(ex) {
             self.found_sig_drop_spans.insert(ex.span);
             return;
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index fba76852344..c9f56e1d980 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{find_format_args, format_args_inputs_span, root_macro_call_first_node};
+use clippy_utils::macros::{format_args_inputs_span, root_macro_call_first_node, FormatArgsStorage};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use rustc_errors::Applicability;
@@ -16,6 +16,7 @@ use super::EXPECT_FUN_CALL;
 #[allow(clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
+    format_args_storage: &FormatArgsStorage,
     expr: &hir::Expr<'_>,
     method_span: Span,
     name: &str,
@@ -134,9 +135,9 @@ pub(super) fn check<'tcx>(
     // Special handling for `format!` as arg_root
     if let Some(macro_call) = root_macro_call_first_node(cx, arg_root) {
         if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id)
-            && let Some(format_args) = find_format_args(cx, arg_root, macro_call.expn)
+            && let Some(format_args) = format_args_storage.get(cx, arg_root, macro_call.expn)
         {
-            let span = format_args_inputs_span(&format_args);
+            let span = format_args_inputs_span(format_args);
             let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
             span_lint_and_sugg(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
index 12647ea1ffc..b93d51eac64 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
@@ -126,15 +126,15 @@ enum FilterType {
 ///
 /// How this is done:
 /// 1. we know that this is invoked in a method call with `filter` as the method name via `mod.rs`
-/// 2. we check that we are in a trait method. Therefore we are in an
-/// `(x as Iterator).filter({filter_arg})` method call.
+/// 2. we check that we are in a trait method. Therefore we are in an `(x as
+///    Iterator).filter({filter_arg})` method call.
 /// 3. we check that the parent expression is not a map. This is because we don't want to lint
 ///    twice, and we already have a specialized lint for that.
 /// 4. we check that the span of the filter does not contain a comment.
 /// 5. we get the type of the `Item` in the `Iterator`, and compare against the type of Option and
-///   Result.
+///    Result.
 /// 6. we finally check the contents of the filter argument to see if it is a call to `is_some` or
-///   `is_ok`.
+///    `is_ok`.
 /// 7. if all of the above are true, then we return the `FilterType`
 fn expression_type(
     cx: &LateContext<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 7c852a3768d..05e77386128 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -12,8 +12,10 @@ use rustc_middle::ty;
 use rustc_span::{sym, Span};
 
 /// lint use of:
+///
 /// - `hashmap.iter().map(|(_, v)| v)`
 /// - `hashmap.into_iter().map(|(_, v)| v)`
+///
 /// on `HashMaps` and `BTreeMaps` in std
 
 pub(super) fn check<'tcx>(
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
index a52d38790a2..5ccb5243e90 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -69,12 +69,9 @@ pub(super) fn check<'tcx>(
                 used_move: HirIdSet::default(),
             };
 
-            ExprUseVisitor::for_clippy(
-                cx,
-                closure.def_id,
-                &mut delegate,
-            )
-            .consume_body(body).into_ok();
+            ExprUseVisitor::for_clippy(cx, closure.def_id, &mut delegate)
+                .consume_body(body)
+                .into_ok();
 
             let mut to_be_discarded = false;
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 2b92bff016d..9d67aa23379 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -133,6 +133,7 @@ use bind_instead_of_map::BindInsteadOfMap;
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::macros::FormatArgsStorage;
 use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
 use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty};
 pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES;
@@ -4087,12 +4088,14 @@ declare_clippy_lint! {
     suspicious,
     "is_empty() called on strings known at compile time"
 }
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
     allow_expect_in_tests: bool,
     allow_unwrap_in_tests: bool,
     allowed_dotfiles: FxHashSet<String>,
+    format_args: FormatArgsStorage,
 }
 
 impl Methods {
@@ -4103,6 +4106,7 @@ impl Methods {
         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));
 
@@ -4112,6 +4116,7 @@ impl Methods {
             allow_expect_in_tests,
             allow_unwrap_in_tests,
             allowed_dotfiles,
+            format_args,
         }
     }
 }
@@ -4281,7 +4286,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             ExprKind::MethodCall(method_call, receiver, args, _) => {
                 let method_span = method_call.ident.span;
                 or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
-                expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
+                expect_fun_call::check(
+                    cx,
+                    &self.format_args,
+                    expr,
+                    method_span,
+                    method_call.ident.as_str(),
+                    receiver,
+                    args,
+                );
                 clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args);
                 clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args);
                 inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 520dcb2d52d..7431dc1cf0b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -3,10 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait};
-use clippy_utils::{fn_def_id, get_parent_expr};
+use clippy_utils::visitors::for_each_expr;
+use clippy_utils::{can_mut_borrow_both, fn_def_id, get_parent_expr, path_to_local};
+use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{BindingMode, Expr, ExprKind, Node, PatKind};
 use rustc_lint::LateContext;
 use rustc_span::{sym, Symbol};
 
@@ -40,6 +42,53 @@ pub fn check_for_loop_iter(
         && !clone_or_copy_needed
         && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
     {
+        // Issue 12098
+        // https://github.com/rust-lang/rust-clippy/issues/12098
+        // if the assignee have `mut borrow` conflict with the iteratee
+        // the lint should not execute, former didn't consider the mut case
+
+        // check whether `expr` is mutable
+        fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+            if let Some(hir_id) = path_to_local(expr)
+                && let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
+            {
+                matches!(pat.kind, PatKind::Binding(BindingMode::MUT, ..))
+            } else {
+                true
+            }
+        }
+
+        fn is_caller_or_fields_change(cx: &LateContext<'_>, body: &Expr<'_>, caller: &Expr<'_>) -> bool {
+            let mut change = false;
+            if let ExprKind::Block(block, ..) = body.kind {
+                for_each_expr(block, |e| {
+                    match e.kind {
+                        ExprKind::Assign(assignee, _, _) | ExprKind::AssignOp(_, assignee, _) => {
+                            change |= !can_mut_borrow_both(cx, caller, assignee);
+                        },
+                        _ => {},
+                    }
+                    // the return value has no effect but the function need one return value
+                    ControlFlow::<()>::Continue(())
+                });
+            }
+            change
+        }
+
+        if let ExprKind::Call(_, [child, ..]) = expr.kind {
+            // filter first layer of iterator
+            let mut child = child;
+            // get inner real caller requests for clone
+            while let ExprKind::MethodCall(_, caller, _, _) = child.kind {
+                child = caller;
+            }
+            if is_mutable(cx, child) && is_caller_or_fields_change(cx, body, child) {
+                // skip lint
+                return true;
+            }
+        };
+
+        // the lint should not be executed if no violation happens
         let snippet = if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind
             && maybe_iter_method_name.ident.name == sym::iter
             && let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index c50f24f824a..34d7b9acbe4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -120,6 +120,7 @@ fn pat_bindings(pat: &Pat<'_>) -> Vec<HirId> {
 /// operations performed on `binding_hir_ids` are:
 /// * to take non-mutable references to them
 /// * to use them as non-mutable `&self` in method calls
+///
 /// If any of `binding_hir_ids` is used in any other way, then `clone_or_copy_needed` will be true
 /// when `CloneOrCopyVisitor` is done visiting.
 struct CloneOrCopyVisitor<'cx, 'tcx> {
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 ae6cf992ef7..daf166bad90 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,6 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
+use clippy_utils::mir::PossibleBorrowerMap;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{implements_trait, is_copy};
 use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode};
@@ -11,7 +11,6 @@ use rustc_hir::{Body, Expr, ExprKind, Mutability, Path, QPath};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::{Rvalue, StatementKind};
 use rustc_middle::ty::{
     self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, ParamTy, ProjectionPredicate, Ty,
 };
@@ -106,7 +105,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> {
             }
             && let count = needless_borrow_count(
                 cx,
-                &mut self.possible_borrowers,
                 fn_id,
                 cx.typeck_results().node_args(hir_id),
                 i,
@@ -155,11 +153,9 @@ fn path_has_args(p: &QPath<'_>) -> bool {
 /// The following constraints will be checked:
 /// * The borrowed expression meets all the generic type's constraints.
 /// * The generic type appears only once in the functions signature.
-/// * The borrowed value will not be moved if it is used later in the function.
-#[expect(clippy::too_many_arguments)]
+/// * The borrowed value is Copy itself OR not a variable (created by a function call)
 fn needless_borrow_count<'tcx>(
     cx: &LateContext<'tcx>,
-    possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
     fn_id: DefId,
     callee_args: ty::GenericArgsRef<'tcx>,
     arg_index: usize,
@@ -234,9 +230,9 @@ fn needless_borrow_count<'tcx>(
 
         let referent_ty = cx.typeck_results().expr_ty(referent);
 
-        if !is_copy(cx, referent_ty)
-            && (referent_ty.has_significant_drop(cx.tcx, cx.param_env)
-                || !referent_used_exactly_once(cx, possible_borrowers, reference))
+        if (!is_copy(cx, referent_ty) && !referent_ty.is_ref())
+            && let ExprKind::AddrOf(_, _, inner) = reference.kind
+            && !matches!(inner.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))
         {
             return false;
         }
@@ -339,37 +335,6 @@ fn is_mixed_projection_predicate<'tcx>(
     }
 }
 
-fn referent_used_exactly_once<'tcx>(
-    cx: &LateContext<'tcx>,
-    possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
-    reference: &Expr<'tcx>,
-) -> bool {
-    if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id)
-        && let Some(local) = expr_local(cx.tcx, reference)
-        && let [location] = *local_assignments(mir, local).as_slice()
-        && let block_data = &mir.basic_blocks[location.block]
-        && let Some(statement) = block_data.statements.get(location.statement_index)
-        && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
-        && !place.is_indirect_first_projection()
-    {
-        let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id);
-        if possible_borrowers
-            .last()
-            .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id)
-        {
-            possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
-        }
-        let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
-        // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
-        // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
-        // itself. See the comment in that method for an explanation as to why.
-        possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
-            && used_exactly_once(mir, place.local).unwrap_or(false)
-    } else {
-        false
-    }
-}
-
 // Iteratively replaces `param_ty` with `new_ty` in `args`, and similarly for each resulting
 // projected type that is a type parameter. Returns `false` if replacing the types would have an
 // effect on the function signature beyond substituting `new_ty` for `param_ty`.
@@ -408,7 +373,11 @@ fn replace_types<'tcx>(
                     && let Some(term_ty) = projection_predicate.term.ty()
                     && let ty::Param(term_param_ty) = term_ty.kind()
                 {
-                    let projection = projection_predicate.projection_term.with_self_ty(cx.tcx, new_ty).expect_ty(cx.tcx).to_ty(cx.tcx);
+                    let projection = projection_predicate
+                        .projection_term
+                        .with_self_ty(cx.tcx, new_ty)
+                        .expect_ty(cx.tcx)
+                        .to_ty(cx.tcx);
 
                     if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
                         && args[term_param_ty.index as usize] != GenericArg::from(projected_ty)
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index 8b4a12bb766..b97cb4579ca 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -178,8 +178,7 @@ impl EarlyLintPass for NeedlessContinue {
 /// Given an expression, returns true if either of the following is true
 ///
 /// - The expression is a `continue` node.
-/// - The expression node is a block with the first statement being a
-/// `continue`.
+/// - The expression node is a block with the first statement being a `continue`.
 fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>) -> bool {
     match else_expr.kind {
         ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block, label),
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index 6605d1fa51a..5a0ae1a4d6d 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -273,24 +273,16 @@ fn check<'tcx>(
                 msg_span,
                 "unneeded late initialization",
                 |diag| {
-                    diag.tool_only_span_suggestion(
-                        local_stmt.span,
-                        "remove the local",
-                        "",
-                        Applicability::MachineApplicable,
-                    );
-
-                    diag.span_suggestion(
-                        assign.lhs_span,
-                        format!("declare `{binding_name}` here"),
-                        let_snippet,
+                    diag.multipart_suggestion(
+                        format!("move the declaration `{binding_name}` here"),
+                        vec![(local_stmt.span, String::new()), (assign.lhs_span, let_snippet)],
                         Applicability::MachineApplicable,
                     );
                 },
             );
         },
         ExprKind::If(cond, then_expr, Some(else_expr)) if !contains_let(cond) => {
-            let (applicability, suggestions) = assignment_suggestions(cx, binding_id, [then_expr, else_expr])?;
+            let (applicability, mut suggestions) = assignment_suggestions(cx, binding_id, [then_expr, else_expr])?;
 
             span_lint_and_then(
                 cx,
@@ -298,30 +290,26 @@ fn check<'tcx>(
                 local_stmt.span,
                 "unneeded late initialization",
                 |diag| {
-                    diag.tool_only_span_suggestion(local_stmt.span, "remove the local", String::new(), applicability);
-
-                    diag.span_suggestion_verbose(
-                        usage.stmt.span.shrink_to_lo(),
-                        format!("declare `{binding_name}` here"),
-                        format!("{let_snippet} = "),
-                        applicability,
-                    );
-
-                    diag.multipart_suggestion("remove the assignments from the branches", suggestions, applicability);
+                    suggestions.push((local_stmt.span, String::new()));
+                    suggestions.push((usage.stmt.span.shrink_to_lo(), format!("{let_snippet} = ")));
 
                     if usage.needs_semi {
-                        diag.span_suggestion(
-                            usage.stmt.span.shrink_to_hi(),
-                            "add a semicolon after the `if` expression",
-                            ";",
-                            applicability,
-                        );
+                        suggestions.push((usage.stmt.span.shrink_to_hi(), ";".to_owned()));
                     }
+
+                    diag.multipart_suggestion(
+                        format!(
+                            "move the declaration `{binding_name}` here and remove the assignments from the branches"
+                        ),
+                        suggestions,
+                        applicability,
+                    );
                 },
             );
         },
         ExprKind::Match(_, arms, MatchSource::Normal) => {
-            let (applicability, suggestions) = assignment_suggestions(cx, binding_id, arms.iter().map(|arm| arm.body))?;
+            let (applicability, mut suggestions) =
+                assignment_suggestions(cx, binding_id, arms.iter().map(|arm| arm.body))?;
 
             span_lint_and_then(
                 cx,
@@ -329,29 +317,18 @@ fn check<'tcx>(
                 local_stmt.span,
                 "unneeded late initialization",
                 |diag| {
-                    diag.tool_only_span_suggestion(local_stmt.span, "remove the local", String::new(), applicability);
+                    suggestions.push((local_stmt.span, String::new()));
+                    suggestions.push((usage.stmt.span.shrink_to_lo(), format!("{let_snippet} = ")));
 
-                    diag.span_suggestion_verbose(
-                        usage.stmt.span.shrink_to_lo(),
-                        format!("declare `{binding_name}` here"),
-                        format!("{let_snippet} = "),
-                        applicability,
-                    );
+                    if usage.needs_semi {
+                        suggestions.push((usage.stmt.span.shrink_to_hi(), ";".to_owned()));
+                    }
 
                     diag.multipart_suggestion(
-                        "remove the assignments from the `match` arms",
+                        format!("move the declaration `{binding_name}` here and remove the assignments from the `match` arms"),
                         suggestions,
                         applicability,
                     );
-
-                    if usage.needs_semi {
-                        diag.span_suggestion(
-                            usage.stmt.span.shrink_to_hi(),
-                            "add a semicolon after the `match` expression",
-                            ";",
-                            applicability,
-                        );
-                    }
                 },
             );
         },
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 9b852f52ea1..da6ed5fb96f 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
@@ -117,7 +117,9 @@ fn check_closures<'tcx>(
             .associated_body()
             .map(|(_, body_id)| hir.body(body_id))
         {
-            euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx).consume_body(body).into_ok();
+            euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx)
+                .consume_body(body)
+                .into_ok();
         }
     }
 }
@@ -194,7 +196,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                 async_closures: FxHashSet::default(),
                 tcx: cx.tcx,
             };
-            euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok();
+            euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx)
+                .consume_body(body)
+                .into_ok();
 
             let mut checked_closures = FxHashSet::default();
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 0986571d0f2..f2e00cef7e9 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -133,7 +133,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         // function body.
         let MovedVariablesCtxt { moved_vars } = {
             let mut ctx = MovedVariablesCtxt::default();
-            euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok();
+            euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx)
+                .consume_body(body)
+                .into_ok();
             ctx
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index f915145e794..87f886b1128 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -94,7 +94,6 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
 
     fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) {
         for hir_id in self.local_bindings.pop().unwrap() {
-            // FIXME(rust/#120456) - is `swap_remove` correct?
             if let Some(span) = self.underscore_bindings.swap_remove(&hir_id) {
                 span_lint_hir(
                     cx,
@@ -109,7 +108,6 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
 
     fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let Some(def_id) = path_to_local(expr) {
-            // FIXME(rust/#120456) - is `swap_remove` correct?
             self.underscore_bindings.swap_remove(&def_id);
         }
     }
@@ -118,7 +116,11 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
 impl NoEffect {
     fn check_no_effect(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
         if let StmtKind::Semi(expr) = stmt.kind {
-            // move `expr.span.from_expansion()` ahead
+            // Covered by rustc `path_statements` lint
+            if matches!(expr.kind, ExprKind::Path(_)) {
+                return true;
+            }
+
             if expr.span.from_expansion() {
                 return false;
             }
diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
index ef51a9a9a1c..75066c1f0d2 100644
--- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
@@ -1,8 +1,14 @@
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_in_test;
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
+
+#[derive(Clone)]
+pub struct PanicUnimplemented {
+    pub allow_panic_in_tests: bool,
+}
 
 declare_clippy_lint! {
     /// ### What it does
@@ -77,7 +83,7 @@ declare_clippy_lint! {
     "usage of the `unreachable!` macro"
 }
 
-declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
+impl_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
 
 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
@@ -85,7 +91,9 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
             return;
         };
         if is_panic(cx, macro_call.def_id) {
-            if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+            if cx.tcx.hir().is_inside_const_context(expr.hir_id)
+                || self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id)
+            {
                 return;
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 87a3c3874d7..292124196ff 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -389,6 +389,10 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]);
 
 impl<'tcx> LateLintPass<'tcx> for StrToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        if expr.span.from_expansion() {
+            return;
+        }
+
         if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
             && path.ident.name == sym::to_string
             && let ty = cx.typeck_results().expr_ty(self_arg)
@@ -437,6 +441,10 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]);
 
 impl<'tcx> LateLintPass<'tcx> for StringToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        if expr.span.from_expansion() {
+            return;
+        }
+
         if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
             && path.ident.name == sym::to_string
             && let ty = cx.typeck_results().expr_ty(self_arg)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
index 7d824ef2139..3729dfd3e86 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
 
     let int_ty = substs.type_at(0);
     if from_ty != int_ty {
-      return false;
+        return false;
     }
 
     span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 5b2841dcd83..c0d9bcdd259 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -251,11 +251,7 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
                 local_id: unwrap_info.local_id,
             };
 
-            let vis = ExprUseVisitor::for_clippy(
-                self.cx,
-                cond.hir_id.owner.def_id,
-                &mut delegate,
-            );
+            let vis = ExprUseVisitor::for_clippy(self.cx, cond.hir_id.owner.def_id, &mut delegate);
             vis.walk_expr(cond).into_ok();
             vis.walk_expr(branch).into_ok();
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
index 58e66c9f9b9..5acfd35fd6a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
@@ -1,4 +1,4 @@
-use clippy_utils::macros::AST_FORMAT_ARGS;
+use clippy_utils::macros::FormatArgsStorage;
 use clippy_utils::source::snippet_opt;
 use itertools::Itertools;
 use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
@@ -9,13 +9,20 @@ use rustc_session::impl_lint_pass;
 use rustc_span::{hygiene, Span};
 use std::iter::once;
 use std::mem;
-use std::rc::Rc;
 
-/// Collects [`rustc_ast::FormatArgs`] so that future late passes can call
-/// [`clippy_utils::macros::find_format_args`]
-#[derive(Default)]
+/// Populates [`FormatArgsStorage`] with AST [`FormatArgs`] nodes
 pub struct FormatArgsCollector {
-    format_args: FxHashMap<Span, Rc<FormatArgs>>,
+    format_args: FxHashMap<Span, FormatArgs>,
+    storage: FormatArgsStorage,
+}
+
+impl FormatArgsCollector {
+    pub fn new(storage: FormatArgsStorage) -> Self {
+        Self {
+            format_args: FxHashMap::default(),
+            storage,
+        }
+    }
 }
 
 impl_lint_pass!(FormatArgsCollector => []);
@@ -27,16 +34,12 @@ impl EarlyLintPass for FormatArgsCollector {
                 return;
             }
 
-            self.format_args
-                .insert(expr.span.with_parent(None), Rc::new((**args).clone()));
+            self.format_args.insert(expr.span.with_parent(None), (**args).clone());
         }
     }
 
     fn check_crate_post(&mut self, _: &EarlyContext<'_>, _: &Crate) {
-        AST_FORMAT_ARGS.with(|ast_format_args| {
-            let result = ast_format_args.set(mem::take(&mut self.format_args));
-            debug_assert!(result.is_ok());
-        });
+        self.storage.set(mem::take(&mut self.format_args));
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 26c6859233d..ff6ee0d10ad 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::macros::{find_format_args, format_arg_removal_span, root_macro_call_first_node, MacroCall};
+use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall};
 use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
 use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_ast::token::LitKind;
@@ -236,13 +236,15 @@ declare_clippy_lint! {
 
 #[derive(Default)]
 pub struct Write {
+    format_args: FormatArgsStorage,
     in_debug_impl: bool,
     allow_print_in_tests: bool,
 }
 
 impl Write {
-    pub fn new(allow_print_in_tests: bool) -> Self {
+    pub fn new(format_args: FormatArgsStorage, allow_print_in_tests: bool) -> Self {
         Self {
+            format_args,
             allow_print_in_tests,
             ..Default::default()
         }
@@ -307,7 +309,7 @@ impl<'tcx> LateLintPass<'tcx> for Write {
             _ => return,
         }
 
-        if let Some(format_args) = find_format_args(cx, expr, macro_call.expn) {
+        if let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) {
             // ignore `writeln!(w)` and `write!(v, some_macro!())`
             if format_args.span.from_expansion() {
                 return;
@@ -315,15 +317,15 @@ impl<'tcx> LateLintPass<'tcx> for Write {
 
             match diag_name {
                 sym::print_macro | sym::eprint_macro | sym::write_macro => {
-                    check_newline(cx, &format_args, &macro_call, name);
+                    check_newline(cx, format_args, &macro_call, name);
                 },
                 sym::println_macro | sym::eprintln_macro | sym::writeln_macro => {
-                    check_empty_string(cx, &format_args, &macro_call, name);
+                    check_empty_string(cx, format_args, &macro_call, name);
                 },
                 _ => {},
             }
 
-            check_literal(cx, &format_args, name);
+            check_literal(cx, format_args, name);
 
             if !self.in_debug_impl {
                 for piece in &format_args.template {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 99d7aba2f7a..4c603bda770 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -193,6 +193,21 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
     None
 }
 
+/// Checks if the given local has an initializer or is from something other than a `let` statement
+///
+/// e.g. returns true for `x` in `fn f(x: usize) { .. }` and `let x = 1;` but false for `let x;`
+pub fn local_is_initialized(cx: &LateContext<'_>, local: HirId) -> bool {
+    for (_, node) in cx.tcx.hir().parent_iter(local) {
+        match node {
+            Node::Pat(..) | Node::PatField(..) => {},
+            Node::LetStmt(let_stmt) => return let_stmt.init.is_some(),
+            _ => return true,
+        }
+    }
+
+    false
+}
+
 /// Returns `true` if the given `NodeId` is inside a constant context
 ///
 /// # Example
@@ -1499,15 +1514,18 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
 }
 
 /// Checks whether the given `Expr` is a range equivalent to a `RangeFull`.
+///
 /// For the lower bound, this means that:
 /// - either there is none
 /// - or it is the smallest value that can be represented by the range's integer type
+///
 /// For the upper bound, this means that:
 /// - either there is none
 /// - or it is the largest value that can be represented by the range's integer type and is
 ///   inclusive
 /// - or it is a call to some container's `len` method and is exclusive, and the range is passed to
 ///   a method call on that same container (e.g. `v.drain(..v.len())`)
+///
 /// If the given `Expr` is not some kind of range, the function returns `false`.
 pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 257dd76ab15..8daab9b0d92 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -5,15 +5,13 @@ use crate::visitors::{for_each_expr, Descend};
 use arrayvec::ArrayVec;
 use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{Lrc, OnceLock};
 use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::LateContext;
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
 use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol};
-use std::cell::OnceCell;
 use std::ops::ControlFlow;
-use std::rc::Rc;
-use std::sync::atomic::{AtomicBool, Ordering};
 
 const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[
     sym::assert_eq_macro,
@@ -388,50 +386,44 @@ fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) ->
     }
 }
 
-thread_local! {
-    /// We preserve the [`FormatArgs`] structs from the early pass for use in the late pass to be
-    /// able to access the many features of a [`LateContext`].
-    ///
-    /// A thread local is used because [`FormatArgs`] is `!Send` and `!Sync`, we are making an
-    /// assumption that the early pass that populates the map and the later late passes will all be
-    /// running on the same thread.
-    #[doc(hidden)]
-    pub static AST_FORMAT_ARGS: OnceCell<FxHashMap<Span, Rc<FormatArgs>>> = {
-        static CALLED: AtomicBool = AtomicBool::new(false);
-        debug_assert!(
-            !CALLED.swap(true, Ordering::SeqCst),
-            "incorrect assumption: `AST_FORMAT_ARGS` should only be accessed by a single thread",
-        );
-
-        OnceCell::new()
-    };
-}
+/// Stores AST [`FormatArgs`] nodes for use in late lint passes, as they are in a desugared form in
+/// the HIR
+#[derive(Default, Clone)]
+pub struct FormatArgsStorage(Lrc<OnceLock<FxHashMap<Span, FormatArgs>>>);
 
-/// Returns an AST [`FormatArgs`] node if a `format_args` expansion is found as a descendant of
-/// `expn_id`
-pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) -> Option<Rc<FormatArgs>> {
-    let format_args_expr = for_each_expr(start, |expr| {
-        let ctxt = expr.span.ctxt();
-        if ctxt.outer_expn().is_descendant_of(expn_id) {
-            if macro_backtrace(expr.span)
-                .map(|macro_call| cx.tcx.item_name(macro_call.def_id))
-                .any(|name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))
-            {
-                ControlFlow::Break(expr)
+impl FormatArgsStorage {
+    /// Returns an AST [`FormatArgs`] node if a `format_args` expansion is found as a descendant of
+    /// `expn_id`
+    ///
+    /// See also [`find_format_arg_expr`]
+    pub fn get(&self, cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) -> Option<&FormatArgs> {
+        let format_args_expr = for_each_expr(start, |expr| {
+            let ctxt = expr.span.ctxt();
+            if ctxt.outer_expn().is_descendant_of(expn_id) {
+                if macro_backtrace(expr.span)
+                    .map(|macro_call| cx.tcx.item_name(macro_call.def_id))
+                    .any(|name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))
+                {
+                    ControlFlow::Break(expr)
+                } else {
+                    ControlFlow::Continue(Descend::Yes)
+                }
             } else {
-                ControlFlow::Continue(Descend::Yes)
+                ControlFlow::Continue(Descend::No)
             }
-        } else {
-            ControlFlow::Continue(Descend::No)
-        }
-    })?;
+        })?;
 
-    AST_FORMAT_ARGS.with(|ast_format_args| {
-        ast_format_args
-            .get()?
-            .get(&format_args_expr.span.with_parent(None))
-            .cloned()
-    })
+        debug_assert!(self.0.get().is_some(), "`FormatArgsStorage` not yet populated");
+
+        self.0.get()?.get(&format_args_expr.span.with_parent(None))
+    }
+
+    /// Should only be called by `FormatArgsCollector`
+    pub fn set(&self, format_args: FxHashMap<Span, FormatArgs>) {
+        self.0
+            .set(format_args)
+            .expect("`FormatArgsStorage::set` should only be called once");
+    }
 }
 
 /// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index ff9f06531ea..8ee7d87acb3 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -3,7 +3,7 @@
 // of terminologies might not be relevant in the context of Clippy. Note that its behavior might
 // differ from the time of `rustc` even if the name stays the same.
 
-use clippy_config::msrvs::Msrv;
+use clippy_config::msrvs::{self, Msrv};
 use hir::LangItem;
 use rustc_attr::StableSince;
 use rustc_const_eval::transform::check_consts::ConstCx;
@@ -42,7 +42,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
     for bb in &*body.basic_blocks {
         check_terminator(tcx, body, bb.terminator(), msrv)?;
         for stmt in &bb.statements {
-            check_statement(tcx, body, def_id, stmt)?;
+            check_statement(tcx, body, def_id, stmt, msrv)?;
         }
     }
     Ok(())
@@ -102,13 +102,14 @@ fn check_rvalue<'tcx>(
     def_id: DefId,
     rvalue: &Rvalue<'tcx>,
     span: Span,
+    msrv: &Msrv,
 ) -> McfResult {
     match rvalue {
         Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
         Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
-            check_place(tcx, *place, span, body)
+            check_place(tcx, *place, span, body, msrv)
         },
-        Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body),
+        Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv),
         Rvalue::Repeat(operand, _)
         | Rvalue::Use(operand)
         | Rvalue::Cast(
@@ -122,7 +123,7 @@ fn check_rvalue<'tcx>(
             | CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer),
             operand,
             _,
-        ) => check_operand(tcx, operand, span, body),
+        ) => check_operand(tcx, operand, span, body, msrv),
         Rvalue::Cast(
             CastKind::PointerCoercion(
                 PointerCoercion::UnsafeFnPointer
@@ -133,15 +134,13 @@ fn check_rvalue<'tcx>(
             _,
         ) => Err((span, "function pointer casts are not allowed in const fn".into())),
         Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => {
-            let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) {
-                deref_ty
-            } else {
+            let Some(pointee_ty) = cast_ty.builtin_deref(true) else {
                 // We cannot allow this for now.
                 return Err((span, "unsizing casts are only allowed for references right now".into()));
             };
             let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
             if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
-                check_operand(tcx, op, span, body)?;
+                check_operand(tcx, op, span, body, msrv)?;
                 // Casting/coercing things to slices is fine.
                 Ok(())
             } else {
@@ -162,8 +161,8 @@ fn check_rvalue<'tcx>(
         )),
         // binops are fine on integers
         Rvalue::BinaryOp(_, box (lhs, rhs)) => {
-            check_operand(tcx, lhs, span, body)?;
-            check_operand(tcx, rhs, span, body)?;
+            check_operand(tcx, lhs, span, body, msrv)?;
+            check_operand(tcx, rhs, span, body, msrv)?;
             let ty = lhs.ty(body, tcx);
             if ty.is_integral() || ty.is_bool() || ty.is_char() {
                 Ok(())
@@ -179,14 +178,14 @@ fn check_rvalue<'tcx>(
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
             if ty.is_integral() || ty.is_bool() {
-                check_operand(tcx, operand, span, body)
+                check_operand(tcx, operand, span, body, msrv)
             } else {
                 Err((span, "only int and `bool` operations are stable in const fn".into()))
             }
         },
         Rvalue::Aggregate(_, operands) => {
             for operand in operands {
-                check_operand(tcx, operand, span, body)?;
+                check_operand(tcx, operand, span, body, msrv)?;
             }
             Ok(())
         },
@@ -198,28 +197,29 @@ fn check_statement<'tcx>(
     body: &Body<'tcx>,
     def_id: DefId,
     statement: &Statement<'tcx>,
+    msrv: &Msrv,
 ) -> McfResult {
     let span = statement.source_info.span;
     match &statement.kind {
         StatementKind::Assign(box (place, rval)) => {
-            check_place(tcx, *place, span, body)?;
-            check_rvalue(tcx, body, def_id, rval, span)
+            check_place(tcx, *place, span, body, msrv)?;
+            check_rvalue(tcx, body, def_id, rval, span, msrv)
         },
 
-        StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body),
+        StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body, msrv),
         // just an assignment
         StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
-            check_place(tcx, **place, span, body)
+            check_place(tcx, **place, span, body, msrv)
         },
 
-        StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body),
+        StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body, msrv),
 
         StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
             rustc_middle::mir::CopyNonOverlapping { dst, src, count },
         )) => {
-            check_operand(tcx, dst, span, body)?;
-            check_operand(tcx, src, span, body)?;
-            check_operand(tcx, count, span, body)
+            check_operand(tcx, dst, span, body, msrv)?;
+            check_operand(tcx, src, span, body, msrv)?;
+            check_operand(tcx, count, span, body, msrv)
         },
         // These are all NOPs
         StatementKind::StorageLive(_)
@@ -233,7 +233,13 @@ fn check_statement<'tcx>(
     }
 }
 
-fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
+fn check_operand<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    operand: &Operand<'tcx>,
+    span: Span,
+    body: &Body<'tcx>,
+    msrv: &Msrv,
+) -> McfResult {
     match operand {
         Operand::Move(place) => {
             if !place.projection.as_ref().is_empty()
@@ -245,9 +251,9 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
                 ));
             }
 
-            check_place(tcx, *place, span, body)
+            check_place(tcx, *place, span, body, msrv)
         },
-        Operand::Copy(place) => check_place(tcx, *place, span, body),
+        Operand::Copy(place) => check_place(tcx, *place, span, body, msrv),
         Operand::Constant(c) => match c.check_static_ptr(tcx) {
             Some(_) => Err((span, "cannot access `static` items in const fn".into())),
             None => Ok(()),
@@ -255,23 +261,27 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
     }
 }
 
-fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
+fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, msrv: &Msrv) -> McfResult {
     for (base, elem) in place.as_ref().iter_projections() {
         match elem {
             ProjectionElem::Field(..) => {
-                let base_ty = base.ty(body, tcx).ty;
-                if let Some(def) = base_ty.ty_adt_def() {
-                    // No union field accesses in `const fn`
-                    if def.is_union() {
-                        return Err((span, "accessing union fields is unstable".into()));
-                    }
+                if base.ty(body, tcx).ty.is_union() && !msrv.meets(msrvs::CONST_FN_UNION) {
+                    return Err((span, "accessing union fields is unstable".into()));
                 }
             },
+            ProjectionElem::Deref => match base.ty(body, tcx).ty.kind() {
+                ty::RawPtr(_, hir::Mutability::Mut) => {
+                    return Err((span, "dereferencing raw mut pointer in const fn is unstable".into()));
+                },
+                ty::RawPtr(_, hir::Mutability::Not) if !msrv.meets(msrvs::CONST_RAW_PTR_DEREF) => {
+                    return Err((span, "dereferencing raw const pointer in const fn is unstable".into()));
+                },
+                _ => (),
+            },
             ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::OpaqueCast(..)
             | ProjectionElem::Downcast(..)
             | ProjectionElem::Subslice { .. }
-            | ProjectionElem::Deref
             | ProjectionElem::Subtype(_)
             | ProjectionElem::Index(_) => {},
         }
@@ -304,7 +314,7 @@ fn check_terminator<'tcx>(
             }
             Ok(())
         },
-        TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
+        TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body, msrv),
         TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => {
             Err((span, "const fn coroutines are unstable".into()))
         },
@@ -341,10 +351,10 @@ fn check_terminator<'tcx>(
                     ));
                 }
 
-                check_operand(tcx, func, span, body)?;
+                check_operand(tcx, func, span, body, msrv)?;
 
                 for arg in args {
-                    check_operand(tcx, &arg.node, span, body)?;
+                    check_operand(tcx, &arg.node, span, body, msrv)?;
                 }
                 Ok(())
             } else {
@@ -357,7 +367,7 @@ fn check_terminator<'tcx>(
             msg: _,
             target: _,
             unwind: _,
-        } => check_operand(tcx, cond, span, body),
+        } => check_operand(tcx, cond, span, body, msrv),
         TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index e72467edeeb..fd67e039c29 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -250,7 +250,7 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<
 /// - Applicability level `Unspecified` will never be changed.
 /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
 /// - If the default value is used and the applicability level is `MachineApplicable`, change it to
-/// `HasPlaceholders`
+///   `HasPlaceholders`
 pub fn snippet_with_applicability<'a, T: LintContext>(
     cx: &T,
     span: Span,
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index bf03c6c1601..6319c7bfa6b 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -67,8 +67,7 @@ impl<'a> Sugg<'a> {
     /// - Applicability level `Unspecified` will never be changed.
     /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
     /// - If the default value is used and the applicability level is `MachineApplicable`, change it
-    ///   to
-    /// `HasPlaceholders`
+    ///   to `HasPlaceholders`
     pub fn hir_with_applicability(
         cx: &LateContext<'_>,
         expr: &hir::Expr<'_>,
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index c29e3feac9a..2dacc34867f 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -273,11 +273,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
     let infcx = tcx.infer_ctxt().build();
     let args = args
         .into_iter()
-        .map(|arg| {
-            arg.into().unwrap_or_else(|| {
-                infcx.next_ty_var(DUMMY_SP).into()
-            })
-        })
+        .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into()))
         .collect::<Vec<_>>();
 
     // If an effect arg was not specified, we need to specify it.
@@ -795,7 +791,8 @@ fn sig_from_bounds<'tcx>(
                 inputs = Some(i);
             },
             ty::ClauseKind::Projection(p)
-                if Some(p.projection_term.def_id) == lang_items.fn_once_output() && p.projection_term.self_ty() == ty =>
+                if Some(p.projection_term.def_id) == lang_items.fn_once_output()
+                    && p.projection_term.self_ty() == ty =>
             {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
@@ -956,11 +953,7 @@ pub struct AdtVariantInfo {
 
 impl AdtVariantInfo {
     /// Returns ADT variants ordered by size
-    pub fn new<'tcx>(
-        cx: &LateContext<'tcx>,
-        adt: AdtDef<'tcx>,
-        subst: GenericArgsRef<'tcx>
-    ) -> Vec<Self> {
+    pub fn new<'tcx>(cx: &LateContext<'tcx>, adt: AdtDef<'tcx>, subst: GenericArgsRef<'tcx>) -> Vec<Self> {
         let mut variants_size = adt
             .variants()
             .iter()
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 9abb4ef9b8d..2a25d51d8e5 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -16,13 +16,9 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) ->
         used_mutably: HirIdSet::default(),
         skip: false,
     };
-    ExprUseVisitor::for_clippy(
-        cx,
-        expr.hir_id.owner.def_id,
-        &mut delegate,
-    )
-    .walk_expr(expr)
-    .into_ok();
+    ExprUseVisitor::for_clippy(cx, expr.hir_id.owner.def_id, &mut delegate)
+        .walk_expr(expr)
+        .into_ok();
 
     if delegate.skip {
         return None;
diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml
index a828d123704..8c5a409e25b 100644
--- a/src/tools/clippy/lintcheck/Cargo.toml
+++ b/src/tools/clippy/lintcheck/Cargo.toml
@@ -13,7 +13,7 @@ default-run = "lintcheck"
 [dependencies]
 anyhow = "1.0.69"
 cargo_metadata = "0.15.3"
-clap = { version = "4.1.8", features = ["derive", "env"] }
+clap = { version = "4.4", features = ["derive", "env"] }
 crates_io_api = "0.8.1"
 crossbeam-channel = "0.5.6"
 flate2 = "1.0"
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 055f305eb8e..a0585ffdb45 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-05-02"
+channel = "nightly-2024-05-16"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
index 103e60d8484..9177e99f8e6 100644
--- a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
+++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
@@ -42,4 +42,32 @@ help: to have lints override the group set `pedantic` to a lower priority
 19 | pedantic = { level = "warn", priority = -2 }
    |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-error: could not compile `fail` (lib) due to 3 previous errors
+error: lint group `rust_2018_idioms` has the same priority (0) as a lint
+  --> Cargo.toml:23:1
+   |
+23 | rust_2018_idioms = "warn"
+   | ^^^^^^^^^^^^^^^^   ------ has an implicit priority of 0
+24 | bare_trait_objects = "allow"
+   | ------------------ has the same priority as this lint
+   |
+   = note: the order of the lints in the table is ignored by Cargo
+help: to have lints override the group set `rust_2018_idioms` to a lower priority
+   |
+23 | rust_2018_idioms = { level = "warn", priority = -1 }
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: lint group `pedantic` has the same priority (0) as a lint
+  --> Cargo.toml:27:1
+   |
+27 | pedantic = "warn"
+   | ^^^^^^^^   ------ has an implicit priority of 0
+28 | similar_names = "allow"
+   | ------------- has the same priority as this lint
+   |
+   = note: the order of the lints in the table is ignored by Cargo
+help: to have lints override the group set `pedantic` to a lower priority
+   |
+27 | pedantic = { level = "warn", priority = -1 }
+   |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: could not compile `fail` (lib) due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml
index 4ce41f78171..e4d4af9cd23 100644
--- a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml
+++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml
@@ -18,3 +18,11 @@ deprecated  = "allow"
 [lints.clippy]
 pedantic = { level = "warn", priority = -1 }
 similar_names = { level = "allow", priority = -1 }
+
+[workspace.lints.rust]
+rust_2018_idioms = "warn"
+bare_trait_objects = "allow"
+
+[workspace.lints.clippy]
+pedantic = "warn"
+similar_names = "allow"
diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
new file mode 100644
index 00000000000..f5e01b431ad
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
@@ -0,0 +1,260 @@
+//! Tests macro_metavars_in_unsafe with default configuration
+#![feature(decl_macro, lint_reasons)]
+#![warn(clippy::macro_metavars_in_unsafe)]
+#![allow(clippy::no_effect)]
+
+#[macro_export]
+macro_rules! allow_works {
+    ($v:expr) => {
+        #[expect(clippy::macro_metavars_in_unsafe)]
+        unsafe {
+            $v;
+        };
+    };
+}
+
+#[macro_export]
+macro_rules! simple {
+    ($v:expr) => {
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            dbg!($v);
+        }
+    };
+}
+
+#[macro_export]
+#[rustfmt::skip] // for some reason rustfmt rewrites $r#unsafe to r#u$nsafe, bug?
+macro_rules! raw_symbol {
+    ($r#mod:expr, $r#unsafe:expr) => {
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            $r#mod;
+        }
+        $r#unsafe;
+    };
+}
+
+#[macro_export]
+macro_rules! multilevel_unsafe {
+    ($v:expr) => {
+        unsafe {
+            unsafe {
+                //~^ ERROR: this macro expands metavariables in an unsafe block
+                $v;
+            }
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! in_function {
+    ($v:expr) => {
+        unsafe {
+            fn f() {
+                // function introduces a new body, so don't lint.
+                $v;
+            }
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! in_function_with_unsafe {
+    ($v:expr) => {
+        unsafe {
+            fn f() {
+                unsafe {
+                    //~^ ERROR: this macro expands metavariables in an unsafe block
+                    $v;
+                }
+            }
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! const_static {
+    ($c:expr, $s:expr) => {
+        unsafe {
+            // const and static introduces new body, don't lint
+            const _X: i32 = $c;
+            static _Y: i32 = $s;
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! const_generic_in_struct {
+    ($inside_unsafe:expr, $outside_unsafe:expr) => {
+        unsafe {
+            struct Ty<
+                const L: i32 = 1,
+                const M: i32 = {
+                    1;
+                    unsafe { $inside_unsafe }
+                    //~^ ERROR: this macro expands metavariables in an unsafe block
+                },
+                const N: i32 = { $outside_unsafe },
+            >;
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! fn_with_const_generic {
+    ($inside_unsafe:expr, $outside_unsafe:expr) => {
+        unsafe {
+            fn f<const N: usize>() {
+                $outside_unsafe;
+                unsafe {
+                    //~^ ERROR: this macro expands metavariables in an unsafe block
+                    $inside_unsafe;
+                }
+            }
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! variables {
+    ($inside_unsafe:expr, $outside_unsafe:expr) => {
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            $inside_unsafe;
+            let inside_unsafe = 1;
+            inside_unsafe;
+        }
+        $outside_unsafe;
+        let outside_unsafe = 1;
+        outside_unsafe;
+    };
+}
+
+#[macro_export]
+macro_rules! multiple_matchers {
+    ($inside_unsafe:expr, $outside_unsafe:expr) => {
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            $inside_unsafe;
+        }
+        $outside_unsafe;
+    };
+    ($($v:expr, $x:expr),+) => {
+        $(
+            $v;
+            unsafe {
+                //~^ ERROR: this macro expands metavariables in an unsafe block
+                $x;
+            }
+        );+
+    };
+}
+
+#[macro_export]
+macro_rules! multiple_unsafe_blocks {
+    ($w:expr, $x:expr, $y:expr) => {
+        $w;
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            $x;
+        }
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            $x;
+            $y;
+        }
+    };
+}
+
+pub macro macro2_0($v:expr) {
+    unsafe {
+        //~^ ERROR: this macro expands metavariables in an unsafe block
+        $v;
+    }
+}
+
+// don't lint private macros with the default configuration
+macro_rules! private_mac {
+    ($v:expr) => {
+        unsafe {
+            $v;
+        }
+    };
+}
+
+// don't lint exported macros that are doc(hidden) because they also aren't part of the public API
+#[macro_export]
+#[doc(hidden)]
+macro_rules! exported_but_hidden {
+    ($v:expr) => {
+        unsafe {
+            $v;
+        }
+    };
+}
+
+// don't lint if the same metavariable is expanded in an unsafe block and then outside of one:
+// unsafe {} is still needed at callsite so not problematic
+#[macro_export]
+macro_rules! does_require_unsafe {
+    ($v:expr) => {
+        unsafe {
+            $v;
+        }
+        $v;
+    };
+}
+
+#[macro_export]
+macro_rules! unsafe_from_root_ctxt {
+    ($v:expr) => {
+        // Expands to unsafe { 1 }, but the unsafe block is from the root ctxt and not this macro,
+        // so no warning.
+        $v;
+    };
+}
+
+// invoked from another macro, should still generate a warning
+#[macro_export]
+macro_rules! nested_macro_helper {
+    ($v:expr) => {{
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            $v;
+        }
+    }};
+}
+
+#[macro_export]
+macro_rules! nested_macros {
+    ($v:expr, $v2:expr) => {{
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            nested_macro_helper!($v);
+            $v;
+        }
+    }};
+}
+
+fn main() {
+    allow_works!(1);
+    simple!(1);
+    raw_symbol!(1, 1);
+    multilevel_unsafe!(1);
+    in_function!(1);
+    in_function_with_unsafe!(1);
+    const_static!(1, 1);
+    const_generic_in_struct!(1, 1);
+    fn_with_const_generic!(1, 1);
+    variables!(1, 1);
+    multiple_matchers!(1, 1);
+    multiple_matchers!(1, 1, 1, 1);
+    macro2_0!(1);
+    private_mac!(1);
+    exported_but_hidden!(1);
+    does_require_unsafe!(1);
+    multiple_unsafe_blocks!(1, 1, 1);
+    unsafe_from_root_ctxt!(unsafe { 1 });
+    nested_macros!(1, 1);
+}
diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr
new file mode 100644
index 00000000000..d6b97f6fde1
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr
@@ -0,0 +1,187 @@
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             dbg!($v);
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+   = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]`
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:30:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             $r#mod;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:42:13
+   |
+LL | /             unsafe {
+LL | |
+LL | |                 $v;
+LL | |             }
+   | |_____________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:67:17
+   |
+LL | /                 unsafe {
+LL | |
+LL | |                     $v;
+LL | |                 }
+   | |_________________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:95:21
+   |
+LL |                     unsafe { $inside_unsafe }
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:110:17
+   |
+LL | /                 unsafe {
+LL | |
+LL | |                     $inside_unsafe;
+LL | |                 }
+   | |_________________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:122:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             $inside_unsafe;
+LL | |             let inside_unsafe = 1;
+LL | |             inside_unsafe;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:137:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             $inside_unsafe;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:146:13
+   |
+LL | /             unsafe {
+LL | |
+LL | |                 $x;
+LL | |             }
+   | |_____________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:171:5
+   |
+LL | /     unsafe {
+LL | |
+LL | |         $v;
+LL | |     }
+   | |_____^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:158:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             $x;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:162:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             $x;
+LL | |             $y;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:222:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             $v;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:232:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             nested_macro_helper!($v);
+LL | |             $v;
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+
+error: aborting due to 14 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml
new file mode 100644
index 00000000000..d4bbc2a1be8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml
@@ -0,0 +1 @@
+warn-unsafe-macro-metavars-in-private-macros = true
diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs
new file mode 100644
index 00000000000..2bbe1fa7b7f
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs
@@ -0,0 +1,15 @@
+//! Tests macro_metavars_in_unsafe with private (non-exported) macros
+#![warn(clippy::macro_metavars_in_unsafe)]
+
+macro_rules! mac {
+    ($v:expr) => {
+        unsafe {
+            //~^ ERROR: this macro expands metavariables in an unsafe block
+            dbg!($v);
+        }
+    };
+}
+
+fn main() {
+    mac!(1);
+}
diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr
new file mode 100644
index 00000000000..f9c418b2218
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr
@@ -0,0 +1,17 @@
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/private/test.rs:6:9
+   |
+LL | /         unsafe {
+LL | |
+LL | |             dbg!($v);
+LL | |         }
+   | |_________^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+   = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/panic/clippy.toml b/src/tools/clippy/tests/ui-toml/panic/clippy.toml
new file mode 100644
index 00000000000..5d6230d092c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/panic/clippy.toml
@@ -0,0 +1 @@
+allow-panic-in-tests = true
diff --git a/src/tools/clippy/tests/ui-toml/panic/panic.rs b/src/tools/clippy/tests/ui-toml/panic/panic.rs
new file mode 100644
index 00000000000..618a37ddfc5
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/panic/panic.rs
@@ -0,0 +1,54 @@
+//@compile-flags: --test
+#![warn(clippy::panic)]
+
+fn main() {
+    enum Enam {
+        A,
+    }
+    let a = Enam::A;
+    match a {
+        Enam::A => {},
+        _ => panic!(""),
+    }
+}
+
+#[test]
+fn lonely_test() {
+    enum Enam {
+        A,
+    }
+    let a = Enam::A;
+    match a {
+        Enam::A => {},
+        _ => panic!(""),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    // should not lint in `#[cfg(test)]` modules
+    #[test]
+    fn test_fn() {
+        enum Enam {
+            A,
+        }
+        let a = Enam::A;
+        match a {
+            Enam::A => {},
+            _ => panic!(""),
+        }
+
+        bar();
+    }
+
+    fn bar() {
+        enum Enam {
+            A,
+        }
+        let a = Enam::A;
+        match a {
+            Enam::A => {},
+            _ => panic!(""),
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui-toml/panic/panic.stderr b/src/tools/clippy/tests/ui-toml/panic/panic.stderr
new file mode 100644
index 00000000000..bf7503e086c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/panic/panic.stderr
@@ -0,0 +1,11 @@
+error: `panic` should not be present in production code
+  --> tests/ui-toml/panic/panic.rs:11:14
+   |
+LL |         _ => panic!(""),
+   |              ^^^^^^^^^^
+   |
+   = note: `-D clippy::panic` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::panic)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/renamed_function_params/default/clippy.toml b/src/tools/clippy/tests/ui-toml/renamed_function_params/default/clippy.toml
new file mode 100644
index 00000000000..5381e70a939
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/renamed_function_params/default/clippy.toml
@@ -0,0 +1,2 @@
+# Ignore `From`, `TryFrom`, `FromStr` by default
+# allow-renamed-params-for = []
diff --git a/src/tools/clippy/tests/ui-toml/renamed_function_params/extend/clippy.toml b/src/tools/clippy/tests/ui-toml/renamed_function_params/extend/clippy.toml
new file mode 100644
index 00000000000..9b3853e7696
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/renamed_function_params/extend/clippy.toml
@@ -0,0 +1,2 @@
+# Ignore `From`, `TryFrom`, `FromStr` by default
+allow-renamed-params-for = [ "..", "std::ops::Add", "renamed_function_params::MyTrait" ]
diff --git a/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr b/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr
new file mode 100644
index 00000000000..2d700f60759
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr
@@ -0,0 +1,46 @@
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:30:18
+   |
+LL |     fn eq(&self, rhs: &Self) -> bool {
+   |                  ^^^ help: consider using the default name: `other`
+   |
+   = note: `-D clippy::renamed-function-params` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]`
+
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:34:18
+   |
+LL |     fn ne(&self, rhs: &Self) -> bool {
+   |                  ^^^ help: consider using the default name: `other`
+
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:48:19
+   |
+LL |     fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend`
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the default name: `val`
+
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:55:31
+   |
+LL |     fn hash<H: Hasher>(&self, states: &mut H) {
+   |                               ^^^^^^ help: consider using the default name: `state`
+
+error: renamed function parameters of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:59:30
+   |
+LL |     fn hash_slice<H: Hasher>(date: &[Self], states: &mut H) {
+   |                              ^^^^           ^^^^^^
+   |
+help: consider using the default names
+   |
+LL |     fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) {
+   |                              ~~~~           ~~~~~
+
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:80:18
+   |
+LL |     fn add(self, b: B) -> C {
+   |                  ^ help: consider using the default name: `rhs`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr b/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr
new file mode 100644
index 00000000000..e57554fa613
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr
@@ -0,0 +1,34 @@
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:30:18
+   |
+LL |     fn eq(&self, rhs: &Self) -> bool {
+   |                  ^^^ help: consider using the default name: `other`
+   |
+   = note: `-D clippy::renamed-function-params` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]`
+
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:34:18
+   |
+LL |     fn ne(&self, rhs: &Self) -> bool {
+   |                  ^^^ help: consider using the default name: `other`
+
+error: renamed function parameter of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:55:31
+   |
+LL |     fn hash<H: Hasher>(&self, states: &mut H) {
+   |                               ^^^^^^ help: consider using the default name: `state`
+
+error: renamed function parameters of trait impl
+  --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:59:30
+   |
+LL |     fn hash_slice<H: Hasher>(date: &[Self], states: &mut H) {
+   |                              ^^^^           ^^^^^^
+   |
+help: consider using the default names
+   |
+LL |     fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) {
+   |                              ~~~~           ~~~~~
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.rs b/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.rs
new file mode 100644
index 00000000000..f3eb910abbd
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/renamed_function_params/renamed_function_params.rs
@@ -0,0 +1,110 @@
+//@no-rustfix
+//@revisions: default extend
+//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/renamed_function_params/default
+//@[extend] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/renamed_function_params/extend
+#![warn(clippy::renamed_function_params)]
+#![allow(clippy::partialeq_ne_impl, clippy::to_string_trait_impl)]
+#![allow(unused)]
+
+use std::hash::{Hash, Hasher};
+
+struct A;
+impl From<A> for String {
+    fn from(_value: A) -> Self {
+        String::new()
+    }
+}
+impl ToString for A {
+    fn to_string(&self) -> String {
+        String::new()
+    }
+}
+
+struct B(u32);
+impl std::convert::From<B> for String {
+    fn from(b: B) -> Self {
+        b.0.to_string()
+    }
+}
+impl PartialEq for B {
+    fn eq(&self, rhs: &Self) -> bool {
+        //~^ ERROR: renamed function parameter of trait impl
+        self.0 == rhs.0
+    }
+    fn ne(&self, rhs: &Self) -> bool {
+        //~^ ERROR: renamed function parameter of trait impl
+        self.0 != rhs.0
+    }
+}
+
+trait MyTrait {
+    fn foo(&self, val: u8);
+    fn bar(a: u8, b: u8);
+    fn baz(self, _val: u8);
+    fn quz(&self, _: u8);
+}
+
+impl MyTrait for B {
+    fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend`
+    fn bar(_a: u8, _: u8) {}
+    fn baz(self, val: u8) {}
+    fn quz(&self, val: u8) {}
+}
+
+impl Hash for B {
+    fn hash<H: Hasher>(&self, states: &mut H) {
+        //~^ ERROR: renamed function parameter of trait impl
+        self.0.hash(states);
+    }
+    fn hash_slice<H: Hasher>(date: &[Self], states: &mut H) {
+        //~^ ERROR: renamed function parameters of trait impl
+        for d in date {
+            d.hash(states);
+        }
+    }
+}
+
+impl B {
+    fn totally_irrelevant(&self, right: bool) {}
+    fn some_fn(&self, other: impl MyTrait) {}
+}
+
+#[derive(Copy, Clone)]
+enum C {
+    A,
+    B(u32),
+}
+
+impl std::ops::Add<B> for C {
+    type Output = C;
+    fn add(self, b: B) -> C {
+        // only lint in `extend`
+        C::B(b.0)
+    }
+}
+
+impl From<A> for C {
+    fn from(_: A) -> C {
+        C::A
+    }
+}
+
+trait CustomTraitA {
+    fn foo(&self, other: u32);
+}
+trait CustomTraitB {
+    fn bar(&self, value: u8);
+}
+
+macro_rules! impl_trait {
+    ($impl_for:ident, $tr:ty, $fn_name:ident, $t:ty) => {
+        impl $tr for $impl_for {
+            fn $fn_name(&self, v: $t) {}
+        }
+    };
+}
+
+impl_trait!(C, CustomTraitA, foo, u32);
+impl_trait!(C, CustomTraitB, bar, u8);
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs
index 7f28efd676f..f02bd07cfe7 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs
@@ -40,3 +40,9 @@ fn main() {
     let _ = HashMap;
     let _: usize = 64_usize;
 }
+
+mod useless_attribute {
+    // Regression test for https://github.com/rust-lang/rust-clippy/issues/12753
+    #[allow(clippy::disallowed_types)]
+    use std::collections::HashMap;
+}
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 722e9b3bc8d..5cf9c0fb271 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -8,8 +8,10 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            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-renamed-params-for
            allow-unwrap-in-tests
            allow-useless-vec-in-tests
            allowed-dotfiles
@@ -74,6 +76,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            vec-box-size-threshold
            verbose-bit-mask-threshold
            warn-on-all-wildcard-imports
+           warn-unsafe-macro-metavars-in-private-macros
   --> $DIR/tests/ui-toml/toml_unknown_key/clippy.toml:2:1
    |
 LL | foobar = 42
@@ -89,8 +92,10 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            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-renamed-params-for
            allow-unwrap-in-tests
            allow-useless-vec-in-tests
            allowed-dotfiles
@@ -155,6 +160,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            vec-box-size-threshold
            verbose-bit-mask-threshold
            warn-on-all-wildcard-imports
+           warn-unsafe-macro-metavars-in-private-macros
   --> $DIR/tests/ui-toml/toml_unknown_key/clippy.toml:4:1
    |
 LL | barfoo = 53
@@ -170,8 +176,10 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            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-renamed-params-for
            allow-unwrap-in-tests
            allow-useless-vec-in-tests
            allowed-dotfiles
@@ -236,6 +244,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            vec-box-size-threshold
            verbose-bit-mask-threshold
            warn-on-all-wildcard-imports
+           warn-unsafe-macro-metavars-in-private-macros
   --> $DIR/tests/ui-toml/toml_unknown_key/clippy.toml:7:1
    |
 LL | allow_mixed_uninlined_format_args = true
diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed
index 8387c7d6156..70ab43b49b3 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.fixed
+++ b/src/tools/clippy/tests/ui/assigning_clones.fixed
@@ -62,6 +62,16 @@ fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFr
     mut_thing.clone_from(ref_thing + ref_thing);
 }
 
+fn clone_method_macro() {
+    let mut s = String::from("");
+    s.clone_from(&format!("{} {}", "hello", "world"));
+}
+
+fn clone_function_macro() {
+    let mut s = String::from("");
+    Clone::clone_from(&mut s, &format!("{} {}", "hello", "world"));
+}
+
 fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom {
     let mut a = HasCloneFrom;
     for _ in 1..10 {
@@ -86,6 +96,12 @@ fn assign_to_uninit_mut_var(b: HasCloneFrom) {
     a = b.clone();
 }
 
+fn late_init_let_tuple() {
+    let (p, q): (String, String);
+    p = "ghi".to_string();
+    q = p.clone();
+}
+
 #[derive(Clone)]
 pub struct HasDeriveClone;
 
@@ -208,6 +224,16 @@ fn owned_function_val(mut mut_thing: String, ref_str: &str) {
     ToOwned::clone_into(ref_str, &mut mut_thing);
 }
 
+fn owned_method_macro() {
+    let mut s = String::from("");
+    format!("{} {}", "hello", "world").clone_into(&mut s);
+}
+
+fn owned_function_macro() {
+    let mut s = String::from("");
+    ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s);
+}
+
 struct FakeToOwned;
 impl FakeToOwned {
     /// This looks just like `ToOwned::to_owned`
diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs
index 6f4da9f652c..9699fed100c 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.rs
+++ b/src/tools/clippy/tests/ui/assigning_clones.rs
@@ -62,6 +62,16 @@ fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFr
     *mut_thing = (ref_thing + ref_thing).clone();
 }
 
+fn clone_method_macro() {
+    let mut s = String::from("");
+    s = format!("{} {}", "hello", "world").clone();
+}
+
+fn clone_function_macro() {
+    let mut s = String::from("");
+    s = Clone::clone(&format!("{} {}", "hello", "world"));
+}
+
 fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom {
     let mut a = HasCloneFrom;
     for _ in 1..10 {
@@ -86,6 +96,12 @@ fn assign_to_uninit_mut_var(b: HasCloneFrom) {
     a = b.clone();
 }
 
+fn late_init_let_tuple() {
+    let (p, q): (String, String);
+    p = "ghi".to_string();
+    q = p.clone();
+}
+
 #[derive(Clone)]
 pub struct HasDeriveClone;
 
@@ -208,6 +224,16 @@ fn owned_function_val(mut mut_thing: String, ref_str: &str) {
     mut_thing = ToOwned::to_owned(ref_str);
 }
 
+fn owned_method_macro() {
+    let mut s = String::from("");
+    s = format!("{} {}", "hello", "world").to_owned();
+}
+
+fn owned_function_macro() {
+    let mut s = String::from("");
+    s = ToOwned::to_owned(&format!("{} {}", "hello", "world"));
+}
+
 struct FakeToOwned;
 impl FakeToOwned {
     /// This looks just like `ToOwned::to_owned`
diff --git a/src/tools/clippy/tests/ui/assigning_clones.stderr b/src/tools/clippy/tests/ui/assigning_clones.stderr
index 793927bd1cb..a68516376ab 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.stderr
+++ b/src/tools/clippy/tests/ui/assigning_clones.stderr
@@ -62,64 +62,88 @@ LL |     *mut_thing = (ref_thing + ref_thing).clone();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing + ref_thing)`
 
 error: assigning the result of `Clone::clone()` may be inefficient
-  --> tests/ui/assigning_clones.rs:68:9
+  --> tests/ui/assigning_clones.rs:67:5
+   |
+LL |     s = format!("{} {}", "hello", "world").clone();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `s.clone_from(&format!("{} {}", "hello", "world"))`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:72:5
+   |
+LL |     s = Clone::clone(&format!("{} {}", "hello", "world"));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut s, &format!("{} {}", "hello", "world"))`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:78:9
    |
 LL |         a = b.clone();
    |         ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
 
 error: assigning the result of `Clone::clone()` may be inefficient
-  --> tests/ui/assigning_clones.rs:133:5
+  --> tests/ui/assigning_clones.rs:149:5
    |
 LL |     a = b.clone();
    |     ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
 
 error: assigning the result of `Clone::clone()` may be inefficient
-  --> tests/ui/assigning_clones.rs:140:5
+  --> tests/ui/assigning_clones.rs:156:5
    |
 LL |     a = b.clone();
    |     ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:141:5
+  --> tests/ui/assigning_clones.rs:157:5
    |
 LL |     a = c.to_owned();
    |     ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:171:5
+  --> tests/ui/assigning_clones.rs:187:5
    |
 LL |     *mut_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:175:5
+  --> tests/ui/assigning_clones.rs:191:5
    |
 LL |     mut_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:196:5
+  --> tests/ui/assigning_clones.rs:212:5
    |
 LL |     **mut_box_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:200:5
+  --> tests/ui/assigning_clones.rs:216:5
    |
 LL |     **mut_box_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:204:5
+  --> tests/ui/assigning_clones.rs:220:5
    |
 LL |     *mut_thing = ToOwned::to_owned(ref_str);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:208:5
+  --> tests/ui/assigning_clones.rs:224:5
    |
 LL |     mut_thing = ToOwned::to_owned(ref_str);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`
 
-error: aborting due to 20 previous errors
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:229:5
+   |
+LL |     s = format!("{} {}", "hello", "world").to_owned();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `format!("{} {}", "hello", "world").clone_into(&mut s)`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:234:5
+   |
+LL |     s = ToOwned::to_owned(&format!("{} {}", "hello", "world"));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s)`
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.fixed b/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.fixed
new file mode 100644
index 00000000000..9877991f183
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.fixed
@@ -0,0 +1,47 @@
+#![warn(clippy::doc_lazy_continuation)]
+
+/// > blockquote with
+/// > lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn first() {}
+
+/// > blockquote with no
+/// > lazy continuation
+fn first_nowarn() {}
+
+/// > blockquote with no
+///
+/// lazy continuation
+fn two_nowarn() {}
+
+/// > nest here
+/// >
+/// > > nest here
+/// > > lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn two() {}
+
+/// > nest here
+/// >
+/// > > nest here
+/// > > lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn three() {}
+
+/// >   * > nest here
+/// >     > lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn four() {}
+
+/// > * > nest here
+/// >   > lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn four_point_1() {}
+
+/// * > nest here lazy continuation
+fn five() {}
+
+/// 1. > nest here
+///    > lazy continuation (this results in strange indentation, but still works)
+//~^ ERROR: doc quote missing `>` marker
+fn six() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.rs b/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.rs
new file mode 100644
index 00000000000..587b2fdd533
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.rs
@@ -0,0 +1,47 @@
+#![warn(clippy::doc_lazy_continuation)]
+
+/// > blockquote with
+/// lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn first() {}
+
+/// > blockquote with no
+/// > lazy continuation
+fn first_nowarn() {}
+
+/// > blockquote with no
+///
+/// lazy continuation
+fn two_nowarn() {}
+
+/// > nest here
+/// >
+/// > > nest here
+/// > lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn two() {}
+
+/// > nest here
+/// >
+/// > > nest here
+/// lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn three() {}
+
+/// >   * > nest here
+/// lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn four() {}
+
+/// > * > nest here
+/// lazy continuation
+//~^ ERROR: doc quote missing `>` marker
+fn four_point_1() {}
+
+/// * > nest here lazy continuation
+fn five() {}
+
+/// 1. > nest here
+///  lazy continuation (this results in strange indentation, but still works)
+//~^ ERROR: doc quote missing `>` marker
+fn six() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.stderr b/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.stderr
new file mode 100644
index 00000000000..975184a01c3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_blockquote.stderr
@@ -0,0 +1,76 @@
+error: doc quote missing `>` marker
+  --> tests/ui/doc/doc_lazy_blockquote.rs:4:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this not intended to be a quote at all, escape it with `\>`
+   = note: `-D clippy::doc-lazy-continuation` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::doc_lazy_continuation)]`
+help: add markers to start of line
+   |
+LL | /// > lazy continuation
+   |     +
+
+error: doc quote missing `>` marker
+  --> tests/ui/doc/doc_lazy_blockquote.rs:20:5
+   |
+LL | /// > lazy continuation
+   |     ^^
+   |
+   = help: if this not intended to be a quote at all, escape it with `\>`
+help: add markers to start of line
+   |
+LL | /// > > lazy continuation
+   |       +
+
+error: doc quote missing `>` marker
+  --> tests/ui/doc/doc_lazy_blockquote.rs:27:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this not intended to be a quote at all, escape it with `\>`
+help: add markers to start of line
+   |
+LL | /// > > lazy continuation
+   |     +++
+
+error: doc quote missing `>` marker
+  --> tests/ui/doc/doc_lazy_blockquote.rs:32:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this not intended to be a quote at all, escape it with `\>`
+help: add markers to start of line
+   |
+LL | /// >     > lazy continuation
+   |     +++++++
+
+error: doc quote missing `>` marker
+  --> tests/ui/doc/doc_lazy_blockquote.rs:37:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this not intended to be a quote at all, escape it with `\>`
+help: add markers to start of line
+   |
+LL | /// >   > lazy continuation
+   |     +++++
+
+error: doc quote missing `>` marker
+  --> tests/ui/doc/doc_lazy_blockquote.rs:45:5
+   |
+LL | ///  lazy continuation (this results in strange indentation, but still works)
+   |     ^
+   |
+   = help: if this not intended to be a quote at all, escape it with `\>`
+help: add markers to start of line
+   |
+LL | ///    > lazy continuation (this results in strange indentation, but still works)
+   |        +
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed b/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed
new file mode 100644
index 00000000000..409e6b0bc22
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed
@@ -0,0 +1,77 @@
+#![warn(clippy::doc_lazy_continuation)]
+
+/// 1. nest here
+///    lazy continuation
+//~^ ERROR: doc list item missing indentation
+fn one() {}
+
+/// 1. first line
+///    lazy list continuations don't make warnings with this lint
+//~^ ERROR: doc list item missing indentation
+///    because they don't have the
+//~^ ERROR: doc list item missing indentation
+fn two() {}
+
+///   - nest here
+///     lazy continuation
+//~^ ERROR: doc list item missing indentation
+fn three() {}
+
+///   - first line
+///     lazy list continuations don't make warnings with this lint
+//~^ ERROR: doc list item missing indentation
+///     because they don't have the
+//~^ ERROR: doc list item missing indentation
+fn four() {}
+
+///   - nest here
+///     lazy continuation
+//~^ ERROR: doc list item missing indentation
+fn five() {}
+
+///   - - first line
+///       this will warn on the lazy continuation
+//~^ ERROR: doc list item missing indentation
+///       and so should this
+//~^ ERROR: doc list item missing indentation
+fn six() {}
+
+///   - - first line
+///
+///     this is not a lazy continuation
+fn seven() {}
+
+#[rustfmt::skip]
+// https://github.com/rust-lang/rust-clippy/pull/12770#issuecomment-2118601768
+/// Returns a list of ProtocolDescriptors from a Serde JSON input.
+///
+/// Defined Protocol Identifiers for the Protocol Descriptor
+/// We intentionally omit deprecated profile identifiers.
+/// From Bluetooth Assigned Numbers:
+/// https://www.bluetooth.com/specifications/assigned-numbers/service-discovery
+///
+/// # Arguments
+/// * `protocol_descriptors`: A Json Representation of the ProtocolDescriptors
+///     to set up. Example:
+///   'protocol_descriptors': [
+//~^ ERROR: doc list item missing indentation
+///      {
+///          'protocol': 25,  # u64 Representation of ProtocolIdentifier::AVDTP
+///          'params': [
+///              {
+///                 'data': 0x0103  # to indicate 1.3
+///              },
+///              {
+///                  'data': 0x0105  # to indicate 1.5
+///              }
+///          ]
+///      },
+///      {
+///          'protocol': 1,  # u64 Representation of ProtocolIdentifier::SDP
+///          'params': [{
+///              'data': 0x0019
+///          }]
+///      }
+///   ]
+//~^ ERROR: doc list item missing indentation
+fn eight() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_list.rs b/src/tools/clippy/tests/ui/doc/doc_lazy_list.rs
new file mode 100644
index 00000000000..30ab448a113
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_list.rs
@@ -0,0 +1,77 @@
+#![warn(clippy::doc_lazy_continuation)]
+
+/// 1. nest here
+/// lazy continuation
+//~^ ERROR: doc list item missing indentation
+fn one() {}
+
+/// 1. first line
+/// lazy list continuations don't make warnings with this lint
+//~^ ERROR: doc list item missing indentation
+/// because they don't have the
+//~^ ERROR: doc list item missing indentation
+fn two() {}
+
+///   - nest here
+/// lazy continuation
+//~^ ERROR: doc list item missing indentation
+fn three() {}
+
+///   - first line
+/// lazy list continuations don't make warnings with this lint
+//~^ ERROR: doc list item missing indentation
+/// because they don't have the
+//~^ ERROR: doc list item missing indentation
+fn four() {}
+
+///   - nest here
+/// lazy continuation
+//~^ ERROR: doc list item missing indentation
+fn five() {}
+
+///   - - first line
+/// this will warn on the lazy continuation
+//~^ ERROR: doc list item missing indentation
+///     and so should this
+//~^ ERROR: doc list item missing indentation
+fn six() {}
+
+///   - - first line
+///
+///     this is not a lazy continuation
+fn seven() {}
+
+#[rustfmt::skip]
+// https://github.com/rust-lang/rust-clippy/pull/12770#issuecomment-2118601768
+/// Returns a list of ProtocolDescriptors from a Serde JSON input.
+///
+/// Defined Protocol Identifiers for the Protocol Descriptor
+/// We intentionally omit deprecated profile identifiers.
+/// From Bluetooth Assigned Numbers:
+/// https://www.bluetooth.com/specifications/assigned-numbers/service-discovery
+///
+/// # Arguments
+/// * `protocol_descriptors`: A Json Representation of the ProtocolDescriptors
+///     to set up. Example:
+///  'protocol_descriptors': [
+//~^ ERROR: doc list item missing indentation
+///      {
+///          'protocol': 25,  # u64 Representation of ProtocolIdentifier::AVDTP
+///          'params': [
+///              {
+///                 'data': 0x0103  # to indicate 1.3
+///              },
+///              {
+///                  'data': 0x0105  # to indicate 1.5
+///              }
+///          ]
+///      },
+///      {
+///          'protocol': 1,  # u64 Representation of ProtocolIdentifier::SDP
+///          'params': [{
+///              'data': 0x0019
+///          }]
+///      }
+///  ]
+//~^ ERROR: doc list item missing indentation
+fn eight() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr b/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr
new file mode 100644
index 00000000000..ddfdc49340c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr
@@ -0,0 +1,136 @@
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:4:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+   = note: `-D clippy::doc-lazy-continuation` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::doc_lazy_continuation)]`
+help: indent this line
+   |
+LL | ///    lazy continuation
+   |     +++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:9:5
+   |
+LL | /// lazy list continuations don't make warnings with this lint
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///    lazy list continuations don't make warnings with this lint
+   |     +++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:11:5
+   |
+LL | /// because they don't have the
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///    because they don't have the
+   |     +++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:16:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///     lazy continuation
+   |     ++++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:21:5
+   |
+LL | /// lazy list continuations don't make warnings with this lint
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///     lazy list continuations don't make warnings with this lint
+   |     ++++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:23:5
+   |
+LL | /// because they don't have the
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///     because they don't have the
+   |     ++++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:28:5
+   |
+LL | /// lazy continuation
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///     lazy continuation
+   |     ++++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:33:5
+   |
+LL | /// this will warn on the lazy continuation
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///       this will warn on the lazy continuation
+   |     ++++++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:35:5
+   |
+LL | ///     and so should this
+   |     ^^^^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///       and so should this
+   |         ++
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:56:5
+   |
+LL | ///  'protocol_descriptors': [
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///   'protocol_descriptors': [
+   |      +
+
+error: doc list item missing indentation
+  --> tests/ui/doc/doc_lazy_list.rs:75:5
+   |
+LL | ///  ]
+   |     ^
+   |
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
+   |
+LL | ///   ]
+   |      +
+
+error: aborting due to 11 previous errors
+
diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.rs b/src/tools/clippy/tests/ui/duplicated_attributes.rs
index d51e7e37beb..97cf4a69682 100644
--- a/src/tools/clippy/tests/ui/duplicated_attributes.rs
+++ b/src/tools/clippy/tests/ui/duplicated_attributes.rs
@@ -1,5 +1,5 @@
 //@aux-build:proc_macro_attr.rs
-
+#![feature(rustc_attrs)]
 #![warn(clippy::duplicated_attributes)]
 #![cfg(any(unix, windows))]
 #![allow(dead_code)]
@@ -20,6 +20,10 @@ fn foo() {}
 #[cfg(unix)] // cfgs are not handled
 fn bar() {}
 
+// No warning:
+#[rustc_on_unimplemented(on(_Self = "&str", label = "`a"), on(_Self = "alloc::string::String", label = "a"))]
+trait Abc {}
+
 #[proc_macro_attr::duplicated_attr()] // Should not warn!
 fn babar() {}
 
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 8c253bfd99a..f9ce1defda1 100644
--- a/src/tools/clippy/tests/ui/from_str_radix_10.fixed
+++ b/src/tools/clippy/tests/ui/from_str_radix_10.fixed
@@ -1,3 +1,4 @@
+#![feature(const_int_from_str)]
 #![warn(clippy::from_str_radix_10)]
 
 mod some_mod {
@@ -59,3 +60,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
 
     Ok(())
 }
+
+fn issue_12732() {
+    const A: Result<u32, std::num::ParseIntError> = u32::from_str_radix("123", 10);
+    const B: () = {
+        let _ = u32::from_str_radix("123", 10);
+    };
+    const fn foo() {
+        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 e9d02215710..2d5b351f8da 100644
--- a/src/tools/clippy/tests/ui/from_str_radix_10.rs
+++ b/src/tools/clippy/tests/ui/from_str_radix_10.rs
@@ -1,3 +1,4 @@
+#![feature(const_int_from_str)]
 #![warn(clippy::from_str_radix_10)]
 
 mod some_mod {
@@ -59,3 +60,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
 
     Ok(())
 }
+
+fn issue_12732() {
+    const A: Result<u32, std::num::ParseIntError> = u32::from_str_radix("123", 10);
+    const B: () = {
+        let _ = u32::from_str_radix("123", 10);
+    };
+    const fn foo() {
+        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 4aa84eca261..01a1bf8940a 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:28:5
+  --> tests/ui/from_str_radix_10.rs:29: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:31:5
+  --> tests/ui/from_str_radix_10.rs:32: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:33:5
+  --> tests/ui/from_str_radix_10.rs:34: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:35:5
+  --> tests/ui/from_str_radix_10.rs:36: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:37:5
+  --> tests/ui/from_str_radix_10.rs:38: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:39:5
+  --> tests/ui/from_str_radix_10.rs:40: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:43:5
+  --> tests/ui/from_str_radix_10.rs:44: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:47:5
+  --> tests/ui/from_str_radix_10.rs:48:5
    |
 LL |     i32::from_str_radix(&stringier, 10)?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `stringier.parse::<i32>()`
diff --git a/src/tools/clippy/tests/ui/match_same_arms.stderr b/src/tools/clippy/tests/ui/match_same_arms.stderr
index a926570b60a..3c0382767c3 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms.stderr
@@ -2,7 +2,7 @@ error: this match arm has an identical body to the `_` wildcard arm
   --> tests/ui/match_same_arms.rs:12:9
    |
 LL |         Abc::A => 0,
-   |         ^^^^^^^^^^^ help: try removing the arm
+   |         ^^^^^^^^^^^^^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
@@ -17,106 +17,114 @@ error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:18:9
    |
 LL |         (1, .., 3) => 42,
-   |         ----------^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `(1, .., 3) | (.., 3)`
+   |         ^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:19:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         (1, .., 3) | (.., 3) => 42,
+   |         ~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         (.., 3) => 42,
    |
-LL |         (.., 3) => 42,
-   |         ^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:25:9
    |
 LL |         51 => 1,
-   |         --^^^^^
-   |         |
-   |         help: try merging the arm patterns: `51 | 42`
+   |         ^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:24:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         51 | 42 => 1,
+   |         ~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         42 => 1,
    |
-LL |         42 => 1,
-   |         ^^^^^^^
 
 error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:26:9
    |
 LL |         41 => 2,
-   |         --^^^^^
-   |         |
-   |         help: try merging the arm patterns: `41 | 52`
+   |         ^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:27:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         41 | 52 => 2,
+   |         ~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         52 => 2,
    |
-LL |         52 => 2,
-   |         ^^^^^^^
 
 error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:33:9
    |
 LL |         2 => 2,
-   |         -^^^^^
-   |         |
-   |         help: try merging the arm patterns: `2 | 1`
+   |         ^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:32:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         2 | 1 => 2,
+   |         ~~~~~
+help: and remove this obsolete arm
+   |
+LL -         1 => 2,
    |
-LL |         1 => 2,
-   |         ^^^^^^
 
 error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:35:9
    |
 LL |         3 => 2,
-   |         -^^^^^
-   |         |
-   |         help: try merging the arm patterns: `3 | 1`
+   |         ^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:32:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         3 | 1 => 2,
+   |         ~~~~~
+help: and remove this obsolete arm
+   |
+LL -         1 => 2,
    |
-LL |         1 => 2,
-   |         ^^^^^^
 
 error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:33:9
    |
 LL |         2 => 2,
-   |         -^^^^^
-   |         |
-   |         help: try merging the arm patterns: `2 | 3`
+   |         ^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:35:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         2 | 3 => 2,
+   |         ~~~~~
+help: and remove this obsolete arm
+   |
+LL -         3 => 2,
+LL +
    |
-LL |         3 => 2,
-   |         ^^^^^^
 
 error: this match arm has an identical body to another arm
   --> tests/ui/match_same_arms.rs:52:17
    |
 LL |                 CommandInfo::External { name, .. } => name.to_string(),
-   |                 ----------------------------------^^^^^^^^^^^^^^^^^^^^
-   |                 |
-   |                 help: try merging the arm patterns: `CommandInfo::External { name, .. } | CommandInfo::BuiltIn { name, .. }`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms.rs:51:17
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |                 CommandInfo::External { name, .. } | CommandInfo::BuiltIn { name, .. } => name.to_string(),
+   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
    |
-LL |                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.fixed b/src/tools/clippy/tests/ui/match_same_arms2.fixed
new file mode 100644
index 00000000000..fba0cf33b3c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_same_arms2.fixed
@@ -0,0 +1,241 @@
+#![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,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 85ad0962eb4..8a4e3b325bb 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -2,9 +2,10 @@
 #![allow(
     clippy::disallowed_names,
     clippy::diverging_sub_expression,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::match_single_binding,
+    clippy::match_like_matches_macro
 )]
-//@no-rustfix
 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 f4c38c1af89..3d15176ccf9 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -1,18 +1,18 @@
 error: this match arm has an identical body to the `_` wildcard arm
-  --> tests/ui/match_same_arms2.rs:15:9
+  --> tests/ui/match_same_arms2.rs:16:9
    |
 LL | /         42 => {
 LL | |             foo();
 LL | |             let mut a = 42 + [23].len() as i32;
 LL | |             if true {
 ...  |
-LL | |             a
 LL | |         },
-   | |_________^ help: try removing the arm
+LL | |         _ => {
+   | |________^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> tests/ui/match_same_arms2.rs:24:9
+  --> tests/ui/match_same_arms2.rs:25:9
    |
 LL | /         _ => {
 LL | |             foo();
@@ -26,203 +26,200 @@ 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:38:9
+  --> tests/ui/match_same_arms2.rs:39:9
    |
 LL |         51 => foo(),
-   |         --^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `51 | 42`
+   |         ^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:37:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         51 | 42 => foo(),
+   |         ~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         42 => foo(),
    |
-LL |         42 => foo(),
-   |         ^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:44:9
+  --> tests/ui/match_same_arms2.rs:45:9
    |
 LL |         None => 24,
-   |         ----^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `None | Some(_)`
+   |         ^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:43:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         None | Some(_) => 24,
+   |         ~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         Some(_) => 24,
    |
-LL |         Some(_) => 24,
-   |         ^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:66:9
+  --> tests/ui/match_same_arms2.rs:67:9
    |
 LL |         (None, Some(a)) => bar(a),
-   |         ---------------^^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:65:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         (None, Some(a)) | (Some(a), None) => bar(a),
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         (Some(a), None) => bar(a),
    |
-LL |         (Some(a), None) => bar(a),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:80:9
+  --> tests/ui/match_same_arms2.rs:81:9
    |
 LL |         (None, Some(a)) if a == 42 => a,
-   |         ---------------^^^^^^^^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:79:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         (None, Some(a)) | (Some(a), None) if a == 42 => a,
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         (Some(a), None) if a == 42 => a,
    |
-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:85:9
+  --> tests/ui/match_same_arms2.rs:86:9
    |
 LL |         (Some(a), ..) => bar(a),
-   |         -------------^^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `(Some(a), ..) | (.., Some(a))`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:86:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         (Some(a), ..) | (.., Some(a)) => bar(a),
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         (.., Some(a)) => bar(a),
    |
-LL |         (.., Some(a)) => bar(a),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:119:9
+  --> tests/ui/match_same_arms2.rs:120:9
    |
 LL |         (Ok(x), Some(_)) => println!("ok {}", x),
-   |         ----------------^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `(Ok(x), Some(_)) | (Ok(_), Some(x))`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:120:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x),
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         (Ok(_), Some(x)) => println!("ok {}", x),
    |
-LL |         (Ok(_), Some(x)) => println!("ok {}", x),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:135:9
+  --> tests/ui/match_same_arms2.rs:136:9
    |
 LL |         Ok(_) => println!("ok"),
-   |         -----^^^^^^^^^^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `Ok(_) | Ok(3)`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:134:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         Ok(_) | Ok(3) => println!("ok"),
+   |         ~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         Ok(3) => println!("ok"),
    |
-LL |         Ok(3) => println!("ok"),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:162:9
+  --> tests/ui/match_same_arms2.rs:163:9
    |
-LL |           1 => {
-   |           ^ help: try merging the arm patterns: `1 | 0`
-   |  _________|
-   | |
+LL | /         1 => {
 LL | |             empty!(0);
 LL | |         },
    | |_________^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:159:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         1 | 0 => {
+   |         ~~~~~
+help: and remove this obsolete arm
+   |
+LL -         0 => {
+LL -             empty!(0);
+LL -         },
    |
-LL | /         0 => {
-LL | |             empty!(0);
-LL | |         },
-   | |_________^
-
-error: match expression looks like `matches!` macro
-  --> tests/ui/match_same_arms2.rs:181:16
-   |
-LL |       let _ans = match x {
-   |  ________________^
-LL | |         E::A => false,
-LL | |         E::B => false,
-LL | |         _ => true,
-LL | |     };
-   | |_____^ help: try: `!matches!(x, E::A | E::B)`
-   |
-   = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::match_like_matches_macro)]`
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:213:9
+  --> tests/ui/match_same_arms2.rs:214:9
    |
 LL |         Foo::X(0) => 1,
-   |         ---------^^^^^
-   |         |
-   |         help: try merging the arm patterns: `Foo::X(0) | Foo::Z(_)`
+   |         ^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:215:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         Foo::X(0) | Foo::Z(_) => 1,
+   |         ~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         Foo::Z(_) => 1,
    |
-LL |         Foo::Z(_) => 1,
-   |         ^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:223:9
+  --> tests/ui/match_same_arms2.rs:224:9
    |
 LL |         Foo::Z(_) => 1,
-   |         ---------^^^^^
-   |         |
-   |         help: try merging the arm patterns: `Foo::Z(_) | Foo::X(0)`
+   |         ^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:221:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         Foo::Z(_) | Foo::X(0) => 1,
+   |         ~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         Foo::X(0) => 1,
    |
-LL |         Foo::X(0) => 1,
-   |         ^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> tests/ui/match_same_arms2.rs:246:9
+  --> tests/ui/match_same_arms2.rs:247:9
    |
 LL |         Some(Bar { y: 0, x: 5, .. }) => 1,
-   |         ----------------------------^^^^^
-   |         |
-   |         help: try merging the arm patterns: `Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. })`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:243:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1,
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -         Some(Bar { x: 0, y: 5, .. }) => 1,
    |
-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:260:9
+  --> tests/ui/match_same_arms2.rs:261:9
    |
 LL |         1 => cfg!(not_enable),
-   |         -^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         help: try merging the arm patterns: `1 | 0`
+   |         ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: or try changing either arm body
-note: other arm here
-  --> tests/ui/match_same_arms2.rs:259:9
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |         1 | 0 => cfg!(not_enable),
+   |         ~~~~~
+help: and remove this obsolete arm
+   |
+LL -         0 => cfg!(not_enable),
    |
-LL |         0 => cfg!(not_enable),
-   |         ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.fixed b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.fixed
new file mode 100644
index 00000000000..804c0a869a9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.fixed
@@ -0,0 +1,61 @@
+#![feature(non_exhaustive_omitted_patterns_lint)]
+#![warn(clippy::match_same_arms)]
+#![no_main]
+use std::sync::atomic::Ordering; // #[non_exhaustive] enum
+
+fn repeat() -> ! {
+    panic!()
+}
+
+pub fn f(x: Ordering) {
+    #[deny(non_exhaustive_omitted_patterns)]
+    match x {
+        Ordering::Relaxed => println!("relaxed"),
+        Ordering::Release => println!("release"),
+        Ordering::Acquire => println!("acquire"),
+        Ordering::AcqRel | Ordering::SeqCst => repeat(),
+        _ => repeat(),
+    }
+}
+
+mod f {
+    #![deny(non_exhaustive_omitted_patterns)]
+
+    use super::*;
+
+    pub fn f(x: Ordering) {
+        match x {
+            Ordering::Relaxed => println!("relaxed"),
+            Ordering::Release => println!("release"),
+            Ordering::Acquire => println!("acquire"),
+            Ordering::AcqRel | Ordering::SeqCst => repeat(),
+            _ => repeat(),
+        }
+    }
+}
+
+// Below should still lint
+
+pub fn g(x: Ordering) {
+    match x {
+        Ordering::Relaxed => println!("relaxed"),
+        Ordering::Release => println!("release"),
+        Ordering::Acquire => println!("acquire"),
+        //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
+        _ => repeat(),
+    }
+}
+
+mod g {
+    use super::*;
+
+    pub fn g(x: Ordering) {
+        match x {
+            Ordering::Relaxed => println!("relaxed"),
+            Ordering::Release => println!("release"),
+            Ordering::Acquire => println!("acquire"),
+            //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
+            _ => repeat(),
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
index 5c277f925a8..e50663932a1 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
@@ -1,7 +1,6 @@
 #![feature(non_exhaustive_omitted_patterns_lint)]
 #![warn(clippy::match_same_arms)]
 #![no_main]
-//@no-rustfix
 use std::sync::atomic::Ordering; // #[non_exhaustive] enum
 
 fn repeat() -> ! {
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
index cf2a75354e1..aa7f8c95dce 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
@@ -1,12 +1,13 @@
 error: this match arm has an identical body to the `_` wildcard arm
-  --> tests/ui/match_same_arms_non_exhaustive.rs:45:9
+  --> tests/ui/match_same_arms_non_exhaustive.rs:44:9
    |
-LL |         Ordering::AcqRel | Ordering::SeqCst => repeat(),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
+LL | /         Ordering::AcqRel | Ordering::SeqCst => repeat(),
+LL | |
+   | |________^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> tests/ui/match_same_arms_non_exhaustive.rs:47:9
+  --> tests/ui/match_same_arms_non_exhaustive.rs:46:9
    |
 LL |         _ => repeat(),
    |         ^^^^^^^^^^^^^
@@ -14,14 +15,15 @@ LL |         _ => repeat(),
    = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
 
 error: this match arm has an identical body to the `_` wildcard arm
-  --> tests/ui/match_same_arms_non_exhaustive.rs:59:13
+  --> tests/ui/match_same_arms_non_exhaustive.rs:58:13
    |
-LL |             Ordering::AcqRel | Ordering::SeqCst => repeat(),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
+LL | /             Ordering::AcqRel | Ordering::SeqCst => repeat(),
+LL | |
+   | |____________^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> tests/ui/match_same_arms_non_exhaustive.rs:61:13
+  --> tests/ui/match_same_arms_non_exhaustive.rs:60:13
    |
 LL |             _ => repeat(),
    |             ^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
index d026e009684..2750e0cdf3f 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
@@ -161,7 +161,23 @@ union U {
     f: u32,
 }
 
-// Do not lint because accessing union fields from const functions is unstable
+// Do not lint because accessing union fields from const functions is unstable in 1.55
+#[clippy::msrv = "1.55"]
 fn h(u: U) -> u32 {
     unsafe { u.f }
 }
+
+mod msrv {
+    struct Foo(*const u8, *mut u8);
+
+    impl Foo {
+        #[clippy::msrv = "1.57"]
+        fn deref_ptr_cannot_be_const(self) -> usize {
+            unsafe { *self.0 as usize }
+        }
+        #[clippy::msrv = "1.58"]
+        fn deref_mut_ptr_cannot_be_const(self) -> usize {
+            unsafe { *self.1 as usize }
+        }
+    }
+}
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 12a8320c8f3..06dbbeb31c0 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
@@ -113,3 +113,31 @@ impl const Drop for D {
 // Lint this, since it can be dropped in const contexts
 // FIXME(effects)
 fn d(this: D) {}
+
+mod msrv {
+    struct Foo(*const u8, &'static u8);
+
+    impl Foo {
+        #[clippy::msrv = "1.58"]
+        fn deref_ptr_can_be_const(self) -> usize {
+            //~^ ERROR: this could be a `const fn`
+            unsafe { *self.0 as usize }
+        }
+
+        fn deref_copied_val(self) -> usize {
+            //~^ ERROR: this could be a `const fn`
+            *self.1 as usize
+        }
+    }
+
+    union Bar {
+        val: u8,
+    }
+
+    #[clippy::msrv = "1.56"]
+    fn union_access_can_be_const() {
+        //~^ ERROR: this could be a `const fn`
+        let bar = Bar { val: 1 };
+        let _ = unsafe { bar.val };
+    }
+}
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
index 082459fd821..b2cade30563 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -102,5 +102,33 @@ LL | |     46
 LL | | }
    | |_^
 
-error: aborting due to 11 previous errors
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:122:9
+   |
+LL | /         fn deref_ptr_can_be_const(self) -> usize {
+LL | |
+LL | |             unsafe { *self.0 as usize }
+LL | |         }
+   | |_________^
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:127:9
+   |
+LL | /         fn deref_copied_val(self) -> usize {
+LL | |
+LL | |             *self.1 as usize
+LL | |         }
+   | |_________^
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:138:5
+   |
+LL | /     fn union_access_can_be_const() {
+LL | |
+LL | |         let bar = Bar { val: 1 };
+LL | |         let _ = unsafe { bar.val };
+LL | |     }
+   | |_____^
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.rs b/src/tools/clippy/tests/ui/missing_panics_doc.rs
index 0e1533fc1ab..b0fa8e98859 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.rs
@@ -191,3 +191,11 @@ fn from_declared_macro_should_lint_at_macrosite() {
     // Not here.
     some_macro_that_panics!()
 }
+
+pub fn issue_12760<const N: usize>() {
+    const {
+        if N == 0 {
+            panic!();
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed
index bd7a9a0b984..5478372cbe0 100644
--- a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed
@@ -141,8 +141,8 @@ fn main() {
         let f = |arg| {
             let loc = "loc".to_owned();
             let _ = std::fs::write("x", &env); // Don't lint. In environment
-            let _ = std::fs::write("x", arg);
-            let _ = std::fs::write("x", loc);
+            let _ = std::fs::write("x", &arg);
+            let _ = std::fs::write("x", &loc);
         };
         let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
         f(arg);
@@ -158,13 +158,13 @@ fn main() {
         fn f(_: impl Debug) {}
 
         let x = X;
-        f(&x); // Don't lint. Has significant drop
+        f(&x); // Don't lint, not copy, passed by a reference to a variable
     }
     {
         fn f(_: impl AsRef<str>) {}
 
         let x = String::new();
-        f(x);
+        f(&x);
     }
     {
         fn f(_: impl AsRef<str>) {}
@@ -299,4 +299,38 @@ fn main() {
             check_str(&owner.0); // Don't lint. `owner` can't be partially moved because it impl Drop
         }
     }
+    {
+        #[derive(Debug)]
+        struct X(Vec<u8>);
+
+        fn f(_: impl Debug) {}
+
+        let x = X(vec![]);
+        f(&x); // Don't lint, makes x unavailable later
+    }
+    {
+        #[derive(Debug)]
+        struct X;
+
+        impl Drop for X {
+            fn drop(&mut self) {}
+        }
+
+        fn f(_: impl Debug) {}
+
+        #[derive(Debug)]
+        struct Y(X);
+
+        let y = Y(X);
+        f(&y); // Don't lint. Not copy, passed by a reference to value
+    }
+    {
+        fn f(_: impl AsRef<str>) {}
+        let x = String::new();
+        f(&x); // Don't lint, not a copy, makes it unavailable later
+        f(String::new()); // Lint, makes no difference
+        let y = "".to_owned();
+        f(&y); // Don't lint
+        f("".to_owned()); // Lint
+    }
 }
diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs
index 5cfd4ce30cc..2643815d939 100644
--- a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs
@@ -158,7 +158,7 @@ fn main() {
         fn f(_: impl Debug) {}
 
         let x = X;
-        f(&x); // Don't lint. Has significant drop
+        f(&x); // Don't lint, not copy, passed by a reference to a variable
     }
     {
         fn f(_: impl AsRef<str>) {}
@@ -299,4 +299,38 @@ fn main() {
             check_str(&owner.0); // Don't lint. `owner` can't be partially moved because it impl Drop
         }
     }
+    {
+        #[derive(Debug)]
+        struct X(Vec<u8>);
+
+        fn f(_: impl Debug) {}
+
+        let x = X(vec![]);
+        f(&x); // Don't lint, makes x unavailable later
+    }
+    {
+        #[derive(Debug)]
+        struct X;
+
+        impl Drop for X {
+            fn drop(&mut self) {}
+        }
+
+        fn f(_: impl Debug) {}
+
+        #[derive(Debug)]
+        struct Y(X);
+
+        let y = Y(X);
+        f(&y); // Don't lint. Not copy, passed by a reference to value
+    }
+    {
+        fn f(_: impl AsRef<str>) {}
+        let x = String::new();
+        f(&x); // Don't lint, not a copy, makes it unavailable later
+        f(&String::new()); // Lint, makes no difference
+        let y = "".to_owned();
+        f(&y); // Don't lint
+        f(&"".to_owned()); // Lint
+    }
 }
diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr
index 83c076f8d86..fba0755d14b 100644
--- a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.stderr
@@ -50,28 +50,22 @@ LL |         let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap();
    |                                         ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
 
 error: the borrowed expression implements the required traits
-  --> tests/ui/needless_borrows_for_generic_args.rs:144:41
-   |
-LL |             let _ = std::fs::write("x", &arg);
-   |                                         ^^^^ help: change this to: `arg`
-
-error: the borrowed expression implements the required traits
-  --> tests/ui/needless_borrows_for_generic_args.rs:145:41
+  --> tests/ui/needless_borrows_for_generic_args.rs:247:13
    |
-LL |             let _ = std::fs::write("x", &loc);
-   |                                         ^^^^ help: change this to: `loc`
+LL |         foo(&a);
+   |             ^^ help: change this to: `a`
 
 error: the borrowed expression implements the required traits
-  --> tests/ui/needless_borrows_for_generic_args.rs:167:11
+  --> tests/ui/needless_borrows_for_generic_args.rs:331:11
    |
-LL |         f(&x);
-   |           ^^ help: change this to: `x`
+LL |         f(&String::new()); // Lint, makes no difference
+   |           ^^^^^^^^^^^^^^ help: change this to: `String::new()`
 
 error: the borrowed expression implements the required traits
-  --> tests/ui/needless_borrows_for_generic_args.rs:247:13
+  --> tests/ui/needless_borrows_for_generic_args.rs:334:11
    |
-LL |         foo(&a);
-   |             ^^ help: change this to: `a`
+LL |         f(&"".to_owned()); // Lint
+   |           ^^^^^^^^^^^^^^ help: change this to: `"".to_owned()`
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr
index 1695784030d..ce64861fa40 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.stderr
+++ b/src/tools/clippy/tests/ui/needless_late_init.stderr
@@ -8,10 +8,11 @@ LL |     a = "zero";
    |
    = note: `-D clippy::needless-late-init` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_late_init)]`
-help: declare `a` here
+help: move the declaration `a` here
+   |
+LL ~     
+LL ~     let a = "zero";
    |
-LL |     let a = "zero";
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:30:5
@@ -22,10 +23,12 @@ LL |     let c;
 LL |     b = 1;
    |     ^^^^^ initialised here
    |
-help: declare `b` here
+help: move the declaration `b` here
+   |
+LL ~     
+LL |     let c;
+LL ~     let b = 1;
    |
-LL |     let b = 1;
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:31:5
@@ -36,10 +39,12 @@ LL |     b = 1;
 LL |     c = 2;
    |     ^^^^^ initialised here
    |
-help: declare `c` here
+help: move the declaration `c` here
+   |
+LL ~     
+LL |     b = 1;
+LL ~     let c = 2;
    |
-LL |     let c = 2;
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:35:5
@@ -49,10 +54,11 @@ LL |     let d: usize;
 LL |     d = 1;
    |     ^^^^^ initialised here
    |
-help: declare `d` here
+help: move the declaration `d` here
+   |
+LL ~     
+LL ~     let d: usize = 1;
    |
-LL |     let d: usize = 1;
-   |     ~~~~~~~~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:38:5
@@ -62,10 +68,11 @@ LL |     let e;
 LL |     e = format!("{}", d);
    |     ^^^^^^^^^^^^^^^^^^^^ initialised here
    |
-help: declare `e` here
+help: move the declaration `e` here
+   |
+LL ~     
+LL ~     let e = format!("{}", d);
    |
-LL |     let e = format!("{}", d);
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:43:5
@@ -73,20 +80,17 @@ error: unneeded late initialization
 LL |     let a;
    |     ^^^^^^
    |
-help: declare `a` here
-   |
-LL |     let a = match n {
-   |     +++++++
-help: remove the assignments from the `match` arms
+help: move the declaration `a` here and remove the assignments from the `match` arms
    |
+LL ~     
+LL |     let n = 1;
+LL ~     let a = match n {
 LL ~         1 => "one",
 LL |         _ => {
 LL ~             "two"
+LL |         },
+LL ~     };
    |
-help: add a semicolon after the `match` expression
-   |
-LL |     };
-   |      +
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:52:5
@@ -94,20 +98,15 @@ error: unneeded late initialization
 LL |     let b;
    |     ^^^^^^
    |
-help: declare `b` here
-   |
-LL |     let b = if n == 3 {
-   |     +++++++
-help: remove the assignments from the branches
+help: move the declaration `b` here and remove the assignments from the branches
    |
+LL ~     
+LL ~     let b = if n == 3 {
 LL ~         "four"
 LL |     } else {
 LL ~         "five"
+LL ~     };
    |
-help: add a semicolon after the `if` expression
-   |
-LL |     };
-   |      +
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:59:5
@@ -115,20 +114,16 @@ error: unneeded late initialization
 LL |     let d;
    |     ^^^^^^
    |
-help: declare `d` here
-   |
-LL |     let d = if true {
-   |     +++++++
-help: remove the assignments from the branches
+help: move the declaration `d` here and remove the assignments from the branches
    |
+LL ~     
+LL ~     let d = if true {
+LL |         let temp = 5;
 LL ~         temp
 LL |     } else {
 LL ~         15
+LL ~     };
    |
-help: add a semicolon after the `if` expression
-   |
-LL |     };
-   |      +
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:67:5
@@ -136,20 +131,15 @@ error: unneeded late initialization
 LL |     let e;
    |     ^^^^^^
    |
-help: declare `e` here
-   |
-LL |     let e = if true {
-   |     +++++++
-help: remove the assignments from the branches
+help: move the declaration `e` here and remove the assignments from the branches
    |
+LL ~     
+LL ~     let e = if true {
 LL ~         format!("{} {}", a, b)
 LL |     } else {
 LL ~         format!("{}", n)
+LL ~     };
    |
-help: add a semicolon after the `if` expression
-   |
-LL |     };
-   |      +
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:74:5
@@ -157,14 +147,11 @@ error: unneeded late initialization
 LL |     let f;
    |     ^^^^^^
    |
-help: declare `f` here
-   |
-LL |     let f = match 1 {
-   |     +++++++
-help: remove the assignments from the `match` arms
+help: move the declaration `f` here and remove the assignments from the `match` arms
    |
-LL -         1 => f = "three",
-LL +         1 => "three",
+LL ~     
+LL ~     let f = match 1 {
+LL ~         1 => "three",
    |
 
 error: unneeded late initialization
@@ -173,19 +160,15 @@ error: unneeded late initialization
 LL |     let g: usize;
    |     ^^^^^^^^^^^^^
    |
-help: declare `g` here
-   |
-LL |     let g: usize = if true {
-   |     ++++++++++++++
-help: remove the assignments from the branches
-   |
-LL -         g = 5;
-LL +         5
+help: move the declaration `g` here and remove the assignments from the branches
    |
-help: add a semicolon after the `if` expression
+LL ~     
+LL ~     let g: usize = if true {
+LL ~         5
+LL |     } else {
+LL |         panic!();
+LL ~     };
    |
-LL |     };
-   |      +
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:88:5
@@ -196,10 +179,12 @@ LL |     let y = SignificantDrop;
 LL |     x = 1;
    |     ^^^^^ initialised here
    |
-help: declare `x` here
+help: move the declaration `x` here
+   |
+LL ~     
+LL |     let y = SignificantDrop;
+LL ~     let x = 1;
    |
-LL |     let x = 1;
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:92:5
@@ -210,10 +195,12 @@ LL |     let y = 1;
 LL |     x = SignificantDrop;
    |     ^^^^^^^^^^^^^^^^^^^ initialised here
    |
-help: declare `x` here
+help: move the declaration `x` here
+   |
+LL ~     
+LL |     let y = 1;
+LL ~     let x = SignificantDrop;
    |
-LL |     let x = SignificantDrop;
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:96:5
@@ -224,10 +211,14 @@ LL |     let x;
 LL |     x = SignificantDrop;
    |     ^^^^^^^^^^^^^^^^^^^ initialised here
    |
-help: declare `x` here
+help: move the declaration `x` here
+   |
+LL ~     
+LL |     // types that should be considered insignificant
+ ...
+LL |     let y = Box::new(4);
+LL ~     let x = SignificantDrop;
    |
-LL |     let x = SignificantDrop;
-   |     ~~~~~
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:115:5
@@ -235,20 +226,17 @@ error: unneeded late initialization
 LL |     let a;
    |     ^^^^^^
    |
-help: declare `a` here
-   |
-LL |     let a = match n {
-   |     +++++++
-help: remove the assignments from the `match` arms
+help: move the declaration `a` here and remove the assignments from the `match` arms
    |
+LL ~     
+LL |     let n = 1;
+LL ~     let a = match n {
 LL ~         1 => f().await,
 LL |         _ => {
 LL ~             "two"
+LL |         },
+LL ~     };
    |
-help: add a semicolon after the `match` expression
-   |
-LL |     };
-   |      +
 
 error: unneeded late initialization
   --> tests/ui/needless_late_init.rs:132:5
@@ -256,20 +244,17 @@ error: unneeded late initialization
 LL |     let a;
    |     ^^^^^^
    |
-help: declare `a` here
-   |
-LL |     let a = match n {
-   |     +++++++
-help: remove the assignments from the `match` arms
+help: move the declaration `a` here and remove the assignments from the `match` arms
    |
+LL ~     
+LL |     let n = 1;
+LL ~     let a = match n {
 LL ~         1 => f(),
 LL |         _ => {
 LL ~             "two"
+LL |         },
+LL ~     };
    |
-help: add a semicolon after the `match` expression
-   |
-LL |     };
-   |      +
 
 error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs
index dabeda72f0c..0ea911c3434 100644
--- a/src/tools/clippy/tests/ui/no_effect.rs
+++ b/src/tools/clippy/tests/ui/no_effect.rs
@@ -1,6 +1,5 @@
 #![feature(fn_traits, unboxed_closures)]
 #![warn(clippy::no_effect_underscore_binding)]
-#![allow(dead_code, path_statements)]
 #![allow(
     clippy::deref_addrof,
     clippy::redundant_field_names,
@@ -33,7 +32,6 @@ impl Neg for Cout {
     }
 }
 
-struct Unit;
 struct Tuple(i32);
 struct Struct {
     field: i32,
@@ -42,10 +40,6 @@ enum Enum {
     Tuple(i32),
     Struct { field: i32 },
 }
-struct DropUnit;
-impl Drop for DropUnit {
-    fn drop(&mut self) {}
-}
 struct DropStruct {
     field: i32,
 }
@@ -117,15 +111,9 @@ impl FnOnce<(&str,)> for GreetStruct3 {
 
 fn main() {
     let s = get_struct();
-    let s2 = get_struct();
 
     0;
     //~^ ERROR: statement with no effect
-    //~| NOTE: `-D clippy::no-effect` implied by `-D warnings`
-    s2;
-    //~^ ERROR: statement with no effect
-    Unit;
-    //~^ ERROR: statement with no effect
     Tuple(0);
     //~^ ERROR: statement with no effect
     Struct { field: 0 };
@@ -192,7 +180,6 @@ fn main() {
     unsafe { unsafe_fn() };
     let _used = get_struct();
     let _x = vec![1];
-    DropUnit;
     DropStruct { field: 0 };
     DropTuple(0);
     DropEnum::Tuple(0);
diff --git a/src/tools/clippy/tests/ui/no_effect.stderr b/src/tools/clippy/tests/ui/no_effect.stderr
index c7c8eecd054..48ec997d938 100644
--- a/src/tools/clippy/tests/ui/no_effect.stderr
+++ b/src/tools/clippy/tests/ui/no_effect.stderr
@@ -1,5 +1,5 @@
 error: statement with no effect
-  --> tests/ui/no_effect.rs:122:5
+  --> tests/ui/no_effect.rs:115:5
    |
 LL |     0;
    |     ^^
@@ -8,151 +8,139 @@ LL |     0;
    = help: to override `-D warnings` add `#[allow(clippy::no_effect)]`
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:125:5
-   |
-LL |     s2;
-   |     ^^^
-
-error: statement with no effect
-  --> tests/ui/no_effect.rs:127:5
-   |
-LL |     Unit;
-   |     ^^^^^
-
-error: statement with no effect
-  --> tests/ui/no_effect.rs:129:5
+  --> tests/ui/no_effect.rs:117:5
    |
 LL |     Tuple(0);
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:131:5
+  --> tests/ui/no_effect.rs:119:5
    |
 LL |     Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:133:5
+  --> tests/ui/no_effect.rs:121:5
    |
 LL |     Struct { ..s };
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:135:5
+  --> tests/ui/no_effect.rs:123:5
    |
 LL |     Union { a: 0 };
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:137:5
+  --> tests/ui/no_effect.rs:125:5
    |
 LL |     Enum::Tuple(0);
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:139:5
+  --> tests/ui/no_effect.rs:127:5
    |
 LL |     Enum::Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:141:5
+  --> tests/ui/no_effect.rs:129:5
    |
 LL |     5 + 6;
    |     ^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:143:5
+  --> tests/ui/no_effect.rs:131:5
    |
 LL |     *&42;
    |     ^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:145:5
+  --> tests/ui/no_effect.rs:133:5
    |
 LL |     &6;
    |     ^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:147:5
+  --> tests/ui/no_effect.rs:135:5
    |
 LL |     (5, 6, 7);
    |     ^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:149:5
+  --> tests/ui/no_effect.rs:137:5
    |
 LL |     ..;
    |     ^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:151:5
+  --> tests/ui/no_effect.rs:139:5
    |
 LL |     5..;
    |     ^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:153:5
+  --> tests/ui/no_effect.rs:141:5
    |
 LL |     ..5;
    |     ^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:155:5
+  --> tests/ui/no_effect.rs:143:5
    |
 LL |     5..6;
    |     ^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:157:5
+  --> tests/ui/no_effect.rs:145:5
    |
 LL |     5..=6;
    |     ^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:159:5
+  --> tests/ui/no_effect.rs:147:5
    |
 LL |     [42, 55];
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:161:5
+  --> tests/ui/no_effect.rs:149:5
    |
 LL |     [42, 55][1];
    |     ^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:163:5
+  --> tests/ui/no_effect.rs:151:5
    |
 LL |     (42, 55).1;
    |     ^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:165:5
+  --> tests/ui/no_effect.rs:153:5
    |
 LL |     [42; 55];
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:167:5
+  --> tests/ui/no_effect.rs:155:5
    |
 LL |     [42; 55][13];
    |     ^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:170:5
+  --> tests/ui/no_effect.rs:158:5
    |
 LL |     || x += 5;
    |     ^^^^^^^^^^
 
 error: statement with no effect
-  --> tests/ui/no_effect.rs:173:5
+  --> tests/ui/no_effect.rs:161:5
    |
 LL |     FooString { s: s };
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> tests/ui/no_effect.rs:175:9
+  --> tests/ui/no_effect.rs:163:9
    |
 LL |     let _unused = 1;
    |         ^^^^^^^
@@ -161,22 +149,22 @@ LL |     let _unused = 1;
    = help: to override `-D warnings` add `#[allow(clippy::no_effect_underscore_binding)]`
 
 error: binding to `_` prefixed variable with no side-effect
-  --> tests/ui/no_effect.rs:178:9
+  --> tests/ui/no_effect.rs:166:9
    |
 LL |     let _penguin = || println!("Some helpful closure");
    |         ^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> tests/ui/no_effect.rs:180:9
+  --> tests/ui/no_effect.rs:168:9
    |
 LL |     let _duck = Struct { field: 0 };
    |         ^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> tests/ui/no_effect.rs:182:9
+  --> tests/ui/no_effect.rs:170:9
    |
 LL |     let _cat = [2, 4, 6, 8][2];
    |         ^^^^
 
-error: aborting due to 29 previous errors
+error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
index 0305d895fc5..7fc89bb9538 100644
--- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
@@ -675,4 +675,60 @@ fn should_not_trigger_on_significant_iterator_drop() {
     }
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/9072
+fn should_not_trigger_lint_if_place_expr_has_significant_drop() {
+    let x = Mutex::new(vec![1, 2, 3]);
+    let x_guard = x.lock().unwrap();
+
+    match x_guard[0] {
+        1 => println!("1!"),
+        x => println!("{x}"),
+    }
+
+    match x_guard.len() {
+        1 => println!("1!"),
+        x => println!("{x}"),
+    }
+}
+
+struct Guard<'a, T>(MutexGuard<'a, T>);
+
+struct Ref<'a, T>(&'a T);
+
+impl<'a, T> Guard<'a, T> {
+    fn guard(&self) -> &MutexGuard<T> {
+        &self.0
+    }
+
+    fn guard_ref(&self) -> Ref<MutexGuard<T>> {
+        Ref(&self.0)
+    }
+
+    fn take(self) -> Box<MutexGuard<'a, T>> {
+        Box::new(self.0)
+    }
+}
+
+fn should_not_trigger_for_significant_drop_ref() {
+    let mutex = Mutex::new(vec![1, 2]);
+    let guard = Guard(mutex.lock().unwrap());
+
+    match guard.guard().len() {
+        0 => println!("empty"),
+        _ => println!("not empty"),
+    }
+
+    match guard.guard_ref().0.len() {
+        0 => println!("empty"),
+        _ => println!("not empty"),
+    }
+
+    match guard.take().len() {
+        //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the
+        //~| NOTE: this might lead to deadlocks or other unexpected behavior
+        0 => println!("empty"),
+        _ => println!("not empty"),
+    };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr
index 7d5b1acc7f0..811bb065527 100644
--- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr
+++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr
@@ -28,6 +28,9 @@ LL |     match s.lock_m().get_the_value() {
 LL |             println!("{}", s.lock_m().get_the_value());
    |                            ---------- another value with significant `Drop` created here
 ...
+LL |             println!("{}", s.lock_m().get_the_value());
+   |                            ---------- another value with significant `Drop` created here
+...
 LL |     }
    |      - temporary lives until here
    |
@@ -47,6 +50,9 @@ LL |     match s.lock_m_m().get_the_value() {
 LL |             println!("{}", s.lock_m().get_the_value());
    |                            ---------- another value with significant `Drop` created here
 ...
+LL |             println!("{}", s.lock_m().get_the_value());
+   |                            ---------- another value with significant `Drop` created here
+...
 LL |     }
    |      - temporary lives until here
    |
@@ -360,7 +366,7 @@ LL |     match s.lock().deref().deref() {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |         _ => println!("Value is {}", s.lock().deref()),
-   |                                      ---------------- another value with significant `Drop` created here
+   |                                      -------- another value with significant `Drop` created here
 LL |     };
    |      - temporary lives until here
    |
@@ -378,7 +384,7 @@ LL |     match s.lock().deref().deref() {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |         matcher => println!("Value is {}", s.lock().deref()),
-   |                                            ---------------- another value with significant `Drop` created here
+   |                                            -------- another value with significant `Drop` created here
 LL |         _ => println!("Value was not a match"),
 LL |     };
    |      - temporary lives until here
@@ -499,5 +505,21 @@ LL ~     let value = mutex.lock().unwrap().foo();
 LL ~     match value {
    |
 
-error: aborting due to 26 previous errors
+error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
+  --> tests/ui/significant_drop_in_scrutinee.rs:726:11
+   |
+LL |     match guard.take().len() {
+   |           ^^^^^^^^^^^^^^^^^^
+...
+LL |     };
+   |      - temporary lives until here
+   |
+   = note: this might lead to deadlocks or other unexpected behavior
+help: try moving the temporary above the match
+   |
+LL ~     let value = guard.take().len();
+LL ~     match value {
+   |
+
+error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
index ad0e5fab029..2c582c90ba8 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.fixed
@@ -21,6 +21,8 @@ fn main() {
     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:
@@ -138,3 +140,33 @@ fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool {
 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;
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
index d3d59c4c70f..a28ccd1efef 100644
--- a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.rs
@@ -21,6 +21,8 @@ fn main() {
     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:
@@ -138,3 +140,33 @@ fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool {
 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;
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr b/src/tools/clippy/tests/ui/unnecessary_iter_cloned.stderr
index 9d3591e0dbf..fb98cfddc26 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:29:22
+  --> tests/ui/unnecessary_iter_cloned.rs:31: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:44:22
+  --> tests/ui/unnecessary_iter_cloned.rs:46:22
    |
 LL |     for (t, path) in files.iter().copied() {
    |                      ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/useless_attribute.fixed b/src/tools/clippy/tests/ui/useless_attribute.fixed
index 81759086f79..231fc0a892a 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.fixed
+++ b/src/tools/clippy/tests/ui/useless_attribute.fixed
@@ -86,8 +86,51 @@ mod module {
 
 #[rustfmt::skip]
 #[allow(unused_import_braces)]
+#[allow(unused_braces)]
 use module::{Struct};
 
 fn main() {
     test_indented_attr();
 }
+
+// Regression test for https://github.com/rust-lang/rust-clippy/issues/4467
+#[allow(dead_code)]
+use std::collections as puppy_doggy;
+
+// Regression test for https://github.com/rust-lang/rust-clippy/issues/11595
+pub mod hidden_glob_reexports {
+    #![allow(unreachable_pub)]
+
+    mod my_prelude {
+        pub struct MyCoolTypeInternal;
+        pub use MyCoolTypeInternal as MyCoolType;
+    }
+
+    mod my_uncool_type {
+        pub(crate) struct MyUncoolType;
+    }
+
+    // This exports `MyCoolType`.
+    pub use my_prelude::*;
+
+    // This hides `my_prelude::MyCoolType`.
+    #[allow(hidden_glob_reexports)]
+    use my_uncool_type::MyUncoolType as MyCoolType;
+}
+
+// Regression test for https://github.com/rust-lang/rust-clippy/issues/10878
+pub mod ambiguous_glob_exports {
+    #![allow(unreachable_pub)]
+
+    mod my_prelude {
+        pub struct MyType;
+    }
+
+    mod my_type {
+        pub struct MyType;
+    }
+
+    #[allow(ambiguous_glob_reexports)]
+    pub use my_prelude::*;
+    pub use my_type::*;
+}
diff --git a/src/tools/clippy/tests/ui/useless_attribute.rs b/src/tools/clippy/tests/ui/useless_attribute.rs
index 59a9dcf093b..8dfcd2110a4 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.rs
+++ b/src/tools/clippy/tests/ui/useless_attribute.rs
@@ -86,8 +86,51 @@ mod module {
 
 #[rustfmt::skip]
 #[allow(unused_import_braces)]
+#[allow(unused_braces)]
 use module::{Struct};
 
 fn main() {
     test_indented_attr();
 }
+
+// Regression test for https://github.com/rust-lang/rust-clippy/issues/4467
+#[allow(dead_code)]
+use std::collections as puppy_doggy;
+
+// Regression test for https://github.com/rust-lang/rust-clippy/issues/11595
+pub mod hidden_glob_reexports {
+    #![allow(unreachable_pub)]
+
+    mod my_prelude {
+        pub struct MyCoolTypeInternal;
+        pub use MyCoolTypeInternal as MyCoolType;
+    }
+
+    mod my_uncool_type {
+        pub(crate) struct MyUncoolType;
+    }
+
+    // This exports `MyCoolType`.
+    pub use my_prelude::*;
+
+    // This hides `my_prelude::MyCoolType`.
+    #[allow(hidden_glob_reexports)]
+    use my_uncool_type::MyUncoolType as MyCoolType;
+}
+
+// Regression test for https://github.com/rust-lang/rust-clippy/issues/10878
+pub mod ambiguous_glob_exports {
+    #![allow(unreachable_pub)]
+
+    mod my_prelude {
+        pub struct MyType;
+    }
+
+    mod my_type {
+        pub struct MyType;
+    }
+
+    #[allow(ambiguous_glob_reexports)]
+    pub use my_prelude::*;
+    pub use my_type::*;
+}
diff --git a/src/tools/clippy/tests/ui/while_float.rs b/src/tools/clippy/tests/ui/while_float.rs
new file mode 100644
index 00000000000..a3b0618948e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/while_float.rs
@@ -0,0 +1,14 @@
+#[deny(clippy::while_float)]
+fn main() {
+    let mut x = 0.0_f32;
+    while x < 42.0_f32 {
+        x += 0.5;
+    }
+    while x < 42.0 {
+        x += 1.0;
+    }
+    let mut x = 0;
+    while x < 42 {
+        x += 1;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/while_float.stderr b/src/tools/clippy/tests/ui/while_float.stderr
new file mode 100644
index 00000000000..b8e934b97c6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/while_float.stderr
@@ -0,0 +1,20 @@
+error: while condition comparing floats
+  --> tests/ui/while_float.rs:4:11
+   |
+LL |     while x < 42.0_f32 {
+   |           ^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui/while_float.rs:1:8
+   |
+LL | #[deny(clippy::while_float)]
+   |        ^^^^^^^^^^^^^^^^^^^
+
+error: while condition comparing floats
+  --> tests/ui/while_float.rs:7:11
+   |
+LL |     while x < 42.0 {
+   |           ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index c63edd5bf70..7fd779fe9a4 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -406,7 +406,7 @@
                 }
 
                 // Search by id
-                if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) {
+                if (lint.id.indexOf(searchStr.replaceAll("-", "_")) !== -1) {
                     return true;
                 }
 
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 3f4fceccab0..96fb8e27e6d 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -234,7 +234,6 @@ run-make/rmeta-preferred/Makefile
 run-make/rustc-macro-dep-files/Makefile
 run-make/rustdoc-io-error/Makefile
 run-make/rustdoc-scrape-examples-macros/Makefile
-run-make/rustdoc-scrape-examples-multiple/Makefile
 run-make/rustdoc-verify-output-files/Makefile
 run-make/rustdoc-with-output-option/Makefile
 run-make/rustdoc-with-short-out-dir-option/Makefile
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 6e92dab1abc..e1c6c9a2dac 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -16,7 +16,7 @@ const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 
 const ISSUES_ENTRY_LIMIT: usize = 1676;
-const ROOT_ENTRY_LIMIT: usize = 859;
+const ROOT_ENTRY_LIMIT: usize = 757;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/Makefile b/tests/run-make/rustdoc-scrape-examples-multiple/Makefile
deleted file mode 100644
index 453a7d4bc8b..00000000000
--- a/tests/run-make/rustdoc-scrape-examples-multiple/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-deps := ex ex2
-
-include ./scrape.mk
-
-all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs b/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs
new file mode 100644
index 00000000000..e9c54fa3922
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs
@@ -0,0 +1,6 @@
+#[path = "../rustdoc-scrape-examples-remap/scrape.rs"]
+mod scrape;
+
+fn main() {
+    scrape::scrape(&[]);
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk b/tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk
deleted file mode 100644
index 57220bc6635..00000000000
--- a/tests/run-make/rustdoc-scrape-examples-multiple/scrape.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-include ../tools.mk
-
-OUTPUT_DIR := "$(TMPDIR)/rustdoc"
-
-$(TMPDIR)/%.calls: $(TMPDIR)/libfoobar.rmeta
-	$(RUSTDOC) examples/$*.rs --crate-name $* --crate-type bin --output $(OUTPUT_DIR) \
-	  --extern foobar=$(TMPDIR)/libfoobar.rmeta \
-		-Z unstable-options \
-		--scrape-examples-output-path $@ \
-		--scrape-examples-target-crate foobar \
-		$(extra_flags)
-
-$(TMPDIR)/lib%.rmeta: src/lib.rs
-	$(RUSTC) src/lib.rs --crate-name $* --crate-type lib --emit=metadata
-
-scrape: $(foreach d,$(deps),$(TMPDIR)/$(d).calls)
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
-		-Z unstable-options \
-		$(foreach d,$(deps),--with-examples $(TMPDIR)/$(d).calls)
-
-	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/ui/empty_global_asm.rs b/tests/ui/asm/empty_global_asm.rs
index 2517796ad10..2517796ad10 100644
--- a/tests/ui/empty_global_asm.rs
+++ b/tests/ui/asm/empty_global_asm.rs
diff --git a/tests/ui/simple_global_asm.rs b/tests/ui/asm/simple_global_asm.rs
index 9b193b3e44c..9b193b3e44c 100644
--- a/tests/ui/simple_global_asm.rs
+++ b/tests/ui/asm/simple_global_asm.rs
diff --git a/tests/ui/backtrace-apple-no-dsymutil.rs b/tests/ui/backtrace/apple-no-dsymutil.rs
index 9924cd13b0a..9924cd13b0a 100644
--- a/tests/ui/backtrace-apple-no-dsymutil.rs
+++ b/tests/ui/backtrace/apple-no-dsymutil.rs
diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs b/tests/ui/backtrace/auxiliary/dylib-dep-helper-aux.rs
index d45e0bcd3b4..d45e0bcd3b4 100644
--- a/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs
+++ b/tests/ui/backtrace/auxiliary/dylib-dep-helper-aux.rs
diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs b/tests/ui/backtrace/auxiliary/dylib-dep-helper.rs
index 565d8b65de0..565d8b65de0 100644
--- a/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs
+++ b/tests/ui/backtrace/auxiliary/dylib-dep-helper.rs
diff --git a/tests/ui/debuginfo/auxiliary/line-tables-only-helper.rs b/tests/ui/backtrace/auxiliary/line-tables-only-helper.rs
index 65da2c3f5c7..65da2c3f5c7 100644
--- a/tests/ui/debuginfo/auxiliary/line-tables-only-helper.rs
+++ b/tests/ui/backtrace/auxiliary/line-tables-only-helper.rs
diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace/backtrace.rs
index 2579ff5203b..2579ff5203b 100644
--- a/tests/ui/backtrace.rs
+++ b/tests/ui/backtrace/backtrace.rs
diff --git a/tests/ui/debuginfo/backtrace-dylib-dep.rs b/tests/ui/backtrace/dylib-dep.rs
index fcd1f92e28e..fcd1f92e28e 100644
--- a/tests/ui/debuginfo/backtrace-dylib-dep.rs
+++ b/tests/ui/backtrace/dylib-dep.rs
diff --git a/tests/ui/debuginfo/backtrace-line-tables-only.rs b/tests/ui/backtrace/line-tables-only.rs
index 044f59e483a..044f59e483a 100644
--- a/tests/ui/debuginfo/backtrace-line-tables-only.rs
+++ b/tests/ui/backtrace/line-tables-only.rs
diff --git a/tests/ui/std-backtrace.rs b/tests/ui/backtrace/std-backtrace.rs
index b4806457877..b4806457877 100644
--- a/tests/ui/std-backtrace.rs
+++ b/tests/ui/backtrace/std-backtrace.rs
diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
index 75df314e0ba..82b2d7d1b1d 100644
--- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
+++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
@@ -1,4 +1,4 @@
-error: `crate_type` within an `#![cfg_attr] attribute is deprecated`
+error: `crate_type` within an `#![cfg_attr]` attribute is deprecated
   --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18
    |
 LL | #![cfg_attr(foo, crate_type="bin")]
@@ -8,7 +8,7 @@ LL | #![cfg_attr(foo, crate_type="bin")]
    = note: for more information, see issue #91632 <https://github.com/rust-lang/rust/issues/91632>
    = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default
 
-error: `crate_name` within an `#![cfg_attr] attribute is deprecated`
+error: `crate_name` within an `#![cfg_attr]` attribute is deprecated
   --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18
    |
 LL | #![cfg_attr(foo, crate_name="bar")]
@@ -17,7 +17,7 @@ LL | #![cfg_attr(foo, crate_name="bar")]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #91632 <https://github.com/rust-lang/rust/issues/91632>
 
-error: `crate_type` within an `#![cfg_attr] attribute is deprecated`
+error: `crate_type` within an `#![cfg_attr]` attribute is deprecated
   --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18
    |
 LL | #![cfg_attr(foo, crate_type="bin")]
@@ -27,7 +27,7 @@ LL | #![cfg_attr(foo, crate_type="bin")]
    = note: for more information, see issue #91632 <https://github.com/rust-lang/rust/issues/91632>
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: `crate_name` within an `#![cfg_attr] attribute is deprecated`
+error: `crate_name` within an `#![cfg_attr]` attribute is deprecated
   --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18
    |
 LL | #![cfg_attr(foo, crate_name="bar")]
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index ae4c1605f01..b311a80c8fd 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE`
 LL | #[cfg(FALSE)]
    |       ^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(FALSE)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index a940eda4689..9d3117ed54d 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 70d3182eec8..14e24cb1429 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
index 4975129802b..08bd43832ea 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value`
 LL | #[cfg(value)]
    |       ^^^^^
    |
-   = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
index 6404556f46c..6db1144eada 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value`
 LL | #[cfg(my_value)]
    |       ^^^^^^^^
    |
-   = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(my_value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
index bda1a601410..a5f8176343a 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `linux`
 LL | #[cfg(linux)]
    |       ^^^^^ help: found config with similar value: `target_os = "linux"`
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(linux)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr
index 079be8d08c2..6fecdb52362 100644
--- a/tests/ui/check-cfg/compact-names.stderr
+++ b/tests/ui/check-cfg/compact-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture`
 LL | #[cfg(target(os = "linux", architecture = "arm"))]
    |                            ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr
index 4fe921dd24b..c8d14f8c02a 100644
--- a/tests/ui/check-cfg/compact-values.stderr
+++ b/tests/ui/check-cfg/compact-values.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value: `X`
 LL | #[cfg(target(os = "linux", pointer_width = "X"))]
    |                            ^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
+   = note: expected values for `target_pointer_width` are: `16`, `32`, and `64`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
diff --git a/tests/ui/check-cfg/concat-values.stderr b/tests/ui/check-cfg/concat-values.stderr
index a508c397661..ec740952f57 100644
--- a/tests/ui/check-cfg/concat-values.stderr
+++ b/tests/ui/check-cfg/concat-values.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value: (none)
 LL | #[cfg(my_cfg)]
    |       ^^^^^^
    |
-   = note: expected values for `my_cfg` are: `bar`, `foo`
+   = note: expected values for `my_cfg` are: `bar` and `foo`
    = help: to expect this configuration use `--check-cfg=cfg(my_cfg)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
@@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `unk`
 LL | #[cfg(my_cfg = "unk")]
    |       ^^^^^^^^^^^^^^
    |
-   = note: expected values for `my_cfg` are: `bar`, `foo`
+   = note: expected values for `my_cfg` are: `bar` and `foo`
    = help: to expect this configuration use `--check-cfg=cfg(my_cfg, values("unk"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index 755373d7b77..2497864e87e 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index 6344739ae76..a7d4c6d4df6 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index 6344739ae76..a7d4c6d4df6 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr
index 605825cd4e5..7ac3241db5f 100644
--- a/tests/ui/check-cfg/exhaustive-names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 54591699145..8c1bf5a1160 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu`
 LL | #[cfg_attr(uu, test)]
    |            ^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(uu)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
@@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra`
 LL |     cfg!(target_feature = "zebra");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 188 more
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, and `bmi2` and 188 more
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 27 warnings emitted
diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr
index ab0deae428d..e8b61d808fe 100644
--- a/tests/ui/check-cfg/stmt-no-ice.stderr
+++ b/tests/ui/check-cfg/stmt-no-ice.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom`
 LL |     #[cfg(crossbeam_loom)]
    |           ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/unexpected-cfg-value.stderr b/tests/ui/check-cfg/unexpected-cfg-value.stderr
index efcf65bb707..0fa0dde41b6 100644
--- a/tests/ui/check-cfg/unexpected-cfg-value.stderr
+++ b/tests/ui/check-cfg/unexpected-cfg-value.stderr
@@ -6,7 +6,7 @@ LL | #[cfg(feature = "sedre")]
    |                 |
    |                 help: there is a expected value with a similar name: `"serde"`
    |
-   = note: expected values for `feature` are: `full`, `serde`
+   = note: expected values for `feature` are: `full` and `serde`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("sedre"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
@@ -17,7 +17,7 @@ warning: unexpected `cfg` condition value: `rand`
 LL | #[cfg(feature = "rand")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `feature` are: `full`, `serde`
+   = note: expected values for `feature` are: `full` and `serde`
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("rand"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index 2ce6fe80ef2..41130210df1 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition name: `features`
 LL | #[cfg(features = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, `windows`
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
    = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index db4a5fd49e6..c13446bb9f8 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -71,7 +71,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     panic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `panic` are: `abort`, `unwind`
+   = note: expected values for `panic` are: `abort` and `unwind`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -91,7 +91,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     relocation_model = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static`
+   = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, and `static`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -111,7 +111,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
+   = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, and `thread`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -120,7 +120,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_abi = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32`
+   = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, and `x32`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -129,7 +129,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_arch = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
+   = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, and `x86_64`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -138,7 +138,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_endian = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_endian` are: `big`, `little`
+   = note: expected values for `target_endian` are: `big` and `little`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -147,7 +147,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p2`, `psx`, `relibc`, `sgx`, `uclibc`
+   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p2`, `psx`, `relibc`, `sgx`, and `uclibc`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_family = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_family` are: `unix`, `wasm`, `windows`
+   = note: expected values for `target_family` are: `unix`, `wasm`, and `windows`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
+   = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, and `ptr`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -183,7 +183,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
+   = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, and `ptr`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -192,7 +192,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
+   = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, and `ptr`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -210,7 +210,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
+   = note: expected values for `target_pointer_width` are: `16`, `32`, and `64`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs`
+   = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -285,7 +285,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |                   |
    |                   help: there is a expected value with a similar name: `"linux"`
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, `zkvm`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 29 warnings emitted
diff --git a/tests/ui/auxiliary/orphan-check-diagnostics.rs b/tests/ui/coherence/auxiliary/orphan-check-diagnostics.rs
index 6b2c42b69b9..6b2c42b69b9 100644
--- a/tests/ui/auxiliary/orphan-check-diagnostics.rs
+++ b/tests/ui/coherence/auxiliary/orphan-check-diagnostics.rs
diff --git a/tests/ui/orphan-check-diagnostics.rs b/tests/ui/coherence/orphan-check-diagnostics.rs
index 4b6557fc9c8..4b6557fc9c8 100644
--- a/tests/ui/orphan-check-diagnostics.rs
+++ b/tests/ui/coherence/orphan-check-diagnostics.rs
diff --git a/tests/ui/orphan-check-diagnostics.stderr b/tests/ui/coherence/orphan-check-diagnostics.stderr
index b9fa7baf4c2..b9fa7baf4c2 100644
--- a/tests/ui/orphan-check-diagnostics.stderr
+++ b/tests/ui/coherence/orphan-check-diagnostics.stderr
diff --git a/tests/ui/cross-crate/xcrate-address-insignificant.rs b/tests/ui/cross-crate/address-insignificant.rs
index 891fe14d9a0..891fe14d9a0 100644
--- a/tests/ui/cross-crate/xcrate-address-insignificant.rs
+++ b/tests/ui/cross-crate/address-insignificant.rs
diff --git a/tests/ui/cross-crate/xcrate-associated-type-defaults.rs b/tests/ui/cross-crate/associated-type-defaults.rs
index 04eb90afae9..04eb90afae9 100644
--- a/tests/ui/cross-crate/xcrate-associated-type-defaults.rs
+++ b/tests/ui/cross-crate/associated-type-defaults.rs
diff --git a/tests/ui/xcrate/auxiliary/static_priv_by_default.rs b/tests/ui/cross-crate/auxiliary/static_priv_by_default.rs
index 39f912066ec..39f912066ec 100644
--- a/tests/ui/xcrate/auxiliary/static_priv_by_default.rs
+++ b/tests/ui/cross-crate/auxiliary/static_priv_by_default.rs
diff --git a/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs b/tests/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
index 4f8b3508398..4f8b3508398 100644
--- a/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs
+++ b/tests/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
diff --git a/tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs b/tests/ui/cross-crate/generic_fn_nested_return.rs
index dbfcdf8197a..dbfcdf8197a 100644
--- a/tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs
+++ b/tests/ui/cross-crate/generic_fn_nested_return.rs
diff --git a/tests/ui/xcrate/xcrate-private-by-default.rs b/tests/ui/cross-crate/private-by-default.rs
index 3a5d8131344..3a5d8131344 100644
--- a/tests/ui/xcrate/xcrate-private-by-default.rs
+++ b/tests/ui/cross-crate/private-by-default.rs
diff --git a/tests/ui/xcrate/xcrate-private-by-default.stderr b/tests/ui/cross-crate/private-by-default.stderr
index 25bbbf5f62a..398c9088aae 100644
--- a/tests/ui/xcrate/xcrate-private-by-default.stderr
+++ b/tests/ui/cross-crate/private-by-default.stderr
@@ -1,5 +1,5 @@
 error[E0603]: static `j` is private
-  --> $DIR/xcrate-private-by-default.rs:23:29
+  --> $DIR/private-by-default.rs:23:29
    |
 LL |     static_priv_by_default::j;
    |                             ^ private static
@@ -11,7 +11,7 @@ LL | static j: isize = 0;
    | ^^^^^^^^^^^^^^^
 
 error[E0603]: function `k` is private
-  --> $DIR/xcrate-private-by-default.rs:25:29
+  --> $DIR/private-by-default.rs:25:29
    |
 LL |     static_priv_by_default::k;
    |                             ^ private function
@@ -23,7 +23,7 @@ LL | fn k() {}
    | ^^^^^^
 
 error[E0603]: unit struct `l` is private
-  --> $DIR/xcrate-private-by-default.rs:27:29
+  --> $DIR/private-by-default.rs:27:29
    |
 LL |     static_priv_by_default::l;
    |                             ^ private unit struct
@@ -35,7 +35,7 @@ LL | struct l;
    | ^^^^^^^^
 
 error[E0603]: enum `m` is private
-  --> $DIR/xcrate-private-by-default.rs:29:35
+  --> $DIR/private-by-default.rs:29:35
    |
 LL |     foo::<static_priv_by_default::m>();
    |                                   ^ private enum
@@ -47,7 +47,7 @@ LL | enum m {}
    | ^^^^^^
 
 error[E0603]: type alias `n` is private
-  --> $DIR/xcrate-private-by-default.rs:31:35
+  --> $DIR/private-by-default.rs:31:35
    |
 LL |     foo::<static_priv_by_default::n>();
    |                                   ^ private type alias
@@ -59,7 +59,7 @@ LL | type n = isize;
    | ^^^^^^
 
 error[E0603]: module `foo` is private
-  --> $DIR/xcrate-private-by-default.rs:35:29
+  --> $DIR/private-by-default.rs:35:29
    |
 LL |     static_priv_by_default::foo::a;
    |                             ^^^  - static `a` is not publicly re-exported
@@ -73,7 +73,7 @@ LL | mod foo {
    | ^^^^^^^
 
 error[E0603]: module `foo` is private
-  --> $DIR/xcrate-private-by-default.rs:37:29
+  --> $DIR/private-by-default.rs:37:29
    |
 LL |     static_priv_by_default::foo::b;
    |                             ^^^  - function `b` is not publicly re-exported
@@ -87,7 +87,7 @@ LL | mod foo {
    | ^^^^^^^
 
 error[E0603]: module `foo` is private
-  --> $DIR/xcrate-private-by-default.rs:39:29
+  --> $DIR/private-by-default.rs:39:29
    |
 LL |     static_priv_by_default::foo::c;
    |                             ^^^  - unit struct `c` is not publicly re-exported
@@ -101,7 +101,7 @@ LL | mod foo {
    | ^^^^^^^
 
 error[E0603]: module `foo` is private
-  --> $DIR/xcrate-private-by-default.rs:41:35
+  --> $DIR/private-by-default.rs:41:35
    |
 LL |     foo::<static_priv_by_default::foo::d>();
    |                                   ^^^  - enum `d` is not publicly re-exported
@@ -115,7 +115,7 @@ LL | mod foo {
    | ^^^^^^^
 
 error[E0603]: module `foo` is private
-  --> $DIR/xcrate-private-by-default.rs:43:35
+  --> $DIR/private-by-default.rs:43:35
    |
 LL |     foo::<static_priv_by_default::foo::e>();
    |                                   ^^^  - type alias `e` is not publicly re-exported
diff --git a/tests/ui/cross-crate/xcrate-static-addresses.rs b/tests/ui/cross-crate/static-addresses.rs
index 66ac467e9ac..66ac467e9ac 100644
--- a/tests/ui/cross-crate/xcrate-static-addresses.rs
+++ b/tests/ui/cross-crate/static-addresses.rs
diff --git a/tests/ui/cross-crate/xcrate-trait-lifetime-param.rs b/tests/ui/cross-crate/trait-lifetime-param.rs
index 28955e62d95..28955e62d95 100644
--- a/tests/ui/cross-crate/xcrate-trait-lifetime-param.rs
+++ b/tests/ui/cross-crate/trait-lifetime-param.rs
diff --git a/tests/ui/xcrate/xcrate-unit-struct-2.rs b/tests/ui/cross-crate/unit-struct-2.rs
index c2e3a761129..c2e3a761129 100644
--- a/tests/ui/xcrate/xcrate-unit-struct-2.rs
+++ b/tests/ui/cross-crate/unit-struct-2.rs
diff --git a/tests/ui/xcrate/xcrate-unit-struct.rs b/tests/ui/cross-crate/unit-struct.rs
index 1517f843eff..1517f843eff 100644
--- a/tests/ui/xcrate/xcrate-unit-struct.rs
+++ b/tests/ui/cross-crate/unit-struct.rs
diff --git a/tests/ui/xcrate/xcrate-unit-struct.stderr b/tests/ui/cross-crate/unit-struct.stderr
index 7365170b69e..a7e3e4685a9 100644
--- a/tests/ui/xcrate/xcrate-unit-struct.stderr
+++ b/tests/ui/cross-crate/unit-struct.stderr
@@ -1,5 +1,5 @@
 error[E0423]: expected value, found struct `xcrate_unit_struct::StructWithFields`
-  --> $DIR/xcrate-unit-struct.rs:9:13
+  --> $DIR/unit-struct.rs:9:13
    |
 LL |     let _ = xcrate_unit_struct::StructWithFields;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `xcrate_unit_struct::StructWithFields { foo: val }`
@@ -10,7 +10,7 @@ LL | pub struct StructWithFields {
    | --------------------------- `xcrate_unit_struct::StructWithFields` defined here
 
 error[E0423]: expected value, found struct `xcrate_unit_struct::StructWithPrivFields`
-  --> $DIR/xcrate-unit-struct.rs:11:13
+  --> $DIR/unit-struct.rs:11:13
    |
 LL |     let _ = xcrate_unit_struct::StructWithPrivFields;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/expr-block-fn.rs b/tests/ui/expr/block-fn.rs
index 1d3689eb4f3..1d3689eb4f3 100644
--- a/tests/ui/expr-block-fn.rs
+++ b/tests/ui/expr/block-fn.rs
diff --git a/tests/ui/expr-block-generic.rs b/tests/ui/expr/block-generic.rs
index b36bda917d6..b36bda917d6 100644
--- a/tests/ui/expr-block-generic.rs
+++ b/tests/ui/expr/block-generic.rs
diff --git a/tests/ui/expr-block.rs b/tests/ui/expr/block.rs
index bf626c9ead3..bf626c9ead3 100644
--- a/tests/ui/expr-block.rs
+++ b/tests/ui/expr/block.rs
diff --git a/tests/ui/expr-copy.rs b/tests/ui/expr/copy.rs
index cfe47ff6d93..cfe47ff6d93 100644
--- a/tests/ui/expr-copy.rs
+++ b/tests/ui/expr/copy.rs
diff --git a/tests/ui/expr-if-generic.rs b/tests/ui/expr/if-generic.rs
index ed99ee63a51..ed99ee63a51 100644
--- a/tests/ui/expr-if-generic.rs
+++ b/tests/ui/expr/if-generic.rs
diff --git a/tests/ui/expr-if-panic-all.rs b/tests/ui/expr/if-panic-all.rs
index 2ba2a36d165..2ba2a36d165 100644
--- a/tests/ui/expr-if-panic-all.rs
+++ b/tests/ui/expr/if-panic-all.rs
diff --git a/tests/ui/expr-scope.rs b/tests/ui/expr/scope.rs
index 57321ce2aa0..57321ce2aa0 100644
--- a/tests/ui/expr-scope.rs
+++ b/tests/ui/expr/scope.rs
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
index bd3b69c2b4a..ca60bc62b51 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
@@ -45,7 +45,7 @@ mod inline {
     //~| NOTE not a function or closure
 
     #[inline = "2100"] fn f() { }
-    //~^ ERROR attribute must be of the form
+    //~^ ERROR valid forms for the attribute are
     //~| WARN this was previously accepted
     //~| NOTE #[deny(ill_formed_attribute_input)]` on by default
     //~| NOTE for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 89fa2abffc2..ac2bf78157d 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -7,7 +7,7 @@ LL | #![rustc_main]
    = help: add `#![feature(rustc_attrs)]` 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: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
+error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]`
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5
    |
 LL |     #[inline = "2100"] fn f() { }
diff --git a/tests/ui/stmt_expr_attrs_no_feature.rs b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs
index a160a9bb082..a160a9bb082 100644
--- a/tests/ui/stmt_expr_attrs_no_feature.rs
+++ b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs
diff --git a/tests/ui/stmt_expr_attrs_no_feature.stderr b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.stderr
index c801268c652..c801268c652 100644
--- a/tests/ui/stmt_expr_attrs_no_feature.stderr
+++ b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.stderr
diff --git a/tests/ui/ffi_const.rs b/tests/ui/ffi-attrs/ffi_const.rs
index aa20a4d4c65..aa20a4d4c65 100644
--- a/tests/ui/ffi_const.rs
+++ b/tests/ui/ffi-attrs/ffi_const.rs
diff --git a/tests/ui/ffi_const.stderr b/tests/ui/ffi-attrs/ffi_const.stderr
index 394b98f8971..394b98f8971 100644
--- a/tests/ui/ffi_const.stderr
+++ b/tests/ui/ffi-attrs/ffi_const.stderr
diff --git a/tests/ui/ffi_const2.rs b/tests/ui/ffi-attrs/ffi_const2.rs
index 82fe8a9c91d..82fe8a9c91d 100644
--- a/tests/ui/ffi_const2.rs
+++ b/tests/ui/ffi-attrs/ffi_const2.rs
diff --git a/tests/ui/ffi_const2.stderr b/tests/ui/ffi-attrs/ffi_const2.stderr
index b8cbc296370..b8cbc296370 100644
--- a/tests/ui/ffi_const2.stderr
+++ b/tests/ui/ffi-attrs/ffi_const2.stderr
diff --git a/tests/ui/ffi_pure.rs b/tests/ui/ffi-attrs/ffi_pure.rs
index 6d2f3a614ec..6d2f3a614ec 100644
--- a/tests/ui/ffi_pure.rs
+++ b/tests/ui/ffi-attrs/ffi_pure.rs
diff --git a/tests/ui/ffi_pure.stderr b/tests/ui/ffi-attrs/ffi_pure.stderr
index 8b61a4b609f..8b61a4b609f 100644
--- a/tests/ui/ffi_pure.stderr
+++ b/tests/ui/ffi-attrs/ffi_pure.stderr
diff --git a/tests/ui/main-wrong-location.rs b/tests/ui/fn-main/wrong-location.rs
index d7deeaed99d..d7deeaed99d 100644
--- a/tests/ui/main-wrong-location.rs
+++ b/tests/ui/fn-main/wrong-location.rs
diff --git a/tests/ui/main-wrong-location.stderr b/tests/ui/fn-main/wrong-location.stderr
index 9486a940562..c47092bc47e 100644
--- a/tests/ui/main-wrong-location.stderr
+++ b/tests/ui/fn-main/wrong-location.stderr
@@ -1,11 +1,11 @@
-error[E0601]: `main` function not found in crate `main_wrong_location`
-  --> $DIR/main-wrong-location.rs:5:2
+error[E0601]: `main` function not found in crate `wrong_location`
+  --> $DIR/wrong-location.rs:5:2
    |
 LL | }
-   |  ^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`)
+   |  ^ the main function must be defined at the crate level (in `$DIR/wrong-location.rs`)
    |
 note: here is a function named `main`
-  --> $DIR/main-wrong-location.rs:4:5
+  --> $DIR/wrong-location.rs:4:5
    |
 LL |     fn main() { }
    |     ^^^^^^^^^
diff --git a/tests/ui/main-wrong-type.rs b/tests/ui/fn-main/wrong-type.rs
index 31deba72af4..31deba72af4 100644
--- a/tests/ui/main-wrong-type.rs
+++ b/tests/ui/fn-main/wrong-type.rs
diff --git a/tests/ui/main-wrong-type.stderr b/tests/ui/fn-main/wrong-type.stderr
index d07fc09064f..2b0096431db 100644
--- a/tests/ui/main-wrong-type.stderr
+++ b/tests/ui/fn-main/wrong-type.stderr
@@ -1,5 +1,5 @@
 error[E0580]: `main` function has wrong type
-  --> $DIR/main-wrong-type.rs:6:1
+  --> $DIR/wrong-type.rs:6:1
    |
 LL | fn main(foo: S) {
    | ^^^^^^^^^^^^^^^ incorrect number of function parameters
diff --git a/tests/ui/foreign-fn-return-lifetime.rs b/tests/ui/foreign/foreign-fn-return-lifetime.rs
index 35595bab36d..35595bab36d 100644
--- a/tests/ui/foreign-fn-return-lifetime.rs
+++ b/tests/ui/foreign/foreign-fn-return-lifetime.rs
diff --git a/tests/ui/foreign-fn-return-lifetime.stderr b/tests/ui/foreign/foreign-fn-return-lifetime.stderr
index e24c0f23c35..e24c0f23c35 100644
--- a/tests/ui/foreign-fn-return-lifetime.stderr
+++ b/tests/ui/foreign/foreign-fn-return-lifetime.stderr
diff --git a/tests/ui/optimization-fuel-0.rs b/tests/ui/fuel/optimization-fuel-0.rs
index cbcb1d329a3..cbcb1d329a3 100644
--- a/tests/ui/optimization-fuel-0.rs
+++ b/tests/ui/fuel/optimization-fuel-0.rs
diff --git a/tests/ui/optimization-fuel-0.stderr b/tests/ui/fuel/optimization-fuel-0.stderr
index f0e2ebfc37a..f0e2ebfc37a 100644
--- a/tests/ui/optimization-fuel-0.stderr
+++ b/tests/ui/fuel/optimization-fuel-0.stderr
diff --git a/tests/ui/optimization-fuel-1.rs b/tests/ui/fuel/optimization-fuel-1.rs
index 97edb0bd259..97edb0bd259 100644
--- a/tests/ui/optimization-fuel-1.rs
+++ b/tests/ui/fuel/optimization-fuel-1.rs
diff --git a/tests/ui/optimization-fuel-1.stderr b/tests/ui/fuel/optimization-fuel-1.stderr
index 53eafb05830..53eafb05830 100644
--- a/tests/ui/optimization-fuel-1.stderr
+++ b/tests/ui/fuel/optimization-fuel-1.stderr
diff --git a/tests/ui/print-fuel/print-fuel.rs b/tests/ui/fuel/print-fuel.rs
index fd7e568bea7..fd7e568bea7 100644
--- a/tests/ui/print-fuel/print-fuel.rs
+++ b/tests/ui/fuel/print-fuel.rs
diff --git a/tests/ui/print-fuel/print-fuel.stderr b/tests/ui/fuel/print-fuel.stderr
index cc88cc077bb..cc88cc077bb 100644
--- a/tests/ui/print-fuel/print-fuel.stderr
+++ b/tests/ui/fuel/print-fuel.stderr
diff --git a/tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.rs b/tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.rs
new file mode 100644
index 00000000000..b2ac332b4f0
--- /dev/null
+++ b/tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.rs
@@ -0,0 +1,28 @@
+#![allow(dead_code)]
+
+trait Trait1<T>
+  where T: for<'a> Trait1<T> + 'b { } //~ ERROR use of undeclared lifetime name `'b`
+
+trait Trait2<T>
+where
+    T: B<'b> + for<'a> A<'a>, //~ ERROR use of undeclared lifetime name `'b`
+{
+}
+
+trait Trait3<T>
+where
+    T: B<'b> + for<'a> A<'a> + 'c {}
+    //~^ ERROR use of undeclared lifetime name `'b`
+    //~| ERROR use of undeclared lifetime name `'c`
+
+trait Trait4<T>
+where
+    T: for<'a> A<'a> + 'x + for<'b> B<'b>, //~ ERROR use of undeclared lifetime name `'x`
+{
+}
+
+trait A<'a> {}
+trait B<'a> {}
+
+
+fn main() {}
diff --git a/tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.stderr b/tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.stderr
new file mode 100644
index 00000000000..40f0769964f
--- /dev/null
+++ b/tests/ui/generics/generic-higher-ranked-lifetime-issue-122714.stderr
@@ -0,0 +1,92 @@
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/generic-higher-ranked-lifetime-issue-122714.rs:4:32
+   |
+LL |   where T: for<'a> Trait1<T> + 'b { }
+   |                                ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL -   where T: for<'a> Trait1<T> + 'b { }
+LL +   where for<'b, 'a> T: Trait1<T> + 'b { }
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait Trait1<'b, T>
+   |              +++
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/generic-higher-ranked-lifetime-issue-122714.rs:8:10
+   |
+LL |     T: B<'b> + for<'a> A<'a>,
+   |          ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |     T: for<'b> B<'b> + for<'a> A<'a>,
+   |        +++++++
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL -     T: B<'b> + for<'a> A<'a>,
+LL +     for<'b, 'a> T: B<'b> + A<'a>,
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait Trait2<'b, T>
+   |              +++
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/generic-higher-ranked-lifetime-issue-122714.rs:14:10
+   |
+LL |     T: B<'b> + for<'a> A<'a> + 'c {}
+   |          ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |     T: for<'b> B<'b> + for<'a> A<'a> + 'c {}
+   |        +++++++
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL -     T: B<'b> + for<'a> A<'a> + 'c {}
+LL +     for<'b, 'a> T: B<'b> + A<'a> + 'c {}
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | trait Trait3<'b, T>
+   |              +++
+
+error[E0261]: use of undeclared lifetime name `'c`
+  --> $DIR/generic-higher-ranked-lifetime-issue-122714.rs:14:32
+   |
+LL |     T: B<'b> + for<'a> A<'a> + 'c {}
+   |                                ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'c` lifetime
+   |
+LL -     T: B<'b> + for<'a> A<'a> + 'c {}
+LL +     for<'c, 'a> T: B<'b> + A<'a> + 'c {}
+   |
+help: consider introducing lifetime `'c` here
+   |
+LL | trait Trait3<'c, T>
+   |              +++
+
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/generic-higher-ranked-lifetime-issue-122714.rs:20:24
+   |
+LL |     T: for<'a> A<'a> + 'x + for<'b> B<'b>,
+   |                        ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'x` lifetime
+   |
+LL -     T: for<'a> A<'a> + 'x + for<'b> B<'b>,
+LL +     for<'x, 'a, 'b> T: A<'a> + 'x + B<'b>,
+   |
+help: consider introducing lifetime `'x` here
+   |
+LL | trait Trait4<'x, T>
+   |              +++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/infer-fn-tail-expr.rs b/tests/ui/inference/infer-fn-tail-expr.rs
index 31b71e49bd6..31b71e49bd6 100644
--- a/tests/ui/infer-fn-tail-expr.rs
+++ b/tests/ui/inference/infer-fn-tail-expr.rs
diff --git a/tests/ui/lambda-infer-unresolved.rs b/tests/ui/inference/lambda-infer-unresolved.rs
index f30832044dc..f30832044dc 100644
--- a/tests/ui/lambda-infer-unresolved.rs
+++ b/tests/ui/inference/lambda-infer-unresolved.rs
diff --git a/tests/ui/order-dependent-cast-inference.rs b/tests/ui/inference/order-dependent-cast-inference.rs
index e666209b912..e666209b912 100644
--- a/tests/ui/order-dependent-cast-inference.rs
+++ b/tests/ui/inference/order-dependent-cast-inference.rs
diff --git a/tests/ui/order-dependent-cast-inference.stderr b/tests/ui/inference/order-dependent-cast-inference.stderr
index ab33b703a05..ab33b703a05 100644
--- a/tests/ui/order-dependent-cast-inference.stderr
+++ b/tests/ui/inference/order-dependent-cast-inference.stderr
diff --git a/tests/ui/intrinsics-always-extern.rs b/tests/ui/intrinsics/always-extern.rs
index 0afd8353455..0afd8353455 100644
--- a/tests/ui/intrinsics-always-extern.rs
+++ b/tests/ui/intrinsics/always-extern.rs
diff --git a/tests/ui/intrinsics-always-extern.stderr b/tests/ui/intrinsics/always-extern.stderr
index 1f7bb5a3b0d..44b889c6faa 100644
--- a/tests/ui/intrinsics-always-extern.stderr
+++ b/tests/ui/intrinsics/always-extern.stderr
@@ -1,11 +1,11 @@
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/intrinsics-always-extern.rs:4:32
+  --> $DIR/always-extern.rs:4:32
    |
 LL |     extern "rust-intrinsic" fn foo(&self);
    |                                ^^^
 
 error[E0093]: unrecognized intrinsic function: `hello`
-  --> $DIR/intrinsics-always-extern.rs:12:28
+  --> $DIR/always-extern.rs:12:28
    |
 LL | extern "rust-intrinsic" fn hello() {
    |                            ^^^^^ unrecognized intrinsic
@@ -13,7 +13,7 @@ LL | extern "rust-intrinsic" fn hello() {
    = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type`
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/intrinsics-always-extern.rs:8:43
+  --> $DIR/always-extern.rs:8:43
    |
 LL |       extern "rust-intrinsic" fn foo(&self) {
    |  ___________________________________________^
@@ -21,7 +21,7 @@ LL | |     }
    | |_____^
 
 error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
-  --> $DIR/intrinsics-always-extern.rs:12:36
+  --> $DIR/always-extern.rs:12:36
    |
 LL |   extern "rust-intrinsic" fn hello() {
    |  ____________________________________^
diff --git a/tests/ui/reify-intrinsic.rs b/tests/ui/intrinsics/reify-intrinsic.rs
index 6c52651f060..6c52651f060 100644
--- a/tests/ui/reify-intrinsic.rs
+++ b/tests/ui/intrinsics/reify-intrinsic.rs
diff --git a/tests/ui/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr
index 0119a1a6650..0119a1a6650 100644
--- a/tests/ui/reify-intrinsic.stderr
+++ b/tests/ui/intrinsics/reify-intrinsic.stderr
diff --git a/tests/ui/lint/anonymous-reexport.stderr b/tests/ui/lint/anonymous-reexport.stderr
index e3854a5459e..c4ee18fe8da 100644
--- a/tests/ui/lint/anonymous-reexport.stderr
+++ b/tests/ui/lint/anonymous-reexport.stderr
@@ -34,7 +34,7 @@ error: unused import: `Bar as _`
 LL | pub use self::my_mod::{Bar as _, Foo as _};
    |                        ^^^^^^^^
 
-error: unused imports: `Bar as _`, `TyBar as _`
+error: unused imports: `Bar as _` and `TyBar as _`
   --> $DIR/anonymous-reexport.rs:17:24
    |
 LL | pub use self::my_mod::{Bar as _, TyBar as _};
diff --git a/tests/ui/lint-group-denied-lint-allowed.rs b/tests/ui/lint/group-denied-lint-allowed.rs
index 86b63bb31e3..86b63bb31e3 100644
--- a/tests/ui/lint-group-denied-lint-allowed.rs
+++ b/tests/ui/lint/group-denied-lint-allowed.rs
diff --git a/tests/ui/lint-group-forbid-always-trumps-cli.rs b/tests/ui/lint/group-forbid-always-trumps-cli.rs
index 4b63452bf5d..4b63452bf5d 100644
--- a/tests/ui/lint-group-forbid-always-trumps-cli.rs
+++ b/tests/ui/lint/group-forbid-always-trumps-cli.rs
diff --git a/tests/ui/lint-group-forbid-always-trumps-cli.stderr b/tests/ui/lint/group-forbid-always-trumps-cli.stderr
index 04a0f56c163..21674ebae9c 100644
--- a/tests/ui/lint-group-forbid-always-trumps-cli.stderr
+++ b/tests/ui/lint/group-forbid-always-trumps-cli.stderr
@@ -1,5 +1,5 @@
 error: unused variable: `x`
-  --> $DIR/lint-group-forbid-always-trumps-cli.rs:4:9
+  --> $DIR/group-forbid-always-trumps-cli.rs:4:9
    |
 LL |     let x = 1;
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
diff --git a/tests/ui/lint-unknown-lints-at-crate-level.rs b/tests/ui/lint/unknown-lints-at-crate-level.rs
index c8cf65ce93a..c8cf65ce93a 100644
--- a/tests/ui/lint-unknown-lints-at-crate-level.rs
+++ b/tests/ui/lint/unknown-lints-at-crate-level.rs
diff --git a/tests/ui/lint/unused/import_remove_line.stderr b/tests/ui/lint/unused/import_remove_line.stderr
index 0e8c5de3558..b2a16669a93 100644
--- a/tests/ui/lint/unused/import_remove_line.stderr
+++ b/tests/ui/lint/unused/import_remove_line.stderr
@@ -1,4 +1,4 @@
-warning: unused imports: `Duration`, `Instant`
+warning: unused imports: `Duration` and `Instant`
   --> $DIR/import_remove_line.rs:7:17
    |
 LL | use std::time::{Duration, Instant};
diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs
index 88f2baa5da9..710fb7a5ed1 100644
--- a/tests/ui/lint/unused/lint-unused-imports.rs
+++ b/tests/ui/lint/unused/lint-unused-imports.rs
@@ -10,7 +10,7 @@ use std::fmt::{};
 
 // Should get errors for both 'Some' and 'None'
 use std::option::Option::{Some, None};
-//~^ ERROR unused imports: `None`, `Some`
+//~^ ERROR unused imports: `None` and `Some`
 
 use test::A;       //~ ERROR unused import: `test::A`
 // Be sure that if we just bring some methods into scope that they're also
diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr
index 07684a84a64..a848fb31eba 100644
--- a/tests/ui/lint/unused/lint-unused-imports.stderr
+++ b/tests/ui/lint/unused/lint-unused-imports.stderr
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
-error: unused imports: `None`, `Some`
+error: unused imports: `None` and `Some`
   --> $DIR/lint-unused-imports.rs:12:27
    |
 LL | use std::option::Option::{Some, None};
diff --git a/tests/ui/compile_error_macro.rs b/tests/ui/macros/compile_error_macro.rs
index 3f7b57cd078..3f7b57cd078 100644
--- a/tests/ui/compile_error_macro.rs
+++ b/tests/ui/macros/compile_error_macro.rs
diff --git a/tests/ui/compile_error_macro.stderr b/tests/ui/macros/compile_error_macro.stderr
index 92d5564e8a7..92d5564e8a7 100644
--- a/tests/ui/compile_error_macro.stderr
+++ b/tests/ui/macros/compile_error_macro.stderr
diff --git a/tests/ui/module-macro_use-arguments.rs b/tests/ui/macros/module-macro_use-arguments.rs
index 121b492e254..121b492e254 100644
--- a/tests/ui/module-macro_use-arguments.rs
+++ b/tests/ui/macros/module-macro_use-arguments.rs
diff --git a/tests/ui/module-macro_use-arguments.stderr b/tests/ui/macros/module-macro_use-arguments.stderr
index 3ac645ad3a9..3ac645ad3a9 100644
--- a/tests/ui/module-macro_use-arguments.stderr
+++ b/tests/ui/macros/module-macro_use-arguments.stderr
diff --git a/tests/ui/no-patterns-in-args-macro.rs b/tests/ui/macros/no-patterns-in-args-macro.rs
index b5109f9c286..b5109f9c286 100644
--- a/tests/ui/no-patterns-in-args-macro.rs
+++ b/tests/ui/macros/no-patterns-in-args-macro.rs
diff --git a/tests/ui/no-patterns-in-args-macro.stderr b/tests/ui/macros/no-patterns-in-args-macro.stderr
index 0016c7953f3..0016c7953f3 100644
--- a/tests/ui/no-patterns-in-args-macro.stderr
+++ b/tests/ui/macros/no-patterns-in-args-macro.stderr
diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs
index ac1444bbaef..f0a7aac59c1 100644
--- a/tests/ui/malformed/malformed-regressions.rs
+++ b/tests/ui/malformed/malformed-regressions.rs
@@ -1,8 +1,8 @@
-#[doc] //~ ERROR attribute must be of the form
+#[doc] //~ ERROR valid forms for the attribute are
 //~^ WARN this was previously accepted
-#[ignore()] //~ ERROR attribute must be of the form
+#[ignore()] //~ ERROR valid forms for the attribute are
 //~^ WARN this was previously accepted
-#[inline = ""] //~ ERROR attribute must be of the form
+#[inline = ""] //~ ERROR valid forms for the attribute are
 //~^ WARN this was previously accepted
 #[link] //~ ERROR attribute must be of the form
 //~^ WARN this was previously accepted
diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr
index 9bfbe7ebafd..e1dbdb9ab3c 100644
--- a/tests/ui/malformed/malformed-regressions.stderr
+++ b/tests/ui/malformed/malformed-regressions.stderr
@@ -1,4 +1,4 @@
-error: attribute must be of the form `#[doc(hidden|inline|...)]` or `#[doc = "string"]`
+error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]`
   --> $DIR/malformed-regressions.rs:1:1
    |
 LL | #[doc]
@@ -8,7 +8,7 @@ LL | #[doc]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: `#[deny(ill_formed_attribute_input)]` on by default
 
-error: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]`
+error: valid forms for the attribute are `#[ignore]` and `#[ignore = "reason"]`
   --> $DIR/malformed-regressions.rs:3:1
    |
 LL | #[ignore()]
@@ -17,7 +17,7 @@ LL | #[ignore()]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
-error: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
+error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]`
   --> $DIR/malformed-regressions.rs:5:1
    |
 LL | #[inline = ""]
diff --git a/tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.rs b/tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.rs
new file mode 100644
index 00000000000..3c0059ba3e3
--- /dev/null
+++ b/tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.rs
@@ -0,0 +1,6 @@
+// Regression test for issue #124935
+// Tests that we do not erroneously emit an error about
+// missing main function when the mod starts with a `;`
+
+; //~ ERROR expected item, found `;`
+fn main() { }
diff --git a/tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.stderr b/tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.stderr
new file mode 100644
index 00000000000..9776677589f
--- /dev/null
+++ b/tests/ui/parser/issues/fn-no-semicolon-issue-124935-semi-after-item.stderr
@@ -0,0 +1,8 @@
+error: expected item, found `;`
+  --> $DIR/fn-no-semicolon-issue-124935-semi-after-item.rs:5:1
+   |
+LL | ;
+   | ^ help: remove this semicolon
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/issue-49040.rs b/tests/ui/parser/issues/issue-49040.rs
index b7a541dd664..68e7cc9f80e 100644
--- a/tests/ui/parser/issues/issue-49040.rs
+++ b/tests/ui/parser/issues/issue-49040.rs
@@ -1,3 +1,3 @@
 #![allow(unused_variables)]; //~ ERROR expected item, found `;`
-//~^ ERROR `main` function
 fn foo() {}
+//~^ ERROR `main` function
diff --git a/tests/ui/parser/issues/issue-49040.stderr b/tests/ui/parser/issues/issue-49040.stderr
index 8af7838c791..11ef5e1aadf 100644
--- a/tests/ui/parser/issues/issue-49040.stderr
+++ b/tests/ui/parser/issues/issue-49040.stderr
@@ -5,10 +5,10 @@ LL | #![allow(unused_variables)];
    |                            ^ help: remove this semicolon
 
 error[E0601]: `main` function not found in crate `issue_49040`
-  --> $DIR/issue-49040.rs:1:29
+  --> $DIR/issue-49040.rs:2:12
    |
-LL | #![allow(unused_variables)];
-   |                             ^ consider adding a `main` function to `$DIR/issue-49040.rs`
+LL | fn foo() {}
+   |            ^ consider adding a `main` function to `$DIR/issue-49040.rs`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.rs b/tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.rs
new file mode 100644
index 00000000000..3fbac5fae23
--- /dev/null
+++ b/tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.rs
@@ -0,0 +1,5 @@
+// Regression test for issue #124935
+// Tests that we still emit an error after an item.
+
+fn main() { }
+; //~ ERROR expected item, found `;`
diff --git a/tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.stderr b/tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.stderr
new file mode 100644
index 00000000000..2d7f540443d
--- /dev/null
+++ b/tests/ui/parser/issues/missing-main-issue-124935-semi-after-item.stderr
@@ -0,0 +1,10 @@
+error: expected item, found `;`
+  --> $DIR/missing-main-issue-124935-semi-after-item.rs:5:1
+   |
+LL | ;
+   | ^ help: remove this semicolon
+   |
+   = help: function declarations are not followed by a semicolon
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/super-fast-paren-parsing.rs b/tests/ui/parser/super-fast-paren-parsing.rs
index ce7283eee03..5b7cd6fe47d 100644
--- a/tests/ui/super-fast-paren-parsing.rs
+++ b/tests/ui/parser/super-fast-paren-parsing.rs
@@ -3,10 +3,7 @@
 #![allow(unused_parens)]
 #![allow(non_upper_case_globals)]
 #![allow(dead_code)]
-//@ exec-env:RUST_MIN_STACK=16000000
-//@ rustc-env:RUST_MIN_STACK=16000000
-//
-// Big stack is needed for pretty printing, a little sad...
+#![cfg_attr(rustfmt, rustfmt::skip)]
 
 static a: isize =
 (((((((((((((((((((((((((((((((((((((((((((((((((((
diff --git a/tests/ui/by-move-pattern-binding.rs b/tests/ui/pattern/by-move-pattern-binding.rs
index f68d181291d..f68d181291d 100644
--- a/tests/ui/by-move-pattern-binding.rs
+++ b/tests/ui/pattern/by-move-pattern-binding.rs
diff --git a/tests/ui/by-move-pattern-binding.stderr b/tests/ui/pattern/by-move-pattern-binding.stderr
index 203e37dc387..203e37dc387 100644
--- a/tests/ui/by-move-pattern-binding.stderr
+++ b/tests/ui/pattern/by-move-pattern-binding.stderr
diff --git a/tests/ui/fn-in-pat.rs b/tests/ui/pattern/fn-in-pat.rs
index 2d7c86b8666..2d7c86b8666 100644
--- a/tests/ui/fn-in-pat.rs
+++ b/tests/ui/pattern/fn-in-pat.rs
diff --git a/tests/ui/fn-in-pat.stderr b/tests/ui/pattern/fn-in-pat.stderr
index 41ea4df72a2..41ea4df72a2 100644
--- a/tests/ui/fn-in-pat.stderr
+++ b/tests/ui/pattern/fn-in-pat.stderr
diff --git a/tests/ui/inc-range-pat.rs b/tests/ui/pattern/inc-range-pat.rs
index 189dac4feed..189dac4feed 100644
--- a/tests/ui/inc-range-pat.rs
+++ b/tests/ui/pattern/inc-range-pat.rs
diff --git a/tests/ui/no-patterns-in-args-2.rs b/tests/ui/pattern/no-patterns-in-args-2.rs
index 85b7fc5cdba..85b7fc5cdba 100644
--- a/tests/ui/no-patterns-in-args-2.rs
+++ b/tests/ui/pattern/no-patterns-in-args-2.rs
diff --git a/tests/ui/no-patterns-in-args-2.stderr b/tests/ui/pattern/no-patterns-in-args-2.stderr
index 6adcbb9dccd..6adcbb9dccd 100644
--- a/tests/ui/no-patterns-in-args-2.stderr
+++ b/tests/ui/pattern/no-patterns-in-args-2.stderr
diff --git a/tests/ui/no-patterns-in-args.rs b/tests/ui/pattern/no-patterns-in-args.rs
index 54836b0a3f5..54836b0a3f5 100644
--- a/tests/ui/no-patterns-in-args.rs
+++ b/tests/ui/pattern/no-patterns-in-args.rs
diff --git a/tests/ui/no-patterns-in-args.stderr b/tests/ui/pattern/no-patterns-in-args.stderr
index 1c2ce866467..1c2ce866467 100644
--- a/tests/ui/no-patterns-in-args.stderr
+++ b/tests/ui/pattern/no-patterns-in-args.stderr
diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs
index 653dcab5771..796ba4d2332 100644
--- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs
+++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs
@@ -6,7 +6,7 @@ mod rank {
     pub use self::Lieutenant::{JuniorGrade, Full};
     //~^ ERROR `JuniorGrade` is private, and cannot be re-exported
     //~| ERROR `Full` is private, and cannot be re-exported
-    //~| ERROR unused imports: `Full`, `JuniorGrade`
+    //~| ERROR unused imports: `Full` and `JuniorGrade`
     pub use self::PettyOfficer::*;
     //~^ ERROR glob import doesn't reexport anything
     //~| ERROR unused import: `self::PettyOfficer::*`
diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr
index 93a39edbb82..f1701d547a6 100644
--- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr
+++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr
@@ -46,7 +46,7 @@ error: unused import: `self::Professor::*`
 LL |     pub use self::Professor::*;
    |             ^^^^^^^^^^^^^^^^^^
 
-error: unused imports: `Full`, `JuniorGrade`
+error: unused imports: `Full` and `JuniorGrade`
   --> $DIR/issue-46209-private-enum-variant-reexport.rs:6:32
    |
 LL |     pub use self::Lieutenant::{JuniorGrade, Full};
diff --git a/tests/ui/env-args-reverse-iterator.rs b/tests/ui/process/env-args-reverse-iterator.rs
index 830e9535466..830e9535466 100644
--- a/tests/ui/env-args-reverse-iterator.rs
+++ b/tests/ui/process/env-args-reverse-iterator.rs
diff --git a/tests/ui/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs
index 314ccaea015..314ccaea015 100644
--- a/tests/ui/env-funky-keys.rs
+++ b/tests/ui/process/env-funky-keys.rs
diff --git a/tests/ui/env-null-vars.rs b/tests/ui/process/env-null-vars.rs
index 24d783553d1..24d783553d1 100644
--- a/tests/ui/env-null-vars.rs
+++ b/tests/ui/process/env-null-vars.rs
diff --git a/tests/ui/env-vars.rs b/tests/ui/process/env-vars.rs
index 73068b5dfb8..73068b5dfb8 100644
--- a/tests/ui/env-vars.rs
+++ b/tests/ui/process/env-vars.rs
diff --git a/tests/ui/exec-env.rs b/tests/ui/process/exec-env.rs
index 9054b378f56..9054b378f56 100644
--- a/tests/ui/exec-env.rs
+++ b/tests/ui/process/exec-env.rs
diff --git a/tests/ui/inherit-env.rs b/tests/ui/process/inherit-env.rs
index 0eb61fcdd53..0eb61fcdd53 100644
--- a/tests/ui/inherit-env.rs
+++ b/tests/ui/process/inherit-env.rs
diff --git a/tests/ui/impossible_range.fixed b/tests/ui/range/impossible_range.fixed
index 423dde94f4f..423dde94f4f 100644
--- a/tests/ui/impossible_range.fixed
+++ b/tests/ui/range/impossible_range.fixed
diff --git a/tests/ui/impossible_range.rs b/tests/ui/range/impossible_range.rs
index 002ea792fbf..002ea792fbf 100644
--- a/tests/ui/impossible_range.rs
+++ b/tests/ui/range/impossible_range.rs
diff --git a/tests/ui/impossible_range.stderr b/tests/ui/range/impossible_range.stderr
index 53c56065c2a..53c56065c2a 100644
--- a/tests/ui/impossible_range.stderr
+++ b/tests/ui/range/impossible_range.stderr
diff --git a/tests/ui/range_inclusive.rs b/tests/ui/range/range_inclusive.rs
index 6e77f0d7767..6e77f0d7767 100644
--- a/tests/ui/range_inclusive.rs
+++ b/tests/ui/range/range_inclusive.rs
diff --git a/tests/ui/conflicting-repr-hints.rs b/tests/ui/repr/conflicting-repr-hints.rs
index ed82b6a742c..ed82b6a742c 100644
--- a/tests/ui/conflicting-repr-hints.rs
+++ b/tests/ui/repr/conflicting-repr-hints.rs
diff --git a/tests/ui/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr
index 4dcd8f4fc28..4dcd8f4fc28 100644
--- a/tests/ui/conflicting-repr-hints.stderr
+++ b/tests/ui/repr/conflicting-repr-hints.stderr
diff --git a/tests/ui/ret-bang.rs b/tests/ui/return/ret-bang.rs
index f0d529ad6a6..f0d529ad6a6 100644
--- a/tests/ui/ret-bang.rs
+++ b/tests/ui/return/ret-bang.rs
diff --git a/tests/ui/ret-non-nil.rs b/tests/ui/return/ret-non-nil.rs
index 1d039ffe18c..1d039ffe18c 100644
--- a/tests/ui/ret-non-nil.rs
+++ b/tests/ui/return/ret-non-nil.rs
diff --git a/tests/ui/ret-non-nil.stderr b/tests/ui/return/ret-non-nil.stderr
index 802900e61a3..802900e61a3 100644
--- a/tests/ui/ret-non-nil.stderr
+++ b/tests/ui/return/ret-non-nil.stderr
diff --git a/tests/ui/return-disjoint-regions.rs b/tests/ui/return/return-disjoint-regions.rs
index d0feb3b65e1..d0feb3b65e1 100644
--- a/tests/ui/return-disjoint-regions.rs
+++ b/tests/ui/return/return-disjoint-regions.rs
diff --git a/tests/ui/return-disjoint-regions.stderr b/tests/ui/return/return-disjoint-regions.stderr
index 7b5b032579a..7b5b032579a 100644
--- a/tests/ui/return-disjoint-regions.stderr
+++ b/tests/ui/return/return-disjoint-regions.stderr
diff --git a/tests/ui/return-nil.rs b/tests/ui/return/return-nil.rs
index 403eae260dc..403eae260dc 100644
--- a/tests/ui/return-nil.rs
+++ b/tests/ui/return/return-nil.rs
diff --git a/tests/ui/span/multispan-import-lint.stderr b/tests/ui/span/multispan-import-lint.stderr
index 4a955d1b31f..a4ea1af237b 100644
--- a/tests/ui/span/multispan-import-lint.stderr
+++ b/tests/ui/span/multispan-import-lint.stderr
@@ -1,4 +1,4 @@
-warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`
+warning: unused imports: `Eq`, `Ord`, `PartialEq`, and `PartialOrd`
   --> $DIR/multispan-import-lint.rs:5:16
    |
 LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
diff --git a/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs b/tests/ui/statics/auxiliary/check_static_recursion_foreign_helper.rs
index bcab5f238c3..bcab5f238c3 100644
--- a/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs
+++ b/tests/ui/statics/auxiliary/check_static_recursion_foreign_helper.rs
diff --git a/tests/ui/check-static-immutable-mut-slices.rs b/tests/ui/statics/check-immutable-mut-slices.rs
index 8f9680778aa..8f9680778aa 100644
--- a/tests/ui/check-static-immutable-mut-slices.rs
+++ b/tests/ui/statics/check-immutable-mut-slices.rs
diff --git a/tests/ui/check-static-immutable-mut-slices.stderr b/tests/ui/statics/check-immutable-mut-slices.stderr
index 402f9032b64..5cb35a7c21e 100644
--- a/tests/ui/check-static-immutable-mut-slices.stderr
+++ b/tests/ui/statics/check-immutable-mut-slices.stderr
@@ -1,5 +1,5 @@
 error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/check-static-immutable-mut-slices.rs:3:37
+  --> $DIR/check-immutable-mut-slices.rs:3:37
    |
 LL | static TEST: &'static mut [isize] = &mut [];
    |                                     ^^^^^^^
diff --git a/tests/ui/check-static-recursion-foreign.rs b/tests/ui/statics/check-recursion-foreign.rs
index 5a0ff7b5962..5a0ff7b5962 100644
--- a/tests/ui/check-static-recursion-foreign.rs
+++ b/tests/ui/statics/check-recursion-foreign.rs
diff --git a/tests/ui/check-static-values-constraints.rs b/tests/ui/statics/check-values-constraints.rs
index 005a7798895..005a7798895 100644
--- a/tests/ui/check-static-values-constraints.rs
+++ b/tests/ui/statics/check-values-constraints.rs
diff --git a/tests/ui/check-static-values-constraints.stderr b/tests/ui/statics/check-values-constraints.stderr
index fe5f2a34272..45a699f575f 100644
--- a/tests/ui/check-static-values-constraints.stderr
+++ b/tests/ui/statics/check-values-constraints.stderr
@@ -1,5 +1,5 @@
 error[E0493]: destructor of `SafeStruct` cannot be evaluated at compile-time
-  --> $DIR/check-static-values-constraints.rs:64:7
+  --> $DIR/check-values-constraints.rs:64:7
    |
 LL |       ..SafeStruct {
    |  _______^
@@ -12,7 +12,7 @@ LL |   };
    |   - value is dropped here
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:81:33
+  --> $DIR/check-values-constraints.rs:81:33
    |
 LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
    |                                 ^^^^^^^^^^^^^ allocation not allowed in statics
@@ -20,7 +20,7 @@ LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:81:33
+  --> $DIR/check-values-constraints.rs:81:33
    |
 LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
    |                                 ^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `<str as ToString>::to_string` in statics
-  --> $DIR/check-static-values-constraints.rs:92:38
+  --> $DIR/check-values-constraints.rs:92:38
    |
 LL |     field2: SafeEnum::Variant4("str".to_string()),
    |                                      ^^^^^^^^^^^
@@ -43,7 +43,7 @@ LL + #![feature(const_trait_impl)]
    |
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:96:5
+  --> $DIR/check-values-constraints.rs:96:5
    |
 LL |     vec![MyOwned],
    |     ^^^^^^^^^^^^^ allocation not allowed in statics
@@ -51,7 +51,7 @@ LL |     vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:96:5
+  --> $DIR/check-values-constraints.rs:96:5
    |
 LL |     vec![MyOwned],
    |     ^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL |     vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:98:5
+  --> $DIR/check-values-constraints.rs:98:5
    |
 LL |     vec![MyOwned],
    |     ^^^^^^^^^^^^^ allocation not allowed in statics
@@ -69,7 +69,7 @@ LL |     vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:98:5
+  --> $DIR/check-values-constraints.rs:98:5
    |
 LL |     vec![MyOwned],
    |     ^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |     vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:103:6
+  --> $DIR/check-values-constraints.rs:103:6
    |
 LL |     &vec![MyOwned],
    |      ^^^^^^^^^^^^^ allocation not allowed in statics
@@ -87,7 +87,7 @@ LL |     &vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:103:6
+  --> $DIR/check-values-constraints.rs:103:6
    |
 LL |     &vec![MyOwned],
    |      ^^^^^^^^^^^^^
@@ -97,7 +97,7 @@ LL |     &vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:105:6
+  --> $DIR/check-values-constraints.rs:105:6
    |
 LL |     &vec![MyOwned],
    |      ^^^^^^^^^^^^^ allocation not allowed in statics
@@ -105,7 +105,7 @@ LL |     &vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:105:6
+  --> $DIR/check-values-constraints.rs:105:6
    |
 LL |     &vec![MyOwned],
    |      ^^^^^^^^^^^^^
@@ -115,7 +115,7 @@ LL |     &vec![MyOwned],
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:111:31
+  --> $DIR/check-values-constraints.rs:111:31
    |
 LL | static STATIC19: Vec<isize> = vec![3];
    |                               ^^^^^^^ allocation not allowed in statics
@@ -123,7 +123,7 @@ LL | static STATIC19: Vec<isize> = vec![3];
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [isize]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:111:31
+  --> $DIR/check-values-constraints.rs:111:31
    |
 LL | static STATIC19: Vec<isize> = vec![3];
    |                               ^^^^^^^
@@ -133,7 +133,7 @@ LL | static STATIC19: Vec<isize> = vec![3];
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:117:32
+  --> $DIR/check-values-constraints.rs:117:32
    |
 LL |         static x: Vec<isize> = vec![3];
    |                                ^^^^^^^ allocation not allowed in statics
@@ -141,7 +141,7 @@ LL |         static x: Vec<isize> = vec![3];
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `slice::<impl [isize]>::into_vec::<std::alloc::Global>` in statics
-  --> $DIR/check-static-values-constraints.rs:117:32
+  --> $DIR/check-values-constraints.rs:117:32
    |
 LL |         static x: Vec<isize> = vec![3];
    |                                ^^^^^^^
@@ -151,7 +151,7 @@ LL |         static x: Vec<isize> = vec![3];
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0507]: cannot move out of static item `x`
-  --> $DIR/check-static-values-constraints.rs:119:9
+  --> $DIR/check-values-constraints.rs:119:9
    |
 LL |         x
    |         ^ move occurs because `x` has type `Vec<isize>`, which does not implement the `Copy` trait
diff --git a/tests/ui/dont-suggest-private-trait-method.rs b/tests/ui/suggestions/dont-suggest-private-trait-method.rs
index 6e2b1abd137..6e2b1abd137 100644
--- a/tests/ui/dont-suggest-private-trait-method.rs
+++ b/tests/ui/suggestions/dont-suggest-private-trait-method.rs
diff --git a/tests/ui/dont-suggest-private-trait-method.stderr b/tests/ui/suggestions/dont-suggest-private-trait-method.stderr
index f251ad59a58..f251ad59a58 100644
--- a/tests/ui/dont-suggest-private-trait-method.stderr
+++ b/tests/ui/suggestions/dont-suggest-private-trait-method.stderr
diff --git a/tests/ui/suggest-null-ptr.fixed b/tests/ui/suggestions/suggest-null-ptr.fixed
index 55c90859c83..55c90859c83 100644
--- a/tests/ui/suggest-null-ptr.fixed
+++ b/tests/ui/suggestions/suggest-null-ptr.fixed
diff --git a/tests/ui/suggest-null-ptr.rs b/tests/ui/suggestions/suggest-null-ptr.rs
index f4f1269d512..f4f1269d512 100644
--- a/tests/ui/suggest-null-ptr.rs
+++ b/tests/ui/suggestions/suggest-null-ptr.rs
diff --git a/tests/ui/suggest-null-ptr.stderr b/tests/ui/suggestions/suggest-null-ptr.stderr
index 66a79d0749e..66a79d0749e 100644
--- a/tests/ui/suggest-null-ptr.stderr
+++ b/tests/ui/suggestions/suggest-null-ptr.stderr
diff --git a/tests/ui/trait-impl-bound-suggestions.fixed b/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
index 9d3168f5acd..9d3168f5acd 100644
--- a/tests/ui/trait-impl-bound-suggestions.fixed
+++ b/tests/ui/suggestions/trait-impl-bound-suggestions.fixed
diff --git a/tests/ui/trait-impl-bound-suggestions.rs b/tests/ui/suggestions/trait-impl-bound-suggestions.rs
index 342fb4416ad..342fb4416ad 100644
--- a/tests/ui/trait-impl-bound-suggestions.rs
+++ b/tests/ui/suggestions/trait-impl-bound-suggestions.rs
diff --git a/tests/ui/trait-impl-bound-suggestions.stderr b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr
index 6a75cbdf639..6a75cbdf639 100644
--- a/tests/ui/trait-impl-bound-suggestions.stderr
+++ b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr
diff --git a/tests/ui/suggestions/unused-imports.stderr b/tests/ui/suggestions/unused-imports.stderr
index bf112608da7..31edb4e5ec2 100644
--- a/tests/ui/suggestions/unused-imports.stderr
+++ b/tests/ui/suggestions/unused-imports.stderr
@@ -1,4 +1,4 @@
-warning: unused imports: `A`, `C`
+warning: unused imports: `A` and `C`
   --> $DIR/unused-imports.rs:22:14
    |
 LL | use nested::{A, B, C};
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
-warning: unused imports: `D`, `E`, `G`
+warning: unused imports: `D`, `E`, and `G`
   --> $DIR/unused-imports.rs:26:5
    |
 LL |     D,
diff --git a/tests/ui/tool_lints-fail.rs b/tests/ui/tool-attributes/tool_lints-fail.rs
index 5cbd63be597..5cbd63be597 100644
--- a/tests/ui/tool_lints-fail.rs
+++ b/tests/ui/tool-attributes/tool_lints-fail.rs
diff --git a/tests/ui/tool_lints-fail.stderr b/tests/ui/tool-attributes/tool_lints-fail.stderr
index 7d80e0728f7..7d80e0728f7 100644
--- a/tests/ui/tool_lints-fail.stderr
+++ b/tests/ui/tool-attributes/tool_lints-fail.stderr
diff --git a/tests/ui/tool_lints-rpass.rs b/tests/ui/tool-attributes/tool_lints-rpass.rs
index 458eca19ed6..458eca19ed6 100644
--- a/tests/ui/tool_lints-rpass.rs
+++ b/tests/ui/tool-attributes/tool_lints-rpass.rs
diff --git a/tests/ui/tool_lints.rs b/tests/ui/tool-attributes/tool_lints.rs
index ef27532f6de..ef27532f6de 100644
--- a/tests/ui/tool_lints.rs
+++ b/tests/ui/tool-attributes/tool_lints.rs
diff --git a/tests/ui/tool_lints.stderr b/tests/ui/tool-attributes/tool_lints.stderr
index f1d825caba1..f1d825caba1 100644
--- a/tests/ui/tool_lints.stderr
+++ b/tests/ui/tool-attributes/tool_lints.stderr
diff --git a/tests/ui/tool_lints_2018_preview.rs b/tests/ui/tool-attributes/tool_lints_2018_preview.rs
index 458eca19ed6..458eca19ed6 100644
--- a/tests/ui/tool_lints_2018_preview.rs
+++ b/tests/ui/tool-attributes/tool_lints_2018_preview.rs
diff --git a/tests/ui/unknown-lint-tool-name.rs b/tests/ui/tool-attributes/unknown-lint-tool-name.rs
index cd5d2f028af..cd5d2f028af 100644
--- a/tests/ui/unknown-lint-tool-name.rs
+++ b/tests/ui/tool-attributes/unknown-lint-tool-name.rs
diff --git a/tests/ui/unknown-lint-tool-name.stderr b/tests/ui/tool-attributes/unknown-lint-tool-name.stderr
index 72731ab1e3d..72731ab1e3d 100644
--- a/tests/ui/unknown-lint-tool-name.stderr
+++ b/tests/ui/tool-attributes/unknown-lint-tool-name.stderr
diff --git a/tests/ui/unknown-tool-name.rs b/tests/ui/tool-attributes/unknown-tool-name.rs
index 73fca61c65d..73fca61c65d 100644
--- a/tests/ui/unknown-tool-name.rs
+++ b/tests/ui/tool-attributes/unknown-tool-name.rs
diff --git a/tests/ui/unknown-tool-name.stderr b/tests/ui/tool-attributes/unknown-tool-name.stderr
index 361d359a10e..361d359a10e 100644
--- a/tests/ui/unknown-tool-name.stderr
+++ b/tests/ui/tool-attributes/unknown-tool-name.stderr
diff --git a/tests/ui/unop-move-semantics.rs b/tests/ui/unop/unop-move-semantics.rs
index 8168da8242f..8168da8242f 100644
--- a/tests/ui/unop-move-semantics.rs
+++ b/tests/ui/unop/unop-move-semantics.rs
diff --git a/tests/ui/unop-move-semantics.stderr b/tests/ui/unop/unop-move-semantics.stderr
index bc9b3ea9903..bc9b3ea9903 100644
--- a/tests/ui/unop-move-semantics.stderr
+++ b/tests/ui/unop/unop-move-semantics.stderr
diff --git a/tests/ui/unop-neg-bool.rs b/tests/ui/unop/unop-neg-bool.rs
index 6f1f1aba459..6f1f1aba459 100644
--- a/tests/ui/unop-neg-bool.rs
+++ b/tests/ui/unop/unop-neg-bool.rs
diff --git a/tests/ui/unop-neg-bool.stderr b/tests/ui/unop/unop-neg-bool.stderr
index 9bc5e7dcf22..9bc5e7dcf22 100644
--- a/tests/ui/unop-neg-bool.stderr
+++ b/tests/ui/unop/unop-neg-bool.stderr
diff --git a/tests/ui/use/use-nested-groups-unused-imports.rs b/tests/ui/use/use-nested-groups-unused-imports.rs
index ca6b8ba94d1..0c8ae558a59 100644
--- a/tests/ui/use/use-nested-groups-unused-imports.rs
+++ b/tests/ui/use/use-nested-groups-unused-imports.rs
@@ -13,7 +13,7 @@ mod foo {
 }
 
 use foo::{Foo, bar::{baz::{}, foobar::*}, *};
-    //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
+    //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, and `foobar::*`
 use foo::bar::baz::{*, *};
     //~^ ERROR unused import: `*`
 use foo::{};
diff --git a/tests/ui/use/use-nested-groups-unused-imports.stderr b/tests/ui/use/use-nested-groups-unused-imports.stderr
index 6610f8ecd4a..dd39a852772 100644
--- a/tests/ui/use/use-nested-groups-unused-imports.stderr
+++ b/tests/ui/use/use-nested-groups-unused-imports.stderr
@@ -1,4 +1,4 @@
-error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
+error: unused imports: `*`, `Foo`, `baz::{}`, and `foobar::*`
   --> $DIR/use-nested-groups-unused-imports.rs:15:11
    |
 LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};