about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--Cargo.lock1135
-rw-r--r--Cargo.toml1
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs133
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs110
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl25
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/cmdline_attrs.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/concat.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs88
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/trace_macros.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs62
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs21
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs27
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs78
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs4
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs116
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs22
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs79
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs34
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs50
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs11
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs6
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/small_str.rs68
-rw-r--r--compiler/rustc_data_structures/src/small_str/tests.rs20
-rw-r--r--compiler/rustc_driver/Cargo.toml3
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs6
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl9
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs148
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs140
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs57
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs2
-rw-r--r--compiler/rustc_infer/src/infer/at.rs1
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs41
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs5
-rw-r--r--compiler/rustc_infer/src/traits/util.rs82
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lint/src/builtin.rs8
-rw-r--r--compiler/rustc_lint/src/drop_forget_useless.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs10
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp90
-rw-r--r--compiler/rustc_log/Cargo.toml2
-rw-r--r--compiler/rustc_macros/Cargo.toml3
-rw-r--r--compiler/rustc_metadata/messages.ftl3
-rw-r--r--compiler/rustc_metadata/src/errors.rs14
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs3
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs35
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs26
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs3
-rw-r--r--compiler/rustc_middle/src/query/erase.rs14
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs52
-rw-r--r--compiler/rustc_middle/src/values.rs7
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs145
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs74
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/un_derefer.rs22
-rw-r--r--compiler/rustc_mir_transform/src/deref_separator.rs10
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs25
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs36
-rw-r--r--compiler/rustc_passes/src/layout_test.rs1
-rw-r--r--compiler/rustc_privacy/messages.ftl2
-rw-r--r--compiler/rustc_privacy/src/errors.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs181
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs5
-rw-r--r--compiler/rustc_resolve/src/ident.rs25
-rw-r--r--compiler/rustc_resolve/src/imports.rs28
-rw-r--r--compiler/rustc_resolve/src/late.rs10
-rw-r--r--compiler/rustc_resolve/src/lib.rs8
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_session/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/config.rs168
-rw-r--r--compiler/rustc_session/src/options.rs39
-rw-r--r--compiler/rustc_span/src/source_map.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/Cargo.toml5
-rw-r--r--compiler/rustc_target/src/spec/avr_gnu_base.rs337
-rw-r--r--compiler/rustc_target/src/spec/mod.rs142
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs28
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs37
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs2
-rw-r--r--compiler/rustc_traits/Cargo.toml6
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/codegen.rs15
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs8
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs17
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs12
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs65
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs4
-rw-r--r--library/alloc/src/ffi/c_str.rs2
-rw-r--r--library/alloc/src/vec/mod.rs29
m---------library/backtrace0
-rw-r--r--library/core/src/convert/mod.rs2
-rw-r--r--library/core/src/ffi/c_str.rs17
-rw-r--r--library/core/src/intrinsics.rs6
-rw-r--r--library/core/src/iter/adapters/flatten.rs12
-rw-r--r--library/core/src/iter/traits/iterator.rs8
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/marker.rs28
-rw-r--r--library/core/src/ops/index.rs2
-rw-r--r--library/core/src/ops/try_trait.rs45
-rw-r--r--library/core/src/slice/index.rs5
-rw-r--r--library/core/src/str/mod.rs40
-rw-r--r--library/std/Cargo.toml9
-rw-r--r--library/std/src/collections/hash/map.rs8
-rw-r--r--library/std/src/sync/barrier.rs14
-rw-r--r--library/test/src/console.rs2
-rw-r--r--library/test/src/lib.rs206
-rw-r--r--library/test/src/types.rs80
-rw-r--r--src/bootstrap/bin/main.rs10
-rw-r--r--src/bootstrap/bootstrap_test.py15
-rw-r--r--src/bootstrap/builder.rs9
-rw-r--r--src/bootstrap/config.rs48
-rw-r--r--src/bootstrap/config/tests.rs15
-rw-r--r--src/bootstrap/defaults/config.dist.toml3
-rw-r--r--src/bootstrap/dist.rs88
-rw-r--r--src/bootstrap/doc.rs50
-rw-r--r--src/bootstrap/lib.rs2
-rw-r--r--src/bootstrap/test.rs51
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/ci/github-actions/ci.yml7
-rwxr-xr-xsrc/ci/stage-build.py9
-rw-r--r--src/doc/rustdoc/src/how-to-read-rustdoc.md5
-rw-r--r--src/doc/rustdoc/src/unstable-features.md2
-rw-r--r--src/doc/style-guide/src/README.md5
-rw-r--r--src/doc/style-guide/src/expressions.md3
-rw-r--r--src/doc/style-guide/src/statements.md26
-rwxr-xr-xsrc/etc/pre-push.sh6
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/render/type_layout.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css30
-rw-r--r--src/librustdoc/html/static/js/search.js255
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.cargo/config.toml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml1
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml1
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml1
-rw-r--r--src/tools/clippy/CHANGELOG.md200
-rw-r--r--src/tools/clippy/Cargo.toml19
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md19
-rw-r--r--src/tools/clippy/book/src/development/basics.md2
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/changelog_update.md22
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md591
-rw-r--r--src/tools/clippy/clippy_dev/src/bless.rs60
-rw-r--r--src/tools/clippy/clippy_dev/src/fmt.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs7
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs10
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs15
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml3
-rw-r--r--src/tools/clippy/clippy_lints/src/allow_attributes.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs72
-rw-r--r--src/tools/clippy/clippy_lints/src/as_conversions.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs95
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs140
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/endian_bytes.rs216
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs181
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_push_string.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/incorrect_impls.rs124
-rw-r--r--src/tools/clippy/clippy_lints/src/items_after_test_module.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_frames.rs162
-rw-r--r--src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs256
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs95
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs92
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs247
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_range_patterns.rs123
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/try_err.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_forget.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/drain_collect.rs85
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs174
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs115
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs211
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs95
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/min_ident_chars.rs153
-rw-r--r--src/tools/clippy/clippy_lints/src/minmax.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mod.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_if.rs75
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs47
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs82
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/eq_op.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_cmp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs105
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs250
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/raw_strings.rs143
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs163
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs210
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs587
-rw-r--r--src/tools/clippy/clippy_lints/src/single_call_fn.rs133
-rw-r--r--src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs147
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs235
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs126
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_async.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs47
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs87
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs156
-rw-r--r--src/tools/clippy/clippy_lints/src/visibility.rs131
-rw-r--r--src/tools/clippy/clippy_test_deps/Cargo.toml23
-rw-r--r--src/tools/clippy/clippy_test_deps/src/lib.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs122
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs147
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs82
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs58
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs2
-rw-r--r--src/tools/clippy/declare_clippy_lint/src/lib.rs4
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/rustfmt.toml1
-rw-r--r--src/tools/clippy/src/driver.rs2
-rw-r--r--src/tools/clippy/src/main.rs8
-rw-r--r--src/tools/clippy/tests/compile-test.rs436
-rw-r--r--src/tools/clippy/tests/headers.rs29
-rw-r--r--src/tools/clippy/tests/lint_message_convention.rs30
-rw-r--r--src/tools/clippy/tests/missing-test-files.rs6
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr (renamed from src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr)7
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr (renamed from src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr)7
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr (renamed from src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr)7
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr21
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr22
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr19
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr20
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr19
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr20
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr19
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr (renamed from src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr)15
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr20
-rw-r--r--src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr (renamed from src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr)2
-rw-r--r--src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr52
-rw-r--r--src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr53
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.stderr43
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr44
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.stderr18
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr19
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr10
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr11
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr10
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr11
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr2
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr4
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr5
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr6
-rwxr-xr-xsrc/tools/clippy/tests/ui-cargo/update-all-references.sh2
-rw-r--r--src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr5
-rw-r--r--src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr6
-rw-r--r--src/tools/clippy/tests/ui-internal/check_formulation.rs54
-rw-r--r--src/tools/clippy/tests/ui-internal/check_formulation.stderr19
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr6
-rw-r--r--src/tools/clippy/tests/ui-internal/if_chain_style.rs7
-rw-r--r--src/tools/clippy/tests/ui-internal/if_chain_style.stderr20
-rw-r--r--src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed1
-rw-r--r--src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr12
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs472
-rw-r--r--src/tools/clippy/tests/ui-toml/excessive_nesting/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs197
-rw-r--r--src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr314
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr10
-rw-r--r--src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs3
-rw-r--r--src/tools/clippy/tests/ui-toml/min_ident_chars/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.rs19
-rw-r--r--src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.stderr46
-rw-r--r--src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs4
-rw-r--r--src/tools/clippy/tests/ui-toml/module_inception/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/module_inception/module_inception.rs34
-rw-r--r--src/tools/clippy/tests/ui-toml/module_inception/module_inception.stderr20
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs5
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed2
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs10
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr28
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr20
-rw-r--r--src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs13
-rw-r--r--src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs567
-rw-r--r--src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr314
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs9
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr62
-rwxr-xr-xsrc/tools/clippy/tests/ui-toml/update-all-references.sh2
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.fixed20
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.rs20
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.stderr4
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_false_positive.rs5
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_without_reason.rs32
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr28
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.fixed2
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.rs2
-rw-r--r--src/tools/clippy/tests/ui/arc_with_non_send_sync.rs17
-rw-r--r--src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr11
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs17
-rw-r--r--src/tools/clippy/tests/ui/as_conversions.rs13
-rw-r--r--src/tools/clippy/tests/ui/as_conversions.stderr6
-rw-r--r--src/tools/clippy/tests/ui/as_ptr_cast_mut.rs2
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax.rs4
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.fixed1
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.rs1
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.stderr14
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.fixed2
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.rs2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/extern_fake_libc.rs10
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs8
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs4
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs114
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs5
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs5
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macros.rs6
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed2
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_if_conditions.rs2
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.rs7
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.stderr4
-rw-r--r--src/tools/clippy/tests/ui/bool_comparison.fixed1
-rw-r--r--src/tools/clippy/tests/ui/bool_comparison.rs1
-rw-r--r--src/tools/clippy/tests/ui/bool_comparison.stderr44
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.fixed9
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.rs9
-rw-r--r--src/tools/clippy/tests/ui/borrow_as_ptr.stderr4
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs26
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr24
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs30
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr34
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs32
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr36
-rw-r--r--src/tools/clippy/tests/ui/builtin_type_shadow.rs2
-rw-r--r--src/tools/clippy/tests/ui/bytecount.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast.rs8
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr118
-rw-r--r--src/tools/clippy/tests/ui/cast_slice_different_sizes.rs2
-rw-r--r--src/tools/clippy/tests/ui/cfg_features.rs12
-rw-r--r--src/tools/clippy/tests/ui/cfg_features.stderr28
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs6
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr40
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs6
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr4
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs6
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr34
-rw-r--r--src/tools/clippy/tests/ui/clone_on_copy_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed1
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.rs1
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr16
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed7
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs7
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.stderr12
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed2
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity.stderr10
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.fixed2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.rs2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed1
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs1
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr18
-rw-r--r--src/tools/clippy/tests/ui/collection_is_never_read.rs2
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.fixed1
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.rs1
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.stderr8
-rw-r--r--src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs8
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10148.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.stderr4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10912.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10912.stderr16
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1782.rs1
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2774.stderr4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3462.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3741.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-4968.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5497.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-5579.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6250.stderr11
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6251.stderr10
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6255.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6256.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6256.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7169.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7169.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7410.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9445.stderr12
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-96721.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-96721.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr4
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr11
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs2
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.rs1
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.stderr36
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs27
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr43
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs16
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr8
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs22
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr22
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.fixed2
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.rs2
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.fixed4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.rs4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed21
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs21
-rw-r--r--src/tools/clippy/tests/ui/derive.rs2
-rw-r--r--src/tools/clippy/tests/ui/disallowed_names.rs1
-rw-r--r--src/tools/clippy/tests/ui/disallowed_names.stderr28
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.rs16
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.stderr46
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.stderr32
-rw-r--r--src/tools/clippy/tests/ui/doc/needless_doctest_main.rs20
-rw-r--r--src/tools/clippy/tests/ui/doc_unsafe.rs2
-rw-r--r--src/tools/clippy/tests/ui/double_comparison.fixed1
-rw-r--r--src/tools/clippy/tests/ui/double_comparison.rs1
-rw-r--r--src/tools/clippy/tests/ui/double_comparison.stderr16
-rw-r--r--src/tools/clippy/tests/ui/drain_collect.fixed77
-rw-r--r--src/tools/clippy/tests/ui/drain_collect.rs77
-rw-r--r--src/tools/clippy/tests/ui/drain_collect.stderr68
-rw-r--r--src/tools/clippy/tests/ui/else_if_without_else.rs4
-rw-r--r--src/tools/clippy/tests/ui/else_if_without_else.stderr4
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/empty_loop_no_std.rs2
-rw-r--r--src/tools/clippy/tests/ui/endian_bytes.rs127
-rw-r--r--src/tools/clippy/tests/ui/endian_bytes.stderr1031
-rw-r--r--src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs2
-rw-r--r--src/tools/clippy/tests/ui/eprint_with_newline.rs2
-rw-r--r--src/tools/clippy/tests/ui/eprint_with_newline.stderr12
-rw-r--r--src/tools/clippy/tests/ui/eq_op.rs4
-rw-r--r--src/tools/clippy/tests/ui/eq_op.stderr20
-rw-r--r--src/tools/clippy/tests/ui/eq_op_macros.rs1
-rw-r--r--src/tools/clippy/tests/ui/eq_op_macros.stderr24
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.fixed11
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.rs11
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.stderr28
-rw-r--r--src/tools/clippy/tests/ui/err_expect.fixed2
-rw-r--r--src/tools/clippy/tests/ui/err_expect.rs2
-rw-r--r--src/tools/clippy/tests/ui/eta.fixed9
-rw-r--r--src/tools/clippy/tests/ui/eta.rs9
-rw-r--r--src/tools/clippy/tests/ui/eta.stderr52
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.fixed15
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.rs15
-rw-r--r--src/tools/clippy/tests/ui/excessive_precision.stderr30
-rw-r--r--src/tools/clippy/tests/ui/expect.rs1
-rw-r--r--src/tools/clippy/tests/ui/expect.stderr6
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.fixed6
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.rs6
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.stderr30
-rw-r--r--src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs2
-rw-r--r--src/tools/clippy/tests/ui/explicit_counter_loop.rs50
-rw-r--r--src/tools/clippy/tests/ui/explicit_counter_loop.stderr10
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.fixed33
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.rs33
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.stderr24
-rw-r--r--src/tools/clippy/tests/ui/explicit_into_iter_loop.fixed69
-rw-r--r--src/tools/clippy/tests/ui/explicit_into_iter_loop.rs69
-rw-r--r--src/tools/clippy/tests/ui/explicit_into_iter_loop.stderr40
-rw-r--r--src/tools/clippy/tests/ui/explicit_iter_loop.fixed154
-rw-r--r--src/tools/clippy/tests/ui/explicit_iter_loop.rs154
-rw-r--r--src/tools/clippy/tests/ui/explicit_iter_loop.stderr142
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_lifetimes.rs2
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed12
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.rs12
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr16
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs4
-rw-r--r--src/tools/clippy/tests/ui/filetype_is_file.rs1
-rw-r--r--src/tools/clippy/tests/ui/filetype_is_file.stderr6
-rw-r--r--src/tools/clippy/tests/ui/find_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/fn_null_check.rs1
-rw-r--r--src/tools/clippy/tests/ui/fn_null_check.stderr10
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.fixed309
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.rs309
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.stderr96
-rw-r--r--src/tools/clippy/tests/ui/for_loop_unfixable.rs16
-rw-r--r--src/tools/clippy/tests/ui/for_loop_unfixable.stderr10
-rw-r--r--src/tools/clippy/tests/ui/format.fixed4
-rw-r--r--src/tools/clippy/tests/ui/format.rs4
-rw-r--r--src/tools/clippy/tests/ui/format.stderr30
-rw-r--r--src/tools/clippy/tests/ui/format_push_string.rs29
-rw-r--r--src/tools/clippy/tests/ui/format_push_string.stderr37
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed1
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs1
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr30
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.fixed9
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs9
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.stderr18
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.rs16
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.stderr10
-rw-r--r--src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs1
-rw-r--r--src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr20
-rw-r--r--src/tools/clippy/tests/ui/get_first.fixed1
-rw-r--r--src/tools/clippy/tests/ui/get_first.rs1
-rw-r--r--src/tools/clippy/tests/ui/get_first.stderr6
-rw-r--r--src/tools/clippy/tests/ui/get_last_with_len.fixed2
-rw-r--r--src/tools/clippy/tests/ui/get_last_with_len.rs2
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.fixed46
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.rs46
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.stderr80
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else.rs10
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else.stderr24
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.rs12
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.stderr37
-rw-r--r--src/tools/clippy/tests/ui/ifs_same_cond.rs14
-rw-r--r--src/tools/clippy/tests/ui/ifs_same_cond.stderr16
-rw-r--r--src/tools/clippy/tests/ui/implicit_hasher.rs2
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed2
-rw-r--r--src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs2
-rw-r--r--src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.fixed97
-rw-r--r--src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.rs107
-rw-r--r--src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.stderr40
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.rs7
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.stderr26
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_slice.rs2
-rw-r--r--src/tools/clippy/tests/ui/into_iter_on_ref.fixed54
-rw-r--r--src/tools/clippy/tests/ui/into_iter_on_ref.rs54
-rw-r--r--src/tools/clippy/tests/ui/into_iter_on_ref.stderr54
-rw-r--r--src/tools/clippy/tests/ui/issue-3145.rs2
-rw-r--r--src/tools/clippy/tests/ui/issue-3145.stderr2
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.stderr8
-rw-r--r--src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr17
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.fixed1
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.rs1
-rw-r--r--src/tools/clippy/tests/ui/iter_cloned_collect.stderr10
-rw-r--r--src/tools/clippy/tests/ui/iter_count.fixed3
-rw-r--r--src/tools/clippy/tests/ui/iter_count.rs3
-rw-r--r--src/tools/clippy/tests/ui/iter_count.stderr50
-rw-r--r--src/tools/clippy/tests/ui/iter_next_loop.rs16
-rw-r--r--src/tools/clippy/tests/ui/iter_next_loop.stderr9
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.fixed1
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.rs1
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.stderr8
-rw-r--r--src/tools/clippy/tests/ui/iter_nth.rs1
-rw-r--r--src/tools/clippy/tests/ui/iter_nth.stderr22
-rw-r--r--src/tools/clippy/tests/ui/iter_nth_zero.fixed15
-rw-r--r--src/tools/clippy/tests/ui/iter_nth_zero.rs15
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_overeager_cloned.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_skip_next.fixed1
-rw-r--r--src/tools/clippy/tests/ui/iter_skip_next.rs1
-rw-r--r--src/tools/clippy/tests/ui/iter_skip_next.stderr14
-rw-r--r--src/tools/clippy/tests/ui/iter_with_drain.fixed2
-rw-r--r--src/tools/clippy/tests/ui/iter_with_drain.rs2
-rw-r--r--src/tools/clippy/tests/ui/iterator_step_by_zero.rs1
-rw-r--r--src/tools/clippy/tests/ui/iterator_step_by_zero.stderr14
-rw-r--r--src/tools/clippy/tests/ui/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/tests/ui/large_futures.rs1
-rw-r--r--src/tools/clippy/tests/ui/large_futures.stderr16
-rw-r--r--src/tools/clippy/tests/ui/large_stack_frames.rs44
-rw-r--r--src/tools/clippy/tests/ui/large_stack_frames.stderr37
-rw-r--r--src/tools/clippy/tests/ui/len_zero.fixed2
-rw-r--r--src/tools/clippy/tests/ui/len_zero.rs2
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.rs2
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.rs25
-rw-r--r--src/tools/clippy/tests/ui/let_with_type_underscore.stderr38
-rw-r--r--src/tools/clippy/tests/ui/lossy_float_literal.fixed4
-rw-r--r--src/tools/clippy/tests/ui/lossy_float_literal.rs4
-rw-r--r--src/tools/clippy/tests/ui/lossy_float_literal.stderr22
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.fixed2
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.rs2
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.stderr16
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports_expect.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_filter_map.stderr54
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.fixed1
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_find_map.stderr60
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs50
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.stderr107
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.rs11
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr27
-rw-r--r--src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs1
-rw-r--r--src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr26
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.fixed35
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.rs35
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.stderr51
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_try_fold.rs100
-rw-r--r--src/tools/clippy/tests/ui/manual_try_fold.stderr28
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_clone.fixed3
-rw-r--r--src/tools/clippy/tests/ui/map_clone.rs3
-rw-r--r--src/tools/clippy/tests/ui/map_clone.stderr12
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or.rs47
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or.stderr44
-rw-r--r--src/tools/clippy/tests/ui/match_on_vec_items.rs1
-rw-r--r--src/tools/clippy/tests/ui/match_on_vec_items.stderr16
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.rs20
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.stderr24
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs23
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr33
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs58
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr29
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.fixed3
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.rs3
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.stderr48
-rw-r--r--src/tools/clippy/tests/ui/mem_forget.rs3
-rw-r--r--src/tools/clippy/tests/ui/mem_forget.stderr15
-rw-r--r--src/tools/clippy/tests/ui/mem_replace_macro.rs2
-rw-r--r--src/tools/clippy/tests/ui/methods.rs1
-rw-r--r--src/tools/clippy/tests/ui/methods.stderr4
-rw-r--r--src/tools/clippy/tests/ui/methods_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/methods_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/methods_fixable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.rs84
-rw-r--r--src/tools/clippy/tests/ui/min_ident_chars.stderr178
-rw-r--r--src/tools/clippy/tests/ui/missing_assert_message.rs11
-rw-r--r--src/tools/clippy/tests/ui/missing_assert_message.stderr32
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs45
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs13
-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_doc.rs2
-rw-r--r--src/tools/clippy/tests/ui/missing_doc_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui/missing_inline_proc_macro.rs1
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.rs80
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.stderr110
-rw-r--r--src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed2
-rw-r--r--src/tools/clippy/tests/ui/mistyped_literal_suffix.rs2
-rw-r--r--src/tools/clippy/tests/ui/module_inception.rs12
-rw-r--r--src/tools/clippy/tests/ui/module_inception.stderr22
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs2
-rw-r--r--src/tools/clippy/tests/ui/must_use_unit.fixed2
-rw-r--r--src/tools/clippy/tests/ui/must_use_unit.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_mut.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.stderr42
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed3
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs3
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.stderr72
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.fixed3
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.rs3
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.stderr34
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.rs3
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.stderr32
-rw-r--r--src/tools/clippy/tests/ui/needless_if.fixed93
-rw-r--r--src/tools/clippy/tests/ui/needless_if.rs94
-rw-r--r--src/tools/clippy/tests/ui/needless_if.stderr65
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.fixed5
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.rs5
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.stderr32
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.stderr184
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.fixed1
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.stderr6
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_value_proc_macro.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_pub_self.fixed33
-rw-r--r--src/tools/clippy/tests/ui/needless_pub_self.rs33
-rw-r--r--src/tools/clippy/tests/ui/needless_pub_self.stderr22
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.rs64
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.stderr28
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop2.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop2.stderr16
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.fixed16
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.rs16
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string.stderr22
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed19
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.rs19
-rw-r--r--src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr58
-rw-r--r--src/tools/clippy/tests/ui/never_loop.rs38
-rw-r--r--src/tools/clippy/tests/ui/never_loop.stderr46
-rw-r--r--src/tools/clippy/tests/ui/no_effect.rs3
-rw-r--r--src/tools/clippy/tests/ui/no_effect.stderr58
-rw-r--r--src/tools/clippy/tests/ui/no_effect_return.rs81
-rw-r--r--src/tools/clippy/tests/ui/no_effect_return.stderr70
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names.rs12
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names.stderr6
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed2
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.rs2
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.rs3
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.stderr26
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed2
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.rs2
-rw-r--r--src/tools/clippy/tests/ui/octal_escapes.stderr6
-rw-r--r--src/tools/clippy/tests/ui/ok_expect.rs2
-rw-r--r--src/tools/clippy/tests/ui/ok_expect.stderr10
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.fixed2
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.rs2
-rw-r--r--src/tools/clippy/tests/ui/option_env_unwrap.rs2
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed16
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs22
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr20
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed8
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs8
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr56
-rw-r--r--src/tools/clippy/tests/ui/or_then_unwrap.fixed2
-rw-r--r--src/tools/clippy/tests/ui/or_then_unwrap.rs2
-rw-r--r--src/tools/clippy/tests/ui/overflow_check_conditional.rs1
-rw-r--r--src/tools/clippy/tests/ui/overflow_check_conditional.stderr16
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.fixed2
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.rs2
-rw-r--r--src/tools/clippy/tests/ui/patterns.fixed11
-rw-r--r--src/tools/clippy/tests/ui/patterns.rs11
-rw-r--r--src/tools/clippy/tests/ui/patterns.stderr6
-rw-r--r--src/tools/clippy/tests/ui/print_with_newline.fixed58
-rw-r--r--src/tools/clippy/tests/ui/print_with_newline.rs2
-rw-r--r--src/tools/clippy/tests/ui/print_with_newline.stderr12
-rw-r--r--src/tools/clippy/tests/ui/proc_macro.rs1
-rw-r--r--src/tools/clippy/tests/ui/proc_macro.stderr2
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.rs33
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.stderr60
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.fixed2
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.rs2
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.fixed21
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.rs31
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.stderr46
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed2
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.rs2
-rw-r--r--src/tools/clippy/tests/ui/pub_with_shorthand.fixed38
-rw-r--r--src/tools/clippy/tests/ui/pub_with_shorthand.rs38
-rw-r--r--src/tools/clippy/tests/ui/pub_with_shorthand.stderr28
-rw-r--r--src/tools/clippy/tests/ui/pub_without_shorthand.fixed38
-rw-r--r--src/tools/clippy/tests/ui/pub_without_shorthand.rs38
-rw-r--r--src/tools/clippy/tests/ui/pub_without_shorthand.stderr22
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed22
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs26
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr42
-rw-r--r--src/tools/clippy/tests/ui/range.rs1
-rw-r--r--src/tools/clippy/tests/ui/range.stderr2
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.rs1
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr8
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.rs1
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr8
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.rs1
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr16
-rw-r--r--src/tools/clippy/tests/ui/redundant_at_rest_pattern.fixed27
-rw-r--r--src/tools/clippy/tests/ui/redundant_at_rest_pattern.rs27
-rw-r--r--src/tools/clippy/tests/ui/redundant_at_rest_pattern.stderr40
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed8
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.rs8
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.stderr60
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed47
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs47
-rw-r--r--src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr62
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed7
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs7
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr44
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr36
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr56
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr36
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs1
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr56
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.fixed8
-rw-r--r--src/tools/clippy/tests/ui/redundant_pub_crate.rs8
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed22
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.rs22
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr24
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.rs6
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.stderr12
-rw-r--r--src/tools/clippy/tests/ui/redundant_type_annotations.rs176
-rw-r--r--src/tools/clippy/tests/ui/redundant_type_annotations.stderr106
-rw-r--r--src/tools/clippy/tests/ui/regex.rs7
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr52
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed6
-rw-r--r--src/tools/clippy/tests/ui/rename.rs6
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr114
-rw-r--r--src/tools/clippy/tests/ui/same_functions_in_if_condition.rs12
-rw-r--r--src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr4
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.rs1
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.stderr16
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.rs2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.rs2
-rw-r--r--src/tools/clippy/tests/ui/self_assignment.rs1
-rw-r--r--src/tools/clippy/tests/ui/self_assignment.stderr22
-rw-r--r--src/tools/clippy/tests/ui/shadow.rs4
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_in_scrutinee.fixed627
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.fixed12
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.rs12
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.stderr6
-rw-r--r--src/tools/clippy/tests/ui/single_call_fn.rs74
-rw-r--r--src/tools/clippy/tests/ui/single_call_fn.stderr55
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.fixed1
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.rs1
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.stderr30
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.stderr4
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.stderr14
-rw-r--r--src/tools/clippy/tests/ui/single_match.fixed47
-rw-r--r--src/tools/clippy/tests/ui/single_match.rs47
-rw-r--r--src/tools/clippy/tests/ui/single_match.stderr36
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_range_in_vec_init.rs58
-rw-r--r--src/tools/clippy/tests/ui/single_range_in_vec_init.stderr145
-rw-r--r--src/tools/clippy/tests/ui/skip_while_next.rs2
-rw-r--r--src/tools/clippy/tests/ui/stable_sort_primitive.fixed1
-rw-r--r--src/tools/clippy/tests/ui/stable_sort_primitive.rs1
-rw-r--r--src/tools/clippy/tests/ui/stable_sort_primitive.stderr14
-rw-r--r--src/tools/clippy/tests/ui/starts_ends_with.fixed2
-rw-r--r--src/tools/clippy/tests/ui/starts_ends_with.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_add.rs2
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.fixed2
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.rs2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_else_formatting.rs16
-rw-r--r--src/tools/clippy/tests/ui/suspicious_else_formatting.stderr18
-rw-r--r--src/tools/clippy/tests/ui/suspicious_unary_op_formatting.rs1
-rw-r--r--src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr8
-rw-r--r--src/tools/clippy/tests/ui/swap.fixed3
-rw-r--r--src/tools/clippy/tests/ui/swap.rs3
-rw-r--r--src/tools/clippy/tests/ui/swap.stderr34
-rw-r--r--src/tools/clippy/tests/ui/tests_outside_test_module.rs1
-rw-r--r--src/tools/clippy/tests/ui/tests_outside_test_module.stderr2
-rw-r--r--src/tools/clippy/tests/ui/to_string_in_format_args_incremental.fixed9
-rw-r--r--src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs9
-rw-r--r--src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr10
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.fixed4
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.rs4
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed5
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs5
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr48
-rw-r--r--src/tools/clippy/tests/ui/try_err.fixed2
-rw-r--r--src/tools/clippy/tests/ui/try_err.rs2
-rw-r--r--src/tools/clippy/tests/ui/tuple_array_conversions.rs73
-rw-r--r--src/tools/clippy/tests/ui/tuple_array_conversions.stderr83
-rw-r--r--src/tools/clippy/tests/ui/type_complexity.rs2
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.rs39
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr18
-rw-r--r--src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs24
-rw-r--r--src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr26
-rw-r--r--src/tools/clippy/tests/ui/unicode.fixed1
-rw-r--r--src/tools/clippy/tests/ui/unicode.rs1
-rw-r--r--src/tools/clippy/tests/ui/unicode.stderr20
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed9
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs9
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.stderr142
-rw-r--r--src/tools/clippy/tests/ui/unit_arg.rs2
-rw-r--r--src/tools/clippy/tests/ui/unit_cmp.rs3
-rw-r--r--src/tools/clippy/tests/ui/unit_cmp.stderr12
-rw-r--r--src/tools/clippy/tests/ui/unit_return_expecting_ord.rs1
-rw-r--r--src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr12
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.fixed81
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.rs81
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.stderr110
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_fold.fixed24
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_fold.rs24
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_fold.stderr56
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed30
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs30
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr102
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr6
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed78
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap.rs78
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr413
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.rs116
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.stderr603
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_safety_comment.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_sort_by.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_sort_by.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.fixed35
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.rs35
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs2
-rw-r--r--src/tools/clippy/tests/ui/unneeded_field_pattern.rs14
-rw-r--r--src/tools/clippy/tests/ui/unneeded_field_pattern.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed9
-rw-r--r--src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs9
-rw-r--r--src/tools/clippy/tests/ui/unneeded_wildcard_pattern.stderr30
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.fixed8
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.rs8
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.stderr34
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns2.fixed7
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns2.rs7
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns2.stderr16
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.rs2
-rw-r--r--src/tools/clippy/tests/ui/unused_async.rs14
-rw-r--r--src/tools/clippy/tests/ui/unused_async.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unwrap.rs1
-rw-r--r--src/tools/clippy/tests/ui/unwrap.stderr6
-rw-r--r--src/tools/clippy/tests/ui/unwrap_expect_used.rs1
-rw-r--r--src/tools/clippy/tests/ui/unwrap_expect_used.stderr12
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or.rs1
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or_else_default.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unwrap_or_else_default.rs2
-rwxr-xr-xsrc/tools/clippy/tests/ui/update-all-references.sh2
-rw-r--r--src/tools/clippy/tests/ui/use_self.fixed2
-rw-r--r--src/tools/clippy/tests/ui/use_self.rs2
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.rs2
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.fixed2
-rw-r--r--src/tools/clippy/tests/ui/useless_attribute.rs2
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed31
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs31
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr62
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion_try.rs1
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion_try.stderr18
-rw-r--r--src/tools/clippy/tests/ui/vec.fixed82
-rw-r--r--src/tools/clippy/tests/ui/vec.rs82
-rw-r--r--src/tools/clippy/tests/ui/vec.stderr56
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.fixed4
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.rs4
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.stderr52
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.fixed2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.rs2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.stderr4
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.rs2
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.stderr32
-rw-r--r--src/tools/clippy/tests/ui/write_with_newline.fixed63
-rw-r--r--src/tools/clippy/tests/ui/write_with_newline.stderr12
-rw-r--r--src/tools/clippy/tests/workspace.rs40
-rw-r--r--src/tools/clippy/tests/workspace_test/Cargo.toml2
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml10
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml9
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs2
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs5
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs13
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs2
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml10
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml9
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs7
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs3
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs3
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs1
-rw-r--r--src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs9
-rw-r--r--src/tools/clippy/util/etc/vscode-tasks.json4
-rw-r--r--src/tools/clippy/util/gh-pages/index.html9
-rw-r--r--src/tools/clippy/util/gh-pages/script.js204
-rw-r--r--src/tools/clippy/util/gh-pages/versions.html9
-rwxr-xr-xsrc/tools/clippy/util/versions.py25
-rw-r--r--src/tools/compiletest/src/common.rs17
-rw-r--r--src/tools/compiletest/src/header.rs48
-rw-r--r--src/tools/compiletest/src/header/needs.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs349
-rw-r--r--src/tools/miri/cargo-miri/src/util.rs4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs29
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs7
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs26
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs8
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs4
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/machine.rs2
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs14
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd.rs1
-rw-r--r--src/tools/miri/tests/compiletest.rs1
-rw-r--r--src/tools/rustfmt/CHANGELOG.md11
-rw-r--r--src/tools/rustfmt/Cargo.lock6
-rw-r--r--src/tools/rustfmt/Cargo.toml2
-rw-r--r--src/tools/rustfmt/Configurations.md77
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.lock4
-rw-r--r--src/tools/rustfmt/rust-toolchain2
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs10
-rw-r--r--src/tools/rustfmt/src/config/mod.rs7
-rw-r--r--src/tools/rustfmt/src/config/options.rs6
-rw-r--r--src/tools/rustfmt/src/expr.rs107
-rw-r--r--src/tools/rustfmt/src/items.rs108
-rw-r--r--src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs40
-rw-r--r--src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs40
-rw-r--r--src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs40
-rw-r--r--src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs10
-rw-r--r--src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs10
-rw-r--r--src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs10
-rw-r--r--src/tools/rustfmt/tests/source/let_else.rs161
-rw-r--r--src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs60
-rw-r--r--src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs62
-rw-r--r--src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs66
-rw-r--r--src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs12
-rw-r--r--src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs10
-rw-r--r--src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs16
-rw-r--r--src/tools/rustfmt/tests/target/let_else.rs253
-rw-r--r--src/tools/tidy/src/deps.rs4
-rw-r--r--tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs (renamed from tests/run-make/coverage/lib/doctest_crate.rs)0
-rw-r--r--tests/run-coverage-rustdoc/doctest.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.doctest.txt)26
-rw-r--r--tests/run-coverage-rustdoc/doctest.rs (renamed from tests/run-make/coverage/doctest.rs)2
-rw-r--r--tests/run-coverage/abort.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.abort.txt)0
-rw-r--r--tests/run-coverage/abort.rs (renamed from tests/run-make/coverage/abort.rs)0
-rw-r--r--tests/run-coverage/assert.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.assert.txt)2
-rw-r--r--tests/run-coverage/assert.rs (renamed from tests/run-make/coverage/assert.rs)2
-rw-r--r--tests/run-coverage/async.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.async.txt)0
-rw-r--r--tests/run-coverage/async.rs (renamed from tests/run-make/coverage/async.rs)0
-rw-r--r--tests/run-coverage/async2.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.async2.txt)0
-rw-r--r--tests/run-coverage/async2.rs (renamed from tests/run-make/coverage/async2.rs)0
-rw-r--r--tests/run-coverage/auxiliary/inline_always_with_dead_code.rs (renamed from tests/run-make/coverage/lib/inline_always_with_dead_code.rs)0
-rw-r--r--tests/run-coverage/auxiliary/unused_mod_helper.rs (renamed from tests/run-make/coverage/lib/unused_mod_helper.rs)0
-rw-r--r--tests/run-coverage/auxiliary/used_crate.rs (renamed from tests/run-make/coverage/lib/used_crate.rs)4
-rw-r--r--tests/run-coverage/auxiliary/used_inline_crate.rs (renamed from tests/run-make/coverage/lib/used_inline_crate.rs)4
-rw-r--r--tests/run-coverage/closure.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.closure.txt)4
-rw-r--r--tests/run-coverage/closure.rs (renamed from tests/run-make/coverage/closure.rs)4
-rw-r--r--tests/run-coverage/closure_macro.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt)0
-rw-r--r--tests/run-coverage/closure_macro.rs (renamed from tests/run-make/coverage/closure_macro.rs)0
-rw-r--r--tests/run-coverage/closure_macro_async.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt)0
-rw-r--r--tests/run-coverage/closure_macro_async.rs (renamed from tests/run-make/coverage/closure_macro_async.rs)0
-rw-r--r--tests/run-coverage/conditions.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.conditions.txt)0
-rw-r--r--tests/run-coverage/conditions.rs (renamed from tests/run-make/coverage/conditions.rs)0
-rw-r--r--tests/run-coverage/continue.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.continue.txt)0
-rw-r--r--tests/run-coverage/continue.rs (renamed from tests/run-make/coverage/continue.rs)0
-rw-r--r--tests/run-coverage/dead_code.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt)0
-rw-r--r--tests/run-coverage/dead_code.rs (renamed from tests/run-make/coverage/dead_code.rs)0
-rw-r--r--tests/run-coverage/drop_trait.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt)2
-rw-r--r--tests/run-coverage/drop_trait.rs (renamed from tests/run-make/coverage/drop_trait.rs)2
-rw-r--r--tests/run-coverage/generator.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.generator.txt)0
-rw-r--r--tests/run-coverage/generator.rs (renamed from tests/run-make/coverage/generator.rs)0
-rw-r--r--tests/run-coverage/generics.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.generics.txt)2
-rw-r--r--tests/run-coverage/generics.rs (renamed from tests/run-make/coverage/generics.rs)2
-rw-r--r--tests/run-coverage/if.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.if.txt)0
-rw-r--r--tests/run-coverage/if.rs (renamed from tests/run-make/coverage/if.rs)0
-rw-r--r--tests/run-coverage/if_else.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.if_else.txt)0
-rw-r--r--tests/run-coverage/if_else.rs (renamed from tests/run-make/coverage/if_else.rs)0
-rw-r--r--tests/run-coverage/inline-dead.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt)0
-rw-r--r--tests/run-coverage/inline-dead.rs (renamed from tests/run-make/coverage/inline-dead.rs)0
-rw-r--r--tests/run-coverage/inline.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.inline.txt)0
-rw-r--r--tests/run-coverage/inline.rs (renamed from tests/run-make/coverage/inline.rs)0
-rw-r--r--tests/run-coverage/inner_items.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt)0
-rw-r--r--tests/run-coverage/inner_items.rs (renamed from tests/run-make/coverage/inner_items.rs)0
-rw-r--r--tests/run-coverage/issue-83601.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt)0
-rw-r--r--tests/run-coverage/issue-83601.rs (renamed from tests/run-make/coverage/issue-83601.rs)0
-rw-r--r--tests/run-coverage/issue-84561.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt)2
-rw-r--r--tests/run-coverage/issue-84561.rs (renamed from tests/run-make/coverage/issue-84561.rs)2
-rw-r--r--tests/run-coverage/issue-85461.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt)26
-rw-r--r--tests/run-coverage/issue-85461.rs (renamed from tests/run-make/coverage/issue-85461.rs)2
-rw-r--r--tests/run-coverage/issue-93054.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt)0
-rw-r--r--tests/run-coverage/issue-93054.rs (renamed from tests/run-make/coverage/issue-93054.rs)0
-rw-r--r--tests/run-coverage/lazy_boolean.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt)0
-rw-r--r--tests/run-coverage/lazy_boolean.rs (renamed from tests/run-make/coverage/lazy_boolean.rs)0
-rw-r--r--tests/run-coverage/loop_break_value.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt)0
-rw-r--r--tests/run-coverage/loop_break_value.rs (renamed from tests/run-make/coverage/loop_break_value.rs)0
-rw-r--r--tests/run-coverage/loops_branches.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt)0
-rw-r--r--tests/run-coverage/loops_branches.rs (renamed from tests/run-make/coverage/loops_branches.rs)0
-rw-r--r--tests/run-coverage/match_or_pattern.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt)0
-rw-r--r--tests/run-coverage/match_or_pattern.rs (renamed from tests/run-make/coverage/match_or_pattern.rs)0
-rw-r--r--tests/run-coverage/nested_loops.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt)0
-rw-r--r--tests/run-coverage/nested_loops.rs (renamed from tests/run-make/coverage/nested_loops.rs)0
-rw-r--r--tests/run-coverage/no_cov_crate.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt)0
-rw-r--r--tests/run-coverage/no_cov_crate.rs (renamed from tests/run-make/coverage/no_cov_crate.rs)0
-rw-r--r--tests/run-coverage/overflow.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.overflow.txt)2
-rw-r--r--tests/run-coverage/overflow.rs (renamed from tests/run-make/coverage/overflow.rs)2
-rw-r--r--tests/run-coverage/panic_unwind.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt)2
-rw-r--r--tests/run-coverage/panic_unwind.rs (renamed from tests/run-make/coverage/panic_unwind.rs)2
-rw-r--r--tests/run-coverage/partial_eq.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt)0
-rw-r--r--tests/run-coverage/partial_eq.rs (renamed from tests/run-make/coverage/partial_eq.rs)0
-rw-r--r--tests/run-coverage/simple_loop.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt)0
-rw-r--r--tests/run-coverage/simple_loop.rs (renamed from tests/run-make/coverage/simple_loop.rs)0
-rw-r--r--tests/run-coverage/simple_match.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt)0
-rw-r--r--tests/run-coverage/simple_match.rs (renamed from tests/run-make/coverage/simple_match.rs)0
-rw-r--r--tests/run-coverage/sort_groups.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt)0
-rw-r--r--tests/run-coverage/sort_groups.rs (renamed from tests/run-make/coverage/sort_groups.rs)0
-rw-r--r--tests/run-coverage/test_harness.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt)0
-rw-r--r--tests/run-coverage/test_harness.rs (renamed from tests/run-make/coverage/test_harness.rs)0
-rw-r--r--tests/run-coverage/tight_inf_loop.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt)0
-rw-r--r--tests/run-coverage/tight_inf_loop.rs (renamed from tests/run-make/coverage/tight_inf_loop.rs)0
-rw-r--r--tests/run-coverage/try_error_result.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt)2
-rw-r--r--tests/run-coverage/try_error_result.rs (renamed from tests/run-make/coverage/try_error_result.rs)2
-rw-r--r--tests/run-coverage/unused.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.unused.txt)0
-rw-r--r--tests/run-coverage/unused.rs (renamed from tests/run-make/coverage/unused.rs)0
-rw-r--r--tests/run-coverage/unused_mod.coverage13
-rw-r--r--tests/run-coverage/unused_mod.rs (renamed from tests/run-make/coverage/unused_mod.rs)2
-rw-r--r--tests/run-coverage/uses_crate.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt)26
-rw-r--r--tests/run-coverage/uses_crate.rs (renamed from tests/run-make/coverage/uses_crate.rs)8
-rw-r--r--tests/run-coverage/uses_inline_crate.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt)29
-rw-r--r--tests/run-coverage/uses_inline_crate.rs (renamed from tests/run-make/coverage/uses_inline_crate.rs)8
-rw-r--r--tests/run-coverage/while.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.while.txt)0
-rw-r--r--tests/run-coverage/while.rs (renamed from tests/run-make/coverage/while.rs)0
-rw-r--r--tests/run-coverage/while_early_ret.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt)2
-rw-r--r--tests/run-coverage/while_early_ret.rs (renamed from tests/run-make/coverage/while_early_ret.rs)2
-rw-r--r--tests/run-coverage/yield.coverage (renamed from tests/run-make/coverage-reports/expected_show_coverage.yield.txt)0
-rw-r--r--tests/run-coverage/yield.rs (renamed from tests/run-make/coverage/yield.rs)0
-rw-r--r--tests/run-make/coverage-llvmir/Makefile2
-rw-r--r--tests/run-make/coverage-reports/Makefile178
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt4
-rwxr-xr-xtests/run-make/coverage-reports/normalize_paths.py12
-rwxr-xr-xtests/run-make/coverage-reports/sort_subviews.py50
-rw-r--r--tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt10
-rw-r--r--tests/run-make/coverage/compiletest-ignore-dir3
-rw-r--r--tests/run-make/coverage/coverage_tools.mk6
-rw-r--r--tests/run-make/optimization-remarks-dir/Makefile12
-rw-r--r--tests/run-make/optimization-remarks-dir/foo.rs6
-rw-r--r--tests/run-make/rust-lld/Makefile8
-rw-r--r--tests/run-make/rust-lld/main.rs4
-rw-r--r--tests/rustdoc-gui/notable-trait.goml30
-rw-r--r--tests/rustdoc-gui/search-filter.goml18
-rw-r--r--tests/rustdoc-gui/search-result-color.goml16
-rw-r--r--tests/rustdoc-gui/search-result-display.goml33
-rw-r--r--tests/rustdoc-gui/search-tab-change-title-fn-sig.goml2
-rw-r--r--tests/rustdoc-js-std/parser-errors.js200
-rw-r--r--tests/rustdoc-js-std/parser-filter.js2
-rw-r--r--tests/rustdoc-js-std/parser-generics.js6
-rw-r--r--tests/rustdoc-js-std/parser-quote.js2
-rw-r--r--tests/rustdoc-js-std/parser-separators.js80
-rw-r--r--tests/rustdoc-js-std/parser-slice-array.js6
-rw-r--r--tests/rustdoc-js-std/parser-weird-queries.js40
-rw-r--r--tests/rustdoc-js-std/vec-new.js29
-rw-r--r--tests/ui/associated-inherent-types/private-in-public.rs5
-rw-r--r--tests/ui/associated-inherent-types/private-in-public.stderr29
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes.rs2
-rw-r--r--tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs64
-rw-r--r--tests/ui/closures/issue-113087.rs11
-rw-r--r--tests/ui/closures/issue-113087.stderr16
-rw-r--r--tests/ui/const-generics/generic_const_exprs/eval-privacy.rs3
-rw-r--r--tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr7
-rw-r--r--tests/ui/error-codes/E0445.rs4
-rw-r--r--tests/ui/error-codes/E0445.stderr35
-rw-r--r--tests/ui/error-codes/E0637.stderr7
-rw-r--r--tests/ui/feature-gates/feature-gate-type_privacy_lints.rs12
-rw-r--r--tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr93
-rw-r--r--tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr7
-rw-r--r--tests/ui/impl-trait/in-trait/foreign.rs4
-rw-r--r--tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr6
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.current.stderr65
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.next.stderr65
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.rs55
-rw-r--r--tests/ui/impl-trait/in-trait/variances-of-gat.rs19
-rw-r--r--tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs27
-rw-r--r--tests/ui/impl-trait/universal_wrong_hrtb.rs2
-rw-r--r--tests/ui/impl-trait/universal_wrong_hrtb.stderr10
-rw-r--r--tests/ui/imports/auxiliary/issue-85992-extern-1.rs6
-rw-r--r--tests/ui/imports/auxiliary/issue-85992-extern-2.rs1
-rw-r--r--tests/ui/imports/issue-56125.stderr15
-rw-r--r--tests/ui/imports/issue-57539.stderr5
-rw-r--r--tests/ui/imports/issue-85992.rs11
-rw-r--r--tests/ui/imports/issue-85992.stderr9
-rw-r--r--tests/ui/issues/issue-18389.rs2
-rw-r--r--tests/ui/issues/issue-18389.stderr15
-rw-r--r--tests/ui/linkage-attr/incompatible-flavor.stderr2
-rw-r--r--tests/ui/linkage-attr/unstable-flavor.bpf.stderr2
-rw-r--r--tests/ui/linkage-attr/unstable-flavor.ptx.stderr2
-rw-r--r--tests/ui/linkage-attr/unstable-flavor.rs8
-rw-r--r--tests/ui/lint/dropping_copy_types.rs19
-rw-r--r--tests/ui/lint/dropping_references.rs19
-rw-r--r--tests/ui/match/issue-113012.rs12
-rw-r--r--tests/ui/privacy/effective_visibilities_full_priv.rs2
-rw-r--r--tests/ui/privacy/effective_visibilities_full_priv.stderr2
-rw-r--r--tests/ui/privacy/private-in-public-non-principal.rs3
-rw-r--r--tests/ui/privacy/private-in-public-non-principal.stderr9
-rw-r--r--tests/ui/privacy/unnameable_types.rs2
-rw-r--r--tests/ui/privacy/where-priv-type.rs8
-rw-r--r--tests/ui/privacy/where-priv-type.stderr56
-rw-r--r--tests/ui/privacy/where-pub-type-impls-priv-trait.rs7
-rw-r--r--tests/ui/privacy/where-pub-type-impls-priv-trait.stderr45
-rw-r--r--tests/ui/proc-macro/derive-helper-shadowing.rs2
-rw-r--r--tests/ui/proc-macro/derive-helper-shadowing.stderr21
-rw-r--r--tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs4
-rw-r--r--tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr35
-rw-r--r--tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr2
-rw-r--r--tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr2
-rw-r--r--tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs4
-rw-r--r--tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr21
-rw-r--r--tests/ui/rust-2018/uniform-paths/ambiguity.rs4
-rw-r--r--tests/ui/rust-2018/uniform-paths/ambiguity.stderr21
-rw-r--r--tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs3
-rw-r--r--tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr24
-rw-r--r--tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs8
-rw-r--r--tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr60
-rw-r--r--tests/ui/rust-2018/uniform-paths/issue-56596.stderr5
-rw-r--r--tests/ui/rust-2018/uniform-paths/macro-rules.rs3
-rw-r--r--tests/ui/rust-2018/uniform-paths/macro-rules.stderr24
-rw-r--r--tests/ui/suggestions/issue-102972.rs16
-rw-r--r--tests/ui/suggestions/issue-102972.stderr33
-rw-r--r--tests/ui/suggestions/suggest-split-at-mut.stderr1
-rw-r--r--tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs2
-rw-r--r--tests/ui/test-attrs/test-panic-abort.rs9
-rw-r--r--tests/ui/test-attrs/test-panic-abort.run.stdout7
-rw-r--r--tests/ui/traits/auxiliary/trivial3.rs1
-rw-r--r--tests/ui/traits/auxiliary/trivial4.rs3
-rw-r--r--tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr17
-rw-r--r--tests/ui/traits/trivial_impl.rs18
-rw-r--r--tests/ui/traits/trivial_impl.stderr14
-rw-r--r--tests/ui/traits/trivial_impl2.rs13
-rw-r--r--tests/ui/traits/trivial_impl2.stderr14
-rw-r--r--tests/ui/traits/trivial_impl3.rs19
-rw-r--r--tests/ui/traits/trivial_impl3.stderr14
-rw-r--r--tests/ui/traits/trivial_impl4.rs21
-rw-r--r--tests/ui/traits/trivial_impl4.stderr14
-rw-r--r--tests/ui/traits/trivial_impl_sized.rs26
-rw-r--r--tests/ui/traits/trivial_impl_sized.stderr25
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed17
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs17
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr (renamed from tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed18
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs18
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr (renamed from tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs18
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed14
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs14
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr (renamed from tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed15
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs15
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr (renamed from tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr)9
-rw-r--r--tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs15
1365 files changed, 28705 insertions, 8979 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8d64b5f076e..ff62e1ded61 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,7 +31,7 @@ defaults:
   run:
     shell: bash
 concurrency:
-  group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}"
+  group: "${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }}"
   cancel-in-progress: true
 jobs:
   pr:
diff --git a/Cargo.lock b/Cargo.lock
index 3aa3e4c4438..5bc2dc5eefa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,12 +4,12 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.19.0"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
 dependencies = [
  "compiler_builtins",
- "gimli 0.27.2",
+ "gimli 0.27.3",
  "rustc-std-workspace-alloc",
  "rustc-std-workspace-core",
 ]
@@ -26,9 +26,9 @@ dependencies = [
 
 [[package]]
 name = "ahash"
-version = "0.7.4"
+version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
 dependencies = [
  "getrandom",
  "once_cell",
@@ -37,9 +37,9 @@ dependencies = [
 
 [[package]]
 name = "ahash"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
+checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -48,9 +48,18 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.18"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
 dependencies = [
  "memchr",
 ]
@@ -67,15 +76,15 @@ dependencies = [
 
 [[package]]
 name = "allocator-api2"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e"
+checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9"
 
 [[package]]
 name = "ammonia"
-version = "3.2.0"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5ed2509ee88cc023cccee37a6fab35826830fe8b748b3869790e7720c2c4a74"
+checksum = "64e6d1c7838db705c9b756557ee27c384ce695a1c51a6fe528784cb1c6840170"
 dependencies = [
  "html5ever",
  "maplit",
@@ -85,6 +94,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
 name = "android_system_properties"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -104,59 +119,59 @@ dependencies = [
 ]
 
 [[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
-[[package]]
 name = "anstream"
-version = "0.2.6"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f"
+checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
 dependencies = [
  "anstyle",
  "anstyle-parse",
+ "anstyle-query",
  "anstyle-wincon",
- "concolor-override",
- "concolor-query",
+ "colorchoice",
  "is-terminal",
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle"
-version = "0.3.5"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2"
+checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.1.1"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116"
+checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "anstyle-wincon"
-version = "0.2.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa"
+checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
 dependencies = [
  "anstyle",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.65"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "ar_archive_writer"
@@ -164,7 +179,7 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "74cfb39880a59e122232cb5fb06b20b4382d58c12fa9747d16f846d38a7b094c"
 dependencies = [
- "object 0.31.1",
+ "object",
 ]
 
 [[package]]
@@ -175,9 +190,9 @@ checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
 
 [[package]]
 name = "arrayvec"
-version = "0.7.0"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
 
 [[package]]
 name = "askama"
@@ -230,16 +245,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "backtrace"
-version = "0.3.67"
+version = "0.3.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
+checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
 dependencies = [
  "addr2line",
  "cc",
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object 0.30.1",
+ "object",
  "rustc-demangle",
 ]
 
@@ -268,19 +283,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
+name = "bitflags"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
+
+[[package]]
 name = "block-buffer"
-version = "0.10.2"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
 dependencies = [
  "generic-array",
 ]
 
 [[package]]
 name = "bstr"
-version = "1.3.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1"
+checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5"
 dependencies = [
  "memchr",
  "once_cell",
@@ -300,7 +321,7 @@ dependencies = [
  "serde_json",
  "sha2",
  "tar",
- "toml 0.5.7",
+ "toml 0.5.11",
  "xz2",
 ]
 
@@ -314,10 +335,10 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "curl",
- "indexmap",
+ "indexmap 1.9.3",
  "serde",
  "serde_json",
- "toml 0.5.7",
+ "toml 0.5.11",
 ]
 
 [[package]]
@@ -328,9 +349,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
 
 [[package]]
 name = "bytecount"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
+checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
 dependencies = [
  "packed_simd_2",
 ]
@@ -343,15 +364,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
 [[package]]
 name = "bytes"
-version = "1.0.1"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
 [[package]]
 name = "camino"
-version = "1.0.9"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412"
+checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
 dependencies = [
  "serde",
 ]
@@ -414,21 +435,21 @@ dependencies = [
 
 [[package]]
 name = "chalk-derive"
-version = "0.87.0"
+version = "0.92.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d552b2fa341f5fc35c6b917b1d289d3c3a34d0b74e579390ea6192d6152a8cdb"
+checksum = "ff5053a8a42dbff5279a82423946fc56dc1253b76cf211b2b3c14b3aad4e1281"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
- "synstructure 0.12.6",
+ "syn 2.0.8",
+ "synstructure 0.13.0",
 ]
 
 [[package]]
 name = "chalk-engine"
-version = "0.87.0"
+version = "0.92.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e54ac43048cb31c470d7b3e3acd409090ef4a5abddfe02455187aebc3d6879f"
+checksum = "b9d0e18f29b8b0f4dcf7d31fe00c884af67719699e381e8dcc9d9624b1621c60"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -439,25 +460,25 @@ dependencies = [
 
 [[package]]
 name = "chalk-ir"
-version = "0.87.0"
+version = "0.92.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43aa55deff4e7fbdb09fa014543372f2c95a06835ac487b9ce57b5099b950838"
+checksum = "8a56de2146a8ed0fcd54f4bd50db852f1de4eac9e1efe568494f106c21b77d2a"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "chalk-derive",
  "lazy_static",
 ]
 
 [[package]]
 name = "chalk-solve"
-version = "0.87.0"
+version = "0.92.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61213deefc36ba265ad01c4d997e18bcddf7922862a4594a47ca4575afb3dab4"
+checksum = "b392e02b4c81ec76d3748da839fc70a5539b83d27c9030668463d34d5110b860"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
  "ena",
- "indexmap",
+ "indexmap 1.9.3",
  "itertools",
  "petgraph",
  "rustc-hash",
@@ -468,12 +489,12 @@ dependencies = [
 
 [[package]]
 name = "chrono"
-version = "0.4.24"
+version = "0.4.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
+checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
 dependencies = [
+ "android-tzdata",
  "iana-time-zone",
- "num-integer",
  "num-traits",
  "serde",
  "winapi",
@@ -481,9 +502,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.2.1"
+version = "4.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3"
+checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -492,13 +513,12 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.2.1"
+version = "4.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
+checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d"
 dependencies = [
  "anstream",
  "anstyle",
- "bitflags",
  "clap_lex",
  "once_cell",
  "strsim",
@@ -507,18 +527,18 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.0.7"
+version = "4.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
+checksum = "7f6b5c519bab3ea61843a7923d074b04245624bb84a64a8c150f5deb014e388b"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.2.0"
+version = "4.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
+checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -528,35 +548,24 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
 
 [[package]]
 name = "clippy"
 version = "0.1.72"
 dependencies = [
- "clap",
  "clippy_lints",
- "clippy_utils",
- "compiletest_rs",
- "derive-new",
  "filetime",
- "futures",
- "if_chain",
  "itertools",
- "parking_lot 0.12.1",
- "quote",
  "regex",
- "rustc-semver",
  "rustc_tools_util",
- "serde",
- "syn 2.0.8",
  "tempfile",
  "termize",
  "tester",
- "tokio",
- "toml 0.7.4",
+ "toml 0.7.5",
+ "ui_test",
  "walkdir",
 ]
 
@@ -564,7 +573,7 @@ dependencies = [
 name = "clippy_dev"
 version = "0.0.1"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 0.7.20",
  "clap",
  "indoc",
  "itertools",
@@ -585,19 +594,38 @@ dependencies = [
  "itertools",
  "pulldown-cmark",
  "quine-mc_cluskey",
- "regex-syntax 0.7.1",
+ "regex",
+ "regex-syntax 0.7.2",
  "rustc-semver",
  "semver",
  "serde",
  "serde_json",
  "tempfile",
- "toml 0.7.4",
+ "toml 0.7.5",
  "unicode-normalization",
  "unicode-script",
  "url",
 ]
 
 [[package]]
+name = "clippy_test_deps"
+version = "0.1.0"
+dependencies = [
+ "clippy_lints",
+ "clippy_utils",
+ "derive-new",
+ "futures",
+ "if_chain",
+ "itertools",
+ "parking_lot 0.12.1",
+ "quote",
+ "regex",
+ "serde",
+ "syn 2.0.8",
+ "tokio",
+]
+
+[[package]]
 name = "clippy_utils"
 version = "0.1.72"
 dependencies = [
@@ -645,6 +673,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
 name = "colored"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -677,7 +711,7 @@ dependencies = [
  "glob",
  "lazycell",
  "libc",
- "miow 0.5.0",
+ "miow",
  "miropt-test-tools",
  "once_cell",
  "regex",
@@ -692,44 +726,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "compiletest_rs"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2731272cf25196735df1b52ab5bcba22cf9f99455626c4c8dc092bd5f7f66d0"
-dependencies = [
- "diff",
- "filetime",
- "getopts",
- "lazy_static",
- "libc",
- "log",
- "miow 0.3.7",
- "regex",
- "rustfix",
- "serde",
- "serde_derive",
- "serde_json",
- "tempfile",
- "tester",
- "winapi",
-]
-
-[[package]]
-name = "concolor-override"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f"
-
-[[package]]
-name = "concolor-query"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
-dependencies = [
- "windows-sys 0.45.0",
-]
-
-[[package]]
 name = "convert_case"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -755,9 +751,9 @@ version = "0.0.0"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.5"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
 dependencies = [
  "libc",
 ]
@@ -783,9 +779,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
 dependencies = [
  "cfg-if",
  "crossbeam-epoch",
@@ -794,22 +790,22 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.14"
+version = "0.9.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
 dependencies = [
  "autocfg",
  "cfg-if",
  "crossbeam-utils",
- "memoffset 0.8.0",
+ "memoffset",
  "scopeguard",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.14"
+version = "0.8.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
 dependencies = [
  "cfg-if",
 ]
@@ -826,9 +822,9 @@ dependencies = [
 
 [[package]]
 name = "ctrlc"
-version = "3.3.1"
+version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7394a21d012ce5c850497fb774b167d81b99f060025fbf06ee92b9848bd97eb2"
+checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
 dependencies = [
  "nix",
  "windows-sys 0.48.0",
@@ -851,9 +847,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.61+curl-8.0.1"
+version = "0.4.63+curl-8.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14d05c10f541ae6f3bc5b3d923c20001f47db7d5f0b2bc6ad16490133842db79"
+checksum = "aeb0fef7046022a1e2ad67a004978f0e3cacb9e3123dc62ce768f92197b771dc"
 dependencies = [
  "cc",
  "libc",
@@ -881,13 +877,13 @@ dependencies = [
 
 [[package]]
 name = "derive-new"
-version = "0.5.8"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
+checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -900,7 +896,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustc_version",
- "syn 1.0.102",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -911,9 +907,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
 
 [[package]]
 name = "digest"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
 dependencies = [
  "block-buffer",
  "crypto-common",
@@ -949,9 +945,9 @@ dependencies = [
 
 [[package]]
 name = "dirs-sys"
-version = "0.3.6"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
 dependencies = [
  "libc",
  "redox_users",
@@ -971,26 +967,26 @@ dependencies = [
 
 [[package]]
 name = "displaydoc"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
+checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
 name = "dissimilar"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
+checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e"
 
 [[package]]
 name = "dlmalloc"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e"
+checksum = "203540e710bfadb90e5e29930baf5d10270cec1f43ab34f46f78b147b2de715a"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -999,15 +995,15 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.6.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "elasticlunr-rs"
-version = "3.0.0"
+version = "3.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6dae5cac90640734ee881bc5f21b6e5123f4e5235e52428db114abffc2391d6"
+checksum = "41e83863a500656dfa214fee6682de9c5b9f03de6860fec531235ed2ae9f6571"
 dependencies = [
  "regex",
  "serde",
@@ -1048,12 +1044,12 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.9.0"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
 dependencies = [
  "atty",
- "humantime 2.0.1",
+ "humantime 2.1.0",
  "log",
  "regex",
  "termcolor",
@@ -1065,7 +1061,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
 dependencies = [
- "humantime 2.0.1",
+ "humantime 2.1.0",
  "is-terminal",
  "log",
  "regex",
@@ -1073,6 +1069,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "equivalent"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
+
+[[package]]
 name = "errno"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1111,9 +1113,9 @@ dependencies = [
 
 [[package]]
 name = "expect-test"
-version = "1.4.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d4661aca38d826eb7c72fe128e4238220616de4c0cc00db7bfc38e2e1364dd3"
+checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3"
 dependencies = [
  "dissimilar",
  "once_cell",
@@ -1137,9 +1139,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
 
 [[package]]
 name = "fastrand"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
 dependencies = [
  "instant",
 ]
@@ -1150,20 +1152,20 @@ version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
 dependencies = [
- "memoffset 0.9.0",
+ "memoffset",
  "rustc_version",
 ]
 
 [[package]]
 name = "filetime"
-version = "0.2.20"
+version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412"
+checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.2.10",
- "windows-sys 0.45.0",
+ "redox_syscall 0.2.16",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1174,9 +1176,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
 
 [[package]]
 name = "flate2"
-version = "1.0.25"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -1224,11 +1226,10 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "form_urlencoded"
-version = "1.0.1"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
 dependencies = [
- "matches",
  "percent-encoding",
 ]
 
@@ -1244,9 +1245,9 @@ dependencies = [
 
 [[package]]
 name = "fs-err"
-version = "2.8.1"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64db3e262960f0662f43a6366788d5f10f7f244b8f7d7d987f560baf5ded5c50"
+checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541"
 
 [[package]]
 name = "futf"
@@ -1365,9 +1366,9 @@ dependencies = [
 
 [[package]]
 name = "generic-array"
-version = "0.14.4"
+version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
  "typenum",
  "version_check",
@@ -1386,9 +1387,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.8"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
 dependencies = [
  "cfg-if",
  "libc",
@@ -1402,15 +1403,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
 dependencies = [
  "fallible-iterator",
- "indexmap",
+ "indexmap 1.9.3",
  "stable_deref_trait",
 ]
 
 [[package]]
 name = "gimli"
-version = "0.27.2"
+version = "0.27.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
+checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -1419,9 +1420,9 @@ dependencies = [
 
 [[package]]
 name = "glob"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 [[package]]
 name = "globset"
@@ -1429,7 +1430,7 @@ version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 0.7.20",
  "bstr",
  "fnv",
  "log",
@@ -1447,9 +1448,9 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
-version = "4.3.3"
+version = "4.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17"
+checksum = "83c3372087601b532857d332f5957cbae686da52bb7810bf038c3e3c3cc2fa0d"
 dependencies = [
  "log",
  "pest",
@@ -1465,16 +1466,16 @@ version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
 dependencies = [
- "ahash 0.7.4",
+ "ahash 0.7.6",
 ]
 
 [[package]]
 name = "hashbrown"
-version = "0.13.1"
+version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
 dependencies = [
- "ahash 0.8.2",
+ "ahash 0.8.3",
 ]
 
 [[package]]
@@ -1491,9 +1492,9 @@ dependencies = [
 
 [[package]]
 name = "heck"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
@@ -1506,9 +1507,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -1517,9 +1518,9 @@ dependencies = [
 
 [[package]]
 name = "hex"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
 [[package]]
 name = "html-checker"
@@ -1540,7 +1541,7 @@ dependencies = [
  "markup5ever",
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1554,15 +1555,15 @@ dependencies = [
 
 [[package]]
 name = "humantime"
-version = "2.0.1"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.56"
+version = "0.1.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
+checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -1643,25 +1644,24 @@ checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "idna"
-version = "0.2.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
+checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
 dependencies = [
- "matches",
  "unicode-bidi",
  "unicode-normalization",
 ]
 
 [[package]]
 name = "if_chain"
-version = "1.0.0"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d"
+checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
 
 [[package]]
 name = "ignore"
@@ -1699,10 +1699,20 @@ dependencies = [
 ]
 
 [[package]]
+name = "indexmap"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.14.0",
+]
+
+[[package]]
 name = "indoc"
-version = "1.0.6"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e"
+checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
 
 [[package]]
 name = "installer"
@@ -1748,23 +1758,23 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.3"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 dependencies = [
+ "hermit-abi 0.3.1",
  "libc",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
 name = "is-terminal"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb"
 dependencies = [
- "hermit-abi 0.3.0",
- "io-lifetimes",
- "rustix",
+ "hermit-abi 0.3.1",
+ "rustix 0.38.1",
  "windows-sys 0.48.0",
 ]
 
@@ -1804,9 +1814,9 @@ dependencies = [
 
 [[package]]
 name = "js-sys"
-version = "0.3.61"
+version = "0.3.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -1864,9 +1874,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.146"
+version = "0.2.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -1892,9 +1902,9 @@ dependencies = [
 
 [[package]]
 name = "libloading"
-version = "0.7.1"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 dependencies = [
  "cfg-if",
  "winapi",
@@ -1908,9 +1918,9 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
 
 [[package]]
 name = "libz-sys"
-version = "1.1.8"
+version = "1.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
+checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db"
 dependencies = [
  "cc",
  "libc",
@@ -1928,9 +1938,9 @@ dependencies = [
 
 [[package]]
 name = "linked-hash-map"
-version = "0.5.4"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "lint-docs"
@@ -1943,9 +1953,15 @@ dependencies = [
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.3.4"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
 
 [[package]]
 name = "litemap"
@@ -1959,9 +1975,9 @@ version = "0.1.0"
 
 [[package]]
 name = "lock_api"
-version = "0.4.7"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -1969,12 +1985,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.14"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if",
-]
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
 
 [[package]]
 name = "lzma-sys"
@@ -2023,25 +2036,19 @@ dependencies = [
 ]
 
 [[package]]
-name = "matches"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-
-[[package]]
 name = "md-5"
-version = "0.10.0"
+version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae"
+checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
 dependencies = [
  "digest",
 ]
 
 [[package]]
 name = "mdbook"
-version = "0.4.28"
+version = "0.4.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "764dcbfc2e5f868bc1b566eb179dff1a06458fd0cff846aae2579392dd3f01a0"
+checksum = "7b67ee4a744f36e6280792016c17e69921b51df357181d1eb17d620fcc3609f3"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -2061,15 +2068,15 @@ dependencies = [
  "serde_json",
  "shlex",
  "tempfile",
- "toml 0.5.7",
+ "toml 0.5.11",
  "topological-sort",
 ]
 
 [[package]]
 name = "measureme"
-version = "10.1.0"
+version = "10.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbdc226fa10994e8f66a4d2f6f000148bc563a1c671b6dcd2135737018033d8a"
+checksum = "1930d162935fecd56fc4e0f6729eb3483bac1264542eb4ea31570b86a434b6bc"
 dependencies = [
  "log",
  "memmap2",
@@ -2091,24 +2098,15 @@ dependencies = [
 
 [[package]]
 name = "memmap2"
-version = "0.2.1"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04e3e85b970d650e2ae6d70592474087051c11c54da7f7b4949725c5735fbcc6"
+checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "memoffset"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "memoffset"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
@@ -2118,9 +2116,9 @@ dependencies = [
 
 [[package]]
 name = "mime"
-version = "0.3.16"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "mime_guess"
@@ -2146,9 +2144,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.6.2"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
 dependencies = [
  "adler",
  "compiler_builtins",
@@ -2158,15 +2156,6 @@ dependencies = [
 
 [[package]]
 name = "miow"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "miow"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123"
@@ -2180,7 +2169,7 @@ version = "0.1.0"
 dependencies = [
  "colored",
  "ctrlc",
- "env_logger 0.9.0",
+ "env_logger 0.9.3",
  "getrandom",
  "lazy_static",
  "libc",
@@ -2214,7 +2203,7 @@ version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "cfg-if",
  "libc",
  "static_assertions",
@@ -2222,67 +2211,57 @@ dependencies = [
 
 [[package]]
 name = "nom"
-version = "7.1.0"
+version = "7.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
 dependencies = [
  "memchr",
  "minimal-lexical",
- "version_check",
 ]
 
 [[package]]
-name = "num-integer"
-version = "0.1.43"
+name = "nu-ansi-term"
+version = "0.46.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
 dependencies = [
- "autocfg",
- "num-traits",
+ "overload",
+ "winapi",
 ]
 
 [[package]]
 name = "num-traits"
-version = "0.2.12"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
 dependencies = [
  "autocfg",
 ]
 
 [[package]]
 name = "num_cpus"
-version = "1.13.1"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
- "hermit-abi 0.1.19",
+ "hermit-abi 0.3.1",
  "libc",
 ]
 
 [[package]]
 name = "object"
-version = "0.30.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a"
-dependencies = [
- "compiler_builtins",
- "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "object"
 version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
 dependencies = [
+ "compiler_builtins",
  "crc32fast",
  "flate2",
- "hashbrown 0.13.1",
- "indexmap",
+ "hashbrown 0.13.2",
+ "indexmap 1.9.3",
  "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
  "ruzstd",
 ]
 
@@ -2297,9 +2276,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.17.1"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
 
 [[package]]
 name = "opener"
@@ -2319,9 +2298,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.87"
+version = "0.9.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
+checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
 dependencies = [
  "cc",
  "libc",
@@ -2330,6 +2309,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
 name = "owo-colors"
 version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2376,7 +2361,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
 dependencies = [
  "instant",
  "lock_api",
- "parking_lot_core 0.8.5",
+ "parking_lot_core 0.8.6",
 ]
 
 [[package]]
@@ -2386,34 +2371,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.4",
+ "parking_lot_core 0.9.8",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.8.5"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
 dependencies = [
  "cfg-if",
  "instant",
  "libc",
- "redox_syscall 0.2.10",
+ "redox_syscall 0.2.16",
  "smallvec",
  "winapi",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.4"
+version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.2.10",
+ "redox_syscall 0.3.5",
  "smallvec",
- "windows-sys 0.42.0",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2424,24 +2409,24 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
 
 [[package]]
 name = "percent-encoding"
-version = "2.1.0"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
 
 [[package]]
 name = "perf-event-open-sys"
-version = "1.0.1"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce9bedf5da2c234fdf2391ede2b90fabf585355f33100689bc364a3ea558561a"
+checksum = "b29be2ba35c12c6939f6bc73187f728bba82c3c062ecdc5fa90ea739282a1f58"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "pest"
-version = "2.5.2"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4"
+checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2449,9 +2434,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.2"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603"
+checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2459,26 +2444,26 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.2"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7"
+checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190"
 dependencies = [
  "pest",
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
 name = "pest_meta"
-version = "2.5.2"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065"
+checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0"
 dependencies = [
  "once_cell",
  "pest",
- "sha1",
+ "sha2",
 ]
 
 [[package]]
@@ -2488,7 +2473,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
 dependencies = [
  "fixedbitset",
- "indexmap",
+ "indexmap 1.9.3",
 ]
 
 [[package]]
@@ -2531,9 +2516,9 @@ dependencies = [
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.8"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
+checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
 
 [[package]]
 name = "pin-utils"
@@ -2543,9 +2528,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "pkg-config"
-version = "0.3.25"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 
 [[package]]
 name = "polonius-engine"
@@ -2560,9 +2545,9 @@ dependencies = [
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.8"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "precomputed-hash"
@@ -2572,15 +2557,15 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "proc-macro-hack"
-version = "0.5.19"
+version = "0.5.20+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.60"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
 dependencies = [
  "unicode-ident",
 ]
@@ -2617,7 +2602,7 @@ version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "memchr",
  "unicase",
 ]
@@ -2642,9 +2627,9 @@ checksum = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"
 dependencies = [
  "proc-macro2",
 ]
@@ -2662,9 +2647,9 @@ dependencies = [
 
 [[package]]
 name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
  "ppv-lite86",
  "rand_core",
@@ -2699,21 +2684,19 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.5.3"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
 dependencies = [
- "autocfg",
- "crossbeam-deque",
  "either",
  "rayon-core",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.9.3"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
 dependencies = [
  "crossbeam-channel",
  "crossbeam-deque",
@@ -2723,11 +2706,11 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.10"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
 ]
 
 [[package]]
@@ -2736,28 +2719,29 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
 ]
 
 [[package]]
 name = "redox_users"
-version = "0.4.0"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
  "getrandom",
- "redox_syscall 0.2.10",
+ "redox_syscall 0.2.16",
+ "thiserror",
 ]
 
 [[package]]
 name = "regex"
-version = "1.5.6"
+version = "1.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
+checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 1.0.2",
  "memchr",
- "regex-syntax 0.6.26",
+ "regex-syntax 0.7.2",
 ]
 
 [[package]]
@@ -2766,7 +2750,7 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 dependencies = [
- "regex-syntax 0.6.26",
+ "regex-syntax 0.6.29",
 ]
 
 [[package]]
@@ -2780,15 +2764,15 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.26"
+version = "0.6.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "regex-syntax"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
 
 [[package]]
 name = "remote-test-client"
@@ -2844,9 +2828,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.21"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -2922,7 +2906,7 @@ dependencies = [
 name = "rustc_abi"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "rand",
  "rand_xoshiro",
  "rustc_data_structures",
@@ -2936,7 +2920,7 @@ dependencies = [
 name = "rustc_apfloat"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "smallvec",
 ]
 
@@ -2951,7 +2935,7 @@ dependencies = [
 name = "rustc_ast"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "memchr",
  "rustc_data_structures",
  "rustc_index",
@@ -3101,10 +3085,10 @@ dependencies = [
 name = "rustc_codegen_llvm"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "libc",
  "measureme",
- "object 0.31.1",
+ "object",
  "rustc-demangle",
  "rustc_ast",
  "rustc_attr",
@@ -3135,12 +3119,12 @@ name = "rustc_codegen_ssa"
 version = "0.0.0"
 dependencies = [
  "ar_archive_writer",
- "bitflags",
+ "bitflags 1.3.2",
  "cc",
  "itertools",
  "jobserver",
  "libc",
- "object 0.31.1",
+ "object",
  "pathdiff",
  "regex",
  "rustc_arena",
@@ -3202,11 +3186,11 @@ name = "rustc_data_structures"
 version = "0.0.0"
 dependencies = [
  "arrayvec",
- "bitflags",
+ "bitflags 1.3.2",
  "cfg-if",
  "elsa",
  "ena",
- "indexmap",
+ "indexmap 1.9.3",
  "itertools",
  "jobserver",
  "libc",
@@ -3234,6 +3218,7 @@ name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
  "rustc_driver_impl",
+ "rustix 0.37.11",
 ]
 
 [[package]]
@@ -3659,7 +3644,7 @@ dependencies = [
 name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "libloading",
  "odht",
  "rustc_ast",
@@ -3689,7 +3674,7 @@ dependencies = [
 name = "rustc_middle"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "chalk-ir",
  "derive_more",
  "either",
@@ -3820,7 +3805,7 @@ dependencies = [
 name = "rustc_parse"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_data_structures",
@@ -3910,7 +3895,7 @@ version = "0.0.0"
 dependencies = [
  "field-offset",
  "measureme",
- "memoffset 0.9.0",
+ "memoffset",
  "rustc-rayon-core",
  "rustc_ast",
  "rustc_data_structures",
@@ -3955,7 +3940,7 @@ dependencies = [
 name = "rustc_resolve"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "pulldown-cmark",
  "rustc_arena",
  "rustc_ast",
@@ -3983,7 +3968,7 @@ dependencies = [
 name = "rustc_serialize"
 version = "0.0.0"
 dependencies = [
- "indexmap",
+ "indexmap 1.9.3",
  "rustc_macros",
  "smallvec",
  "tempfile",
@@ -3995,6 +3980,7 @@ name = "rustc_session"
 version = "0.0.0"
 dependencies = [
  "atty",
+ "bitflags 1.3.2",
  "getopts",
  "libc",
  "rustc_ast",
@@ -4030,7 +4016,7 @@ name = "rustc_span"
 version = "0.0.0"
 dependencies = [
  "cfg-if",
- "indexmap",
+ "indexmap 1.9.3",
  "md-5",
  "rustc_arena",
  "rustc_data_structures",
@@ -4048,7 +4034,7 @@ dependencies = [
 name = "rustc_symbol_mangling"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "punycode",
  "rustc-demangle",
  "rustc_data_structures",
@@ -4068,7 +4054,8 @@ dependencies = [
 name = "rustc_target"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
+ "object",
  "rustc_abi",
  "rustc_data_structures",
  "rustc_feature",
@@ -4169,7 +4156,7 @@ dependencies = [
 name = "rustc_type_ir"
 version = "0.0.0"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "rustc_data_structures",
  "rustc_index",
  "rustc_macros",
@@ -4263,7 +4250,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.5.3"
+version = "1.6.0"
 dependencies = [
  "annotate-snippets",
  "anyhow",
@@ -4284,7 +4271,7 @@ dependencies = [
  "serde_json",
  "term",
  "thiserror",
- "toml 0.7.4",
+ "toml 0.7.5",
  "unicode-segmentation",
  "unicode-width",
  "unicode_categories",
@@ -4292,23 +4279,36 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.37.7"
+version = "0.37.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d"
+checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "errno",
  "io-lifetimes",
  "libc",
- "linux-raw-sys",
- "windows-sys 0.45.0",
+ "linux-raw-sys 0.3.8",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3"
+dependencies = [
+ "bitflags 2.3.3",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.4.3",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
 name = "rustversion"
-version = "1.0.5"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
+checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
 
 [[package]]
 name = "ruzstd"
@@ -4323,9 +4323,9 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.5"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "same-file"
@@ -4338,19 +4338,18 @@ dependencies = [
 
 [[package]]
 name = "schannel"
-version = "0.1.19"
+version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
+checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
 dependencies = [
- "lazy_static",
- "winapi",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
 name = "scoped-tls"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
 
 [[package]]
 name = "scopeguard"
@@ -4366,27 +4365,27 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
 
 [[package]]
 name = "semver"
-version = "1.0.12"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.160"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.160"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4395,11 +4394,11 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.85"
+version = "1.0.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
 dependencies = [
- "indexmap",
+ "indexmap 2.0.0",
  "itoa",
  "ryu",
  "serde",
@@ -4407,9 +4406,9 @@ dependencies = [
 
 [[package]]
 name = "serde_spanned"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
+checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
 dependencies = [
  "serde",
 ]
@@ -4427,9 +4426,9 @@ dependencies = [
 
 [[package]]
 name = "sha2"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -4438,9 +4437,9 @@ dependencies = [
 
 [[package]]
 name = "sharded-slab"
-version = "0.1.1"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3"
+checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
 dependencies = [
  "lazy_static",
 ]
@@ -4453,21 +4452,24 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
 
 [[package]]
 name = "shlex"
-version = "1.0.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
+checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
 
 [[package]]
 name = "siphasher"
-version = "0.3.3"
+version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
 
 [[package]]
 name = "slab"
-version = "0.4.2"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
 
 [[package]]
 name = "smallvec"
@@ -4483,9 +4485,9 @@ checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
 
 [[package]]
 name = "socket2"
-version = "0.4.1"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
 dependencies = [
  "libc",
  "winapi",
@@ -4505,9 +4507,9 @@ dependencies = [
 
 [[package]]
 name = "spdx-rs"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b1ec09829bf2d82c175c121b20de11ffab2def83bd55979002099b1f9956c9b"
+checksum = "74f1f9cfa402cd27dd022fd1943f0f969b10dda75d5e50e3a78ccee9c0188e2a"
 dependencies = [
  "chrono",
  "log",
@@ -4557,10 +4559,10 @@ dependencies = [
  "dlmalloc",
  "fortanix-sgx-abi",
  "hashbrown 0.14.0",
- "hermit-abi 0.3.0",
+ "hermit-abi 0.3.1",
  "libc",
  "miniz_oxide",
- "object 0.30.1",
+ "object",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -4585,13 +4587,13 @@ dependencies = [
 
 [[package]]
 name = "string_cache"
-version = "0.8.3"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26"
+checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
 dependencies = [
- "lazy_static",
  "new_debug_unreachable",
- "parking_lot 0.11.2",
+ "once_cell",
+ "parking_lot 0.12.1",
  "phf_shared",
  "precomputed-hash",
  "serde",
@@ -4631,7 +4633,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 1.0.102",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -4645,9 +4647,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.102"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4673,7 +4675,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
  "unicode-xid",
 ]
 
@@ -4711,15 +4713,16 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.5.0"
+version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
 dependencies = [
+ "autocfg",
  "cfg-if",
  "fastrand",
  "redox_syscall 0.3.5",
- "rustix",
- "windows-sys 0.45.0",
+ "rustix 0.37.11",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -4746,9 +4749,9 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.1.3"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
 dependencies = [
  "winapi-util",
 ]
@@ -4759,7 +4762,7 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
 dependencies = [
- "rustix",
+ "rustix 0.37.11",
  "windows-sys 0.48.0",
 ]
 
@@ -4786,9 +4789,9 @@ dependencies = [
 
 [[package]]
 name = "tester"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb"
+checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f"
 dependencies = [
  "cfg-if",
  "getopts",
@@ -4831,16 +4834,17 @@ checksum = "98c040e1340b889d4180c64e1d787efa9c32cb1617757e101480b61238b0d927"
 dependencies = [
  "gimli 0.26.2",
  "hashbrown 0.12.3",
- "object 0.31.1",
+ "object",
  "tracing",
 ]
 
 [[package]]
 name = "thread_local"
-version = "1.1.4"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
+checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
 dependencies = [
+ "cfg-if",
  "once_cell",
 ]
 
@@ -4893,36 +4897,36 @@ dependencies = [
 
 [[package]]
 name = "tinyvec_macros"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.28.2"
+version = "1.29.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
+checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
 dependencies = [
  "autocfg",
+ "backtrace",
  "bytes",
  "pin-project-lite",
- "windows-sys 0.48.0",
 ]
 
 [[package]]
 name = "toml"
-version = "0.5.7"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "toml"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
+checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -4932,20 +4936,20 @@ dependencies = [
 
 [[package]]
 name = "toml_datetime"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "toml_edit"
-version = "0.19.10"
+version = "0.19.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
+checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7"
 dependencies = [
- "indexmap",
+ "indexmap 2.0.0",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -4960,9 +4964,9 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
 
 [[package]]
 name = "tracing"
-version = "0.1.35"
+version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if",
  "pin-project-lite",
@@ -4972,20 +4976,20 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.22"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
+checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
 name = "tracing-core"
-version = "0.1.28"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
 dependencies = [
  "once_cell",
  "valuable",
@@ -5003,9 +5007,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-log"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
+checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
 dependencies = [
  "lazy_static",
  "log",
@@ -5014,14 +5018,14 @@ dependencies = [
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.3.3"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
 dependencies = [
- "ansi_term",
- "lazy_static",
  "matchers",
- "parking_lot 0.11.2",
+ "nu-ansi-term",
+ "once_cell",
+ "parking_lot 0.12.1",
  "regex",
  "sharded-slab",
  "smallvec",
@@ -5033,12 +5037,12 @@ dependencies = [
 
 [[package]]
 name = "tracing-tree"
-version = "0.2.0"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7"
+checksum = "4f9742d8df709837409dbb22aa25dd7769c260406f20ff48a2320b80a4a6aed0"
 dependencies = [
- "ansi_term",
  "atty",
+ "nu-ansi-term",
  "tracing-core",
  "tracing-log",
  "tracing-subscriber",
@@ -5072,11 +5076,11 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
 
 [[package]]
 name = "ucd-parse"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5269f8d35df6b8b60758343a6d742ecf09e4bca13faee32af5503aebd1e11b7c"
+checksum = "fc2d0556a998f4c55500ce1730901ba32bafbe820068cbdc091421525d61253b"
 dependencies = [
- "lazy_static",
+ "once_cell",
  "regex",
 ]
 
@@ -5179,7 +5183,7 @@ checksum = "1f5cdec05b907f4e2f6843f4354f4ce6a5bebe1a56df320a49134944477ce4d8"
 dependencies = [
  "proc-macro-hack",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
  "unic-langid-impl",
 ]
 
@@ -5210,18 +5214,15 @@ dependencies = [
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.4"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
-dependencies = [
- "matches",
-]
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
 
 [[package]]
 name = "unicode-normalization"
@@ -5250,9 +5251,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.10.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
 
 [[package]]
 name = "unicode-width"
@@ -5307,21 +5308,20 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "2.2.2"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
 dependencies = [
  "form_urlencoded",
  "idna",
- "matches",
  "percent-encoding",
 ]
 
 [[package]]
 name = "utf-8"
-version = "0.7.5"
+version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
 [[package]]
 name = "utf8parse"
@@ -5331,9 +5331,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 [[package]]
 name = "uuid"
-version = "1.3.1"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb"
+checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be"
 dependencies = [
  "getrandom",
 ]
@@ -5346,9 +5346,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 [[package]]
 name = "vcpkg"
-version = "0.2.10"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
 
 [[package]]
 name = "version_check"
@@ -5358,12 +5358,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "walkdir"
-version = "2.3.2"
+version = "2.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
 dependencies = [
  "same-file",
- "winapi",
  "winapi-util",
 ]
 
@@ -5380,9 +5379,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.84"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -5390,24 +5389,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.84"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.84"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -5415,22 +5414,22 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.84"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.84"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
 
 [[package]]
 name = "winapi"
@@ -5469,7 +5468,7 @@ version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
 dependencies = [
- "windows-targets 0.48.0",
+ "windows-targets",
 ]
 
 [[package]]
@@ -5505,42 +5504,18 @@ dependencies = [
 
 [[package]]
 name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets 0.42.2",
-]
-
-[[package]]
-name = "windows-sys"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets",
 ]
 
 [[package]]
 name = "windows-targets"
-version = "0.48.0"
+version = "0.48.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
 dependencies = [
  "windows_aarch64_gnullvm 0.48.0",
  "windows_aarch64_msvc 0.48.0",
@@ -5643,24 +5618,24 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
 
 [[package]]
 name = "winnow"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
+checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "writeable"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92d74a687e3b9a7a129db0a8c82b4d464eb9c36f5a66ca68572a7e5f1cfdb5bc"
+checksum = "60e49e42bdb1d5dc76f4cd78102f8f0714d32edfa3efb82286eb0f0b1fc0da0f"
 
 [[package]]
 name = "xattr"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
+checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
 dependencies = [
  "libc",
 ]
@@ -5687,9 +5662,9 @@ dependencies = [
 
 [[package]]
 name = "yaml-rust"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
 dependencies = [
  "linked-hash-map",
 ]
@@ -5717,34 +5692,34 @@ dependencies = [
 
 [[package]]
 name = "yoke-derive"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca800d73d6b7a7ee54f2608205c98b549fca71c9500c1abcb3abdc7708b4a8cb"
+checksum = "af46c169923ed7516eef0aa32b56d2651b229f57458ebe46b49ddd6efef5b7a2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
  "synstructure 0.12.6",
 ]
 
 [[package]]
 name = "zerofrom"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
+checksum = "df54d76c3251de27615dfcce21e636c172dafb2549cd7fd93e21c66f6ca6bea2"
 dependencies = [
  "zerofrom-derive",
 ]
 
 [[package]]
 name = "zerofrom-derive"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e8aa86add9ddbd2409c1ed01e033cd457d79b1b1229b64922c25095c595e829"
+checksum = "b4eae7c1f7d4b8eafce526bc0771449ddc2f250881ae31c50d22c032b5a1c499"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
  "synstructure 0.12.6",
 ]
 
@@ -5761,12 +5736,12 @@ dependencies = [
 
 [[package]]
 name = "zerovec-derive"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2154cb6e2a748163354165e22c6a555effb09ca2d16334767bf66bb404f2206e"
+checksum = "486558732d5dde10d0f8cb2936507c1bb21bc539d924c949baf5f36a58e51bac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 1.0.109",
  "synstructure 0.12.6",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 6e84df5c693..20b1c656d35 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ members = [
   "src/tools/cargotest",
   "src/tools/clippy",
   "src/tools/clippy/clippy_dev",
+  "src/tools/clippy/clippy_test_deps",
   "src/tools/compiletest",
   "src/tools/error_index_generator",
   "src/tools/linkchecker",
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 8d4f96639ef..429e62c4a1c 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1539,9 +1539,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         );
         debug!(?opaque_ty_def_id);
 
-        // Contains the new lifetime definitions created for the TAIT (if any).
-        let mut collected_lifetimes = Vec::new();
-
         // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
         // to capture the lifetimes that appear in the bounds. So visit the bounds to find out
         // exactly which ones those are.
@@ -1558,20 +1555,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         debug!(?lifetimes_to_remap);
 
-        self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
-            let mut new_remapping = FxHashMap::default();
+        let mut new_remapping = FxHashMap::default();
 
-            // If this opaque type is only capturing a subset of the lifetimes (those that appear
-            // in bounds), then create the new lifetime parameters required and create a mapping
-            // from the old `'a` (on the function) to the new `'a` (on the opaque type).
-            collected_lifetimes = lctx.create_lifetime_defs(
-                opaque_ty_def_id,
-                &lifetimes_to_remap,
-                &mut new_remapping,
-            );
-            debug!(?collected_lifetimes);
-            debug!(?new_remapping);
+        // Contains the new lifetime definitions created for the TAIT (if any).
+        // If this opaque type is only capturing a subset of the lifetimes (those that appear in
+        // bounds), then create the new lifetime parameters required and create a mapping from the
+        // old `'a` (on the function) to the new `'a` (on the opaque type).
+        let collected_lifetimes =
+            self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping);
+        debug!(?collected_lifetimes);
+        debug!(?new_remapping);
+
+        // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
+        // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
+        let collected_lifetime_mapping: Vec<_> = collected_lifetimes
+            .iter()
+            .map(|(node_id, lifetime)| {
+                let id = self.next_node_id();
+                let lifetime = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
+                let def_id = self.local_def_id(*node_id);
+                (lifetime, def_id)
+            })
+            .collect();
+        debug!(?collected_lifetime_mapping);
 
+        self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
             // Install the remapping from old to new (if any):
             lctx.with_remapping(new_remapping, |lctx| {
                 // This creates HIR lifetime definitions as `hir::GenericParam`, in the given
@@ -1610,6 +1618,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let hir_bounds = lctx.lower_param_bounds(bounds, itctx);
                 debug!(?hir_bounds);
 
+                let lifetime_mapping = if in_trait {
+                    self.arena.alloc_from_iter(
+                        collected_lifetime_mapping
+                            .iter()
+                            .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                    )
+                } else {
+                    &mut []
+                };
+
                 let opaque_ty_item = hir::OpaqueTy {
                     generics: self.arena.alloc(hir::Generics {
                         params: lifetime_defs,
@@ -1620,6 +1638,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }),
                     bounds: hir_bounds,
                     origin,
+                    lifetime_mapping,
                     in_trait,
                 };
                 debug!(?opaque_ty_item);
@@ -1628,20 +1647,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             })
         });
 
-        // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
-        // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
-        let lifetimes =
-            self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
-                let id = self.next_node_id();
-                let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
-                hir::GenericArg::Lifetime(l)
-            }));
-        debug!(?lifetimes);
-
         // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
         hir::TyKind::OpaqueDef(
             hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
-            lifetimes,
+            self.arena.alloc_from_iter(
+                collected_lifetime_mapping
+                    .iter()
+                    .map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
+            ),
             in_trait,
         )
     }
@@ -1655,7 +1668,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         opaque_ty_span: Span,
     ) -> hir::OwnerNode<'hir> {
-        let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
+        let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(self.arena.alloc(opaque_ty_item));
         // Generate an `type Foo = impl Trait;` declaration.
         trace!("registering opaque type with id {:#?}", opaque_ty_id);
         let opaque_ty_item = hir::Item {
@@ -1983,7 +1996,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             let lifetime = Lifetime { id: outer_node_id, ident };
             collected_lifetimes.push((inner_node_id, lifetime, Some(inner_res)));
         }
-
         debug!(?collected_lifetimes);
 
         // We only want to capture the lifetimes that appear in the bounds. So visit the bounds to
@@ -1993,22 +2005,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let lifetimes_to_remap = lifetime_collector::lifetimes_in_ret_ty(&self.resolver, output);
         debug!(?lifetimes_to_remap);
 
-        self.with_hir_id_owner(opaque_ty_node_id, |this| {
-            // If this opaque type is only capturing a subset of the lifetimes (those that appear
-            // in bounds), then create the new lifetime parameters required and create a mapping
-            // from the old `'a` (on the function) to the new `'a` (on the opaque type).
-            collected_lifetimes.extend(
-                this.create_lifetime_defs(
-                    opaque_ty_def_id,
-                    &lifetimes_to_remap,
-                    &mut new_remapping,
-                )
+        // If this opaque type is only capturing a subset of the lifetimes (those that appear in
+        // bounds), then create the new lifetime parameters required and create a mapping from the
+        // old `'a` (on the function) to the new `'a` (on the opaque type).
+        collected_lifetimes.extend(
+            self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping)
                 .into_iter()
                 .map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)),
-            );
-            debug!(?collected_lifetimes);
-            debug!(?new_remapping);
+        );
+        debug!(?collected_lifetimes);
+        debug!(?new_remapping);
+
+        // This creates pairs of HIR lifetimes and def_ids. In the given example `type
+        // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing the
+        // new lifetime of the RPIT 'x and the def_id of the lifetime 'x corresponding to
+        // `TestReturn`.
+        let collected_lifetime_mapping: Vec<_> = collected_lifetimes
+            .iter()
+            .map(|(node_id, lifetime, res)| {
+                let id = self.next_node_id();
+                let res = res.unwrap_or(
+                    self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
+                );
+                let lifetime = self.new_named_lifetime_with_res(id, lifetime.ident, res);
+                let def_id = self.local_def_id(*node_id);
+                (lifetime, def_id)
+            })
+            .collect();
+        debug!(?collected_lifetime_mapping);
 
+        self.with_hir_id_owner(opaque_ty_node_id, |this| {
             // Install the remapping from old to new (if any):
             this.with_remapping(new_remapping, |this| {
                 // We have to be careful to get elision right here. The
@@ -2063,6 +2089,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 ));
                 debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
 
+                let lifetime_mapping = if in_trait {
+                    self.arena.alloc_from_iter(
+                        collected_lifetime_mapping
+                            .iter()
+                            .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                    )
+                } else {
+                    &mut []
+                };
+
                 let opaque_ty_item = hir::OpaqueTy {
                     generics: this.arena.alloc(hir::Generics {
                         params: generic_params,
@@ -2073,6 +2109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }),
                     bounds: arena_vec![this; future_bound],
                     origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+                    lifetime_mapping,
                     in_trait,
                 };
 
@@ -2096,15 +2133,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         //
         // For the "output" lifetime parameters, we just want to
         // generate `'_`.
-        let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
-            |(_, lifetime, res)| {
-                let id = self.next_node_id();
-                let res = res.unwrap_or(
-                    self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
-                );
-                hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
-            },
-        ));
+        let generic_args = self.arena.alloc_from_iter(
+            collected_lifetime_mapping
+                .iter()
+                .map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
+        );
 
         // Create the `Foo<...>` reference itself. Note that the `type
         // Foo = impl Trait` is, internally, created as a child of the
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 39b05829888..c8c8b72b389 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1,6 +1,5 @@
-use std::iter;
-
 use either::Either;
+use hir::PatField;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{
@@ -28,6 +27,7 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::ObligationCtxt;
+use std::iter;
 
 use crate::borrow_set::TwoPhaseActivation;
 use crate::borrowck_errors;
@@ -982,7 +982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     &msg_borrow,
                     None,
                 );
-                self.suggest_split_at_mut_if_applicable(
+                self.suggest_slice_method_if_applicable(
                     &mut err,
                     place,
                     issued_borrow.borrowed_place,
@@ -992,6 +992,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     issued_borrow.borrowed_place,
                     &issued_spans,
                 );
+                self.explain_iterator_advancement_in_for_loop_if_applicable(
+                    &mut err,
+                    span,
+                    &issued_spans,
+                );
                 err
             }
 
@@ -1262,7 +1267,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         );
     }
 
-    fn suggest_split_at_mut_if_applicable(
+    fn suggest_slice_method_if_applicable(
         &self,
         err: &mut Diagnostic,
         place: Place<'tcx>,
@@ -1274,7 +1279,75 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.help(
                 "consider using `.split_at_mut(position)` or similar method to obtain \
                      two mutable non-overlapping sub-slices",
-            );
+            )
+            .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
+        }
+    }
+
+    /// Suggest using `while let` for call `next` on an iterator in a for loop.
+    ///
+    /// For example:
+    /// ```ignore (illustrative)
+    ///
+    /// for x in iter {
+    ///     ...
+    ///     iter.next()
+    /// }
+    /// ```
+    pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable(
+        &self,
+        err: &mut Diagnostic,
+        span: Span,
+        issued_spans: &UseSpans<'tcx>,
+    ) {
+        let issue_span = issued_spans.args_or_use();
+        let tcx = self.infcx.tcx;
+        let hir = tcx.hir();
+
+        let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
+        let typeck_results = tcx.typeck(self.mir_def_id());
+
+        struct ExprFinder<'hir> {
+            issue_span: Span,
+            expr_span: Span,
+            body_expr: Option<&'hir hir::Expr<'hir>>,
+            loop_bind: Option<Symbol>,
+        }
+        impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
+            fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
+                if let hir::ExprKind::Loop(hir::Block{ stmts: [stmt, ..], ..}, _, hir::LoopSource::ForLoop, _) = ex.kind &&
+                    let hir::StmtKind::Expr(hir::Expr{ kind: hir::ExprKind::Match(call, [_, bind, ..], _), ..}) = stmt.kind &&
+                    let hir::ExprKind::Call(path, _args) = call.kind &&
+                    let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _, )) = path.kind &&
+                    let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind &&
+                    let hir::QPath::LangItem(LangItem::OptionSome, _, _) = path &&
+                    let PatField { pat: hir::Pat{ kind: hir::PatKind::Binding(_, _, ident, ..), .. }, ..} = field &&
+                    self.issue_span.source_equal(call.span) {
+                        self.loop_bind = Some(ident.name);
+                    }
+
+                if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
+                    body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
+                        self.body_expr = Some(ex);
+                }
+
+                hir::intravisit::walk_expr(self, ex);
+            }
+        }
+        let mut finder =
+            ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
+        finder.visit_expr(hir.body(body_id).value);
+
+        if let Some(loop_bind) = finder.loop_bind &&
+            let Some(body_expr) = finder.body_expr &&
+                let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) &&
+                let Some(trait_did) = tcx.trait_of_item(def_id) &&
+                tcx.is_diagnostic_item(sym::Iterator, trait_did) {
+                    err.note(format!(
+                        "a for loop advances the iterator for you, the result is stored in `{}`.",
+                        loop_bind
+                    ));
+                    err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
         }
     }
 
@@ -1730,18 +1803,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             (
                 Some(name),
                 BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
-            ) => self.report_escaping_closure_capture(
-                borrow_spans,
-                borrow_span,
-                &RegionName {
-                    name: self.synthesize_region_name(),
-                    source: RegionNameSource::Static,
-                },
-                ConstraintCategory::CallArgument(None),
-                var_or_use_span,
-                &format!("`{}`", name),
-                "block",
-            ),
+            ) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
+                .report_escaping_closure_capture(
+                    borrow_spans,
+                    borrow_span,
+                    &RegionName {
+                        name: self.synthesize_region_name(),
+                        source: RegionNameSource::Static,
+                    },
+                    ConstraintCategory::CallArgument(None),
+                    var_or_use_span,
+                    &format!("`{}`", name),
+                    "block",
+                ),
             (
                 Some(name),
                 BorrowExplanation::MustBeValidFor {
@@ -1754,7 +1828,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     span,
                     ..
                 },
-            ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
+            ) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
                 .report_escaping_closure_capture(
                     borrow_spans,
                     borrow_span,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 2f8c970f806..42e50fd0fad 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1146,6 +1146,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
+                        self.explain_iterator_advancement_in_for_loop_if_applicable(
+                            err,
+                            span,
+                            &move_spans,
+                        );
+
                         let func = tcx.def_path_str(method_did);
                         err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
                             func,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index be3a3b77797..97d15cb53db 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -222,7 +222,7 @@ fn do_mir_borrowck<'tcx>(
 
     let (move_data, move_errors): (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>) =
         match MoveData::gather_moves(&body, tcx, param_env) {
-            Ok((_, move_data)) => (move_data, Vec::new()),
+            Ok(move_data) => (move_data, Vec::new()),
             Err((move_data, move_errors)) => (move_data, move_errors),
         };
     let promoted_errors = promoted
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index f00cd39cbc8..322222ae330 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -1,4 +1,5 @@
 builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
+builtin_macros_alloc_must_statics = allocators must be statics
 
 builtin_macros_asm_clobber_abi = clobber_abi
 builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
@@ -56,6 +57,9 @@ builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `e
     .label = not applicable here
     .label2 = not a `struct`, `enum` or `union`
 
+builtin_macros_bench_sig = functions used as benches must have signature `fn(&mut Bencher) -> impl Termination`
+
+
 builtin_macros_cannot_derive_union = this trait cannot be derived for unions
 
 builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
@@ -84,6 +88,7 @@ builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
 builtin_macros_concat_bytes_oob = numeric literal is out of bounds
 
 builtin_macros_concat_bytestr = cannot concatenate a byte string literal
+builtin_macros_concat_c_str_lit = cannot concatenate a C string literal
 
 builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
 
@@ -111,6 +116,10 @@ builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
 
 builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
 
+builtin_macros_expected_register_class_or_explicit_register = expected register class or explicit register
+
+builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently
+
 builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
     .label1 = previously here
     .label2 = duplicate argument
@@ -158,6 +167,8 @@ builtin_macros_format_unused_args = multiple unused formatting arguments
 
 builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
 
+builtin_macros_invalid_crate_attribute = invalid crate attribute
+
 builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
     .note = only one `#[default]` attribute is needed
     .label = `#[default]` used here
@@ -177,6 +188,8 @@ builtin_macros_no_default_variant = no default declared
     .help = make a unit variant default by placing `#[default]` above it
     .suggestion = make `{$ident}` default
 
+builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
+
 builtin_macros_non_exhaustive_default = default variant must be exhaustive
     .label = declared `#[non_exhaustive]` here
     .help = consider a manual implementation of `Default`
@@ -184,12 +197,20 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive
 builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
     .help = consider a manual implementation of `Default`
 
+builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
+
 builtin_macros_requires_cfg_pattern =
     macro requires a cfg-pattern as an argument
     .label = cfg-pattern required
 
+builtin_macros_should_panic = functions using `#[should_panic]` must return `()`
+
 builtin_macros_sugg = consider using a positional formatting argument instead
 
+builtin_macros_test_arg_non_lifetime = functions used as tests can not have any non-lifetime generic parameters
+
+builtin_macros_test_args = functions used as tests can not have any arguments
+
 builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
     .label = `{$kind}` because of this
 
@@ -198,6 +219,10 @@ builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on
 builtin_macros_test_runner_invalid = `test_runner` argument must be a path
 builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument
 
+builtin_macros_tests_not_support = building tests with panic=abort is not supported without `-Zpanic_abort_tests`
+
+builtin_macros_trace_macros = trace_macros! accepts only `true` or `false`
+
 builtin_macros_unexpected_lit = expected path to a trait, found literal
     .label = not a trait
     .str_lit = try using `#[derive({$sym})]`
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 9734fc2b36d..6187e4f513b 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -371,11 +371,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
     p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
 
     if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
-        let err = p.sess.span_diagnostic.struct_span_err(
-            p.token.span,
-            "at least one abi must be provided as an argument to `clobber_abi`",
-        );
-        return Err(err);
+        return Err(p.sess.span_diagnostic.create_err(errors::NonABI { span: p.token.span }));
     }
 
     let mut new_abis = Vec::new();
@@ -428,9 +424,9 @@ fn parse_reg<'a>(
             ast::InlineAsmRegOrRegClass::Reg(symbol)
         }
         _ => {
-            return Err(
-                p.struct_span_err(p.token.span, "expected register class or explicit register")
-            );
+            return Err(p.sess.create_err(errors::ExpectedRegisterClassOrExplicitRegister {
+                span: p.token.span,
+            }));
         }
     };
     p.bump();
diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
index 2b6fcc169be..7b75d7d84e4 100644
--- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
+++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
@@ -1,5 +1,6 @@
 //! Attributes injected into the crate root from command line using `-Z crate-attr`.
 
+use crate::errors;
 use rustc_ast::attr::mk_attr;
 use rustc_ast::token;
 use rustc_ast::{self as ast, AttrItem, AttrStyle};
@@ -24,7 +25,9 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
         };
         let end_span = parser.token.span;
         if parser.token != token::Eof {
-            parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute");
+            parse_sess
+                .span_diagnostic
+                .emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
             continue;
         }
 
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index 50e88ae2eee..9695fb4fee1 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -33,7 +33,7 @@ pub fn expand_concat(
                     accumulator.push_str(&b.to_string());
                 }
                 Ok(ast::LitKind::CStr(..)) => {
-                    cx.span_err(e.span, "cannot concatenate a C string literal");
+                    cx.emit_err(errors::ConcatCStrLit{ span: e.span});
                     has_errors = true;
                 }
                 Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 5ef35af0a05..6a1586f071c 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -21,7 +21,7 @@ fn invalid_type_err(
         Ok(ast::LitKind::CStr(_, _)) => {
             // FIXME(c_str_literals): should concatenation of C string literals
             // include the null bytes in the end?
-            cx.span_err(span, "cannot concatenate C string literals");
+            cx.emit_err(errors::ConcatCStrLit { span: span });
         }
         Ok(ast::LitKind::Char(_)) => {
             let sugg =
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index f1ab279daba..7b2a375a822 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -88,6 +88,83 @@ pub(crate) struct ConcatBytestr {
 }
 
 #[derive(Diagnostic)]
+#[diag(builtin_macros_concat_c_str_lit)]
+pub(crate) struct ConcatCStrLit {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_export_macro_rules)]
+pub(crate) struct ExportMacroRules {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_proc_macro)]
+pub(crate) struct ProcMacro {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_invalid_crate_attribute)]
+pub(crate) struct InvalidCrateAttr {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_non_abi)]
+pub(crate) struct NonABI {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_trace_macros)]
+pub(crate) struct TraceMacros {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_bench_sig)]
+pub(crate) struct BenchSig {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_test_arg_non_lifetime)]
+pub(crate) struct TestArgNonLifetime {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_should_panic)]
+pub(crate) struct ShouldPanic {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_test_args)]
+pub(crate) struct TestArgs {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_alloc_must_statics)]
+pub(crate) struct AllocMustStatics {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(builtin_macros_concat_bytes_invalid)]
 pub(crate) struct ConcatBytesInvalid {
     #[primary_span]
@@ -202,6 +279,10 @@ pub(crate) struct BadDeriveTarget {
 }
 
 #[derive(Diagnostic)]
+#[diag(builtin_macros_tests_not_support)]
+pub(crate) struct TestsNotSupport {}
+
+#[derive(Diagnostic)]
 #[diag(builtin_macros_unexpected_lit, code = "E0777")]
 pub(crate) struct BadDeriveLit {
     #[primary_span]
@@ -732,3 +813,10 @@ pub(crate) struct TestRunnerNargs {
     #[primary_span]
     pub(crate) span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_expected_register_class_or_explicit_register)]
+pub(crate) struct ExpectedRegisterClassOrExplicitRegister {
+    #[primary_span]
+    pub(crate) span: Span,
+}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index f0d378d12f7..5772471931f 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -1,5 +1,6 @@
 use crate::util::check_builtin_macro_attribute;
 
+use crate::errors;
 use rustc_ast::expand::allocator::{
     global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
 };
@@ -34,7 +35,7 @@ pub fn expand(
         {
             (item, true, ecx.with_def_site_ctxt(ty.span))
         } else {
-            ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
+            ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocMustStatics{span: item.span()});
             return vec![orig_item];
         };
 
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 52b5601bb11..b35a2e2a292 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -1,3 +1,4 @@
+use crate::errors;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{self as ast, attr, NodeId};
@@ -83,12 +84,7 @@ pub fn inject(
 impl<'a> CollectProcMacros<'a> {
     fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
         if self.is_proc_macro_crate && self.in_root && vis.kind.is_pub() {
-            self.handler.span_err(
-                sp,
-                "`proc-macro` crate types currently cannot export any items other \
-                    than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, \
-                    or `#[proc_macro_attribute]`",
-            );
+            self.handler.emit_err(errors::ProcMacro { span: sp });
         }
     }
 
@@ -157,9 +153,9 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
     fn visit_item(&mut self, item: &'a ast::Item) {
         if let ast::ItemKind::MacroDef(..) = item.kind {
             if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) {
-                let msg =
-                    "cannot export macro_rules! macros from a `proc-macro` crate type currently";
-                self.handler.span_err(self.source_map.guess_head_span(item.span), msg);
+                self.handler.emit_err(errors::ExportMacroRules {
+                    span: self.source_map.guess_head_span(item.span),
+                });
             }
         }
 
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index d7a92dac50f..6bc4f6fc1fc 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -576,12 +576,7 @@ fn check_bench_signature(
     // N.B., inadequate check, but we're running
     // well before resolve, can't get too deep.
     if f.sig.decl.inputs.len() != 1 {
-        return Err(cx.sess.parse_sess.span_diagnostic.span_err(
-            i.span,
-            "functions used as benches must have \
-            signature `fn(&mut Bencher) -> impl Termination`",
-        ));
+        return Err(cx.sess.parse_sess.span_diagnostic.emit_err(errors::BenchSig { span: i.span }));
     }
-
     Ok(())
 }
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 9bc1e27b4ec..81b618548da 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -63,10 +63,7 @@ pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn Resolve
                     // Silently allow compiling with panic=abort on these platforms,
                     // but with old behavior (abort if a test fails).
                 } else {
-                    span_diagnostic.err(
-                        "building tests with panic=abort is not supported \
-                                         without `-Zpanic_abort_tests`",
-                    );
+                    span_diagnostic.emit_err(errors::TestsNotSupport {});
                 }
                 PanicStrategy::Unwind
             }
diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs
index 9c98723e1f4..af1a392acc5 100644
--- a/compiler/rustc_builtin_macros/src/trace_macros.rs
+++ b/compiler/rustc_builtin_macros/src/trace_macros.rs
@@ -1,3 +1,4 @@
+use crate::errors;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_expand::base::{self, ExtCtxt};
 use rustc_span::symbol::kw;
@@ -20,7 +21,7 @@ pub fn expand_trace_macros(
     };
     err |= cursor.next().is_some();
     if err {
-        cx.span_err(sp, "trace_macros! accepts only `true` or `false`")
+        cx.emit_err(errors::TraceMacros { span: sp });
     } else {
         cx.set_trace_macros(value);
     }
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
index 463de6a91c7..1b454b6667c 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
@@ -81,7 +81,7 @@ impl DebugContext {
 
         match tcx.sess.source_map().lookup_line(span.lo()) {
             Ok(SourceFileAndLine { sf: file, line }) => {
-                let line_pos = file.line_begin_pos(span.lo());
+                let line_pos = file.lines(|lines| lines[line]);
 
                 (
                     file,
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 6d00464e0a0..39275272e42 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -1,7 +1,6 @@
 //! Set and unset common attributes on LLVM values.
 
 use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::small_str::SmallStr;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::{self, TyCtxt};
@@ -481,8 +480,8 @@ pub fn from_fn_attrs<'ll, 'tcx>(
 
     let global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
     let function_features = function_features.iter().map(|s| s.as_str());
-    let target_features =
-        global_features.chain(function_features).intersperse(",").collect::<SmallStr<1024>>();
+    let target_features: String =
+        global_features.chain(function_features).intersperse(",").collect();
     if !target_features.is_empty() {
         to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &target_features));
     }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 8b05af7bed9..94885b40cc1 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -1,4 +1,4 @@
-use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
+use crate::back::write::{self, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers};
 use crate::errors::{
     DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
 };
@@ -302,7 +302,13 @@ fn fat_lto(
         // The linking steps below may produce errors and diagnostics within LLVM
         // which we'd like to handle and print, so set up our diagnostic handlers
         // (which get unregistered when they go out of scope below).
-        let _handler = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
+        let _handler = DiagnosticHandlers::new(
+            cgcx,
+            diag_handler,
+            llcx,
+            &module,
+            CodegenDiagnosticsStage::LTO,
+        );
 
         // For all other modules we codegened we'll need to link them into our own
         // bitcode. All modules were codegened in their own LLVM context, however,
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 53b4296802e..998e3b300da 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -268,6 +268,16 @@ pub(crate) fn save_temp_bitcode(
     }
 }
 
+/// In what context is a dignostic handler being attached to a codegen unit?
+pub enum CodegenDiagnosticsStage {
+    /// Prelink optimization stage.
+    Opt,
+    /// LTO/ThinLTO postlink optimization stage.
+    LTO,
+    /// Code generation.
+    Codegen,
+}
+
 pub struct DiagnosticHandlers<'a> {
     data: *mut (&'a CodegenContext<LlvmCodegenBackend>, &'a Handler),
     llcx: &'a llvm::Context,
@@ -279,6 +289,8 @@ impl<'a> DiagnosticHandlers<'a> {
         cgcx: &'a CodegenContext<LlvmCodegenBackend>,
         handler: &'a Handler,
         llcx: &'a llvm::Context,
+        module: &ModuleCodegen<ModuleLlvm>,
+        stage: CodegenDiagnosticsStage,
     ) -> Self {
         let remark_passes_all: bool;
         let remark_passes: Vec<CString>;
@@ -295,6 +307,20 @@ impl<'a> DiagnosticHandlers<'a> {
         };
         let remark_passes: Vec<*const c_char> =
             remark_passes.iter().map(|name: &CString| name.as_ptr()).collect();
+        let remark_file = cgcx
+            .remark_dir
+            .as_ref()
+            // Use the .opt.yaml file suffix, which is supported by LLVM's opt-viewer.
+            .map(|dir| {
+                let stage_suffix = match stage {
+                    CodegenDiagnosticsStage::Codegen => "codegen",
+                    CodegenDiagnosticsStage::Opt => "opt",
+                    CodegenDiagnosticsStage::LTO => "lto",
+                };
+                dir.join(format!("{}.{stage_suffix}.opt.yaml", module.name))
+            })
+            .and_then(|dir| dir.to_str().and_then(|p| CString::new(p).ok()));
+
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
             let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx);
@@ -305,6 +331,9 @@ impl<'a> DiagnosticHandlers<'a> {
                 remark_passes_all,
                 remark_passes.as_ptr(),
                 remark_passes.len(),
+                // The `as_ref()` is important here, otherwise the `CString` will be dropped
+                // too soon!
+                remark_file.as_ref().map(|dir| dir.as_ptr()).unwrap_or(std::ptr::null()),
             );
             DiagnosticHandlers { data, llcx, old_handler }
         }
@@ -523,7 +552,8 @@ pub(crate) unsafe fn optimize(
 
     let llmod = module.module_llvm.llmod();
     let llcx = &*module.module_llvm.llcx;
-    let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
+    let _handlers =
+        DiagnosticHandlers::new(cgcx, diag_handler, llcx, module, CodegenDiagnosticsStage::Opt);
 
     let module_name = module.name.clone();
     let module_name = Some(&module_name[..]);
@@ -582,7 +612,13 @@ pub(crate) unsafe fn codegen(
         let tm = &*module.module_llvm.tm;
         let module_name = module.name.clone();
         let module_name = Some(&module_name[..]);
-        let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
+        let _handlers = DiagnosticHandlers::new(
+            cgcx,
+            diag_handler,
+            llcx,
+            &module,
+            CodegenDiagnosticsStage::Codegen,
+        );
 
         if cgcx.msvc_imps_needed {
             create_msvc_imps(cgcx, llcx, llmod);
@@ -775,7 +811,6 @@ pub(crate) unsafe fn codegen(
         }
 
         record_llvm_cgu_instructions_stats(&cgcx.prof, llmod);
-        drop(handlers);
     }
 
     // `.dwo` files are only emitted if:
@@ -875,14 +910,19 @@ unsafe fn embed_bitcode(
     //   passed though then these sections will show up in the final output.
     //   Additionally the flag that we need to set here is `SHF_EXCLUDE`.
     //
+    // * XCOFF - AIX linker ignores content in .ipa and .info if no auxiliary
+    //   symbol associated with these sections.
+    //
     // Unfortunately, LLVM provides no way to set custom section flags. For ELF
     // and COFF we emit the sections using module level inline assembly for that
     // reason (see issue #90326 for historical background).
+    let is_aix = cgcx.opts.target_triple.triple().contains("-aix");
     let is_apple = cgcx.opts.target_triple.triple().contains("-ios")
         || cgcx.opts.target_triple.triple().contains("-darwin")
         || cgcx.opts.target_triple.triple().contains("-tvos")
         || cgcx.opts.target_triple.triple().contains("-watchos");
     if is_apple
+        || is_aix
         || cgcx.opts.target_triple.triple().starts_with("wasm")
         || cgcx.opts.target_triple.triple().starts_with("asmjs")
     {
@@ -895,7 +935,13 @@ unsafe fn embed_bitcode(
         );
         llvm::LLVMSetInitializer(llglobal, llconst);
 
-        let section = if is_apple { c"__LLVM,__bitcode" } else { c".llvmbc" };
+        let section = if is_apple {
+            c"__LLVM,__bitcode"
+        } else if is_aix {
+            c".ipa"
+        } else {
+            c".llvmbc"
+        };
         llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
         llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
         llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
@@ -907,7 +953,13 @@ unsafe fn embed_bitcode(
             c"rustc.embedded.cmdline".as_ptr().cast(),
         );
         llvm::LLVMSetInitializer(llglobal, llconst);
-        let section = if is_apple { c"__LLVM,__cmdline" } else { c".llvmcmd" };
+        let section = if is_apple {
+            c"__LLVM,__cmdline"
+        } else if is_aix {
+            c".info"
+        } else {
+            c".llvmcmd"
+        };
         llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
         llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
     } else {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 43258078bd7..9863ca35202 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -23,6 +23,7 @@ use rustc_span::Span;
 use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi, TypeIdOptions};
 use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
 use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
+use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::iter;
 use std::ops::Deref;
@@ -225,7 +226,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         let args = self.check_call("invoke", llty, llfn, args);
         let funclet_bundle = funclet.map(|funclet| funclet.bundle());
         let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
-        let mut bundles = vec![funclet_bundle];
+        let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
+        if let Some(funclet_bundle) = funclet_bundle {
+            bundles.push(funclet_bundle);
+        }
 
         // Emit CFI pointer type membership test
         self.cfi_type_test(fn_attrs, fn_abi, llfn);
@@ -233,9 +237,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         // Emit KCFI operand bundle
         let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
         let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
-        bundles.push(kcfi_bundle);
+        if let Some(kcfi_bundle) = kcfi_bundle {
+            bundles.push(kcfi_bundle);
+        }
 
-        bundles.retain(|bundle| bundle.is_some());
         let invoke = unsafe {
             llvm::LLVMRustBuildInvoke(
                 self.llbuilder,
@@ -1181,7 +1186,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         let args = self.check_call("call", llty, llfn, args);
         let funclet_bundle = funclet.map(|funclet| funclet.bundle());
         let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
-        let mut bundles = vec![funclet_bundle];
+        let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
+        if let Some(funclet_bundle) = funclet_bundle {
+            bundles.push(funclet_bundle);
+        }
 
         // Emit CFI pointer type membership test
         self.cfi_type_test(fn_attrs, fn_abi, llfn);
@@ -1189,9 +1197,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         // Emit KCFI operand bundle
         let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
         let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
-        bundles.push(kcfi_bundle);
+        if let Some(kcfi_bundle) = kcfi_bundle {
+            bundles.push(kcfi_bundle);
+        }
 
-        bundles.retain(|bundle| bundle.is_some());
         let call = unsafe {
             llvm::LLVMRustBuildCall(
                 self.llbuilder,
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index e8a7afcc632..287a22bc9a6 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -8,7 +8,7 @@ use crate::llvm_util;
 use crate::type_::Type;
 use crate::value::Value;
 
-use rustc_codegen_ssa::base::wants_msvc_seh;
+use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
@@ -532,19 +532,28 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         if let Some(llpersonality) = self.eh_personality.get() {
             return llpersonality;
         }
+
+        let name = if wants_msvc_seh(self.sess()) {
+            Some("__CxxFrameHandler3")
+        } else if wants_wasm_eh(self.sess()) {
+            // LLVM specifically tests for the name of the personality function
+            // There is no need for this function to exist anywhere, it will
+            // not be called. However, its name has to be "__gxx_wasm_personality_v0"
+            // for native wasm exceptions.
+            Some("__gxx_wasm_personality_v0")
+        } else {
+            None
+        };
+
         let tcx = self.tcx;
         let llfn = match tcx.lang_items().eh_personality() {
-            Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr(
+            Some(def_id) if name.is_none() => self.get_fn_addr(
                 ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, ty::List::empty())
                     .unwrap()
                     .unwrap(),
             ),
             _ => {
-                let name = if wants_msvc_seh(self.sess()) {
-                    "__CxxFrameHandler3"
-                } else {
-                    "rust_eh_personality"
-                };
+                let name = name.unwrap_or("rust_eh_personality");
                 if let Some(llfn) = self.get_declared_value(name) {
                     llfn
                 } else {
@@ -662,6 +671,10 @@ impl<'ll> CodegenCx<'ll, '_> {
         let t_f32 = self.type_f32();
         let t_f64 = self.type_f64();
         let t_metadata = self.type_metadata();
+        let t_token = self.type_token();
+
+        ifn!("llvm.wasm.get.exception", fn(t_token) -> i8p);
+        ifn!("llvm.wasm.get.ehselector", fn(t_token) -> t_i32);
 
         ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32);
         ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 64961baf272..65cbd5edc59 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -65,10 +65,10 @@ fn make_mir_scope<'ll, 'tcx>(
         debug_context.scopes[parent]
     } else {
         // The root is the function itself.
-        let loc = cx.lookup_debug_loc(mir.span.lo());
+        let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
         debug_context.scopes[scope] = DebugScope {
-            file_start_pos: loc.file.start_pos,
-            file_end_pos: loc.file.end_pos,
+            file_start_pos: file.start_pos,
+            file_end_pos: file.end_pos,
             ..debug_context.scopes[scope]
         };
         instantiated.insert(scope);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index aa7ae9355bc..c2f16cad3fc 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -262,7 +262,7 @@ impl CodegenCx<'_, '_> {
     pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
         let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
             Ok(SourceFileAndLine { sf: file, line }) => {
-                let line_pos = file.line_begin_pos(pos);
+                let line_pos = file.lines(|lines| lines[line]);
 
                 // Use 1-based indexing.
                 let line = (line + 1) as u32;
@@ -331,7 +331,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
         };
 
-        let mut name = String::new();
+        let mut name = String::with_capacity(64);
         type_names::push_item_name(tcx, def_id, false, &mut name);
 
         // Find the enclosing function, in case this is a closure.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index d5ea48c311b..fa61c7dde18 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -28,7 +28,7 @@ pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DISco
         .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));
 
     let namespace_name_string = {
-        let mut output = String::new();
+        let mut output = String::with_capacity(64);
         type_names::push_item_name(cx.tcx, def_id, false, &mut output);
         output
     };
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 4e28034a850..31bafa87814 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -7,7 +7,7 @@ use crate::type_of::LayoutLlvmExt;
 use crate::va_arg::emit_va_arg;
 use crate::value::Value;
 
-use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
+use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
 use rustc_codegen_ssa::mir::operand::OperandRef;
@@ -452,6 +452,8 @@ fn try_intrinsic<'ll>(
         bx.store(bx.const_i32(0), dest, ret_align);
     } else if wants_msvc_seh(bx.sess()) {
         codegen_msvc_try(bx, try_func, data, catch_func, dest);
+    } else if wants_wasm_eh(bx.sess()) {
+        codegen_wasm_try(bx, try_func, data, catch_func, dest);
     } else if bx.sess().target.os == "emscripten" {
         codegen_emcc_try(bx, try_func, data, catch_func, dest);
     } else {
@@ -610,6 +612,80 @@ fn codegen_msvc_try<'ll>(
     bx.store(ret, dest, i32_align);
 }
 
+// WASM's definition of the `rust_try` function.
+fn codegen_wasm_try<'ll>(
+    bx: &mut Builder<'_, 'll, '_>,
+    try_func: &'ll Value,
+    data: &'ll Value,
+    catch_func: &'ll Value,
+    dest: &'ll Value,
+) {
+    let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
+        bx.set_personality_fn(bx.eh_personality());
+
+        let normal = bx.append_sibling_block("normal");
+        let catchswitch = bx.append_sibling_block("catchswitch");
+        let catchpad = bx.append_sibling_block("catchpad");
+        let caught = bx.append_sibling_block("caught");
+
+        let try_func = llvm::get_param(bx.llfn(), 0);
+        let data = llvm::get_param(bx.llfn(), 1);
+        let catch_func = llvm::get_param(bx.llfn(), 2);
+
+        // We're generating an IR snippet that looks like:
+        //
+        //   declare i32 @rust_try(%try_func, %data, %catch_func) {
+        //      %slot = alloca i8*
+        //      invoke %try_func(%data) to label %normal unwind label %catchswitch
+        //
+        //   normal:
+        //      ret i32 0
+        //
+        //   catchswitch:
+        //      %cs = catchswitch within none [%catchpad] unwind to caller
+        //
+        //   catchpad:
+        //      %tok = catchpad within %cs [null]
+        //      %ptr = call @llvm.wasm.get.exception(token %tok)
+        //      %sel = call @llvm.wasm.get.ehselector(token %tok)
+        //      call %catch_func(%data, %ptr)
+        //      catchret from %tok to label %caught
+        //
+        //   caught:
+        //      ret i32 1
+        //   }
+        //
+        let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
+        bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
+
+        bx.switch_to_block(normal);
+        bx.ret(bx.const_i32(0));
+
+        bx.switch_to_block(catchswitch);
+        let cs = bx.catch_switch(None, None, &[catchpad]);
+
+        bx.switch_to_block(catchpad);
+        let null = bx.const_null(bx.type_i8p());
+        let funclet = bx.catch_pad(cs, &[null]);
+
+        let ptr = bx.call_intrinsic("llvm.wasm.get.exception", &[funclet.cleanuppad()]);
+        let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[funclet.cleanuppad()]);
+
+        let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
+        bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
+        bx.catch_ret(&funclet, caught);
+
+        bx.switch_to_block(caught);
+        bx.ret(bx.const_i32(1));
+    });
+
+    // Note that no invoke is used here because by definition this function
+    // can't panic (that's what it's catching).
+    let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
+    let i32_align = bx.tcx().data_layout.i32_align.abi;
+    bx.store(ret, dest, i32_align);
+}
+
 // Definition of the standard `try` function for Rust using the GNU-like model
 // of exceptions (e.g., the normal semantics of LLVM's `landingpad` and `invoke`
 // instructions).
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 6ef3418cc5f..b667bc4f6d4 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1071,6 +1071,7 @@ extern "C" {
 
     // Operations on other types
     pub fn LLVMVoidTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMTokenTypeInContext(C: &Context) -> &Type;
     pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
 
     // Operations on all values
@@ -1301,7 +1302,7 @@ extern "C" {
         NumArgs: c_uint,
         Then: &'a BasicBlock,
         Catch: &'a BasicBlock,
-        OpBundles: *const Option<&OperandBundleDef<'a>>,
+        OpBundles: *const &OperandBundleDef<'a>,
         NumOpBundles: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
@@ -1673,7 +1674,7 @@ extern "C" {
         Fn: &'a Value,
         Args: *const &'a Value,
         NumArgs: c_uint,
-        OpBundles: *const Option<&OperandBundleDef<'a>>,
+        OpBundles: *const &OperandBundleDef<'a>,
         NumOpBundles: c_uint,
     ) -> &'a Value;
     pub fn LLVMRustBuildMemCpy<'a>(
@@ -2512,6 +2513,7 @@ extern "C" {
         remark_all_passes: bool,
         remark_passes: *const *const c_char,
         remark_passes_len: usize,
+        remark_file: *const c_char,
     );
 
     #[allow(improper_ctypes)]
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index 4ffa2b9c6a3..7e672a8dc33 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -52,6 +52,10 @@ impl<'ll> CodegenCx<'ll, '_> {
         unsafe { llvm::LLVMVoidTypeInContext(self.llcx) }
     }
 
+    pub(crate) fn type_token(&self) -> &'ll Type {
+        unsafe { llvm::LLVMTokenTypeInContext(self.llcx) }
+    }
+
     pub(crate) fn type_metadata(&self) -> &'ll Type {
         unsafe { llvm::LLVMMetadataTypeInContext(self.llcx) }
     }
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 5ecb63986fe..f73080182bf 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -21,6 +21,8 @@ codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
 
 codegen_ssa_erroneous_constant = erroneous constant encountered
 
+codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
+
 codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
 
 codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 557b120b2c8..c7925be0d7d 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -12,7 +12,7 @@ use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
 use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
+use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, Strip};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
 use rustc_session::cstore::DllImport;
 use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
@@ -1688,7 +1688,7 @@ fn detect_self_contained_mingw(sess: &Session) -> bool {
 /// instead of being found somewhere on the host system.
 /// We only provide such support for a very limited number of targets.
 fn self_contained(sess: &Session, crate_type: CrateType) -> bool {
-    if let Some(self_contained) = sess.opts.cg.link_self_contained {
+    if let Some(self_contained) = sess.opts.cg.link_self_contained.explicitly_set {
         if sess.target.link_self_contained == LinkSelfContainedDefault::False {
             sess.emit_err(errors::UnsupportedLinkSelfContained);
         }
@@ -2246,7 +2246,8 @@ fn add_order_independent_options(
     out_filename: &Path,
     tmpdir: &Path,
 ) {
-    add_gcc_ld_path(cmd, sess, flavor);
+    // Take care of the flavors and CLI options requesting the `lld` linker.
+    add_lld_args(cmd, sess, flavor);
 
     add_apple_sdk(cmd, sess, flavor);
 
@@ -2948,55 +2949,66 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
     }
 }
 
-fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
-    if let Some(ld_impl) = sess.opts.unstable_opts.gcc_ld {
-        if let LinkerFlavor::Gnu(Cc::Yes, _)
-        | LinkerFlavor::Darwin(Cc::Yes, _)
-        | LinkerFlavor::WasmLld(Cc::Yes) = flavor
-        {
-            match ld_impl {
-                LdImpl::Lld => {
-                    // Implement the "self-contained" part of -Zgcc-ld
-                    // by adding rustc distribution directories to the tool search path.
-                    for path in sess.get_tools_search_paths(false) {
-                        cmd.arg({
-                            let mut arg = OsString::from("-B");
-                            arg.push(path.join("gcc-ld"));
-                            arg
-                        });
-                    }
-                    // Implement the "linker flavor" part of -Zgcc-ld
-                    // by asking cc to use some kind of lld.
-                    cmd.arg("-fuse-ld=lld");
-
-                    if !flavor.is_gnu() {
-                        // Tell clang to use a non-default LLD flavor.
-                        // Gcc doesn't understand the target option, but we currently assume
-                        // that gcc is not used for Apple and Wasm targets (#97402).
-                        //
-                        // Note that we don't want to do that by default on macOS: e.g. passing a
-                        // 10.7 target to LLVM works, but not to recent versions of clang/macOS, as
-                        // shown in issue #101653 and the discussion in PR #101792.
-                        //
-                        // It could be required in some cases of cross-compiling with
-                        // `-Zgcc-ld=lld`, but this is generally unspecified, and we don't know
-                        // which specific versions of clang, macOS SDK, host and target OS
-                        // combinations impact us here.
-                        //
-                        // So we do a simple first-approximation until we know more of what the
-                        // Apple targets require (and which would be handled prior to hitting this
-                        // `-Zgcc-ld=lld` codepath anyway), but the expectation is that until then
-                        // this should be manually passed if needed. We specify the target when
-                        // targeting a different linker flavor on macOS, and that's also always
-                        // the case when targeting WASM.
-                        if sess.target.linker_flavor != sess.host.linker_flavor {
-                            cmd.arg(format!("--target={}", sess.target.llvm_target));
-                        }
-                    }
-                }
-            }
-        } else {
-            sess.emit_fatal(errors::OptionGccOnly);
+/// When using the linker flavors opting in to `lld`, or the unstable `-Zgcc-ld=lld` flag, add the
+/// necessary paths and arguments to invoke it:
+/// - when the self-contained linker flag is active: the build of `lld` distributed with rustc,
+/// - or any `lld` available to `cc`.
+fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
+    let unstable_use_lld = sess.opts.unstable_opts.gcc_ld.is_some();
+    debug!("add_lld_args requested, flavor: '{flavor:?}', `-Zgcc-ld=lld`: {unstable_use_lld}");
+
+    // Sanity check: using the old unstable `-Zgcc-ld=lld` option requires a `cc`-using flavor.
+    let flavor_uses_cc = flavor.uses_cc();
+    if unstable_use_lld && !flavor_uses_cc {
+        sess.emit_fatal(errors::OptionGccOnly);
+    }
+
+    // If the flavor doesn't use a C/C++ compiler to invoke the linker, or doesn't opt in to `lld`,
+    // we don't need to do anything.
+    let use_lld = flavor.uses_lld() || unstable_use_lld;
+    if !flavor_uses_cc || !use_lld {
+        return;
+    }
+
+    // 1. Implement the "self-contained" part of this feature by adding rustc distribution
+    //    directories to the tool's search path.
+    let self_contained_linker = sess.opts.cg.link_self_contained.linker() || unstable_use_lld;
+    if self_contained_linker {
+        for path in sess.get_tools_search_paths(false) {
+            cmd.arg({
+                let mut arg = OsString::from("-B");
+                arg.push(path.join("gcc-ld"));
+                arg
+            });
+        }
+    }
+
+    // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of
+    //    `lld` as the linker.
+    cmd.arg("-fuse-ld=lld");
+
+    if !flavor.is_gnu() {
+        // Tell clang to use a non-default LLD flavor.
+        // Gcc doesn't understand the target option, but we currently assume
+        // that gcc is not used for Apple and Wasm targets (#97402).
+        //
+        // Note that we don't want to do that by default on macOS: e.g. passing a
+        // 10.7 target to LLVM works, but not to recent versions of clang/macOS, as
+        // shown in issue #101653 and the discussion in PR #101792.
+        //
+        // It could be required in some cases of cross-compiling with
+        // `-Zgcc-ld=lld`, but this is generally unspecified, and we don't know
+        // which specific versions of clang, macOS SDK, host and target OS
+        // combinations impact us here.
+        //
+        // So we do a simple first-approximation until we know more of what the
+        // Apple targets require (and which would be handled prior to hitting this
+        // `-Zgcc-ld=lld` codepath anyway), but the expectation is that until then
+        // this should be manually passed if needed. We specify the target when
+        // targeting a different linker flavor on macOS, and that's also always
+        // the case when targeting WASM.
+        if sess.target.linker_flavor != sess.host.linker_flavor {
+            cmd.arg(format!("--target={}", sess.target.llvm_target));
         }
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index b198e35e0c1..00e6acb5c1a 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -20,7 +20,7 @@ use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
 use rustc_session::Session;
 use rustc_target::abi::Endian;
-use rustc_target::spec::{RelocModel, Target};
+use rustc_target::spec::{ef_avr_arch, RelocModel, Target};
 
 /// The default metadata loader. This is used by cg_llvm and cg_clif.
 ///
@@ -284,8 +284,24 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
             e_flags
         }
         Architecture::LoongArch64 => {
-            // Source: https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_e_flags_identifies_abi_type_and_version
-            elf::EF_LARCH_OBJABI_V1 | elf::EF_LARCH_ABI_DOUBLE_FLOAT
+            // Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
+            let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;
+            let features = &sess.target.options.features;
+
+            // Select the appropriate floating-point ABI
+            if features.contains("+d") {
+                e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT;
+            } else if features.contains("+f") {
+                e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT;
+            } else {
+                e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT;
+            }
+            e_flags
+        }
+        Architecture::Avr => {
+            // Resolve the ISA revision and set
+            // the appropriate EF_AVR_ARCH flag.
+            ef_avr_arch(&sess.target.options.cpu)
         }
         _ => 0,
     };
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 51ac441a7a4..ececa29b231 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -35,6 +35,7 @@ use rustc_span::symbol::sym;
 use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
 use rustc_target::spec::{MergeFunctions, SanitizerSet};
 
+use crate::errors::ErrorCreatingRemarkDir;
 use std::any::Any;
 use std::borrow::Cow;
 use std::fs;
@@ -345,6 +346,9 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub diag_emitter: SharedEmitter,
     /// LLVM optimizations for which we want to print remarks.
     pub remark: Passes,
+    /// Directory into which should the LLVM optimization remarks be written.
+    /// If `None`, they will be written to stderr.
+    pub remark_dir: Option<PathBuf>,
     /// Worker thread number
     pub worker: usize,
     /// The incremental compilation session directory, or None if we are not
@@ -698,28 +702,49 @@ impl<B: WriteBackendMethods> WorkItem<B> {
 
     /// Generate a short description of this work item suitable for use as a thread name.
     fn short_description(&self) -> String {
-        // `pthread_setname()` on *nix is limited to 15 characters and longer names are ignored.
-        // Use very short descriptions in this case to maximize the space available for the module name.
-        // Windows does not have that limitation so use slightly more descriptive names there.
+        // `pthread_setname()` on *nix ignores anything beyond the first 15
+        // bytes. Use short descriptions to maximize the space available for
+        // the module name.
+        #[cfg(not(windows))]
+        fn desc(short: &str, _long: &str, name: &str) -> String {
+            // The short label is three bytes, and is followed by a space. That
+            // leaves 11 bytes for the CGU name. How we obtain those 11 bytes
+            // depends on the the CGU name form.
+            //
+            // - Non-incremental, e.g. `regex.f10ba03eb5ec7975-cgu.0`: the part
+            //   before the `-cgu.0` is the same for every CGU, so use the
+            //   `cgu.0` part. The number suffix will be different for each
+            //   CGU.
+            //
+            // - Incremental (normal), e.g. `2i52vvl2hco29us0`: use the whole
+            //   name because each CGU will have a unique ASCII hash, and the
+            //   first 11 bytes will be enough to identify it.
+            //
+            // - Incremental (with `-Zhuman-readable-cgu-names`), e.g.
+            //   `regex.f10ba03eb5ec7975-re_builder.volatile`: use the whole
+            //   name. The first 11 bytes won't be enough to uniquely identify
+            //   it, but no obvious substring will, and this is a rarely used
+            //   option so it doesn't matter much.
+            //
+            assert_eq!(short.len(), 3);
+            let name = if let Some(index) = name.find("-cgu.") {
+                &name[index + 1..] // +1 skips the leading '-'.
+            } else {
+                name
+            };
+            format!("{short} {name}")
+        }
+
+        // Windows has no thread name length limit, so use more descriptive names.
+        #[cfg(windows)]
+        fn desc(_short: &str, long: &str, name: &str) -> String {
+            format!("{long} {name}")
+        }
+
         match self {
-            WorkItem::Optimize(m) => {
-                #[cfg(windows)]
-                return format!("optimize module {}", m.name);
-                #[cfg(not(windows))]
-                return format!("opt {}", m.name);
-            }
-            WorkItem::CopyPostLtoArtifacts(m) => {
-                #[cfg(windows)]
-                return format!("copy LTO artifacts for {}", m.name);
-                #[cfg(not(windows))]
-                return format!("copy {}", m.name);
-            }
-            WorkItem::LTO(m) => {
-                #[cfg(windows)]
-                return format!("LTO module {}", m.name());
-                #[cfg(not(windows))]
-                return format!("LTO {}", m.name());
-            }
+            WorkItem::Optimize(m) => desc("opt", "optimize module {}", &m.name),
+            WorkItem::CopyPostLtoArtifacts(m) => desc("cpy", "copy LTO artifacts for {}", &m.name),
+            WorkItem::LTO(m) => desc("lto", "LTO module {}", m.name()),
         }
     }
 }
@@ -1041,6 +1066,17 @@ fn start_executing_work<B: ExtraBackendMethods>(
             tcx.backend_optimization_level(())
         };
     let backend_features = tcx.global_backend_features(());
+
+    let remark_dir = if let Some(ref dir) = sess.opts.unstable_opts.remark_dir {
+        let result = fs::create_dir_all(dir).and_then(|_| dir.canonicalize());
+        match result {
+            Ok(dir) => Some(dir),
+            Err(error) => sess.emit_fatal(ErrorCreatingRemarkDir { error }),
+        }
+    } else {
+        None
+    };
+
     let cgcx = CodegenContext::<B> {
         crate_types: sess.crate_types().to_vec(),
         each_linked_rlib_for_lto,
@@ -1052,6 +1088,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         prof: sess.prof.clone(),
         exported_symbols,
         remark: sess.opts.cg.remark.clone(),
+        remark_dir,
         worker: 0,
         incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
         cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 28f3c23364c..f8ced6949d5 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -357,6 +357,13 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     }
 }
 
+// Returns `true` if this session's target will use native wasm
+// exceptions. This means that the VM does the unwinding for
+// us
+pub fn wants_wasm_eh(sess: &Session) -> bool {
+    sess.target.is_like_wasm && sess.target.os != "emscripten"
+}
+
 /// Returns `true` if this session's target will use SEH-based unwinding.
 ///
 /// This is only true for MSVC targets, and even then the 64-bit MSVC target
@@ -366,6 +373,13 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
     sess.target.is_like_msvc
 }
 
+/// Returns `true` if this session's target requires the new exception
+/// handling LLVM IR instructions (catchpad / cleanuppad / ... instead
+/// of landingpad)
+pub fn wants_new_eh_instructions(sess: &Session) -> bool {
+    wants_wasm_eh(sess) || wants_msvc_seh(sess)
+}
+
 pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     bx: &mut Bx,
     dst: Bx::Value,
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 989274308fb..056b4abd235 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1023,3 +1023,9 @@ pub struct TargetFeatureSafeTrait {
     #[label(codegen_ssa_label_def)]
     pub def: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_error_creating_remark_dir)]
+pub struct ErrorCreatingRemarkDir {
+    pub error: std::io::Error,
+}
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 5e40b672866..93bed3a4a4a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -79,8 +79,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
             lltarget = fx.landing_pad_for(target);
         }
         if is_cleanupret {
-            // MSVC cross-funclet jump - need a trampoline
-            debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess));
+            // Cross-funclet jump - need a trampoline
+            debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
             debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
             let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
             let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
@@ -177,9 +177,16 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
             mir::UnwindAction::Continue => None,
             mir::UnwindAction::Unreachable => None,
             mir::UnwindAction::Terminate => {
-                if fx.mir[self.bb].is_cleanup && base::wants_msvc_seh(fx.cx.tcx().sess) {
-                    // SEH will abort automatically if an exception tries to
+                if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) {
+                    // MSVC SEH will abort automatically if an exception tries to
                     // propagate out from cleanup.
+
+                    // FIXME(@mirkootter): For wasm, we currently do not support terminate during
+                    // cleanup, because this requires a few more changes: The current code
+                    // caches the `terminate_block` for each function; funclet based code - however -
+                    // requires a different terminate_block for each funclet
+                    // Until this is implemented, we just do not unwind inside cleanup blocks
+
                     None
                 } else {
                     Some(fx.terminate_block())
@@ -863,13 +870,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // promotes any complex rvalues to constants.
                         if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
                             if let mir::Operand::Constant(constant) = arg {
-                                let c = self.eval_mir_constant(constant);
-                                let (llval, ty) = self.simd_shuffle_indices(
-                                    &bx,
-                                    constant.span,
-                                    self.monomorphize(constant.ty()),
-                                    c,
-                                );
+                                let (llval, ty) = self.simd_shuffle_indices(&bx, constant);
                                 return OperandRef {
                                     val: Immediate(llval),
                                     layout: bx.layout_of(ty),
@@ -1528,7 +1529,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     // FIXME(eddyb) rename this to `eh_pad_for_uncached`.
     fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
         let llbb = self.llbb(bb);
-        if base::wants_msvc_seh(self.cx.sess()) {
+        if base::wants_new_eh_instructions(self.cx.sess()) {
             let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
             let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
             let funclet = cleanup_bx.cleanup_pad(None, &[]);
@@ -1587,6 +1588,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 //      } catch (...) {
                 //          bar();
                 //      }
+                //
+                // which creates an IR snippet like
+                //
+                //      cs_terminate:
+                //         %cs = catchswitch within none [%cp_terminate] unwind to caller
+                //      cp_terminate:
+                //         %cp = catchpad within %cs [null, i32 64, null]
+                //         ...
+
                 llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
                 let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 14fe84a146d..1c5031dfc4b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -5,7 +5,6 @@ use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::source_map::Span;
 use rustc_target::abi::Abi;
 
 use super::FunctionCx;
@@ -59,22 +58,40 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         })
     }
 
+    /// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
+    /// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to
+    /// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
+    pub fn eval_unevaluated_mir_constant_to_valtree(
+        &self,
+        constant: &mir::Constant<'tcx>,
+    ) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
+        let uv = match constant.literal {
+            mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
+            other => span_bug!(constant.span, "{other:#?}"),
+        };
+        let uv = self.monomorphize(uv);
+        self.cx.tcx().const_eval_resolve_for_typeck(
+            ty::ParamEnv::reveal_all(),
+            uv,
+            Some(constant.span),
+        )
+    }
+
     /// process constant containing SIMD shuffle indices
     pub fn simd_shuffle_indices(
         &mut self,
         bx: &Bx,
-        span: Span,
-        ty: Ty<'tcx>,
-        constant: Result<ConstValue<'tcx>, ErrorHandled>,
+        constant: &mir::Constant<'tcx>,
     ) -> (Bx::Value, Ty<'tcx>) {
-        constant
+        let ty = self.monomorphize(constant.ty());
+        let val = self
+            .eval_unevaluated_mir_constant_to_valtree(constant)
+            .ok()
+            .flatten()
             .map(|val| {
                 let field_ty = ty.builtin_index().unwrap();
-                let c = mir::ConstantKind::from_value(val, ty);
-                let values: Vec<_> = bx
-                    .tcx()
-                    .destructure_mir_constant(ty::ParamEnv::reveal_all(), c)
-                    .fields
+                let values: Vec<_> = val
+                    .unwrap_branch()
                     .iter()
                     .map(|field| {
                         if let Some(prim) = field.try_to_scalar() {
@@ -88,15 +105,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         }
                     })
                     .collect();
-                let llval = bx.const_struct(&values, false);
-                (llval, c.ty())
+                bx.const_struct(&values, false)
             })
-            .unwrap_or_else(|_| {
-                bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span });
+            .unwrap_or_else(|| {
+                bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span: constant.span });
                 // We've errored, so we don't have to produce working code.
-                let ty = self.monomorphize(ty);
                 let llty = bx.backend_type(bx.layout_of(ty));
-                (bx.const_undef(llty), ty)
-            })
+                bx.const_undef(llty)
+            });
+        (val, ty)
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 15b0e34b8e4..9ff6a249748 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -179,7 +179,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         start_bx.set_personality_fn(cx.eh_personality());
     }
 
-    let cleanup_kinds = base::wants_msvc_seh(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
+    let cleanup_kinds =
+        base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
 
     let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
         mir.basic_blocks
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 6a3a31a0d60..9e06fec550d 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -284,6 +284,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     // tidy-alphabetical-start
     ("atomics", Some(sym::wasm_target_feature)),
     ("bulk-memory", Some(sym::wasm_target_feature)),
+    ("exception-handling", Some(sym::wasm_target_feature)),
     ("multivalue", Some(sym::wasm_target_feature)),
     ("mutable-globals", Some(sym::wasm_target_feature)),
     ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index b9ab0a4b7c8..5cc1fa2a497 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -92,7 +92,6 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     val: mir::ConstantKind<'tcx>,
 ) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> {
-    trace!("destructure_mir_constant: {:?}", val);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
     let op = ecx.eval_mir_constant(&val, None, None)?;
 
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 8f4cf23770e..4f10e4837ce 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -72,7 +72,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
         }
         sym::pref_align_of => {
             // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
-            let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
+            let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?;
             ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
         }
         sym::type_id => {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index a2d23425f3b..36c76e53231 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -344,15 +344,18 @@ where
     };
 
     // Check the qualifs of the value of `const` items.
-    // FIXME(valtrees): check whether const qualifs should behave the same
-    // way for type and mir constants.
     let uneval = match constant.literal {
         ConstantKind::Ty(ct)
-            if matches!(ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_)) =>
+            if matches!(
+                ct.kind(),
+                ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
+            ) =>
         {
             None
         }
-        ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
+        ConstantKind::Ty(c) => {
+            bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
+        }
         ConstantKind::Unevaluated(uv, _) => Some(uv),
         ConstantKind::Val(..) => None,
     };
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index f56798d4c32..2d1970791ca 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -21,7 +21,7 @@ pub fn check_validity_requirement<'tcx>(
     tcx: TyCtxt<'tcx>,
     kind: ValidityRequirement,
     param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> Result<bool, LayoutError<'tcx>> {
+) -> Result<bool, &'tcx LayoutError<'tcx>> {
     let layout = tcx.layout_of(param_env_and_ty)?;
 
     // There is nothing strict or lax about inhabitedness.
@@ -43,7 +43,7 @@ fn might_permit_raw_init_strict<'tcx>(
     ty: TyAndLayout<'tcx>,
     tcx: TyCtxt<'tcx>,
     kind: ValidityRequirement,
-) -> Result<bool, LayoutError<'tcx>> {
+) -> Result<bool, &'tcx LayoutError<'tcx>> {
     let machine = CompileTimeInterpreter::new(CanAccessStatics::No, CheckAlignment::Error);
 
     let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
@@ -75,7 +75,7 @@ fn might_permit_raw_init_lax<'tcx>(
     this: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     init_kind: ValidityRequirement,
-) -> Result<bool, LayoutError<'tcx>> {
+) -> Result<bool, &'tcx LayoutError<'tcx>> {
     let scalar_allows_raw_init = move |s: Scalar| -> bool {
         match init_kind {
             ValidityRequirement::Inhabited => {
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 859e384d8b5..3deb9c5c2f5 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -68,7 +68,6 @@ pub mod macros;
 pub mod obligation_forest;
 pub mod sip128;
 pub mod small_c_str;
-pub mod small_str;
 pub mod snapshot_map;
 pub mod svh;
 pub use ena::snapshot_vec;
diff --git a/compiler/rustc_data_structures/src/small_str.rs b/compiler/rustc_data_structures/src/small_str.rs
deleted file mode 100644
index 800acb1b03e..00000000000
--- a/compiler/rustc_data_structures/src/small_str.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use smallvec::SmallVec;
-
-#[cfg(test)]
-mod tests;
-
-/// Like SmallVec but for strings.
-#[derive(Default)]
-pub struct SmallStr<const N: usize>(SmallVec<[u8; N]>);
-
-impl<const N: usize> SmallStr<N> {
-    #[inline]
-    pub fn new() -> Self {
-        SmallStr(SmallVec::default())
-    }
-
-    #[inline]
-    pub fn push_str(&mut self, s: &str) {
-        self.0.extend_from_slice(s.as_bytes());
-    }
-
-    #[inline]
-    pub fn empty(&self) -> bool {
-        self.0.is_empty()
-    }
-
-    #[inline]
-    pub fn spilled(&self) -> bool {
-        self.0.spilled()
-    }
-
-    #[inline]
-    pub fn as_str(&self) -> &str {
-        unsafe { std::str::from_utf8_unchecked(self.0.as_slice()) }
-    }
-}
-
-impl<const N: usize> std::ops::Deref for SmallStr<N> {
-    type Target = str;
-
-    #[inline]
-    fn deref(&self) -> &str {
-        self.as_str()
-    }
-}
-
-impl<const N: usize, A: AsRef<str>> FromIterator<A> for SmallStr<N> {
-    #[inline]
-    fn from_iter<T>(iter: T) -> Self
-    where
-        T: IntoIterator<Item = A>,
-    {
-        let mut s = SmallStr::default();
-        s.extend(iter);
-        s
-    }
-}
-
-impl<const N: usize, A: AsRef<str>> Extend<A> for SmallStr<N> {
-    #[inline]
-    fn extend<T>(&mut self, iter: T)
-    where
-        T: IntoIterator<Item = A>,
-    {
-        for a in iter.into_iter() {
-            self.push_str(a.as_ref());
-        }
-    }
-}
diff --git a/compiler/rustc_data_structures/src/small_str/tests.rs b/compiler/rustc_data_structures/src/small_str/tests.rs
deleted file mode 100644
index 7635a9b7204..00000000000
--- a/compiler/rustc_data_structures/src/small_str/tests.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use super::*;
-
-#[test]
-fn empty() {
-    let s = SmallStr::<1>::new();
-    assert!(s.empty());
-    assert_eq!("", s.as_str());
-    assert!(!s.spilled());
-}
-
-#[test]
-fn from_iter() {
-    let s = ["aa", "bb", "cc"].iter().collect::<SmallStr<6>>();
-    assert_eq!("aabbcc", s.as_str());
-    assert!(!s.spilled());
-
-    let s = ["aa", "bb", "cc", "dd"].iter().collect::<SmallStr<6>>();
-    assert_eq!("aabbccdd", s.as_str());
-    assert!(s.spilled());
-}
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index d7c295418ba..86a54f6befd 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -8,3 +8,6 @@ crate-type = ["dylib"]
 
 [dependencies]
 rustc_driver_impl = { path = "../rustc_driver_impl" }
+# FIXME(Nilstrieb): 0.37.12 adds eventfd support for FreeBSD,
+# but FreeBSD 12 does not support it: https://github.com/bytecodealliance/rustix/issues/716
+rustix = "=0.37.11"
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 93f968aa851..906c31c9a3d 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -543,6 +543,8 @@ declare_features! (
     /// Allows creation of instances of a struct by moving fields that have
     /// not changed from prior instances of the same struct (RFC #2528)
     (active, type_changing_struct_update, "1.58.0", Some(86555), None),
+    /// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`).
+    (active, type_privacy_lints, "CURRENT_RUSTC_VERSION", Some(48054), None),
     /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
     (active, unix_sigpipe, "1.65.0", Some(97889), None),
     /// Allows unsized fn parameters.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 591831b59a1..6c419471de1 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2664,6 +2664,10 @@ pub struct OpaqueTy<'hir> {
     pub generics: &'hir Generics<'hir>,
     pub bounds: GenericBounds<'hir>,
     pub origin: OpaqueTyOrigin,
+    // Opaques have duplicated lifetimes, this mapping connects the original lifetime with the copy
+    // so we can later generate bidirectional outlives predicates to enforce that these lifetimes
+    // stay in sync.
+    pub lifetime_mapping: &'hir [(Lifetime, LocalDefId)],
     pub in_trait: bool,
 }
 
@@ -3315,7 +3319,7 @@ pub enum ItemKind<'hir> {
     /// A type alias, e.g., `type Foo = Bar<u8>`.
     TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
     /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
-    OpaqueTy(OpaqueTy<'hir>),
+    OpaqueTy(&'hir OpaqueTy<'hir>),
     /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
     Enum(EnumDef<'hir>, &'hir Generics<'hir>),
     /// A struct definition, e.g., `struct Foo<A> {x: A}`.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 1886a91bda8..347c1f4637f 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -502,7 +502,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             visitor.visit_ty(ty);
             visitor.visit_generics(generics)
         }
-        ItemKind::OpaqueTy(OpaqueTy { ref generics, bounds, .. }) => {
+        ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
             visitor.visit_id(item.hir_id());
             walk_generics(visitor, generics);
             walk_list!(visitor, visit_param_bound, bounds);
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index edc6bcacc68..ad26c495c02 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
 hir_analysis_invalid_union_field_sugg =
     wrap the field type in `ManuallyDrop<...>`
 
+hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
+    .label = const parameter declared here
+
+hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
+    .label = lifetime declared here
+
+hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
+    .label = type parameter declared here
+
 hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
     lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
     .label = lifetimes do not match {$item_kind} in trait
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 5032378923b..2f5bcf8d647 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1984,7 +1984,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .copied()
                 .filter(|&(impl_, _)| {
                     infcx.probe(|_| {
-                        let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+                        let ocx = ObligationCtxt::new(&infcx);
                         ocx.register_obligations(obligations.clone());
 
                         let impl_substs = infcx.fresh_substs_for_item(span, impl_);
@@ -2809,7 +2809,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let opaque_ty = tcx.hir().item(item_id);
 
                 match opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
+                    hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => {
                         let local_def_id = item_id.owner_id.def_id;
                         // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
                         // generate the def_id of an associated type for the trait and return as
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 6eb18aecd65..8aa9a2c2734 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -161,7 +161,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         &self,
         ty: Ty<'tcx>,
     ) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
-        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.infcx);
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.infcx);
 
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
         let normalized_ty = match self
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a7e81f41c69..346e153a69d 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -299,7 +299,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
         }
     }
 
-    if let ItemKind::OpaqueTy(hir::OpaqueTy {
+    if let ItemKind::OpaqueTy(&hir::OpaqueTy {
         origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
         in_trait,
         ..
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 3048c175e1e..76edeccaf29 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -19,7 +19,7 @@ use rustc_middle::ty::{
     self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
@@ -651,11 +651,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     let impl_sig = ocx.normalize(
         &norm_cause,
         param_env,
-        infcx.instantiate_binder_with_fresh_vars(
-            return_span,
-            infer::HigherRankedType,
-            tcx.fn_sig(impl_m.def_id).subst_identity(),
-        ),
+        tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
     );
     impl_sig.error_reported()?;
     let impl_return_ty = impl_sig.output();
@@ -665,9 +661,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     // them with inference variables.
     // We will use these inference variables to collect the hidden types of RPITITs.
     let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
-    let unnormalized_trait_sig = tcx
-        .liberate_late_bound_regions(
-            impl_m.def_id,
+    let unnormalized_trait_sig = infcx
+        .instantiate_binder_with_fresh_vars(
+            return_span,
+            infer::HigherRankedType,
             tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
         )
         .fold_with(&mut collector);
@@ -760,15 +757,17 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
 
     let mut collected_tys = FxHashMap::default();
     for (def_id, (ty, substs)) in collected_types {
-        match infcx.fully_resolve(ty) {
-            Ok(ty) => {
+        match infcx.fully_resolve((ty, substs)) {
+            Ok((ty, substs)) => {
                 // `ty` contains free regions that we created earlier while liberating the
                 // trait fn signature. However, projection normalization expects `ty` to
                 // contains `def_id`'s early-bound regions.
                 let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
                 debug!(?id_substs, ?substs);
-                let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> =
-                    std::iter::zip(substs, id_substs).collect();
+                let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
+                    .skip(tcx.generics_of(trait_m.def_id).count())
+                    .filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
+                    .collect();
                 debug!(?map);
 
                 // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
@@ -793,25 +792,19 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                 // same generics.
                 let num_trait_substs = trait_to_impl_substs.len();
                 let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
-                let ty = tcx.fold_regions(ty, |region, _| {
-                    match region.kind() {
-                        // Remap all free regions, which correspond to late-bound regions in the function.
-                        ty::ReFree(_) => {}
-                        // Remap early-bound regions as long as they don't come from the `impl` itself.
-                        ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {}
-                        _ => return region,
-                    }
-                    let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
-                    else {
-                        return ty::Region::new_error_with_message(tcx, return_span, "expected ReFree to map to ReEarlyBound")
-                    };
-                    ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion {
-                        def_id: e.def_id,
-                        name: e.name,
-                        index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
-                    })
-                });
-                debug!(%ty);
+                let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
+                    tcx,
+                    map,
+                    num_trait_substs,
+                    num_impl_substs,
+                    def_id,
+                    impl_def_id: impl_m.container_id(tcx),
+                    ty,
+                    return_span,
+                }) {
+                    Ok(ty) => ty,
+                    Err(guar) => tcx.ty_error(guar),
+                };
                 collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
             }
             Err(err) => {
@@ -895,6 +888,97 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
     }
 }
 
+struct RemapHiddenTyRegions<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
+    num_trait_substs: usize,
+    num_impl_substs: usize,
+    def_id: DefId,
+    impl_def_id: DefId,
+    ty: Ty<'tcx>,
+    return_span: Span,
+}
+
+impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
+    type Error = ErrorGuaranteed;
+
+    fn interner(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
+            let mut mapped_substs = Vec::with_capacity(substs.len());
+            for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
+                mapped_substs.push(match (arg.unpack(), v) {
+                    // Skip uncaptured opaque substs
+                    (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
+                    _ => arg.try_fold_with(self)?,
+                });
+            }
+            Ok(self.tcx.mk_opaque(def_id, self.tcx.mk_substs(&mapped_substs)))
+        } else {
+            t.try_super_fold_with(self)
+        }
+    }
+
+    fn try_fold_region(
+        &mut self,
+        region: ty::Region<'tcx>,
+    ) -> Result<ty::Region<'tcx>, Self::Error> {
+        match region.kind() {
+            // Remap all free regions, which correspond to late-bound regions in the function.
+            ty::ReFree(_) => {}
+            // Remap early-bound regions as long as they don't come from the `impl` itself,
+            // in which case we don't really need to renumber them.
+            ty::ReEarlyBound(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
+            _ => return Ok(region),
+        }
+
+        let e = if let Some(region) = self.map.get(&region) {
+            if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() }
+        } else {
+            let guar = match region.kind() {
+                ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. })
+                | ty::ReFree(ty::FreeRegion {
+                    bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
+                    ..
+                }) => {
+                    let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
+                        self.tcx.def_span(opaque_ty.def_id)
+                    } else {
+                        self.return_span
+                    };
+                    self.tcx
+                        .sess
+                        .struct_span_err(
+                            return_span,
+                            "return type captures more lifetimes than trait definition",
+                        )
+                        .span_label(self.tcx.def_span(def_id), "this lifetime was captured")
+                        .span_note(
+                            self.tcx.def_span(self.def_id),
+                            "hidden type must only reference lifetimes captured by this impl trait",
+                        )
+                        .note(format!("hidden type inferred to be `{}`", self.ty))
+                        .emit()
+                }
+                _ => self.tcx.sess.delay_span_bug(DUMMY_SP, "should've been able to remap region"),
+            };
+            return Err(guar);
+        };
+
+        Ok(ty::Region::new_early_bound(
+            self.tcx,
+            ty::EarlyBoundRegion {
+                def_id: e.def_id,
+                name: e.name,
+                index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
+            },
+        ))
+    }
+}
+
 fn report_trait_method_mismatch<'tcx>(
     infcx: &InferCtxt<'tcx>,
     mut cause: ObligationCause<'tcx>,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index eba943e0072..d7ac9e7ce73 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1328,7 +1328,7 @@ fn suggest_impl_trait<'tcx>(
         {
             continue;
         }
-        let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+        let ocx = ObligationCtxt::new(&infcx);
         let item_ty = ocx.normalize(
             &ObligationCause::misc(span, def_id),
             param_env,
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index e92a0dcc1fb..2206f640529 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -144,7 +144,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
             Some(tcx.typeck_root_def_id(def_id.to_def_id()))
         }
         Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(hir::OpaqueTy {
+            ItemKind::OpaqueTy(&hir::OpaqueTy {
                 origin:
                     hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
                 in_trait,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index d9b2aacab9d..b9e71aaa004 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -2,7 +2,7 @@ use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
-use hir::{HirId, Node};
+use hir::{HirId, Lifetime, Node};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -10,9 +10,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, ToPredicate};
+use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
 use rustc_span::symbol::{sym, Ident};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
 
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -62,6 +62,54 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
 fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
     use rustc_hir::*;
 
+    match tcx.opt_rpitit_info(def_id.to_def_id()) {
+        Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
+            let opaque_ty_node = tcx.hir().get(opaque_ty_id);
+            let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
+                bug!("unexpected {opaque_ty_node:?}")
+            };
+
+            let mut predicates = Vec::new();
+            compute_bidirectional_outlives_predicates(
+                tcx,
+                def_id,
+                lifetime_mapping.iter().map(|(lifetime, def_id)| {
+                    (*lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
+                }),
+                tcx.generics_of(def_id.to_def_id()),
+                &mut predicates,
+            );
+
+            return ty::GenericPredicates {
+                parent: Some(tcx.parent(def_id.to_def_id())),
+                predicates: tcx.arena.alloc_from_iter(predicates),
+            };
+        }
+
+        Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
+            let assoc_item = tcx.associated_item(def_id);
+            let trait_assoc_predicates = tcx.predicates_of(assoc_item.trait_item_def_id.unwrap());
+
+            let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+            let impl_def_id = tcx.parent(fn_def_id);
+            let impl_trait_ref_substs =
+                tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().substs;
+
+            let impl_assoc_substs =
+                impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
+
+            let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
+
+            return ty::GenericPredicates {
+                parent: Some(impl_def_id),
+                predicates: tcx.arena.alloc_from_iter(impl_predicates),
+            };
+        }
+
+        None => {}
+    }
+
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let node = tcx.hir().get(hir_id);
 
@@ -289,38 +337,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             bug!("unexpected {opaque_ty_node:?}")
         };
         debug!(?lifetimes);
-        for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
-            let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
-            let orig_region = icx.astconv().ast_region_to_region(&arg, None);
-            if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
-                // Only early-bound regions can point to the original generic parameter.
-                continue;
-            }
-
-            let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
-            let dup_def = duplicate.def_id.to_def_id();
 
-            let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
+        let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
+            .map(|(arg, dup)| {
+                let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
+                (**arg, dup)
+            })
+            .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
+            .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
 
-            let dup_region = ty::Region::new_early_bound(
-                tcx,
-                ty::EarlyBoundRegion {
-                    def_id: dup_def,
-                    index: dup_index,
-                    name: duplicate.name.ident().name,
-                },
-            );
-            predicates.push((
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
-                    .to_predicate(icx.tcx),
-                duplicate.span,
-            ));
-            predicates.push((
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
-                    .to_predicate(icx.tcx),
-                duplicate.span,
-            ));
-        }
+        compute_bidirectional_outlives_predicates(
+            tcx,
+            def_id,
+            lifetime_mapping,
+            generics,
+            &mut predicates,
+        );
         debug!(?predicates);
     }
 
@@ -330,6 +362,46 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     }
 }
 
+/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
+/// enforce that these lifetimes stay in sync.
+fn compute_bidirectional_outlives_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item_def_id: LocalDefId,
+    lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
+    generics: &Generics,
+    predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
+) {
+    let icx = ItemCtxt::new(tcx, item_def_id);
+
+    for (arg, (dup_def, name, span)) in lifetime_mapping {
+        let orig_region = icx.astconv().ast_region_to_region(&arg, None);
+        if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
+            // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
+            // show up in the opaque's parent's substs.
+            continue;
+        }
+
+        let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
+
+        let dup_region = ty::Region::new_early_bound(
+            tcx,
+            ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
+        );
+
+        predicates.push((
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
+                .to_predicate(tcx),
+            span,
+        ));
+
+        predicates.push((
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
+                .to_predicate(tcx),
+            span,
+        ));
+    }
+}
+
 fn const_evaluatable_predicates_of(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
@@ -668,7 +740,7 @@ pub(super) fn type_param_predicates(
                 ItemKind::Fn(.., generics, _)
                 | ItemKind::Impl(&hir::Impl { generics, .. })
                 | ItemKind::TyAlias(_, generics)
-                | ItemKind::OpaqueTy(OpaqueTy {
+                | ItemKind::OpaqueTy(&OpaqueTy {
                     generics,
                     origin: hir::OpaqueTyOrigin::TyAlias { .. },
                     ..
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 3d75df8c69f..97a3e01c52a 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -556,7 +556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     });
                 }
             }
-            hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+            hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
                 origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
                 generics,
                 ..
@@ -1344,12 +1344,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Binder {
                     where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
                 } => {
-                    let mut err = self.tcx.sess.struct_span_err(
-                        lifetime_ref.ident.span,
-                        "`impl Trait` can only mention lifetimes bound at the fn or impl level",
-                    );
-                    err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
-                    err.emit();
+                    self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
+                        span: lifetime_ref.ident.span,
+                        param_span: self.tcx.def_span(region_def_id),
+                    });
                     return;
                 }
                 Scope::Root { .. } => break,
@@ -1379,6 +1377,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let mut late_depth = 0;
         let mut scope = self.scope;
         let mut crossed_anon_const = false;
+
         let result = loop {
             match *scope {
                 Scope::Body { s, .. } => {
@@ -1446,6 +1445,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             return;
         }
 
+        // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
+        // AST-based resolution does not care for impl-trait desugaring, which are the
+        // responsibility of lowering. This may create a mismatch between the resolution
+        // AST found (`param_def_id`) which points to HRTB, and what HIR allows.
+        // ```
+        // fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
+        // ```
+        //
+        // In such case, walk back the binders to diagnose it properly.
+        let mut scope = self.scope;
+        loop {
+            match *scope {
+                Scope::Binder {
+                    where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
+                } => {
+                    let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
+                        DefKind::TyParam => errors::LateBoundInApit::Type {
+                            span: self.tcx.hir().span(hir_id),
+                            param_span: self.tcx.def_span(param_def_id),
+                        },
+                        DefKind::ConstParam => errors::LateBoundInApit::Const {
+                            span: self.tcx.hir().span(hir_id),
+                            param_span: self.tcx.def_span(param_def_id),
+                        },
+                        kind => {
+                            bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
+                        }
+                    });
+                    self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+                    return;
+                }
+                Scope::Root { .. } => break,
+                Scope::Binder { s, .. }
+                | Scope::Body { s, .. }
+                | Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
+                    scope = s;
+                }
+            }
+        }
+
         self.tcx.sess.delay_span_bug(
             self.tcx.hir().span(hir_id),
             format!("could not resolve {param_def_id:?}"),
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 318d0d0c223..bd92ee4b550 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -435,7 +435,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
                     ..
                 }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
                 // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(OpaqueTy {
+                ItemKind::OpaqueTy(&OpaqueTy {
                     origin:
                         hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
                     in_trait,
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7dce1272f96..cb840592edd 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -875,3 +875,28 @@ pub(crate) enum ReturnTypeNotationIllegalParam {
         param_span: Span,
     },
 }
+
+#[derive(Diagnostic)]
+pub(crate) enum LateBoundInApit {
+    #[diag(hir_analysis_late_bound_type_in_apit)]
+    Type {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+    #[diag(hir_analysis_late_bound_const_in_apit)]
+    Const {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+    #[diag(hir_analysis_late_bound_lifetime_in_apit)]
+    Lifetime {
+        #[primary_span]
+        span: Span,
+        #[label]
+        param_span: Span,
+    },
+}
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 23d8da88a45..49aee6b59a2 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, CrateVariancesMap, ImplTraitInTraitData, SubstsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
 
@@ -51,20 +51,26 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
         | DefKind::Struct
         | DefKind::Union
         | DefKind::Variant
-        | DefKind::Ctor(..) => {}
+        | DefKind::Ctor(..) => {
+            // These are inferred.
+            let crate_map = tcx.crate_variances(());
+            return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
+        }
         DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
             return variance_of_opaque(tcx, item_def_id);
         }
-        _ => {
-            // Variance not relevant.
-            span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item")
+        DefKind::AssocTy => {
+            if let Some(ImplTraitInTraitData::Trait { .. }) =
+                tcx.opt_rpitit_info(item_def_id.to_def_id())
+            {
+                return variance_of_opaque(tcx, item_def_id);
+            }
         }
+        _ => {}
     }
 
-    // Everything else must be inferred.
-
-    let crate_map = tcx.crate_variances(());
-    crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
+    // Variance not relevant.
+    span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
 }
 
 #[instrument(level = "trace", skip(tcx), ret)]
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index c0c839b1f18..5f98bacaf2a 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1033,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let Ok(ok) = coerce.coerce(source, target) else {
                 return false;
             };
-            let ocx = ObligationCtxt::new_in_snapshot(self);
+            let ocx = ObligationCtxt::new(self);
             ocx.register_obligations(ok.obligations);
             ocx.select_where_possible().is_empty()
         })
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 8d621c5a42b..f5be030c1a5 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2962,7 +2962,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         self.commit_if_ok(|_| {
-            let ocx = ObligationCtxt::new_in_snapshot(self);
+            let ocx = ObligationCtxt::new(self);
             let impl_substs = self.fresh_substs_for_item(base_expr.span, impl_def_id);
             let impl_trait_ref =
                 self.tcx.impl_trait_ref(impl_def_id).unwrap().subst(self.tcx, impl_substs);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index cf6d9eda321..0ee87173a36 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -2,7 +2,7 @@ use crate::callee::{self, DeferredCallResolution};
 use crate::errors::CtorIsPrivate;
 use crate::method::{self, MethodCallee, SelfSource};
 use crate::rvalue_scopes;
-use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
+use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, RawTy};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
@@ -135,7 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         format!("{:p}", self)
     }
 
-    pub fn local_ty(&self, span: Span, nid: hir::HirId) -> LocalTy<'tcx> {
+    pub fn local_ty(&self, span: Span, nid: hir::HirId) -> Ty<'tcx> {
         self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| {
             span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid))
         })
@@ -746,7 +746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let expect_args = self
             .fudge_inference_if_ok(|| {
-                let ocx = ObligationCtxt::new_in_snapshot(self);
+                let ocx = ObligationCtxt::new(self);
 
                 // Attempt to apply a subtyping relationship between the formal
                 // return type (likely containing type variables if the function
@@ -1152,7 +1152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         if let Res::Local(hid) = res {
-            let ty = self.local_ty(span, hid).decl_ty;
+            let ty = self.local_ty(span, hid);
             let ty = self.normalize(span, ty);
             self.write_ty(hir_id, ty);
             return (ty, res);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 3c67280e0d4..dacd5559c71 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -6,8 +6,7 @@ use crate::method::MethodCallee;
 use crate::TupleArgumentsFlag::*;
 use crate::{errors, Expectation::*};
 use crate::{
-    struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy,
-    TupleArgumentsFlag,
+    struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy, TupleArgumentsFlag,
 };
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
@@ -1423,7 +1422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // See #44848.
         let ref_bindings = pat.contains_explicit_ref_binding();
 
-        let local_ty = self.local_ty(init.span, hir_id).revealed_ty;
+        let local_ty = self.local_ty(init.span, hir_id);
         if let Some(m) = ref_bindings {
             // Somewhat subtle: if we have a `ref` binding in the pattern,
             // we want to avoid introducing coercions for the RHS. This is
@@ -1453,7 +1452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
         // Determine and write the type which we'll check the pattern against.
-        let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty;
+        let decl_ty = self.local_ty(decl.span, decl.hir_id);
         self.write_ty(decl.hir_id, decl_ty);
 
         // Type check the initializer.
@@ -1799,9 +1798,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let err = self.tcx.ty_error(guar);
             self.write_ty(hir_id, err);
             self.write_ty(pat.hir_id, err);
-            let local_ty = LocalTy { decl_ty: err, revealed_ty: err };
-            self.locals.borrow_mut().insert(hir_id, local_ty);
-            self.locals.borrow_mut().insert(pat.hir_id, local_ty);
+            self.locals.borrow_mut().insert(hir_id, err);
+            self.locals.borrow_mut().insert(pat.hir_id, err);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 00a3f47b306..e035d233bf7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -163,7 +163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     return fn_sig;
                 }
                 self.probe(|_| {
-                    let ocx = ObligationCtxt::new_in_snapshot(self);
+                    let ocx = ObligationCtxt::new(self);
                     let normalized_fn_sig =
                         ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig);
                     if ocx.select_all_or_error().is_empty() {
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index d9b9b34ba58..4f45a24b216 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -1,4 +1,4 @@
-use crate::{FnCtxt, LocalTy};
+use crate::FnCtxt;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::PatKind;
@@ -48,7 +48,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
         Self { fcx, outermost_fn_param_pat: None }
     }
 
-    fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
+    fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
                 // Infer the variable's type.
@@ -56,23 +56,20 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
                     kind: TypeVariableOriginKind::TypeInference,
                     span,
                 });
-                self.fcx
-                    .locals
-                    .borrow_mut()
-                    .insert(nid, LocalTy { decl_ty: var_ty, revealed_ty: var_ty });
+                self.fcx.locals.borrow_mut().insert(nid, var_ty);
                 var_ty
             }
             Some(typ) => {
                 // Take type that the user specified.
                 self.fcx.locals.borrow_mut().insert(nid, typ);
-                typ.revealed_ty
+                typ
             }
         }
     }
 
-    /// Allocates a [LocalTy] for a declaration, which may have a type annotation. If it does have
-    /// a type annotation, then the LocalTy stored will be the resolved type. This may be found
-    /// again during type checking by querying [FnCtxt::local_ty] for the same hir_id.
+    /// Allocates a type for a declaration, which may have a type annotation. If it does have
+    /// a type annotation, then the [`Ty`] stored will be the resolved type. This may be found
+    /// again during type checking by querying [`FnCtxt::local_ty`] for the same hir_id.
     fn declare(&mut self, decl: Declaration<'tcx>) {
         let local_ty = match decl.ty {
             Some(ref ty) => {
@@ -87,7 +84,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
                     .user_provided_types_mut()
                     .insert(ty.hir_id, c_ty);
 
-                Some(LocalTy { decl_ty: o_ty.normalized, revealed_ty: o_ty.normalized })
+                Some(o_ty.normalized)
             }
             None => None,
         };
@@ -96,7 +93,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
         debug!(
             "local variable {:?} is assigned type {}",
             decl.pat,
-            self.fcx.ty_to_string(self.fcx.locals.borrow().get(&decl.hir_id).unwrap().decl_ty)
+            self.fcx.ty_to_string(*self.fcx.locals.borrow().get(&decl.hir_id).unwrap())
         );
     }
 }
@@ -151,7 +148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
             debug!(
                 "pattern binding {} is assigned to {} with type {:?}",
                 ident,
-                self.fcx.ty_to_string(self.fcx.locals.borrow().get(&p.hir_id).unwrap().decl_ty),
+                self.fcx.ty_to_string(*self.fcx.locals.borrow().get(&p.hir_id).unwrap()),
                 var_ty
             );
         }
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index c193d761804..05e5db9f0f3 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -30,7 +30,7 @@ pub struct Inherited<'tcx> {
 
     pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>,
 
-    pub(super) locals: RefCell<HirIdMap<super::LocalTy<'tcx>>>,
+    pub(super) locals: RefCell<HirIdMap<Ty<'tcx>>>,
 
     pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
 
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 362c07431e0..e58efc9d1e3 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -81,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // Try to display a sensible error with as much information as possible.
-        let skeleton_string = |ty: Ty<'tcx>, sk| match sk {
+        let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk {
             Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
             Ok(SizeSkeleton::Known(size)) => {
                 if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
@@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             Err(LayoutError::Unknown(bad)) => {
-                if bad == ty {
+                if *bad == ty {
                     "this type does not have a fixed size".to_owned()
                 } else {
                     format!("size can vary because of {bad}")
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 7a897778ff7..6f7288ed7e5 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -89,13 +89,6 @@ macro_rules! type_error_struct {
     })
 }
 
-/// The type of a local binding, including the revealed type for anon types.
-#[derive(Copy, Clone, Debug)]
-pub struct LocalTy<'tcx> {
-    decl_ty: Ty<'tcx>,
-    revealed_ty: Ty<'tcx>,
-}
-
 /// If this `DefId` is a "primary tables entry", returns
 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
 ///
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 5af955d3134..9c989d3b4b2 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -594,7 +594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
 
-        let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
+        let local_ty = self.local_ty(pat.span, pat.hir_id);
         let eq_ty = match bm {
             ty::BindByReference(mutbl) => {
                 // If the binding is like `ref x | ref mut x`,
@@ -635,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ty: Ty<'tcx>,
         ti: TopInfo<'tcx>,
     ) {
-        let var_ty = self.local_ty(span, var_id).decl_ty;
+        let var_ty = self.local_ty(span, var_id);
         if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
             let hir = self.tcx.hir();
             let var_ty = self.resolve_vars_with_obligations(var_ty);
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 29abe921bbd..0cf3a4e877a 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -348,7 +348,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
 
     fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
         intravisit::walk_local(self, l);
-        let var_ty = self.fcx.local_ty(l.span, l.hir_id).decl_ty;
+        let var_ty = self.fcx.local_ty(l.span, l.hir_id);
         let var_ty = self.resolve(var_ty, &l.span);
         self.write_ty_to_typeck_results(l.hir_id, var_ty);
     }
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 1f0bf4f9887..f1a187d2677 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -79,7 +79,6 @@ impl<'tcx> InferCtxt<'tcx> {
             reported_closure_mismatch: self.reported_closure_mismatch.clone(),
             tainted_by_errors: self.tainted_by_errors.clone(),
             err_count_on_creation: self.err_count_on_creation,
-            in_snapshot: self.in_snapshot.clone(),
             universe: self.universe.clone(),
             intercrate: self.intercrate,
             next_trait_solver: self.next_trait_solver,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 7dbc18908d5..f1f5ac81fb7 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -6,6 +6,7 @@ pub use self::RegionVariableOrigin::*;
 pub use self::SubregionOrigin::*;
 pub use self::ValuePairs::*;
 pub use combine::ObligationEmittingRelation;
+use rustc_data_structures::undo_log::UndoLogs;
 
 use self::opaque_types::OpaqueTypeStorage;
 pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
@@ -297,9 +298,6 @@ pub struct InferCtxt<'tcx> {
     // FIXME(matthewjasper) Merge into `tainted_by_errors`
     err_count_on_creation: usize,
 
-    /// This flag is true while there is an active snapshot.
-    in_snapshot: Cell<bool>,
-
     /// What is the innermost universe we have created? Starts out as
     /// `UniverseIndex::root()` but grows from there as we enter
     /// universal quantifiers.
@@ -643,7 +641,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             reported_closure_mismatch: Default::default(),
             tainted_by_errors: Cell::new(None),
             err_count_on_creation: tcx.sess.err_count(),
-            in_snapshot: Cell::new(false),
             universe: Cell::new(ty::UniverseIndex::ROOT),
             intercrate,
             next_trait_solver,
@@ -679,7 +676,6 @@ pub struct CombinedSnapshot<'tcx> {
     undo_snapshot: Snapshot<'tcx>,
     region_constraints_snapshot: RegionSnapshot,
     universe: ty::UniverseIndex,
-    was_in_snapshot: bool,
 }
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -702,10 +698,6 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
-    pub fn is_in_snapshot(&self) -> bool {
-        self.in_snapshot.get()
-    }
-
     pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
@@ -766,31 +758,30 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
+    pub fn in_snapshot(&self) -> bool {
+        UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log)
+    }
+
+    pub fn num_open_snapshots(&self) -> usize {
+        UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log)
+    }
+
     fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
         debug!("start_snapshot()");
 
-        let in_snapshot = self.in_snapshot.replace(true);
-
         let mut inner = self.inner.borrow_mut();
 
         CombinedSnapshot {
             undo_snapshot: inner.undo_log.start_snapshot(),
             region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
             universe: self.universe(),
-            was_in_snapshot: in_snapshot,
         }
     }
 
     #[instrument(skip(self, snapshot), level = "debug")]
     fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) {
-        let CombinedSnapshot {
-            undo_snapshot,
-            region_constraints_snapshot,
-            universe,
-            was_in_snapshot,
-        } = snapshot;
-
-        self.in_snapshot.set(was_in_snapshot);
+        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot;
+
         self.universe.set(universe);
 
         let mut inner = self.inner.borrow_mut();
@@ -800,14 +791,8 @@ impl<'tcx> InferCtxt<'tcx> {
 
     #[instrument(skip(self, snapshot), level = "debug")]
     fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) {
-        let CombinedSnapshot {
-            undo_snapshot,
-            region_constraints_snapshot: _,
-            universe: _,
-            was_in_snapshot,
-        } = snapshot;
-
-        self.in_snapshot.set(was_in_snapshot);
+        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } =
+            snapshot;
 
         self.inner.borrow_mut().commit(undo_snapshot);
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 9c20c814b69..73df6d03f86 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -125,10 +125,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// right before lexical region resolution.
     #[instrument(level = "debug", skip(self, outlives_env))]
     pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
-        assert!(
-            !self.in_snapshot.get(),
-            "cannot process registered region obligations in a snapshot"
-        );
+        assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
 
         let my_region_obligations = self.take_registered_region_obligations();
 
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 847b267b614..66389cf5995 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -80,14 +80,14 @@ pub struct Elaborator<'tcx, O> {
 pub trait Elaboratable<'tcx> {
     fn predicate(&self) -> ty::Predicate<'tcx>;
 
-    // Makes a new `Self` but with a different predicate.
-    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self;
+    // Makes a new `Self` but with a different clause that comes from elaboration.
+    fn child(&self, clause: ty::Clause<'tcx>) -> Self;
 
-    // Makes a new `Self` but with a different predicate and a different cause
-    // code (if `Self` has one).
+    // Makes a new `Self` but with a different clause and a different cause
+    // code (if `Self` has one, such as [`PredicateObligation`]).
     fn child_with_derived_cause(
         &self,
-        predicate: ty::Predicate<'tcx>,
+        clause: ty::Clause<'tcx>,
         span: Span,
         parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         index: usize,
@@ -99,18 +99,18 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> {
         self.predicate
     }
 
-    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
+    fn child(&self, clause: ty::Clause<'tcx>) -> Self {
         Obligation {
             cause: self.cause.clone(),
             param_env: self.param_env,
             recursion_depth: 0,
-            predicate,
+            predicate: clause.as_predicate(),
         }
     }
 
     fn child_with_derived_cause(
         &self,
-        predicate: ty::Predicate<'tcx>,
+        clause: ty::Clause<'tcx>,
         span: Span,
         parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         index: usize,
@@ -123,7 +123,12 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> {
                 span,
             }))
         });
-        Obligation { cause, param_env: self.param_env, recursion_depth: 0, predicate }
+        Obligation {
+            cause,
+            param_env: self.param_env,
+            recursion_depth: 0,
+            predicate: clause.as_predicate(),
+        }
     }
 }
 
@@ -132,18 +137,18 @@ impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> {
         *self
     }
 
-    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
-        predicate
+    fn child(&self, clause: ty::Clause<'tcx>) -> Self {
+        clause.as_predicate()
     }
 
     fn child_with_derived_cause(
         &self,
-        predicate: ty::Predicate<'tcx>,
+        clause: ty::Clause<'tcx>,
         _span: Span,
         _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         _index: usize,
     ) -> Self {
-        predicate
+        clause.as_predicate()
     }
 }
 
@@ -152,18 +157,18 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
         self.0
     }
 
-    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
-        (predicate, self.1)
+    fn child(&self, clause: ty::Clause<'tcx>) -> Self {
+        (clause.as_predicate(), self.1)
     }
 
     fn child_with_derived_cause(
         &self,
-        predicate: ty::Predicate<'tcx>,
+        clause: ty::Clause<'tcx>,
         _span: Span,
         _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         _index: usize,
     ) -> Self {
-        (predicate, self.1)
+        (clause.as_predicate(), self.1)
     }
 }
 
@@ -172,18 +177,18 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) {
         self.0.as_predicate()
     }
 
-    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
-        (predicate.expect_clause(), self.1)
+    fn child(&self, clause: ty::Clause<'tcx>) -> Self {
+        (clause, self.1)
     }
 
     fn child_with_derived_cause(
         &self,
-        predicate: ty::Predicate<'tcx>,
+        clause: ty::Clause<'tcx>,
         _span: Span,
         _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         _index: usize,
     ) -> Self {
-        (predicate.expect_clause(), self.1)
+        (clause, self.1)
     }
 }
 
@@ -192,18 +197,18 @@ impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
         self.as_predicate()
     }
 
-    fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
-        predicate.expect_clause()
+    fn child(&self, clause: ty::Clause<'tcx>) -> Self {
+        clause
     }
 
     fn child_with_derived_cause(
         &self,
-        predicate: ty::Predicate<'tcx>,
+        clause: ty::Clause<'tcx>,
         _span: Span,
         _parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
         _index: usize,
     ) -> Self {
-        predicate.expect_clause()
+        clause
     }
 }
 
@@ -252,14 +257,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                 };
 
                 let obligations =
-                    predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {
+                    predicates.predicates.iter().enumerate().map(|(index, &(mut clause, span))| {
                         // when parent predicate is non-const, elaborate it to non-const predicates.
                         if data.constness == ty::BoundConstness::NotConst {
-                            pred = pred.without_const(tcx);
+                            clause = clause.without_const(tcx);
                         }
                         elaboratable.child_with_derived_cause(
-                            pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref))
-                                .as_predicate(),
+                            clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
                             span,
                             bound_predicate.rebind(data),
                             index,
@@ -333,17 +337,15 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                                 if r.is_late_bound() {
                                     None
                                 } else {
-                                    Some(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
-                                        ty::OutlivesPredicate(r, r_min),
+                                    Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+                                        r, r_min,
                                     )))
                                 }
                             }
 
                             Component::Param(p) => {
                                 let ty = tcx.mk_ty_param(p.index, p.name);
-                                Some(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
-                                    ty::OutlivesPredicate(ty, r_min),
-                                )))
+                                Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
                             }
 
                             Component::UnresolvedInferenceVariable(_) => None,
@@ -351,8 +353,9 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                             Component::Alias(alias_ty) => {
                                 // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
                                 // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
-                                Some(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
-                                    ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min),
+                                Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
+                                    alias_ty.to_ty(tcx),
+                                    r_min,
                                 )))
                             }
 
@@ -362,10 +365,9 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                                 None
                             }
                         })
-                        .map(|predicate_kind| {
-                            bound_predicate.rebind(predicate_kind).to_predicate(tcx)
-                        })
-                        .map(|predicate| elaboratable.child(predicate)),
+                        .map(|clause| {
+                            elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx))
+                        }),
                 );
             }
             ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 6054b48b0b5..0f5dba1df14 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -8,6 +8,7 @@ use rustc_session::config::rustc_optgroups;
 use rustc_session::config::DebugInfo;
 use rustc_session::config::Input;
 use rustc_session::config::InstrumentXRay;
+use rustc_session::config::LinkSelfContained;
 use rustc_session::config::TraitSolver;
 use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
 use rustc_session::config::{
@@ -579,7 +580,7 @@ fn test_codegen_options_tracking_hash() {
     untracked!(incremental, Some(String::from("abc")));
     // `link_arg` is omitted because it just forwards to `link_args`.
     untracked!(link_args, vec![String::from("abc"), String::from("def")]);
-    untracked!(link_self_contained, Some(true));
+    untracked!(link_self_contained, LinkSelfContained::on());
     untracked!(linker, Some(PathBuf::from("linker")));
     untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc));
     untracked!(no_stack_check, true);
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 53aad6d8b31..3a177038ca8 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -665,9 +665,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
 
 impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
-            && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
-        {
+        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
             return;
         }
         let (def, ty) = match item.kind {
@@ -786,9 +784,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
-            && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
-        {
+        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
             return;
         }
 
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index 4cea6169dc3..467f53d445c 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -194,7 +194,7 @@ fn is_single_call_in_arm<'tcx>(
     arg: &'tcx Expr<'_>,
     drop_expr: &'tcx Expr<'_>,
 ) -> bool {
-    if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
+    if arg.can_have_side_effects() {
         let parent_node = cx.tcx.hir().find_parent(drop_expr.hir_id);
         if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
             return body.hir_id == drop_expr.hir_id;
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index cbb4458d1d4..ef82a6c17ee 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4264,6 +4264,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,compile_fail
+    /// # #![feature(type_privacy_lints)]
     /// # #![allow(unused)]
     /// # #![allow(private_in_public)]
     /// #![deny(private_interfaces)]
@@ -4288,6 +4289,7 @@ declare_lint! {
     pub PRIVATE_INTERFACES,
     Allow,
     "private type in primary interface of an item",
+    @feature_gate = sym::type_privacy_lints;
 }
 
 declare_lint! {
@@ -4298,6 +4300,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,compile_fail
+    /// # #![feature(type_privacy_lints)]
     /// # #![allow(private_in_public)]
     /// # #![allow(unused)]
     /// #![deny(private_bounds)]
@@ -4317,7 +4320,8 @@ declare_lint! {
     /// the item actually provides.
     pub PRIVATE_BOUNDS,
     Allow,
-    "private type in secondary interface of an item"
+    "private type in secondary interface of an item",
+    @feature_gate = sym::type_privacy_lints;
 }
 
 declare_lint! {
@@ -4327,6 +4331,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,compile_fail
+    /// # #![feature(type_privacy_lints)]
     /// # #![allow(unused)]
     /// #![deny(unnameable_types)]
     /// mod m {
@@ -4345,5 +4350,6 @@ declare_lint! {
     /// you can name the type `T` as well, this lint attempts to enforce this rule.
     pub UNNAMEABLE_TYPES,
     Allow,
-    "effective visibility of a type is larger than the area in which it can be named"
+    "effective visibility of a type is larger than the area in which it can be named",
+    @feature_gate = sym::type_privacy_lints;
 }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index ea04899ab68..553fe6cf087 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -7,7 +7,12 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsARM.h"
+#include "llvm/IR/LLVMRemarkStreamer.h"
 #include "llvm/IR/Mangler.h"
+#include "llvm/Remarks/RemarkStreamer.h"
+#include "llvm/Remarks/RemarkSerializer.h"
+#include "llvm/Remarks/RemarkFormat.h"
+#include "llvm/Support/ToolOutputFile.h"
 #if LLVM_VERSION_GE(16, 0)
 #include "llvm/Support/ModRef.h"
 #endif
@@ -1855,23 +1860,44 @@ using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
 // When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
 // the RemarkPasses array specifies individual passes for which remarks will be
 // enabled.
+//
+// If RemarkFilePath is not NULL, optimization remarks will be streamed directly into this file,
+// bypassing the diagnostics handler.
 extern "C" void LLVMRustContextConfigureDiagnosticHandler(
     LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
     void *DiagnosticHandlerContext, bool RemarkAllPasses,
-    const char * const * RemarkPasses, size_t RemarkPassesLen) {
+    const char * const * RemarkPasses, size_t RemarkPassesLen,
+    const char * RemarkFilePath
+) {
 
   class RustDiagnosticHandler final : public DiagnosticHandler {
   public:
-    RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
-                          void *DiagnosticHandlerContext,
-                          bool RemarkAllPasses,
-                          std::vector<std::string> RemarkPasses)
+    RustDiagnosticHandler(
+      LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
+      void *DiagnosticHandlerContext,
+      bool RemarkAllPasses,
+      std::vector<std::string> RemarkPasses,
+      std::unique_ptr<ToolOutputFile> RemarksFile,
+      std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer,
+      std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer
+    )
         : DiagnosticHandlerCallback(DiagnosticHandlerCallback),
           DiagnosticHandlerContext(DiagnosticHandlerContext),
           RemarkAllPasses(RemarkAllPasses),
-          RemarkPasses(RemarkPasses) {}
+          RemarkPasses(std::move(RemarkPasses)),
+          RemarksFile(std::move(RemarksFile)),
+          RemarkStreamer(std::move(RemarkStreamer)),
+          LlvmRemarkStreamer(std::move(LlvmRemarkStreamer)) {}
 
     virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
+      if (this->LlvmRemarkStreamer) {
+        if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) {
+          if (OptDiagBase->isEnabled()) {
+            this->LlvmRemarkStreamer->emit(*OptDiagBase);
+            return true;
+          }
+        }
+      }
       if (DiagnosticHandlerCallback) {
         DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
         return true;
@@ -1912,14 +1938,64 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
 
     bool RemarkAllPasses = false;
     std::vector<std::string> RemarkPasses;
+
+    // Since LlvmRemarkStreamer contains a pointer to RemarkStreamer, the ordering of the three
+    // members below is important.
+    std::unique_ptr<ToolOutputFile> RemarksFile;
+    std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer;
+    std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer;
   };
 
   std::vector<std::string> Passes;
   for (size_t I = 0; I != RemarkPassesLen; ++I)
+  {
     Passes.push_back(RemarkPasses[I]);
+  }
+
+  // We need to hold onto both the streamers and the opened file
+  std::unique_ptr<ToolOutputFile> RemarkFile;
+  std::unique_ptr<llvm::remarks::RemarkStreamer> RemarkStreamer;
+  std::unique_ptr<LLVMRemarkStreamer> LlvmRemarkStreamer;
+
+  if (RemarkFilePath != nullptr) {
+    std::error_code EC;
+    RemarkFile = std::make_unique<ToolOutputFile>(
+      RemarkFilePath,
+      EC,
+      llvm::sys::fs::OF_TextWithCRLF
+    );
+    if (EC) {
+      std::string Error = std::string("Cannot create remark file: ") +
+              toString(errorCodeToError(EC));
+      report_fatal_error(Twine(Error));
+    }
+
+    // Do not delete the file after we gather remarks
+    RemarkFile->keep();
+
+    auto RemarkSerializer = remarks::createRemarkSerializer(
+      llvm::remarks::Format::YAML,
+      remarks::SerializerMode::Separate,
+      RemarkFile->os()
+    );
+    if (Error E = RemarkSerializer.takeError())
+    {
+      std::string Error = std::string("Cannot create remark serializer: ") + toString(std::move(E));
+      report_fatal_error(Twine(Error));
+    }
+    RemarkStreamer = std::make_unique<llvm::remarks::RemarkStreamer>(std::move(*RemarkSerializer));
+    LlvmRemarkStreamer = std::make_unique<LLVMRemarkStreamer>(*RemarkStreamer);
+  }
 
   unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
-      DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
+    DiagnosticHandlerCallback,
+    DiagnosticHandlerContext,
+    RemarkAllPasses,
+    Passes,
+    std::move(RemarkFile),
+    std::move(RemarkStreamer),
+    std::move(LlvmRemarkStreamer)
+  ));
 }
 
 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml
index 7f955b0a750..aa6e46cd8de 100644
--- a/compiler/rustc_log/Cargo.toml
+++ b/compiler/rustc_log/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 tracing = "0.1.28"
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 tracing-tree = "0.2.0"
-tracing-core = "0.1.28"
+tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
 
 [dev-dependencies]
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index 1f1201b0035..16c4a850012 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -8,6 +8,7 @@ proc-macro = true
 
 [dependencies]
 synstructure = "0.13.0"
-syn = { version = "2", features = ["full"] }
+# FIXME(Nilstrieb): Updating this causes changes in the diagnostics output.
+syn = { version = "=2.0.8", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 13b3dac85d1..cc58d51befd 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -25,6 +25,9 @@ metadata_conflicting_alloc_error_handler =
 metadata_conflicting_global_alloc =
     the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}
 
+metadata_consider_adding_std =
+    consider adding the standard library to the sysroot with `x build library --target {$locator_triple}`
+
 metadata_consider_building_std =
     consider building the standard library from source with `cargo build -Zbuild-std`
 
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index fca06c0f47c..b6c82376f4e 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -646,12 +646,18 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
             } else {
                 diag.note(fluent::metadata_target_no_std_support);
             }
-            // NOTE: this suggests using rustup, even though the user may not have it installed.
-            // That's because they could choose to install it; or this may give them a hint which
-            // target they need to install from their distro.
+
             if self.missing_core {
-                diag.help(fluent::metadata_consider_downloading_target);
+                if env!("CFG_RELEASE_CHANNEL") == "dev" {
+                    diag.help(fluent::metadata_consider_adding_std);
+                } else {
+                    // NOTE: this suggests using rustup, even though the user may not have it installed.
+                    // That's because they could choose to install it; or this may give them a hint which
+                    // target they need to install from their distro.
+                    diag.help(fluent::metadata_consider_downloading_target);
+                }
             }
+
             // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
             // NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
             // If it's not a dummy, that means someone added `extern crate std` explicitly and
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index b80019bf155..efe49d687c9 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1447,6 +1447,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     .is_type_alias_impl_trait
                     .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
             }
+            if let DefKind::ImplTraitPlaceholder = def_kind {
+                self.encode_explicit_item_bounds(def_id);
+            }
             if tcx.impl_method_has_trait_impl_trait_tys(def_id)
                 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
             {
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 7c56af1da41..07ab3ba4e8a 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 [dependencies]
 bitflags = "1.2.1"
-chalk-ir = "0.87.0"
+chalk-ir = "0.92.0"
 derive_more = "0.99.17"
 either = "1.5.0"
 gsgdt = "0.1.2"
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index f45cf788dd9..5baeb1ee0cf 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -4,6 +4,7 @@
 use crate::ty::{TyCtxt, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def::DefKind;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
@@ -148,13 +149,12 @@ impl EffectiveVisibilities {
         };
     }
 
-    pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
+    pub fn check_invariants(&self, tcx: TyCtxt<'_>) {
         if !cfg!(debug_assertions) {
             return;
         }
         for (&def_id, ev) in &self.map {
             // More direct visibility levels can never go farther than less direct ones,
-            // neither of effective visibilities can go farther than nominal visibility,
             // and all effective visibilities are larger or equal than private visibility.
             let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id));
             let span = tcx.def_span(def_id.to_def_id());
@@ -175,17 +175,20 @@ impl EffectiveVisibilities {
                     ev.reachable_through_impl_trait
                 );
             }
-            let nominal_vis = tcx.visibility(def_id);
-            // FIXME: `rustc_privacy` is not yet updated for the new logic and can set
-            // effective visibilities that are larger than the nominal one.
-            if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early {
-                span_bug!(
-                    span,
-                    "{:?}: reachable_through_impl_trait {:?} > nominal {:?}",
-                    def_id,
-                    ev.reachable_through_impl_trait,
-                    nominal_vis
-                );
+            // All effective visibilities except `reachable_through_impl_trait` are limited to
+            // nominal visibility. For some items nominal visibility doesn't make sense so we
+            // don't check this condition for them.
+            if !matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
+                let nominal_vis = tcx.visibility(def_id);
+                if !nominal_vis.is_at_least(ev.reachable, tcx) {
+                    span_bug!(
+                        span,
+                        "{:?}: reachable {:?} > nominal {:?}",
+                        def_id,
+                        ev.reachable,
+                        nominal_vis
+                    );
+                }
             }
         }
     }
@@ -212,7 +215,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
     pub fn update(
         &mut self,
         id: Id,
-        nominal_vis: Option<Visibility>,
+        max_vis: Option<Visibility>,
         lazy_private_vis: impl FnOnce() -> Visibility,
         inherited_effective_vis: EffectiveVisibility,
         level: Level,
@@ -236,8 +239,8 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
                 if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
                     && level != l)
                 {
-                    calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
-                        nominal_vis
+                    calculated_effective_vis = if let Some(max_vis) = max_vis && !max_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
+                        max_vis
                     } else {
                         inherited_effective_vis_at_level
                     }
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index ae32a54be3d..9c97431f361 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -95,11 +95,15 @@ impl<'tcx> TyCtxt<'tcx> {
                     // used generic parameters is a bug of evaluation, so checking for it
                     // here does feel somewhat sensible.
                     if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
-                        assert!(matches!(
-                            self.def_kind(ct.def),
-                            DefKind::InlineConst | DefKind::AnonConst
-                        ));
-                        let mir_body = self.mir_for_ctfe(ct.def);
+                        let def_kind = self.def_kind(instance.def_id());
+                        assert!(
+                            matches!(
+                                def_kind,
+                                DefKind::InlineConst | DefKind::AnonConst | DefKind::AssocConst
+                            ),
+                            "{cid:?} is {def_kind:?}",
+                        );
+                        let mir_body = self.mir_for_ctfe(instance.def_id());
                         if mir_body.is_polymorphic {
                             let Some(local_def_id) = ct.def.as_local() else { return };
                             self.struct_span_lint_hir(
@@ -239,15 +243,3 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
         self.eval_to_allocation_raw(param_env.and(gid))
     }
 }
-
-impl<'tcx> TyCtxt<'tcx> {
-    /// Destructure a mir constant ADT or array into its variant index and its field values.
-    /// Panics if the destructuring fails, use `try_destructure_mir_constant` for fallible version.
-    pub fn destructure_mir_constant(
-        self,
-        param_env: ty::ParamEnv<'tcx>,
-        constant: mir::ConstantKind<'tcx>,
-    ) -> mir::DestructuredConstant<'tcx> {
-        self.try_destructure_mir_constant(param_env.and(constant)).unwrap()
-    }
-}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 669c609d995..ad1c93c31e9 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2581,10 +2581,9 @@ pub struct UnevaluatedConst<'tcx> {
 }
 
 impl<'tcx> UnevaluatedConst<'tcx> {
-    // FIXME: probably should get rid of this method. It's also wrong to
-    // shrink and then later expand a promoted.
     #[inline]
     pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
+        assert_eq!(self.promoted, None);
         ty::UnevaluatedConst { def: self.def, substs: self.substs }
     }
 }
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index f1ae4942b7b..e8f4fca147b 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -71,8 +71,8 @@ impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
     type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
 }
 
-impl<T> EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> {
-    type Result = [u8; size_of::<Result<&'static (), ty::layout::FnAbiError<'static>>>()];
+impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
+    type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
 }
 
 impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> {
@@ -96,15 +96,17 @@ impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
     type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
 }
 
-impl EraseType for Result<bool, ty::layout::LayoutError<'_>> {
-    type Result = [u8; size_of::<Result<bool, ty::layout::LayoutError<'static>>>()];
+impl EraseType for Result<bool, &ty::layout::LayoutError<'_>> {
+    type Result = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()];
 }
 
-impl EraseType for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, ty::layout::LayoutError<'_>> {
+impl EraseType
+    for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>>
+{
     type Result = [u8; size_of::<
         Result<
             rustc_target::abi::TyAndLayout<'static, Ty<'static>>,
-            ty::layout::LayoutError<'static>,
+            &'static ty::layout::LayoutError<'static>,
         >,
     >()];
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 15215552f52..c12587845e5 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1383,7 +1383,7 @@ rustc_queries! {
     /// executes in "reveal all" mode, and will normalize the input type.
     query layout_of(
         key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
-    ) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> {
+    ) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
         depth_limit
         desc { "computing layout of `{}`", key.value }
     }
@@ -1394,7 +1394,7 @@ rustc_queries! {
     /// instead, where the instance is an `InstanceDef::Virtual`.
     query fn_abi_of_fn_ptr(
         key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
-    ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+    ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
         desc { "computing call ABI of `{}` function pointers", key.value.0 }
     }
 
@@ -1405,7 +1405,7 @@ rustc_queries! {
     /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
     query fn_abi_of_instance(
         key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
-    ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+    ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
         desc { "computing call ABI of `{}`", key.value.0 }
     }
 
@@ -2164,7 +2164,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
+    query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
         desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
     }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index c1d6856d33c..9485106e95e 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -310,7 +310,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
         ty: Ty<'tcx>,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-    ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
+    ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
         debug_assert!(!ty.has_non_region_infer());
 
         // First try computing a static layout.
@@ -353,13 +353,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
                             let size = s
                                 .bytes()
                                 .checked_mul(c)
-                                .ok_or_else(|| LayoutError::SizeOverflow(ty))?;
+                                .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
                             return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
                         }
                         let len = tcx.expand_abstract_consts(len);
                         let prev = ty::Const::from_target_usize(tcx, s.bytes());
                         let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
-                            return Err(LayoutError::SizeOverflow(ty));
+                            return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
                         };
                         Ok(SizeSkeleton::Generic(gen_size))
                     }
@@ -367,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     SizeSkeleton::Generic(g) => {
                         let len = tcx.expand_abstract_consts(len);
                         let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
-                            return Err(LayoutError::SizeOverflow(ty));
+                            return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
                         };
                         Ok(SizeSkeleton::Generic(gen_size))
                     }
@@ -672,7 +672,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
 
         MaybeResult::from(
             tcx.layout_of(self.param_env().and(ty))
-                .map_err(|err| self.handle_layout_err(err, span, ty)),
+                .map_err(|err| self.handle_layout_err(*err, span, ty)),
         )
     }
 }
@@ -680,16 +680,21 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
 impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
 
 impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
-    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
 
     #[inline]
-    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
-        err
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        _: Span,
+        _: Ty<'tcx>,
+    ) -> &'tcx LayoutError<'tcx> {
+        self.tcx.arena.alloc(err)
     }
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
-    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
 
     #[inline]
     fn layout_tcx_at_span(&self) -> Span {
@@ -697,8 +702,13 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
     }
 
     #[inline]
-    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
-        err
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        _: Span,
+        _: Ty<'tcx>,
+    ) -> &'tcx LayoutError<'tcx> {
+        self.tcx.arena.alloc(err)
     }
 }
 
@@ -1250,18 +1260,6 @@ pub enum FnAbiError<'tcx> {
     AdjustForForeignAbi(call::AdjustForForeignAbiError),
 }
 
-impl<'tcx> From<LayoutError<'tcx>> for FnAbiError<'tcx> {
-    fn from(err: LayoutError<'tcx>) -> Self {
-        Self::Layout(err)
-    }
-}
-
-impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
-    fn from(err: call::AdjustForForeignAbiError) -> Self {
-        Self::AdjustForForeignAbi(err)
-    }
-}
-
 impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> {
     fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
         match self {
@@ -1321,7 +1319,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
         let tcx = self.tcx().at(span);
 
         MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
-            |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+            |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
         ))
     }
 
@@ -1348,7 +1346,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
                 // However, we don't do this early in order to avoid calling
                 // `def_span` unconditionally (which may have a perf penalty).
                 let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
-                self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
+                self.handle_fn_abi_err(
+                    *err,
+                    span,
+                    FnAbiRequest::OfInstance { instance, extra_args },
+                )
             }),
         )
     }
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index a00c77ccbcd..8758cd04d67 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -106,9 +106,12 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::F
     }
 }
 
-impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, ty::layout::LayoutError<'_>> {
+impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, &'_ ty::layout::LayoutError<'_>> {
     fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo<DepKind>]) -> Self {
-        Err(ty::layout::LayoutError::Cycle)
+        // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
+        // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
+        // tcx.arena.alloc is pretty much equal to leaking).
+        Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle)))
     }
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 900d438f8d5..d43446bc5b2 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -43,7 +43,6 @@ pub mod impls;
 pub mod move_paths;
 pub mod rustc_peek;
 pub mod storage;
-pub mod un_derefer;
 pub mod value_analysis;
 
 fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 2b37b55d278..dc7e9ab3ce6 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -1,11 +1,10 @@
-use crate::move_paths::FxHashMap;
-use crate::un_derefer::UnDerefer;
 use rustc_index::IndexVec;
 use rustc_middle::mir::tcx::RvalueInitializationState;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 use smallvec::{smallvec, SmallVec};
 
+use std::iter;
 use std::mem;
 
 use super::abs_domain::Lift;
@@ -21,7 +20,6 @@ struct MoveDataBuilder<'a, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
     data: MoveData<'tcx>,
     errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
-    un_derefer: UnDerefer<'tcx>,
 }
 
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
@@ -35,25 +33,29 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
             tcx,
             param_env,
             errors: Vec::new(),
-            un_derefer: UnDerefer { tcx: tcx, derefer_sidetable: Default::default() },
             data: MoveData {
                 moves: IndexVec::new(),
                 loc_map: LocationMap::new(body),
                 rev_lookup: MovePathLookup {
                     locals: body
                         .local_decls
-                        .indices()
-                        .map(|i| {
-                            Self::new_move_path(
-                                &mut move_paths,
-                                &mut path_map,
-                                &mut init_path_map,
-                                None,
-                                Place::from(i),
+                        .iter_enumerated()
+                        .filter(|(_, l)| !l.is_deref_temp())
+                        .map(|(i, _)| {
+                            (
+                                i,
+                                Self::new_move_path(
+                                    &mut move_paths,
+                                    &mut path_map,
+                                    &mut init_path_map,
+                                    None,
+                                    Place::from(i),
+                                ),
                             )
                         })
                         .collect(),
                     projections: Default::default(),
+                    derefer_sidetable: Default::default(),
                 },
                 move_paths,
                 path_map,
@@ -98,13 +100,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     ///
     /// Maybe we should have separate "borrowck" and "moveck" modes.
     fn move_path_for(&mut self, place: Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
-        if let Some(new_place) = self.builder.un_derefer.derefer(place.as_ref(), self.builder.body)
-        {
-            return self.move_path_for(new_place);
-        }
+        let deref_chain = self.builder.data.rev_lookup.deref_chain(place.as_ref());
 
         debug!("lookup({:?})", place);
-        let mut base = self.builder.data.rev_lookup.locals[place.local];
+        let mut base =
+            self.builder.data.rev_lookup.find_local(deref_chain.first().unwrap_or(&place).local);
 
         // The move path index of the first union that we find. Once this is
         // some we stop creating child move paths, since moves from unions
@@ -113,51 +113,55 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         // from `*(u.f: &_)` isn't allowed.
         let mut union_path = None;
 
-        for (place_ref, elem) in place.as_ref().iter_projections() {
-            let body = self.builder.body;
-            let tcx = self.builder.tcx;
-            let place_ty = place_ref.ty(body, tcx).ty;
-
-            match place_ty.kind() {
-                ty::Ref(..) | ty::RawPtr(..) => {
-                    return Err(MoveError::cannot_move_out_of(
-                        self.loc,
-                        BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) },
-                    ));
-                }
-                ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
-                    return Err(MoveError::cannot_move_out_of(
-                        self.loc,
-                        InteriorOfTypeWithDestructor { container_ty: place_ty },
-                    ));
-                }
-                ty::Adt(adt, _) if adt.is_union() => {
-                    union_path.get_or_insert(base);
-                }
-                ty::Slice(_) => {
-                    return Err(MoveError::cannot_move_out_of(
-                        self.loc,
-                        InteriorOfSliceOrArray {
-                            ty: place_ty,
-                            is_index: matches!(elem, ProjectionElem::Index(..)),
-                        },
-                    ));
-                }
-
-                ty::Array(..) => {
-                    if let ProjectionElem::Index(..) = elem {
+        for place in deref_chain.into_iter().chain(iter::once(place)) {
+            for (place_ref, elem) in place.as_ref().iter_projections() {
+                let body = self.builder.body;
+                let tcx = self.builder.tcx;
+                let place_ty = place_ref.ty(body, tcx).ty;
+                match place_ty.kind() {
+                    ty::Ref(..) | ty::RawPtr(..) => {
                         return Err(MoveError::cannot_move_out_of(
                             self.loc,
-                            InteriorOfSliceOrArray { ty: place_ty, is_index: true },
+                            BorrowedContent {
+                                target_place: place_ref.project_deeper(&[elem], tcx),
+                            },
+                        ));
+                    }
+                    ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
+                        return Err(MoveError::cannot_move_out_of(
+                            self.loc,
+                            InteriorOfTypeWithDestructor { container_ty: place_ty },
+                        ));
+                    }
+                    ty::Adt(adt, _) if adt.is_union() => {
+                        union_path.get_or_insert(base);
+                    }
+                    ty::Slice(_) => {
+                        return Err(MoveError::cannot_move_out_of(
+                            self.loc,
+                            InteriorOfSliceOrArray {
+                                ty: place_ty,
+                                is_index: matches!(elem, ProjectionElem::Index(..)),
+                            },
                         ));
                     }
-                }
 
-                _ => {}
-            };
+                    ty::Array(..) => {
+                        if let ProjectionElem::Index(..) = elem {
+                            return Err(MoveError::cannot_move_out_of(
+                                self.loc,
+                                InteriorOfSliceOrArray { ty: place_ty, is_index: true },
+                            ));
+                        }
+                    }
+
+                    _ => {}
+                };
 
-            if union_path.is_none() {
-                base = self.add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx));
+                if union_path.is_none() {
+                    base = self
+                        .add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx));
+                }
             }
         }
 
@@ -198,10 +202,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     }
 }
 
-pub type MoveDat<'tcx> = Result<
-    (FxHashMap<Local, Place<'tcx>>, MoveData<'tcx>),
-    (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>),
->;
+pub type MoveDat<'tcx> =
+    Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)>;
 
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     fn finalize(self) -> MoveDat<'tcx> {
@@ -217,11 +219,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
             "done dumping moves"
         });
 
-        if self.errors.is_empty() {
-            Ok((self.un_derefer.derefer_sidetable, self.data))
-        } else {
-            Err((self.data, self.errors))
-        }
+        if self.errors.is_empty() { Ok(self.data) } else { Err((self.data, self.errors)) }
     }
 }
 
@@ -250,7 +248,7 @@ pub(super) fn gather_moves<'tcx>(
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     fn gather_args(&mut self) {
         for arg in self.body.args_iter() {
-            let path = self.data.rev_lookup.locals[arg];
+            let path = self.data.rev_lookup.find_local(arg);
 
             let init = self.data.inits.push(Init {
                 path,
@@ -286,7 +284,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
                 assert!(place.projection.is_empty());
                 if self.builder.body.local_decls[place.local].is_deref_temp() {
-                    self.builder.un_derefer.derefer_sidetable.insert(place.local, *reffed);
+                    self.builder.data.rev_lookup.derefer_sidetable.insert(place.local, *reffed);
                 }
             }
             StatementKind::Assign(box (place, rval)) => {
@@ -308,7 +306,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             StatementKind::StorageLive(_) => {}
             StatementKind::StorageDead(local) => {
                 // DerefTemp locals (results of CopyForDeref) don't actually move anything.
-                if !self.builder.un_derefer.derefer_sidetable.contains_key(&local) {
+                if !self.builder.data.rev_lookup.derefer_sidetable.contains_key(&local) {
                     self.gather_move(Place::from(*local));
                 }
             }
@@ -450,12 +448,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
 
     fn gather_move(&mut self, place: Place<'tcx>) {
         debug!("gather_move({:?}, {:?})", self.loc, place);
-        if let Some(new_place) = self.builder.un_derefer.derefer(place.as_ref(), self.builder.body)
-        {
-            self.gather_move(new_place);
-            return;
-        }
-
         if let [ref base @ .., ProjectionElem::Subslice { from, to, from_end: false }] =
             **place.projection
         {
@@ -512,11 +504,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
         debug!("gather_init({:?}, {:?})", self.loc, place);
 
-        if let Some(new_place) = self.builder.un_derefer.derefer(place, self.builder.body) {
-            self.gather_init(new_place.as_ref(), kind);
-            return;
-        }
-
         let mut place = place;
 
         // Check if we are assigning into a field of a union, if so, lookup the place
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index ab1a6715361..aa901f66d3f 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -1,5 +1,5 @@
 use crate::move_paths::builder::MoveDat;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
@@ -175,7 +175,7 @@ pub struct MoveData<'tcx> {
     /// particular path being moved.)
     pub loc_map: LocationMap<SmallVec<[MoveOutIndex; 4]>>,
     pub path_map: IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
-    pub rev_lookup: MovePathLookup,
+    pub rev_lookup: MovePathLookup<'tcx>,
     pub inits: IndexVec<InitIndex, Init>,
     /// Each Location `l` is mapped to the Inits that are effects
     /// of executing the code at `l`.
@@ -289,8 +289,8 @@ impl Init {
 
 /// Tables mapping from a place to its MovePathIndex.
 #[derive(Debug)]
-pub struct MovePathLookup {
-    locals: IndexVec<Local, MovePathIndex>,
+pub struct MovePathLookup<'tcx> {
+    locals: FxIndexMap<Local, MovePathIndex>,
 
     /// projections are made from a base-place and a projection
     /// elem. The base-place will have a unique MovePathIndex; we use
@@ -299,6 +299,9 @@ pub struct MovePathLookup {
     /// base-place). For the remaining lookup, we map the projection
     /// elem to the associated MovePathIndex.
     projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>,
+
+    /// Maps `DerefTemp` locals to the `Place`s assigned to them.
+    derefer_sidetable: FxHashMap<Local, Place<'tcx>>,
 }
 
 mod builder;
@@ -309,27 +312,59 @@ pub enum LookupResult {
     Parent(Option<MovePathIndex>),
 }
 
-impl MovePathLookup {
+impl<'tcx> MovePathLookup<'tcx> {
     // Unlike the builder `fn move_path_for` below, this lookup
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
     // parent.
     pub fn find(&self, place: PlaceRef<'_>) -> LookupResult {
-        let mut result = self.locals[place.local];
+        let deref_chain = self.deref_chain(place);
 
-        for elem in place.projection.iter() {
-            if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
-                result = subpath;
-            } else {
+        let local = match deref_chain.first() {
+            Some(place) => place.local,
+            None => place.local,
+        };
+
+        let mut result = *self.locals.get(&local).unwrap_or_else(|| {
+            bug!("base local ({local:?}) of deref_chain should not be a deref temp")
+        });
+
+        // this needs to be a closure because `place` has a different lifetime than `prefix`'s places
+        let mut subpaths_for_place = |place: PlaceRef<'_>| {
+            for elem in place.projection.iter() {
+                if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
+                    result = subpath;
+                } else {
+                    return Some(result);
+                }
+            }
+            None
+        };
+
+        for place in deref_chain {
+            if let Some(result) = subpaths_for_place(place.as_ref()) {
                 return LookupResult::Parent(Some(result));
             }
         }
 
+        if let Some(result) = subpaths_for_place(place) {
+            return LookupResult::Parent(Some(result));
+        }
+
         LookupResult::Exact(result)
     }
 
     pub fn find_local(&self, local: Local) -> MovePathIndex {
-        self.locals[local]
+        let deref_chain = self.deref_chain(Place::from(local).as_ref());
+
+        let local = match deref_chain.last() {
+            Some(place) => place.local,
+            None => local,
+        };
+
+        *self.locals.get(&local).unwrap_or_else(|| {
+            bug!("base local ({local:?}) of deref_chain should not be a deref temp")
+        })
     }
 
     /// An enumerated iterator of `local`s and their associated
@@ -337,7 +372,22 @@ impl MovePathLookup {
     pub fn iter_locals_enumerated(
         &self,
     ) -> impl DoubleEndedIterator<Item = (Local, MovePathIndex)> + ExactSizeIterator + '_ {
-        self.locals.iter_enumerated().map(|(l, &idx)| (l, idx))
+        self.locals.iter().map(|(&l, &idx)| (l, idx))
+    }
+
+    /// Returns the chain of places behind `DerefTemp` locals in `place`
+    pub fn deref_chain(&self, place: PlaceRef<'_>) -> Vec<Place<'tcx>> {
+        let mut prefix = Vec::new();
+        let mut local = place.local;
+
+        while let Some(&reffed) = self.derefer_sidetable.get(&local) {
+            prefix.insert(0, reffed);
+            local = reffed.local;
+        }
+
+        debug!("deref_chain({place:?}) = {prefix:?}");
+
+        prefix
     }
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 0cbc7442cf1..156231c3ae1 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -34,7 +34,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
         }
 
         let param_env = tcx.param_env(def_id);
-        let (_, move_data) = MoveData::gather_moves(body, tcx, param_env).unwrap();
+        let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap();
         let mdpe = MoveDataParamEnv { move_data, param_env };
 
         if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs
deleted file mode 100644
index 7e6e25cc603..00000000000
--- a/compiler/rustc_mir_dataflow/src/un_derefer.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
-
-/// Used for reverting changes made by `DerefSeparator`
-pub struct UnDerefer<'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-    pub derefer_sidetable: FxHashMap<Local, Place<'tcx>>,
-}
-
-impl<'tcx> UnDerefer<'tcx> {
-    #[inline]
-    pub fn derefer(&self, place: PlaceRef<'tcx>, body: &Body<'tcx>) -> Option<Place<'tcx>> {
-        let reffed = self.derefer_sidetable.get(&place.local)?;
-
-        let new_place = reffed.project_deeper(place.projection, self.tcx);
-        if body.local_decls[new_place.local].is_deref_temp() {
-            return self.derefer(new_place.as_ref(), body);
-        }
-        Some(new_place)
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index a39026751a7..95898b5b73c 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -8,13 +8,13 @@ use rustc_middle::ty::TyCtxt;
 
 pub struct Derefer;
 
-pub struct DerefChecker<'tcx> {
+pub struct DerefChecker<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     patcher: MirPatch<'tcx>,
-    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+    local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
 }
 
-impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
+impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -36,7 +36,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
 
             for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
                 if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref {
-                    let ty = p_ref.ty(&self.local_decls, self.tcx).ty;
+                    let ty = p_ref.ty(self.local_decls, self.tcx).ty;
                     let temp = self.patcher.new_internal_with_info(
                         ty,
                         self.local_decls[p_ref.local].source_info.span,
@@ -70,7 +70,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
 
 pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let patch = MirPatch::new(body);
-    let mut checker = DerefChecker { tcx, patcher: patch, local_decls: body.local_decls.clone() };
+    let mut checker = DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls };
 
     for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
         checker.visit_basic_block_data(bb, data);
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index fda0e1023f7..d5664e2b40a 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -10,7 +10,6 @@ use rustc_mir_dataflow::elaborate_drops::{DropElaborator, DropFlagMode, DropStyl
 use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
 use rustc_mir_dataflow::on_lookup_result_bits;
-use rustc_mir_dataflow::un_derefer::UnDerefer;
 use rustc_mir_dataflow::MoveDataParamEnv;
 use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits};
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -54,20 +53,19 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
 
         let def_id = body.source.def_id();
         let param_env = tcx.param_env_reveal_all_normalized(def_id);
-        let (side_table, move_data) = match MoveData::gather_moves(body, tcx, param_env) {
+        let move_data = match MoveData::gather_moves(body, tcx, param_env) {
             Ok(move_data) => move_data,
             Err((move_data, _)) => {
                 tcx.sess.delay_span_bug(
                     body.span,
                     "No `move_errors` should be allowed in MIR borrowck",
                 );
-                (Default::default(), move_data)
+                move_data
             }
         };
-        let un_derefer = UnDerefer { tcx: tcx, derefer_sidetable: side_table };
         let elaborate_patch = {
             let env = MoveDataParamEnv { move_data, param_env };
-            remove_dead_unwinds(tcx, body, &env, &un_derefer);
+            remove_dead_unwinds(tcx, body, &env);
 
             let inits = MaybeInitializedPlaces::new(tcx, body, &env)
                 .into_engine(tcx, body)
@@ -92,7 +90,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
                 init_data: InitializationData { inits, uninits },
                 drop_flags,
                 patch: MirPatch::new(body),
-                un_derefer: un_derefer,
                 reachable,
             }
             .elaborate()
@@ -108,7 +105,6 @@ fn remove_dead_unwinds<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &mut Body<'tcx>,
     env: &MoveDataParamEnv<'tcx>,
-    und: &UnDerefer<'tcx>,
 ) {
     debug!("remove_dead_unwinds({:?})", body.span);
     // We only need to do this pass once, because unwind edges can only
@@ -121,9 +117,7 @@ fn remove_dead_unwinds<'tcx>(
         .into_results_cursor(body);
     for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
         let place = match bb_data.terminator().kind {
-            TerminatorKind::Drop { ref place, unwind: UnwindAction::Cleanup(_), .. } => {
-                und.derefer(place.as_ref(), body).unwrap_or(*place)
-            }
+            TerminatorKind::Drop { place, unwind: UnwindAction::Cleanup(_), .. } => place,
             _ => continue,
         };
 
@@ -296,7 +290,6 @@ struct ElaborateDropsCtxt<'a, 'tcx> {
     init_data: InitializationData<'a, 'tcx>,
     drop_flags: IndexVec<MovePathIndex, Option<Local>>,
     patch: MirPatch<'tcx>,
-    un_derefer: UnDerefer<'tcx>,
     reachable: BitSet<BasicBlock>,
 }
 
@@ -342,9 +335,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             }
             let terminator = data.terminator();
             let place = match terminator.kind {
-                TerminatorKind::Drop { ref place, .. } => {
-                    self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place)
-                }
+                TerminatorKind::Drop { ref place, .. } => place,
                 _ => continue,
             };
 
@@ -401,11 +392,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             let terminator = data.terminator();
 
             match terminator.kind {
-                TerminatorKind::Drop { mut place, target, unwind, replace } => {
-                    if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
-                        place = new_place;
-                    }
-
+                TerminatorKind::Drop { place, target, unwind, replace } => {
                     self.init_data.seek_before(loc);
                     match self.move_data().rev_lookup.find(place.as_ref()) {
                         LookupResult::Exact(path) => {
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 1f9e521d315..283931de043 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -22,7 +22,7 @@ pub struct RemoveUninitDrops;
 impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let param_env = tcx.param_env(body.source.def_id());
-        let Ok((_,move_data)) = MoveData::gather_moves(body, tcx, param_env) else {
+        let Ok(move_data) = MoveData::gather_moves(body, tcx, param_env) else {
             // We could continue if there are move errors, but there's not much point since our
             // init data isn't complete.
             return;
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 97e3748b8b8..e663f4486f7 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -368,6 +368,7 @@ fn merge_codegen_units<'tcx>(
 
     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
 
+    // Rename the newly merged CGUs.
     if cx.tcx.sess.opts.incremental.is_some() {
         // If we are doing incremental compilation, we want CGU names to
         // reflect the path of the source level module they correspond to.
@@ -404,18 +405,41 @@ fn merge_codegen_units<'tcx>(
                 }
             }
         }
+
+        // A sorted order here ensures what follows can be deterministic.
+        codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
     } else {
-        // If we are compiling non-incrementally we just generate simple CGU
-        // names containing an index.
+        // When compiling non-incrementally, we rename the CGUS so they have
+        // identical names except for the numeric suffix, something like
+        // `regex.f10ba03eb5ec7975-cgu.N`, where `N` varies.
+        //
+        // It is useful for debugging and profiling purposes if the resulting
+        // CGUs are sorted by name *and* reverse sorted by size. (CGU 0 is the
+        // biggest, CGU 1 is the second biggest, etc.)
+        //
+        // So first we reverse sort by size. Then we generate the names with
+        // zero-padded suffixes, which means they are automatically sorted by
+        // names. The numeric suffix width depends on the number of CGUs, which
+        // is always greater than zero:
+        // - [1,9]     CGUS: `0`, `1`, `2`, ...
+        // - [10,99]   CGUS: `00`, `01`, `02`, ...
+        // - [100,999] CGUS: `000`, `001`, `002`, ...
+        // - etc.
+        //
+        // If we didn't zero-pad the sorted-by-name order would be `XYZ-cgu.0`,
+        // `XYZ-cgu.1`, `XYZ-cgu.10`, `XYZ-cgu.11`, ..., `XYZ-cgu.2`, etc.
+        codegen_units.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+        let num_digits = codegen_units.len().ilog10() as usize + 1;
         for (index, cgu) in codegen_units.iter_mut().enumerate() {
+            // Note: `WorkItem::short_description` depends on this name ending
+            // with `-cgu.` followed by a numeric suffix. Please keep it in
+            // sync with this code.
+            let suffix = format!("{index:0num_digits$}");
             let numbered_codegen_unit_name =
-                cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index));
+                cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(suffix));
             cgu.set_name(numbered_codegen_unit_name);
         }
     }
-
-    // A sorted order here ensures what follows can be deterministic.
-    codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 }
 
 fn internalize_symbols<'tcx>(
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 9971bdf45bb..098107f8f23 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -94,6 +94,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
         Err(layout_error) => {
             tcx.sess.emit_fatal(Spanned {
                 node: layout_error.into_diagnostic(),
+
                 span: tcx.def_span(item_def_id.to_def_id()),
             });
         }
diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl
index 6f51981cf09..b91e0d18a80 100644
--- a/compiler/rustc_privacy/messages.ftl
+++ b/compiler/rustc_privacy/messages.ftl
@@ -18,7 +18,7 @@ privacy_private_in_public_lint =
     })
 
 privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}`
-    .item_note = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}`
+    .item_label = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}`
     .ty_note = but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}`
 
 privacy_report_effective_visibility = {$descr}
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index 67689b5e713..da18f0c8268 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -116,7 +116,7 @@ pub struct UnnameableTypesLint<'a> {
 #[derive(LintDiagnostic)]
 #[diag(privacy_private_interface_or_bounds_lint)]
 pub struct PrivateInterfacesOrBoundsLint<'a> {
-    #[note(privacy_item_note)]
+    #[label(privacy_item_label)]
     pub item_span: Span,
     pub item_kind: &'a str,
     pub item_descr: DiagnosticArgFromDisplay<'a>,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 5f7313dcca6..055006373ef 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -73,14 +73,10 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
 /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
 trait DefIdVisitor<'tcx> {
     type BreakTy = ();
+    const SHALLOW: bool = false;
+    const SKIP_ASSOC_TYS: bool = false;
 
     fn tcx(&self) -> TyCtxt<'tcx>;
-    fn shallow(&self) -> bool {
-        false
-    }
-    fn skip_assoc_tys(&self) -> bool {
-        false
-    }
     fn visit_def_id(
         &mut self,
         def_id: DefId,
@@ -135,11 +131,7 @@ where
     fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
         let TraitRef { def_id, substs, .. } = trait_ref;
         self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
-        if self.def_id_visitor.shallow() {
-            ControlFlow::Continue(())
-        } else {
-            substs.visit_with(self)
-        }
+        if V::SHALLOW { ControlFlow::Continue(()) } else { substs.visit_with(self) }
     }
 
     fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
@@ -158,7 +150,7 @@ where
             )
         };
         self.visit_trait(trait_ref)?;
-        if self.def_id_visitor.shallow() {
+        if V::SHALLOW {
             ControlFlow::Continue(())
         } else {
             assoc_substs.iter().try_for_each(|subst| subst.visit_with(self))
@@ -208,7 +200,7 @@ where
             | ty::Closure(def_id, ..)
             | ty::Generator(def_id, ..) => {
                 self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
-                if self.def_id_visitor.shallow() {
+                if V::SHALLOW {
                     return ControlFlow::Continue(());
                 }
                 // Default type visitor doesn't visit signatures of fn types.
@@ -232,7 +224,7 @@ where
                 self.def_id_visitor.visit_def_id(alias.def_id, "type alias", &ty);
             }
             ty::Alias(ty::Projection, proj) => {
-                if self.def_id_visitor.skip_assoc_tys() {
+                if V::SKIP_ASSOC_TYS {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `<Type as Trait>::Alias`
                     // as visible/reachable even if both `Type` and `Trait` are private.
@@ -244,7 +236,7 @@ where
                 return self.visit_projection_ty(proj);
             }
             ty::Alias(ty::Inherent, data) => {
-                if self.def_id_visitor.skip_assoc_tys() {
+                if V::SKIP_ASSOC_TYS {
                     // Visitors searching for minimal visibility/reachability want to
                     // conservatively approximate associated types like `Type::Alias`
                     // as visible/reachable even if `Type` is private.
@@ -260,7 +252,7 @@ where
                 )?;
 
                 // This will also visit substs if necessary, so we don't need to recurse.
-                return if self.def_id_visitor.shallow() {
+                return if V::SHALLOW {
                     ControlFlow::Continue(())
                 } else {
                     data.substs.iter().try_for_each(|subst| subst.visit_with(self))
@@ -319,11 +311,7 @@ where
             }
         }
 
-        if self.def_id_visitor.shallow() {
-            ControlFlow::Continue(())
-        } else {
-            ty.super_visit_with(self)
-        }
+        if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) }
     }
 
     fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -340,22 +328,20 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib
 /// Visitor used to determine impl visibility and reachability.
 ////////////////////////////////////////////////////////////////////////////////
 
-struct FindMin<'a, 'tcx, VL: VisibilityLike> {
+struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
     tcx: TyCtxt<'tcx>,
     effective_visibilities: &'a EffectiveVisibilities,
     min: VL,
 }
 
-impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL> {
+impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
+    for FindMin<'a, 'tcx, VL, SHALLOW>
+{
+    const SHALLOW: bool = SHALLOW;
+    const SKIP_ASSOC_TYS: bool = true;
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn shallow(&self) -> bool {
-        VL::SHALLOW
-    }
-    fn skip_assoc_tys(&self) -> bool {
-        true
-    }
     fn visit_def_id(
         &mut self,
         def_id: DefId,
@@ -371,17 +357,19 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL>
 
 trait VisibilityLike: Sized {
     const MAX: Self;
-    const SHALLOW: bool = false;
-    fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self;
+    fn new_min<const SHALLOW: bool>(
+        find: &FindMin<'_, '_, Self, SHALLOW>,
+        def_id: LocalDefId,
+    ) -> Self;
 
-    // Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
+    // Returns an over-approximation (`SKIP_ASSOC_TYS` = true) of visibility due to
     // associated types for which we can't determine visibility precisely.
-    fn of_impl(
+    fn of_impl<const SHALLOW: bool>(
         def_id: LocalDefId,
         tcx: TyCtxt<'_>,
         effective_visibilities: &EffectiveVisibilities,
     ) -> Self {
-        let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX };
+        let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
         find.visit(tcx.type_of(def_id).subst_identity());
         if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
             find.visit_trait(trait_ref.subst_identity());
@@ -391,49 +379,28 @@ trait VisibilityLike: Sized {
 }
 impl VisibilityLike for ty::Visibility {
     const MAX: Self = ty::Visibility::Public;
-    fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
+    fn new_min<const SHALLOW: bool>(
+        find: &FindMin<'_, '_, Self, SHALLOW>,
+        def_id: LocalDefId,
+    ) -> Self {
         min(find.tcx.local_visibility(def_id), find.min, find.tcx)
     }
 }
 
-struct NonShallowEffectiveVis(EffectiveVisibility);
-
-impl VisibilityLike for NonShallowEffectiveVis {
-    const MAX: Self = NonShallowEffectiveVis(EffectiveVisibility::from_vis(ty::Visibility::Public));
-    const SHALLOW: bool = false;
-
-    fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
-        let find = FindMin {
-            tcx: find.tcx,
-            effective_visibilities: find.effective_visibilities,
-            min: ShallowEffectiveVis(find.min.0),
-        };
-        NonShallowEffectiveVis(VisibilityLike::new_min(&find, def_id).0)
-    }
-}
-
-struct ShallowEffectiveVis(EffectiveVisibility);
-impl VisibilityLike for ShallowEffectiveVis {
-    const MAX: Self = ShallowEffectiveVis(EffectiveVisibility::from_vis(ty::Visibility::Public));
-    // Type inference is very smart sometimes.
-    // It can make an impl reachable even some components of its type or trait are unreachable.
-    // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
-    // can be usable from other crates (#57264). So we skip substs when calculating reachability
-    // and consider an impl reachable if its "shallow" type and trait are reachable.
-    //
-    // The assumption we make here is that type-inference won't let you use an impl without knowing
-    // both "shallow" version of its self type and "shallow" version of its trait if it exists
-    // (which require reaching the `DefId`s in them).
-    const SHALLOW: bool = true;
-    fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
+impl VisibilityLike for EffectiveVisibility {
+    const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
+    fn new_min<const SHALLOW: bool>(
+        find: &FindMin<'_, '_, Self, SHALLOW>,
+        def_id: LocalDefId,
+    ) -> Self {
         let effective_vis =
-            find.effective_visibilities.effective_vis(def_id).cloned().unwrap_or_else(|| {
+            find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
                 let private_vis =
                     ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id));
                 EffectiveVisibility::from_vis(private_vis)
             });
 
-        ShallowEffectiveVis(effective_vis.min(find.min.0, find.tcx))
+        effective_vis.min(find.min, find.tcx)
     }
 }
 
@@ -492,14 +459,14 @@ impl<'tcx> EmbargoVisitor<'tcx> {
         &mut self,
         def_id: LocalDefId,
         inherited_effective_vis: EffectiveVisibility,
-        nominal_vis: Option<ty::Visibility>,
+        max_vis: Option<ty::Visibility>,
         level: Level,
     ) {
         let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
-        if Some(private_vis) != nominal_vis {
+        if max_vis != Some(private_vis) {
             self.changed |= self.effective_visibilities.update(
                 def_id,
-                nominal_vis,
+                max_vis,
                 || private_vis,
                 inherited_effective_vis,
                 level,
@@ -771,12 +738,21 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 }
             }
             hir::ItemKind::Impl(ref impl_) => {
-                let item_ev = ShallowEffectiveVis::of_impl(
+                // Type inference is very smart sometimes. It can make an impl reachable even some
+                // components of its type or trait are unreachable. E.g. methods of
+                // `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
+                // can be usable from other crates (#57264). So we skip substs when calculating
+                // reachability and consider an impl reachable if its "shallow" type and trait are
+                // reachable.
+                //
+                // The assumption we make here is that type-inference won't let you use an impl
+                // without knowing both "shallow" version of its self type and "shallow" version of
+                // its trait if it exists (which require reaching the `DefId`s in them).
+                let item_ev = EffectiveVisibility::of_impl::<true>(
                     item.owner_id.def_id,
                     self.tcx,
                     &self.effective_visibilities,
-                )
-                .0;
+                );
 
                 self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
 
@@ -784,9 +760,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
 
                 for impl_item_ref in impl_.items {
                     let def_id = impl_item_ref.id.owner_id.def_id;
-                    let nominal_vis =
+                    let max_vis =
                         impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
-                    self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
+                    self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
 
                     if let Some(impl_item_ev) = self.get(def_id) {
                         self.reach(def_id, impl_item_ev).generics().predicates().ty();
@@ -904,7 +880,12 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
         _descr: &dyn fmt::Display,
     ) -> ControlFlow<Self::BreakTy> {
         if let Some(def_id) = def_id.as_local() {
-            self.ev.update_eff_vis(def_id, self.effective_vis, None, self.level);
+            // All effective visibilities except `reachable_through_impl_trait` are limited to
+            // nominal visibility. If any type or trait is leaked farther than that, it will
+            // produce type privacy errors on any use, so we don't consider it leaked.
+            let max_vis = (self.level != Level::ReachableThroughImplTrait)
+                .then(|| self.ev.tcx.local_visibility(def_id));
+            self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
         }
         ControlFlow::Continue(())
     }
@@ -1876,18 +1857,18 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
             return false;
         };
 
-        // FIXME: `Level::Reachable` should be taken instead of `Level::Reexported`
-        let reexported_at_vis = *effective_vis.at_level(Level::Reexported);
+        let reachable_at_vis = *effective_vis.at_level(Level::Reachable);
 
-        if !vis.is_at_least(reexported_at_vis, self.tcx) {
+        if !vis.is_at_least(reachable_at_vis, self.tcx) {
             let lint = if self.in_primary_interface {
                 lint::builtin::PRIVATE_INTERFACES
             } else {
                 lint::builtin::PRIVATE_BOUNDS
             };
-            self.tcx.emit_lint(
+            self.tcx.emit_spanned_lint(
                 lint,
                 hir_id,
+                span,
                 PrivateInterfacesOrBoundsLint {
                     item_span: span,
                     item_kind: self.tcx.def_descr(self.item_def_id.to_def_id()),
@@ -1896,7 +1877,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                         tcx: self.tcx,
                     })
                         .into(),
-                    item_vis_descr: &vis_to_string(self.item_def_id, reexported_at_vis, self.tcx),
+                    item_vis_descr: &vis_to_string(self.item_def_id, reachable_at_vis, self.tcx),
                     ty_span: vis_span,
                     ty_kind: kind,
                     ty_descr: descr.into(),
@@ -2137,32 +2118,35 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
             DefKind::Impl { .. } => {
                 let item = tcx.hir().item(id);
                 if let hir::ItemKind::Impl(ref impl_) = item.kind {
-                    let impl_vis =
-                        ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default());
+                    let impl_vis = ty::Visibility::of_impl::<false>(
+                        item.owner_id.def_id,
+                        tcx,
+                        &Default::default(),
+                    );
 
-                    // we are using the non-shallow version here, unlike when building the
+                    // We are using the non-shallow version here, unlike when building the
                     // effective visisibilities table to avoid large number of false positives.
-                    // For example:
+                    // For example in
                     //
                     // impl From<Priv> for Pub {
                     //     fn from(_: Priv) -> Pub {...}
                     // }
                     //
-                    // lints shouldn't be emmited even `from` effective visibility
-                    // is larger then `Priv` nominal visibility.
-                    let impl_ev = Some(
-                        NonShallowEffectiveVis::of_impl(
-                            item.owner_id.def_id,
-                            tcx,
-                            self.effective_visibilities,
-                        )
-                        .0,
+                    // lints shouldn't be emmited even if `from` effective visibility
+                    // is larger than `Priv` nominal visibility and if `Priv` can leak
+                    // in some scenarios due to type inference.
+                    let impl_ev = EffectiveVisibility::of_impl::<false>(
+                        item.owner_id.def_id,
+                        tcx,
+                        self.effective_visibilities,
                     );
 
                     // check that private components do not appear in the generics or predicates of inherent impls
                     // this check is intentionally NOT performed for impls of traits, per #90586
                     if impl_.of_trait.is_none() {
-                        self.check(item.owner_id.def_id, impl_vis, impl_ev).generics().predicates();
+                        self.check(item.owner_id.def_id, impl_vis, Some(impl_ev))
+                            .generics()
+                            .predicates();
                     }
                     for impl_item_ref in impl_.items {
                         let impl_item_vis = if impl_.of_trait.is_none() {
@@ -2177,8 +2161,9 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
 
                         let impl_item_ev = if impl_.of_trait.is_none() {
                             self.get(impl_item_ref.id.owner_id.def_id)
+                                .map(|ev| ev.min(impl_ev, self.tcx))
                         } else {
-                            impl_ev
+                            Some(impl_ev)
                         };
 
                         self.check_assoc_item(
@@ -2284,7 +2269,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
         changed: false,
     };
 
-    visitor.effective_visibilities.check_invariants(tcx, true);
+    visitor.effective_visibilities.check_invariants(tcx);
     if visitor.impl_trait_pass {
         // Underlying types of `impl Trait`s are marked as reachable unconditionally,
         // so this pass doesn't need to be a part of the fixed point iteration below.
@@ -2301,7 +2286,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
             break;
         }
     }
-    visitor.effective_visibilities.check_invariants(tcx, false);
+    visitor.effective_visibilities.check_invariants(tcx);
 
     let mut check_visitor =
         TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d77fb922e84..d9e4974626d 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1403,7 +1403,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
             if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
                 ident,
-                ScopeSet::All(ns, false),
+                ScopeSet::All(ns),
                 &parent_scope,
                 None,
                 false,
@@ -1841,10 +1841,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         _ => None,
                     }
                 } else {
-                    let scopes = ScopeSet::All(ns_to_try, opt_ns.is_none());
                     self.early_resolve_ident_in_lexical_scope(
                         ident,
-                        scopes,
+                        ScopeSet::All(ns_to_try),
                         parent_scope,
                         None,
                         false,
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index e5fa062967f..36f01676e7e 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -88,7 +88,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         let rust_2015 = ctxt.edition().is_rust_2015();
         let (ns, macro_kind, is_absolute_path) = match scope_set {
-            ScopeSet::All(ns, _) => (ns, None, false),
+            ScopeSet::All(ns) => (ns, None, false),
             ScopeSet::AbsolutePath(ns) => (ns, None, true),
             ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
             ScopeSet::Late(ns, ..) => (ns, None, false),
@@ -370,7 +370,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// expansion and import resolution (perhaps they can be merged in the future).
     /// The function is used for resolving initial segments of macro paths (e.g., `foo` in
     /// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
-    #[instrument(level = "debug", skip(self, scope_set))]
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn early_resolve_ident_in_lexical_scope(
         &mut self,
         orig_ident: Ident,
@@ -397,11 +397,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             return Err(Determinacy::Determined);
         }
 
-        let (ns, macro_kind, is_import) = match scope_set {
-            ScopeSet::All(ns, is_import) => (ns, None, is_import),
-            ScopeSet::AbsolutePath(ns) => (ns, None, false),
-            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
-            ScopeSet::Late(ns, ..) => (ns, None, false),
+        let (ns, macro_kind) = match scope_set {
+            ScopeSet::All(ns) => (ns, None),
+            ScopeSet::AbsolutePath(ns) => (ns, None),
+            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
+            ScopeSet::Late(ns, ..) => (ns, None),
         };
 
         // This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -631,9 +631,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 let derive_helper_compat =
                                     Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
 
-                                let ambiguity_error_kind = if is_import {
-                                    Some(AmbiguityKind::Import)
-                                } else if is_builtin(innermost_res) || is_builtin(res) {
+                                let ambiguity_error_kind = if is_builtin(innermost_res)
+                                    || is_builtin(res)
+                                {
                                     Some(AmbiguityKind::BuiltinAttr)
                                 } else if innermost_res == derive_helper_compat
                                     || res == derive_helper_compat && innermost_res != derive_helper
@@ -853,10 +853,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                 }
 
-                let scopes = ScopeSet::All(ns, true);
                 let binding = self.early_resolve_ident_in_lexical_scope(
                     ident,
-                    scopes,
+                    ScopeSet::All(ns),
                     parent_scope,
                     finalize,
                     finalize.is_some(),
@@ -1497,7 +1496,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             } else {
                 self.early_resolve_ident_in_lexical_scope(
                     ident,
-                    ScopeSet::All(ns, opt_ns.is_none()),
+                    ScopeSet::All(ns),
                     parent_scope,
                     finalize,
                     finalize.is_some(),
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 35491ebe10c..074f761c53b 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -10,10 +10,7 @@ use crate::errors::{
 use crate::Determinacy::{self, *};
 use crate::{fluent_generated as fluent, Namespace::*};
 use crate::{module_to_string, names_to_string, ImportSuggestion};
-use crate::{
-    AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, ModuleKind, ResolutionError,
-    Resolver, Segment,
-};
+use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
 use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
 use crate::{NameBinding, NameBindingKind, PathResult};
 
@@ -897,8 +894,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
                 return None;
             }
-            PathResult::NonModule(_) => {
-                if no_ambiguity {
+            PathResult::NonModule(partial_res) => {
+                if no_ambiguity && partial_res.full_res() != Some(Res::Err) {
+                    // Check if there are no ambiguities and the result is not dummy.
                     assert!(import.imported_module.get().is_none());
                 }
                 // The error was already reported earlier.
@@ -984,7 +982,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 match binding {
                     Ok(binding) => {
                         // Consistency checks, analogous to `finalize_macro_resolutions`.
-                        let initial_binding = source_bindings[ns].get().map(|initial_binding| {
+                        let initial_res = source_bindings[ns].get().map(|initial_binding| {
                             all_ns_err = false;
                             if let Some(target_binding) = target_bindings[ns].get() {
                                 if target.name == kw::Underscore
@@ -998,20 +996,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                     );
                                 }
                             }
-                            initial_binding
+                            initial_binding.res()
                         });
                         let res = binding.res();
-                        if let Ok(initial_binding) = initial_binding {
-                            let initial_res = initial_binding.res();
+                        if let Ok(initial_res) = initial_res {
                             if res != initial_res && this.ambiguity_errors.is_empty() {
-                                this.ambiguity_errors.push(AmbiguityError {
-                                    kind: AmbiguityKind::Import,
-                                    ident,
-                                    b1: initial_binding,
-                                    b2: binding,
-                                    misc1: AmbiguityErrorMisc::None,
-                                    misc2: AmbiguityErrorMisc::None,
-                                });
+                                span_bug!(import.span, "inconsistent resolution for an import");
                             }
                         } else if res != Res::Err
                             && this.ambiguity_errors.is_empty()
@@ -1283,7 +1273,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                 match this.early_resolve_ident_in_lexical_scope(
                     target,
-                    ScopeSet::All(ns, false),
+                    ScopeSet::All(ns),
                     &import.parent_scope,
                     None,
                     false,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9f4573ea025..744dcf0db84 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1632,9 +1632,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                                 ..
                             } = &rib.kind
                             {
-                                diag.span_help(
-                                    *span,
-                                    "consider introducing a higher-ranked lifetime here with `for<'a>`",
+                                diag.multipart_suggestion(
+                                    "consider introducing a higher-ranked lifetime here",
+                                    vec![
+                                        (span.shrink_to_lo(), "for<'a> ".into()),
+                                        (lifetime.ident.span.shrink_to_hi(), "'a ".into()),
+                                    ],
+                                    Applicability::MachineApplicable,
                                 );
                                 break;
                             }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 8c1cd2f1557..cc4cb9fa30c 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -128,10 +128,10 @@ enum Scope<'a> {
 /// with different restrictions when looking up the resolution.
 /// This enum is currently used only for early resolution (imports and macros),
 /// but not for late resolution yet.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 enum ScopeSet<'a> {
     /// All scopes with the given namespace.
-    All(Namespace, /*is_import*/ bool),
+    All(Namespace),
     /// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros).
     AbsolutePath(Namespace),
     /// All scopes with macro namespace and the given macro kind restriction.
@@ -718,7 +718,6 @@ struct UseError<'a> {
 
 #[derive(Clone, Copy, PartialEq, Debug)]
 enum AmbiguityKind {
-    Import,
     BuiltinAttr,
     DeriveHelper,
     MacroRulesVsModularized,
@@ -731,7 +730,6 @@ enum AmbiguityKind {
 impl AmbiguityKind {
     fn descr(self) -> &'static str {
         match self {
-            AmbiguityKind::Import => "multiple potential import sources",
             AmbiguityKind::BuiltinAttr => "a name conflict with a builtin attribute",
             AmbiguityKind::DeriveHelper => "a name conflict with a derive helper attribute",
             AmbiguityKind::MacroRulesVsModularized => {
@@ -1557,7 +1555,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
 
-        self.visit_scopes(ScopeSet::All(TypeNS, false), parent_scope, ctxt, |this, scope, _, _| {
+        self.visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| {
             match scope {
                 Scope::Module(module, _) => {
                     this.traits_in_module(module, assoc_item, &mut found_traits);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 4dcef8f6efd..d33e8d40b63 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -645,7 +645,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
             res
         } else {
-            let scope_set = kind.map_or(ScopeSet::All(MacroNS, false), ScopeSet::Macro);
+            let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
             let binding = self.early_resolve_ident_in_lexical_scope(
                 path[0].ident,
                 scope_set,
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 90ad3f90f2c..1291d1454a6 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 atty = "0.2.13"
+bitflags = "1.2.1"
 getopts = "0.2"
 rustc_macros = { path = "../rustc_macros" }
 tracing = "0.1"
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 480d2478e81..2fe7a6f511b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -9,10 +9,9 @@ use crate::{lint, HashStableContext};
 use crate::{EarlyErrorHandler, Session};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
 use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_target::abi::Align;
-use rustc_target::spec::{LinkerFlavorCli, PanicStrategy, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
 use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
 
 use crate::parse::{CrateCheckConfig, CrateConfig};
@@ -201,6 +200,128 @@ pub enum LinkerPluginLto {
     Disabled,
 }
 
+impl LinkerPluginLto {
+    pub fn enabled(&self) -> bool {
+        match *self {
+            LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true,
+            LinkerPluginLto::Disabled => false,
+        }
+    }
+}
+
+/// The different values `-C link-self-contained` can take: a list of individually enabled or
+/// disabled components used during linking, coming from the rustc distribution, instead of being
+/// found somewhere on the host system.
+///
+/// They can be set in bulk via `-C link-self-contained=yes|y|on` or `-C
+/// link-self-contained=no|n|off`, and those boolean values are the historical defaults.
+///
+/// But each component is fine-grained, and can be unstably targeted, to use:
+/// - some CRT objects
+/// - the libc static library
+/// - libgcc/libunwind libraries
+/// - a linker we distribute
+/// - some sanitizer runtime libraries
+/// - all other MinGW libraries and Windows import libs
+///
+#[derive(Default, Clone, PartialEq, Debug)]
+pub struct LinkSelfContained {
+    /// Whether the user explicitly set `-C link-self-contained` on or off, the historical values.
+    /// Used for compatibility with the existing opt-in and target inference.
+    pub explicitly_set: Option<bool>,
+
+    /// The components that are enabled.
+    components: LinkSelfContainedComponents,
+}
+
+bitflags::bitflags! {
+    #[derive(Default)]
+    /// The `-C link-self-contained` components that can individually be enabled or disabled.
+    pub struct LinkSelfContainedComponents: u8 {
+        /// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets)
+        const CRT_OBJECTS = 1 << 0;
+        /// libc static library (e.g. on `musl`, `wasi` targets)
+        const LIBC        = 1 << 1;
+        /// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets)
+        const UNWIND      = 1 << 2;
+        /// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`)
+        const LINKER      = 1 << 3;
+        /// Sanitizer runtime libraries
+        const SANITIZERS  = 1 << 4;
+        /// Other MinGW libs and Windows import libs
+        const MINGW       = 1 << 5;
+    }
+}
+
+impl FromStr for LinkSelfContainedComponents {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(match s {
+            "crto" => LinkSelfContainedComponents::CRT_OBJECTS,
+            "libc" => LinkSelfContainedComponents::LIBC,
+            "unwind" => LinkSelfContainedComponents::UNWIND,
+            "linker" => LinkSelfContainedComponents::LINKER,
+            "sanitizers" => LinkSelfContainedComponents::SANITIZERS,
+            "mingw" => LinkSelfContainedComponents::MINGW,
+            _ => return Err(()),
+        })
+    }
+}
+
+impl LinkSelfContained {
+    /// Incorporates an enabled or disabled component as specified on the CLI, if possible.
+    /// For example: `+linker`, and `-crto`.
+    pub(crate) fn handle_cli_component(&mut self, component: &str) -> Result<(), ()> {
+        // Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit
+        // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been
+        // set in bulk with its historical values, then manually setting a component clears that
+        // `explicitly_set` state.
+        if let Some(component_to_enable) = component.strip_prefix("+") {
+            self.explicitly_set = None;
+            self.components.insert(component_to_enable.parse()?);
+            Ok(())
+        } else if let Some(component_to_disable) = component.strip_prefix("-") {
+            self.explicitly_set = None;
+            self.components.remove(component_to_disable.parse()?);
+            Ok(())
+        } else {
+            Err(())
+        }
+    }
+
+    /// Turns all components on or off and records that this was done explicitly for compatibility
+    /// purposes.
+    pub(crate) fn set_all_explicitly(&mut self, enabled: bool) {
+        self.explicitly_set = Some(enabled);
+        self.components = if enabled {
+            LinkSelfContainedComponents::all()
+        } else {
+            LinkSelfContainedComponents::empty()
+        };
+    }
+
+    /// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests.
+    pub fn on() -> Self {
+        let mut on = LinkSelfContained::default();
+        on.set_all_explicitly(true);
+        on
+    }
+
+    /// To help checking CLI usage while some of the values are unstable: returns whether one of the
+    /// components was set individually. This would also require the `-Zunstable-options` flag, to
+    /// be allowed.
+    fn are_unstable_variants_set(&self) -> bool {
+        let any_component_set = !self.components.is_empty();
+        self.explicitly_set.is_none() && any_component_set
+    }
+
+    /// Returns whether the self-contained linker component is enabled.
+    pub fn linker(&self) -> bool {
+        self.components.contains(LinkSelfContainedComponents::LINKER)
+    }
+}
+
 /// Used with `-Z assert-incr-state`.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum IncrementalStateAssertion {
@@ -213,15 +334,6 @@ pub enum IncrementalStateAssertion {
     NotLoaded,
 }
 
-impl LinkerPluginLto {
-    pub fn enabled(&self) -> bool {
-        match *self {
-            LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true,
-            LinkerPluginLto::Disabled => false,
-        }
-    }
-}
-
 /// The different settings that can be enabled via the `-Z location-detail` flag.
 #[derive(Copy, Clone, PartialEq, Hash, Debug)]
 pub struct LocationDetail {
@@ -2544,16 +2656,28 @@ pub fn build_session_options(
         }
     }
 
-    if let Some(flavor) = cg.linker_flavor {
-        if matches!(flavor, LinkerFlavorCli::BpfLinker | LinkerFlavorCli::PtxLinker)
-            && !nightly_options::is_unstable_enabled(matches)
-        {
-            let msg = format!(
-                "linker flavor `{}` is unstable, `-Z unstable-options` \
-                 flag must also be passed to explicitly use it",
-                flavor.desc()
+    // For testing purposes, until we have more feedback about these options: ensure `-Z
+    // unstable-options` is required when using the unstable `-C link-self-contained` options, like
+    // `-C link-self-contained=+linker`, and when using the unstable `-C linker-flavor` options, like
+    // `-C linker-flavor=gnu-lld-cc`.
+    if !nightly_options::is_unstable_enabled(matches) {
+        let uses_unstable_self_contained_option =
+            cg.link_self_contained.are_unstable_variants_set();
+        if uses_unstable_self_contained_option {
+            handler.early_error(
+                "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
+                the `-Z unstable-options` flag must also be passed to use the unstable values",
             );
-            handler.early_error(msg);
+        }
+
+        if let Some(flavor) = cg.linker_flavor {
+            if flavor.is_unstable() {
+                handler.early_error(format!(
+                    "the linker flavor `{}` is unstable, the `-Z unstable-options` \
+                        flag must also be passed to use the unstable values",
+                    flavor.desc()
+                ));
+            }
         }
     }
 
@@ -2583,6 +2707,10 @@ pub fn build_session_options(
         handler.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations");
     }
 
+    if cg.remark.is_empty() && unstable_opts.remark_dir.is_some() {
+        handler.early_warn("using -Z remark-dir without enabling remarks using e.g. -C remark=all");
+    }
+
     let externs = parse_externs(handler, matches, &unstable_opts);
 
     let crate_name = matches.opt_str("crate-name");
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index e5063eef47a..16a4c2a8b3d 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -410,6 +410,8 @@ mod desc {
     pub const parse_split_dwarf_kind: &str =
         "one of supported split dwarf modes (`split` or `single`)";
     pub const parse_gcc_ld: &str = "one of: no value, `lld`";
+    pub const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \
+        components: `crto`, `libc`, `unwind`, `linker`, `sanitizers`, `mingw`";
     pub const parse_stack_protector: &str =
         "one of (`none` (default), `basic`, `strong`, or `all`)";
     pub const parse_branch_protection: &str =
@@ -1122,6 +1124,34 @@ mod parse {
         }
     }
 
+    pub(crate) fn parse_link_self_contained(slot: &mut LinkSelfContained, v: Option<&str>) -> bool {
+        // Whenever `-C link-self-contained` is passed without a value, it's an opt-in
+        // just like `parse_opt_bool`, the historical value of this flag.
+        //
+        // 1. Parse historical single bool values
+        let s = v.unwrap_or("y");
+        match s {
+            "y" | "yes" | "on" => {
+                slot.set_all_explicitly(true);
+                return true;
+            }
+            "n" | "no" | "off" => {
+                slot.set_all_explicitly(false);
+                return true;
+            }
+            _ => {}
+        }
+
+        // 2. Parse a list of enabled and disabled components.
+        for comp in s.split(",") {
+            if slot.handle_cli_component(comp).is_err() {
+                return false;
+            }
+        }
+
+        true
+    }
+
     pub(crate) fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool {
         match v {
             Some("command") => *slot = Some(WasiExecModel::Command),
@@ -1265,9 +1295,9 @@ options! {
     #[rustc_lint_opt_deny_field_access("use `Session::link_dead_code` instead of this field")]
     link_dead_code: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "keep dead code at link time (useful for code coverage) (default: no)"),
-    link_self_contained: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
+    link_self_contained: LinkSelfContained = (LinkSelfContained::default(), parse_link_self_contained, [UNTRACKED],
         "control whether to link Rust provided C objects/libraries or rely
-        on C toolchain installed in the system"),
+        on a C toolchain or linker installed in the system"),
     linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
         "system linker to link outputs with"),
     linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
@@ -1314,7 +1344,7 @@ options! {
         "control generation of position-independent code (PIC) \
         (`rustc --print relocation-models` for details)"),
     remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED],
-        "print remarks for these optimization passes (space separated, or \"all\")"),
+        "output remarks for these optimization passes (space separated, or \"all\")"),
     rpath: bool = (false, parse_bool, [UNTRACKED],
         "set rpath values in libs/exes (default: no)"),
     save_temps: bool = (false, parse_bool, [UNTRACKED],
@@ -1659,6 +1689,9 @@ options! {
         "choose which RELRO level to use"),
     remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "remap paths under the current working directory to this path prefix"),
+    remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
+        "directory into which to write optimization remarks (if not specified, they will be \
+written to standard error output)"),
     report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
         "immediately print bugs registered with `delay_span_bug` (default: no)"),
     sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index c53fe084c4d..86716da1712 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -1072,11 +1072,7 @@ impl SourceMap {
     /// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
     /// since `source_files` is a `MonotonicVec`
     pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
-        self.files
-            .borrow()
-            .source_files
-            .binary_search_by_key(&pos, |key| key.start_pos)
-            .unwrap_or_else(|p| p - 1)
+        self.files.borrow().source_files.partition_point(|x| x.start_pos <= pos) - 1
     }
 
     pub fn count_lines(&self) -> usize {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index c71ed2097b8..c58d85b99f7 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1558,6 +1558,7 @@ symbols! {
         type_length_limit,
         type_macros,
         type_name,
+        type_privacy_lints,
         u128,
         u16,
         u32,
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index dff22fad4ec..a71e2e8cc57 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -14,3 +14,8 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
+
+[dependencies.object]
+version = "0.31.1"
+default-features = false
+features = ["elf"]
diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs
index 9c3406b5313..fbec44b716a 100644
--- a/compiler/rustc_target/src/spec/avr_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs
@@ -1,4 +1,5 @@
 use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
+use object::elf;
 
 /// A base target for AVR devices using the GNU toolchain.
 ///
@@ -29,3 +30,339 @@ pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
         },
     }
 }
+
+/// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the
+/// name of the target CPU / MCU.
+///
+/// In ELF files using the AVR architecture, the lower 7 bits of the e_flags
+/// field is a code that identifies the "ISA revision" of the object code.
+///
+/// This flag is generally set by AVR compilers in their output ELF files,
+/// and linkers like avr-ld check this flag in all of their input files to
+/// make sure they are compiled with the same ISA revision.
+pub fn ef_avr_arch(target_cpu: &str) -> u32 {
+    // Adapted from llvm-project/llvm/lib/target/AVR/AVRDevices.td
+    match target_cpu {
+        // Generic MCUs
+        "avr1" => elf::EF_AVR_ARCH_AVR1,
+        "avr2" => elf::EF_AVR_ARCH_AVR2,
+        "avr25" => elf::EF_AVR_ARCH_AVR25,
+        "avr3" => elf::EF_AVR_ARCH_AVR3,
+        "avr31" => elf::EF_AVR_ARCH_AVR31,
+        "avr35" => elf::EF_AVR_ARCH_AVR35,
+        "avr4" => elf::EF_AVR_ARCH_AVR4,
+        "avr5" => elf::EF_AVR_ARCH_AVR5,
+        "avr51" => elf::EF_AVR_ARCH_AVR51,
+        "avr6" => elf::EF_AVR_ARCH_AVR6,
+        "avrxmega1" => elf::EF_AVR_ARCH_XMEGA1,
+        "avrxmega2" => elf::EF_AVR_ARCH_XMEGA2,
+        "avrxmega3" => elf::EF_AVR_ARCH_XMEGA3,
+        "avrxmega4" => elf::EF_AVR_ARCH_XMEGA4,
+        "avrxmega5" => elf::EF_AVR_ARCH_XMEGA5,
+        "avrxmega6" => elf::EF_AVR_ARCH_XMEGA6,
+        "avrxmega7" => elf::EF_AVR_ARCH_XMEGA7,
+        "avrtiny" => elf::EF_AVR_ARCH_AVRTINY,
+
+        // Specific MCUs
+        "at90s1200" => elf::EF_AVR_ARCH_AVR1,
+        "attiny11" => elf::EF_AVR_ARCH_AVR1,
+        "attiny12" => elf::EF_AVR_ARCH_AVR1,
+        "attiny15" => elf::EF_AVR_ARCH_AVR1,
+        "attiny28" => elf::EF_AVR_ARCH_AVR1,
+        "at90s2313" => elf::EF_AVR_ARCH_AVR2,
+        "at90s2323" => elf::EF_AVR_ARCH_AVR2,
+        "at90s2333" => elf::EF_AVR_ARCH_AVR2,
+        "at90s2343" => elf::EF_AVR_ARCH_AVR2,
+        "attiny22" => elf::EF_AVR_ARCH_AVR2,
+        "attiny26" => elf::EF_AVR_ARCH_AVR2,
+        "at86rf401" => elf::EF_AVR_ARCH_AVR25,
+        "at90s4414" => elf::EF_AVR_ARCH_AVR2,
+        "at90s4433" => elf::EF_AVR_ARCH_AVR2,
+        "at90s4434" => elf::EF_AVR_ARCH_AVR2,
+        "at90s8515" => elf::EF_AVR_ARCH_AVR2,
+        "at90c8534" => elf::EF_AVR_ARCH_AVR2,
+        "at90s8535" => elf::EF_AVR_ARCH_AVR2,
+        "ata5272" => elf::EF_AVR_ARCH_AVR25,
+        "ata6616c" => elf::EF_AVR_ARCH_AVR25,
+        "attiny13" => elf::EF_AVR_ARCH_AVR25,
+        "attiny13a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny2313" => elf::EF_AVR_ARCH_AVR25,
+        "attiny2313a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny24" => elf::EF_AVR_ARCH_AVR25,
+        "attiny24a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny4313" => elf::EF_AVR_ARCH_AVR25,
+        "attiny44" => elf::EF_AVR_ARCH_AVR25,
+        "attiny44a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny84" => elf::EF_AVR_ARCH_AVR25,
+        "attiny84a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny25" => elf::EF_AVR_ARCH_AVR25,
+        "attiny45" => elf::EF_AVR_ARCH_AVR25,
+        "attiny85" => elf::EF_AVR_ARCH_AVR25,
+        "attiny261" => elf::EF_AVR_ARCH_AVR25,
+        "attiny261a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny441" => elf::EF_AVR_ARCH_AVR25,
+        "attiny461" => elf::EF_AVR_ARCH_AVR25,
+        "attiny461a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny841" => elf::EF_AVR_ARCH_AVR25,
+        "attiny861" => elf::EF_AVR_ARCH_AVR25,
+        "attiny861a" => elf::EF_AVR_ARCH_AVR25,
+        "attiny87" => elf::EF_AVR_ARCH_AVR25,
+        "attiny43u" => elf::EF_AVR_ARCH_AVR25,
+        "attiny48" => elf::EF_AVR_ARCH_AVR25,
+        "attiny88" => elf::EF_AVR_ARCH_AVR25,
+        "attiny828" => elf::EF_AVR_ARCH_AVR25,
+        "at43usb355" => elf::EF_AVR_ARCH_AVR3,
+        "at76c711" => elf::EF_AVR_ARCH_AVR3,
+        "atmega103" => elf::EF_AVR_ARCH_AVR31,
+        "at43usb320" => elf::EF_AVR_ARCH_AVR31,
+        "attiny167" => elf::EF_AVR_ARCH_AVR35,
+        "at90usb82" => elf::EF_AVR_ARCH_AVR35,
+        "at90usb162" => elf::EF_AVR_ARCH_AVR35,
+        "ata5505" => elf::EF_AVR_ARCH_AVR35,
+        "ata6617c" => elf::EF_AVR_ARCH_AVR35,
+        "ata664251" => elf::EF_AVR_ARCH_AVR35,
+        "atmega8u2" => elf::EF_AVR_ARCH_AVR35,
+        "atmega16u2" => elf::EF_AVR_ARCH_AVR35,
+        "atmega32u2" => elf::EF_AVR_ARCH_AVR35,
+        "attiny1634" => elf::EF_AVR_ARCH_AVR35,
+        "atmega8" => elf::EF_AVR_ARCH_AVR4,
+        "ata6289" => elf::EF_AVR_ARCH_AVR4,
+        "atmega8a" => elf::EF_AVR_ARCH_AVR4,
+        "ata6285" => elf::EF_AVR_ARCH_AVR4,
+        "ata6286" => elf::EF_AVR_ARCH_AVR4,
+        "ata6612c" => elf::EF_AVR_ARCH_AVR4,
+        "atmega48" => elf::EF_AVR_ARCH_AVR4,
+        "atmega48a" => elf::EF_AVR_ARCH_AVR4,
+        "atmega48pa" => elf::EF_AVR_ARCH_AVR4,
+        "atmega48pb" => elf::EF_AVR_ARCH_AVR4,
+        "atmega48p" => elf::EF_AVR_ARCH_AVR4,
+        "atmega88" => elf::EF_AVR_ARCH_AVR4,
+        "atmega88a" => elf::EF_AVR_ARCH_AVR4,
+        "atmega88p" => elf::EF_AVR_ARCH_AVR4,
+        "atmega88pa" => elf::EF_AVR_ARCH_AVR4,
+        "atmega88pb" => elf::EF_AVR_ARCH_AVR4,
+        "atmega8515" => elf::EF_AVR_ARCH_AVR4,
+        "atmega8535" => elf::EF_AVR_ARCH_AVR4,
+        "atmega8hva" => elf::EF_AVR_ARCH_AVR4,
+        "at90pwm1" => elf::EF_AVR_ARCH_AVR4,
+        "at90pwm2" => elf::EF_AVR_ARCH_AVR4,
+        "at90pwm2b" => elf::EF_AVR_ARCH_AVR4,
+        "at90pwm3" => elf::EF_AVR_ARCH_AVR4,
+        "at90pwm3b" => elf::EF_AVR_ARCH_AVR4,
+        "at90pwm81" => elf::EF_AVR_ARCH_AVR4,
+        "ata5702m322" => elf::EF_AVR_ARCH_AVR5,
+        "ata5782" => elf::EF_AVR_ARCH_AVR5,
+        "ata5790" => elf::EF_AVR_ARCH_AVR5,
+        "ata5790n" => elf::EF_AVR_ARCH_AVR5,
+        "ata5791" => elf::EF_AVR_ARCH_AVR5,
+        "ata5795" => elf::EF_AVR_ARCH_AVR5,
+        "ata5831" => elf::EF_AVR_ARCH_AVR5,
+        "ata6613c" => elf::EF_AVR_ARCH_AVR5,
+        "ata6614q" => elf::EF_AVR_ARCH_AVR5,
+        "ata8210" => elf::EF_AVR_ARCH_AVR5,
+        "ata8510" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega161" => elf::EF_AVR_ARCH_AVR5,
+        "atmega162" => elf::EF_AVR_ARCH_AVR5,
+        "atmega163" => elf::EF_AVR_ARCH_AVR5,
+        "atmega164a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega164p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega164pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega165" => elf::EF_AVR_ARCH_AVR5,
+        "atmega165a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega165p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega165pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega168" => elf::EF_AVR_ARCH_AVR5,
+        "atmega168a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega168p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega168pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega168pb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega169" => elf::EF_AVR_ARCH_AVR5,
+        "atmega169a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega169p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega169pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega323" => elf::EF_AVR_ARCH_AVR5,
+        "atmega324a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega324p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega324pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega324pb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega325" => elf::EF_AVR_ARCH_AVR5,
+        "atmega325a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega325p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega325pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3250" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3250a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3250p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3250pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega328" => elf::EF_AVR_ARCH_AVR5,
+        "atmega328p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega328pb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega329" => elf::EF_AVR_ARCH_AVR5,
+        "atmega329a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega329p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega329pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3290" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3290a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3290p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega3290pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega406" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega640" => elf::EF_AVR_ARCH_AVR5,
+        "atmega644" => elf::EF_AVR_ARCH_AVR5,
+        "atmega644a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega644p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega644pa" => elf::EF_AVR_ARCH_AVR5,
+        "atmega645" => elf::EF_AVR_ARCH_AVR5,
+        "atmega645a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega645p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega649" => elf::EF_AVR_ARCH_AVR5,
+        "atmega649a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega649p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega6450" => elf::EF_AVR_ARCH_AVR5,
+        "atmega6450a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega6450p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega6490" => elf::EF_AVR_ARCH_AVR5,
+        "atmega6490a" => elf::EF_AVR_ARCH_AVR5,
+        "atmega6490p" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64rfr2" => elf::EF_AVR_ARCH_AVR5,
+        "atmega644rfr2" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16hva" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16hva2" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16hvb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16hvbrevb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32hvb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32hvbrevb" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64hve" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64hve2" => elf::EF_AVR_ARCH_AVR5,
+        "at90can32" => elf::EF_AVR_ARCH_AVR5,
+        "at90can64" => elf::EF_AVR_ARCH_AVR5,
+        "at90pwm161" => elf::EF_AVR_ARCH_AVR5,
+        "at90pwm216" => elf::EF_AVR_ARCH_AVR5,
+        "at90pwm316" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32c1" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64c1" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16m1" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32m1" => elf::EF_AVR_ARCH_AVR5,
+        "atmega64m1" => elf::EF_AVR_ARCH_AVR5,
+        "atmega16u4" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32u4" => elf::EF_AVR_ARCH_AVR5,
+        "atmega32u6" => elf::EF_AVR_ARCH_AVR5,
+        "at90usb646" => elf::EF_AVR_ARCH_AVR5,
+        "at90usb647" => elf::EF_AVR_ARCH_AVR5,
+        "at90scr100" => elf::EF_AVR_ARCH_AVR5,
+        "at94k" => elf::EF_AVR_ARCH_AVR5,
+        "m3000" => elf::EF_AVR_ARCH_AVR5,
+        "atmega128" => elf::EF_AVR_ARCH_AVR51,
+        "atmega128a" => elf::EF_AVR_ARCH_AVR51,
+        "atmega1280" => elf::EF_AVR_ARCH_AVR51,
+        "atmega1281" => elf::EF_AVR_ARCH_AVR51,
+        "atmega1284" => elf::EF_AVR_ARCH_AVR51,
+        "atmega1284p" => elf::EF_AVR_ARCH_AVR51,
+        "atmega128rfa1" => elf::EF_AVR_ARCH_AVR51,
+        "atmega128rfr2" => elf::EF_AVR_ARCH_AVR51,
+        "atmega1284rfr2" => elf::EF_AVR_ARCH_AVR51,
+        "at90can128" => elf::EF_AVR_ARCH_AVR51,
+        "at90usb1286" => elf::EF_AVR_ARCH_AVR51,
+        "at90usb1287" => elf::EF_AVR_ARCH_AVR51,
+        "atmega2560" => elf::EF_AVR_ARCH_AVR6,
+        "atmega2561" => elf::EF_AVR_ARCH_AVR6,
+        "atmega256rfr2" => elf::EF_AVR_ARCH_AVR6,
+        "atmega2564rfr2" => elf::EF_AVR_ARCH_AVR6,
+        "atxmega16a4" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega16a4u" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega16c4" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega16d4" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32a4" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32a4u" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32c3" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32c4" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32d3" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32d4" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega32e5" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega16e5" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega8e5" => elf::EF_AVR_ARCH_XMEGA2,
+        "atxmega64a3" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64a3u" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64a4u" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64b1" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64b3" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64c3" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64d3" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64d4" => elf::EF_AVR_ARCH_XMEGA4,
+        "atxmega64a1" => elf::EF_AVR_ARCH_XMEGA5,
+        "atxmega64a1u" => elf::EF_AVR_ARCH_XMEGA5,
+        "atxmega128a3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128a3u" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128b1" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128b3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128c3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128d3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128d4" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega192a3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega192a3u" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega192c3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega192d3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega256a3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega256a3u" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega256a3b" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega256a3bu" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega256c3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega256d3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega384c3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega384d3" => elf::EF_AVR_ARCH_XMEGA6,
+        "atxmega128a1" => elf::EF_AVR_ARCH_XMEGA7,
+        "atxmega128a1u" => elf::EF_AVR_ARCH_XMEGA7,
+        "atxmega128a4u" => elf::EF_AVR_ARCH_XMEGA7,
+        "attiny4" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny5" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny9" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny10" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny20" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny40" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny102" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny104" => elf::EF_AVR_ARCH_AVRTINY,
+        "attiny202" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny402" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny204" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny404" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny804" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1604" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny406" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny806" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1606" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny807" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1607" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny212" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny412" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny214" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny414" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny814" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1614" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny416" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny816" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1616" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny3216" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny417" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny817" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1617" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny3217" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1624" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1626" => elf::EF_AVR_ARCH_XMEGA3,
+        "attiny1627" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega808" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega809" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega1608" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega1609" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega3208" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega3209" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega4808" => elf::EF_AVR_ARCH_XMEGA3,
+        "atmega4809" => elf::EF_AVR_ARCH_XMEGA3,
+
+        // Unknown target CPU => Unspecified/generic code
+        _ => 0,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 88fbe2a8be1..2e5bb3db886 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -62,6 +62,7 @@ mod android_base;
 mod apple_base;
 pub use apple_base::deployment_target as current_apple_deployment_target;
 mod avr_gnu_base;
+pub use avr_gnu_base::ef_avr_arch;
 mod bpf_base;
 mod dragonfly_base;
 mod freebsd_base;
@@ -160,15 +161,49 @@ pub enum LinkerFlavor {
 /// linker flavors (`LinkerFlavor`).
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
 pub enum LinkerFlavorCli {
+    // New (unstable) flavors, with direct counterparts in `LinkerFlavor`.
+    Gnu(Cc, Lld),
+    Darwin(Cc, Lld),
+    WasmLld(Cc),
+    Unix(Cc),
+    // Note: `Msvc(Lld::No)` is also a stable value.
+    Msvc(Lld),
+    EmCc,
+    Bpf,
+    Ptx,
+
+    // Below: the legacy stable values.
     Gcc,
     Ld,
     Lld(LldFlavor),
-    Msvc,
     Em,
     BpfLinker,
     PtxLinker,
 }
 
+impl LinkerFlavorCli {
+    /// Returns whether this `-C linker-flavor` option is one of the unstable values.
+    pub fn is_unstable(&self) -> bool {
+        match self {
+            LinkerFlavorCli::Gnu(..)
+            | LinkerFlavorCli::Darwin(..)
+            | LinkerFlavorCli::WasmLld(..)
+            | LinkerFlavorCli::Unix(..)
+            | LinkerFlavorCli::Msvc(Lld::Yes)
+            | LinkerFlavorCli::EmCc
+            | LinkerFlavorCli::Bpf
+            | LinkerFlavorCli::Ptx
+            | LinkerFlavorCli::BpfLinker
+            | LinkerFlavorCli::PtxLinker => true,
+            LinkerFlavorCli::Gcc
+            | LinkerFlavorCli::Ld
+            | LinkerFlavorCli::Lld(..)
+            | LinkerFlavorCli::Msvc(Lld::No)
+            | LinkerFlavorCli::Em => false,
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
 pub enum LldFlavor {
     Wasm,
@@ -211,6 +246,16 @@ impl LinkerFlavor {
     /// of truth, other flags are used in case of ambiguities.
     fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
         match cli {
+            LinkerFlavorCli::Gnu(cc, lld) => LinkerFlavor::Gnu(cc, lld),
+            LinkerFlavorCli::Darwin(cc, lld) => LinkerFlavor::Darwin(cc, lld),
+            LinkerFlavorCli::WasmLld(cc) => LinkerFlavor::WasmLld(cc),
+            LinkerFlavorCli::Unix(cc) => LinkerFlavor::Unix(cc),
+            LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
+            LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
+            LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
+            LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
+
+            // Below: legacy stable values
             LinkerFlavorCli::Gcc => match lld_flavor {
                 LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
                 LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::Yes, Lld::No),
@@ -226,7 +271,6 @@ impl LinkerFlavor {
             LinkerFlavorCli::Lld(LldFlavor::Ld64) => LinkerFlavor::Darwin(Cc::No, Lld::Yes),
             LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No),
             LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes),
-            LinkerFlavorCli::Msvc => LinkerFlavor::Msvc(Lld::No),
             LinkerFlavorCli::Em => LinkerFlavor::EmCc,
             LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf,
             LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx,
@@ -246,7 +290,7 @@ impl LinkerFlavor {
                 LinkerFlavorCli::Ld
             }
             LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link),
-            LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc,
+            LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
             LinkerFlavor::EmCc => LinkerFlavorCli::Em,
             LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker,
             LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker,
@@ -255,9 +299,20 @@ impl LinkerFlavor {
 
     fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
         match cli {
-            LinkerFlavorCli::Gcc | LinkerFlavorCli::Em => (Some(Cc::Yes), None),
+            LinkerFlavorCli::Gnu(cc, lld) | LinkerFlavorCli::Darwin(cc, lld) => {
+                (Some(cc), Some(lld))
+            }
+            LinkerFlavorCli::WasmLld(cc) => (Some(cc), Some(Lld::Yes)),
+            LinkerFlavorCli::Unix(cc) => (Some(cc), None),
+            LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
+            LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
+            LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
+
+            // Below: legacy stable values
+            LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
+            LinkerFlavorCli::Ld => (Some(Cc::No), Some(Lld::No)),
             LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)),
-            LinkerFlavorCli::Ld | LinkerFlavorCli::Msvc => (Some(Cc::No), Some(Lld::No)),
+            LinkerFlavorCli::Em => (Some(Cc::Yes), Some(Lld::Yes)),
             LinkerFlavorCli::BpfLinker | LinkerFlavorCli::PtxLinker => (None, None),
         }
     }
@@ -320,8 +375,24 @@ impl LinkerFlavor {
     }
 
     pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
-        // The CLI flavor should be compatible with the target if it survives this roundtrip.
-        let compatible = |cli| cli == self.with_cli_hints(cli).to_cli();
+        let compatible = |cli| {
+            // The CLI flavor should be compatible with the target if:
+            // 1. they are counterparts: they have the same principal flavor.
+            match (self, cli) {
+                (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
+                | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
+                | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
+                | (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
+                | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
+                | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
+                | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
+                | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
+                _ => {}
+            }
+
+            // 2. or, the flavor is legacy and survives this roundtrip.
+            cli == self.with_cli_hints(cli).to_cli()
+        };
         (!compatible(cli)).then(|| {
             LinkerFlavorCli::all()
                 .iter()
@@ -348,6 +419,43 @@ impl LinkerFlavor {
     pub fn is_gnu(self) -> bool {
         matches!(self, LinkerFlavor::Gnu(..))
     }
+
+    /// Returns whether the flavor uses the `lld` linker.
+    pub fn uses_lld(self) -> bool {
+        // Exhaustive match in case new flavors are added in the future.
+        match self {
+            LinkerFlavor::Gnu(_, Lld::Yes)
+            | LinkerFlavor::Darwin(_, Lld::Yes)
+            | LinkerFlavor::WasmLld(..)
+            | LinkerFlavor::EmCc
+            | LinkerFlavor::Msvc(Lld::Yes) => true,
+            LinkerFlavor::Gnu(..)
+            | LinkerFlavor::Darwin(..)
+            | LinkerFlavor::Msvc(_)
+            | LinkerFlavor::Unix(_)
+            | LinkerFlavor::Bpf
+            | LinkerFlavor::Ptx => false,
+        }
+    }
+
+    /// Returns whether the flavor calls the linker via a C/C++ compiler.
+    pub fn uses_cc(self) -> bool {
+        // Exhaustive match in case new flavors are added in the future.
+        match self {
+            LinkerFlavor::Gnu(Cc::Yes, _)
+            | LinkerFlavor::Darwin(Cc::Yes, _)
+            | LinkerFlavor::WasmLld(Cc::Yes)
+            | LinkerFlavor::Unix(Cc::Yes)
+            | LinkerFlavor::EmCc => true,
+            LinkerFlavor::Gnu(..)
+            | LinkerFlavor::Darwin(..)
+            | LinkerFlavor::WasmLld(_)
+            | LinkerFlavor::Msvc(_)
+            | LinkerFlavor::Unix(_)
+            | LinkerFlavor::Bpf
+            | LinkerFlavor::Ptx => false,
+        }
+    }
 }
 
 macro_rules! linker_flavor_cli_impls {
@@ -378,13 +486,31 @@ macro_rules! linker_flavor_cli_impls {
 }
 
 linker_flavor_cli_impls! {
+    (LinkerFlavorCli::Gnu(Cc::No, Lld::No)) "gnu"
+    (LinkerFlavorCli::Gnu(Cc::No, Lld::Yes)) "gnu-lld"
+    (LinkerFlavorCli::Gnu(Cc::Yes, Lld::No)) "gnu-cc"
+    (LinkerFlavorCli::Gnu(Cc::Yes, Lld::Yes)) "gnu-lld-cc"
+    (LinkerFlavorCli::Darwin(Cc::No, Lld::No)) "darwin"
+    (LinkerFlavorCli::Darwin(Cc::No, Lld::Yes)) "darwin-lld"
+    (LinkerFlavorCli::Darwin(Cc::Yes, Lld::No)) "darwin-cc"
+    (LinkerFlavorCli::Darwin(Cc::Yes, Lld::Yes)) "darwin-lld-cc"
+    (LinkerFlavorCli::WasmLld(Cc::No)) "wasm-lld"
+    (LinkerFlavorCli::WasmLld(Cc::Yes)) "wasm-lld-cc"
+    (LinkerFlavorCli::Unix(Cc::No)) "unix"
+    (LinkerFlavorCli::Unix(Cc::Yes)) "unix-cc"
+    (LinkerFlavorCli::Msvc(Lld::Yes)) "msvc-lld"
+    (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
+    (LinkerFlavorCli::EmCc) "em-cc"
+    (LinkerFlavorCli::Bpf) "bpf"
+    (LinkerFlavorCli::Ptx) "ptx"
+
+    // Below: legacy stable values
     (LinkerFlavorCli::Gcc) "gcc"
     (LinkerFlavorCli::Ld) "ld"
     (LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
     (LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
     (LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
     (LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
-    (LinkerFlavorCli::Msvc) "msvc"
     (LinkerFlavorCli::Em) "em"
     (LinkerFlavorCli::BpfLinker) "bpf-linker"
     (LinkerFlavorCli::PtxLinker) "ptx-linker"
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 5c62ea64f99..fc848fe3080 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -26,20 +26,27 @@ use super::{Certainty, InferCtxtEvalExt};
 /// here as this will have to deal with far more root goals than `evaluate_all`.
 pub struct FulfillmentCtxt<'tcx> {
     obligations: Vec<PredicateObligation<'tcx>>,
+
+    /// The snapshot in which this context was created. Using the context
+    /// outside of this snapshot leads to subtle bugs if the snapshot
+    /// gets rolled back. Because of this we explicitly check that we only
+    /// use the context in exactly this snapshot.
+    usable_in_snapshot: usize,
 }
 
 impl<'tcx> FulfillmentCtxt<'tcx> {
-    pub fn new() -> FulfillmentCtxt<'tcx> {
-        FulfillmentCtxt { obligations: Vec::new() }
+    pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> {
+        FulfillmentCtxt { obligations: Vec::new(), usable_in_snapshot: infcx.num_open_snapshots() }
     }
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
     fn register_predicate_obligation(
         &mut self,
-        _infcx: &InferCtxt<'tcx>,
+        infcx: &InferCtxt<'tcx>,
         obligation: PredicateObligation<'tcx>,
     ) {
+        assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
         self.obligations.push(obligation);
     }
 
@@ -77,6 +84,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
     }
 
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
         let mut errors = Vec::new();
         for i in 0.. {
             if !infcx.tcx.recursion_limit().value_within_limit(i) {
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 28967e1cc55..3ecae429c59 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -13,16 +13,19 @@ use rustc_middle::ty::TypeVisitableExt;
 pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
 
-    usable_in_snapshot: bool,
+    /// The snapshot in which this context was created. Using the context
+    /// outside of this snapshot leads to subtle bugs if the snapshot
+    /// gets rolled back. Because of this we explicitly check that we only
+    /// use the context in exactly this snapshot.
+    usable_in_snapshot: usize,
 }
 
-impl FulfillmentContext<'_> {
-    pub(super) fn new() -> Self {
-        FulfillmentContext { obligations: FxIndexSet::default(), usable_in_snapshot: false }
-    }
-
-    pub(crate) fn new_in_snapshot() -> Self {
-        FulfillmentContext { usable_in_snapshot: true, ..Self::new() }
+impl<'tcx> FulfillmentContext<'tcx> {
+    pub(super) fn new(infcx: &InferCtxt<'tcx>) -> Self {
+        FulfillmentContext {
+            obligations: FxIndexSet::default(),
+            usable_in_snapshot: infcx.num_open_snapshots(),
+        }
     }
 }
 
@@ -32,9 +35,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         infcx: &InferCtxt<'tcx>,
         obligation: PredicateObligation<'tcx>,
     ) {
-        if !self.usable_in_snapshot {
-            assert!(!infcx.is_in_snapshot());
-        }
+        assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
         let obligation = infcx.resolve_vars_if_possible(obligation);
 
         self.obligations.insert(obligation);
@@ -58,9 +59,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     }
 
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
-        if !self.usable_in_snapshot {
-            assert!(!infcx.is_in_snapshot());
-        }
+        assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
 
         let mut errors = Vec::new();
         let mut next_round = FxIndexSet::default();
@@ -94,12 +93,11 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                                 &orig_values,
                                 &response,
                             ) {
-                                Ok(infer_ok) => next_round.extend(
-                                    infer_ok.obligations.into_iter().map(|obligation| {
-                                        assert!(!infcx.is_in_snapshot());
-                                        infcx.resolve_vars_if_possible(obligation)
-                                    }),
-                                ),
+                                Ok(infer_ok) => {
+                                    next_round.extend(infer_ok.obligations.into_iter().map(
+                                        |obligation| infcx.resolve_vars_if_possible(obligation),
+                                    ))
+                                }
 
                                 Err(_err) => errors.push(FulfillmentError {
                                     obligation: obligation.clone(),
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index ab4727b8697..8dc13b827e5 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -176,7 +176,7 @@ fn satisfied_from_param_env<'tcx>(
         fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             debug!("is_const_evaluatable: candidate={:?}", c);
             if self.infcx.probe(|_| {
-                let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+                let ocx = ObligationCtxt::new(self.infcx);
                 ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok()
                     && ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
                     && ocx.select_all_or_error().is_empty()
@@ -219,7 +219,7 @@ fn satisfied_from_param_env<'tcx>(
     }
 
     if let Some(Ok(c)) = single_match {
-        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let ocx = ObligationCtxt::new(infcx);
         assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
         assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
         assert!(ocx.select_all_or_error().is_empty());
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 90699c3cadc..faa675054b7 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -28,36 +28,18 @@ use rustc_span::Span;
 
 pub trait TraitEngineExt<'tcx> {
     fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
-    fn new_in_snapshot(infcx: &InferCtxt<'tcx>) -> Box<Self>;
 }
 
 impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
     fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
         match (infcx.tcx.sess.opts.unstable_opts.trait_solver, infcx.next_trait_solver()) {
             (TraitSolver::Classic, false) | (TraitSolver::NextCoherence, false) => {
-                Box::new(FulfillmentContext::new())
+                Box::new(FulfillmentContext::new(infcx))
             }
             (TraitSolver::Next | TraitSolver::NextCoherence, true) => {
-                Box::new(NextFulfillmentCtxt::new())
+                Box::new(NextFulfillmentCtxt::new(infcx))
             }
-            (TraitSolver::Chalk, false) => Box::new(ChalkFulfillmentContext::new()),
-            _ => bug!(
-                "incompatible combination of -Ztrait-solver flag ({:?}) and InferCtxt::next_trait_solver ({:?})",
-                infcx.tcx.sess.opts.unstable_opts.trait_solver,
-                infcx.next_trait_solver()
-            ),
-        }
-    }
-
-    fn new_in_snapshot(infcx: &InferCtxt<'tcx>) -> Box<Self> {
-        match (infcx.tcx.sess.opts.unstable_opts.trait_solver, infcx.next_trait_solver()) {
-            (TraitSolver::Classic, false) | (TraitSolver::NextCoherence, false) => {
-                Box::new(FulfillmentContext::new_in_snapshot())
-            }
-            (TraitSolver::Next | TraitSolver::NextCoherence, true) => {
-                Box::new(NextFulfillmentCtxt::new())
-            }
-            (TraitSolver::Chalk, false) => Box::new(ChalkFulfillmentContext::new_in_snapshot()),
+            (TraitSolver::Chalk, false) => Box::new(ChalkFulfillmentContext::new(infcx)),
             _ => bug!(
                 "incompatible combination of -Ztrait-solver flag ({:?}) and InferCtxt::next_trait_solver ({:?})",
                 infcx.tcx.sess.opts.unstable_opts.trait_solver,
@@ -79,10 +61,6 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx)) }
     }
 
-    pub fn new_in_snapshot(infcx: &'a InferCtxt<'tcx>) -> Self {
-        Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new_in_snapshot(infcx)) }
-    }
-
     pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
         self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 96c183f9a58..7b5d4f456ff 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -20,7 +20,7 @@ pub fn recompute_applicable_impls<'tcx>(
     let param_env = obligation.param_env;
 
     let impl_may_apply = |impl_def_id| {
-        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let ocx = ObligationCtxt::new(infcx);
         let placeholder_obligation =
             infcx.instantiate_binder_with_placeholders(obligation.predicate);
         let obligation_trait_ref =
@@ -45,7 +45,7 @@ pub fn recompute_applicable_impls<'tcx>(
     };
 
     let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
-        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let ocx = ObligationCtxt::new(infcx);
         let placeholder_obligation =
             infcx.instantiate_binder_with_placeholders(obligation.predicate);
         let obligation_trait_ref =
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index c259260c1fa..f7670d51bdc 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -377,7 +377,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                     param_env,
                     ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }),
                 );
-                let ocx = ObligationCtxt::new_in_snapshot(self);
+                let ocx = ObligationCtxt::new(self);
                 ocx.register_obligation(obligation);
                 if ocx.select_all_or_error().is_empty() {
                     return Ok((
@@ -1599,7 +1599,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         self.probe(|_| {
-            let ocx = ObligationCtxt::new_in_snapshot(self);
+            let ocx = ObligationCtxt::new(self);
 
             // try to find the mismatched types to report the error with.
             //
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 43b63762ba3..619a099fcb5 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -3825,7 +3825,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
-        let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+        let ocx = ObligationCtxt::new(self.infcx);
         let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
         for diff in type_diffs {
             let Sorts(expected_found) = diff else { continue; };
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index f2f99eb60e4..e3472a1c4c1 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -50,20 +50,15 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
 /// method `select_all_or_error` can be used to report any remaining
 /// ambiguous cases as errors.
 pub struct FulfillmentContext<'tcx> {
-    // A list of all obligations that have been registered with this
-    // fulfillment context.
+    /// A list of all obligations that have been registered with this
+    /// fulfillment context.
     predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
 
-    // Is it OK to register obligations into this infcx inside
-    // an infcx snapshot?
-    //
-    // The "primary fulfillment" in many cases in typeck lives
-    // outside of any snapshot, so any use of it inside a snapshot
-    // will lead to trouble and therefore is checked against, but
-    // other fulfillment contexts sometimes do live inside of
-    // a snapshot (they don't *straddle* a snapshot, so there
-    // is no trouble there).
-    usable_in_snapshot: bool,
+    /// The snapshot in which this context was created. Using the context
+    /// outside of this snapshot leads to subtle bugs if the snapshot
+    /// gets rolled back. Because of this we explicitly check that we only
+    /// use the context in exactly this snapshot.
+    usable_in_snapshot: usize,
 }
 
 #[derive(Clone, Debug)]
@@ -80,18 +75,17 @@ pub struct PendingPredicateObligation<'tcx> {
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(PendingPredicateObligation<'_>, 72);
 
-impl<'a, 'tcx> FulfillmentContext<'tcx> {
+impl<'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
-    pub(super) fn new() -> FulfillmentContext<'tcx> {
-        FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: false }
-    }
-
-    pub(super) fn new_in_snapshot() -> FulfillmentContext<'tcx> {
-        FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: true }
+    pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> {
+        FulfillmentContext {
+            predicates: ObligationForest::new(),
+            usable_in_snapshot: infcx.num_open_snapshots(),
+        }
     }
 
     /// Attempts to select obligations using `selcx`.
-    fn select(&mut self, selcx: SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+    fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
         let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
         let _enter = span.enter();
 
@@ -122,14 +116,13 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         infcx: &InferCtxt<'tcx>,
         obligation: PredicateObligation<'tcx>,
     ) {
+        assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
         // this helps to reduce duplicate errors, as well as making
         // debug output much nicer to read and so on.
         let obligation = infcx.resolve_vars_if_possible(obligation);
 
         debug!(?obligation, "register_predicate_obligation");
 
-        assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
-
         self.predicates
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index ae76651c336..5dc5ddbddbd 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -161,7 +161,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
         // the we do no inference in the process of checking this obligation.
         let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
         infcx.probe(|_| {
-            let ocx = ObligationCtxt::new_in_snapshot(infcx);
+            let ocx = ObligationCtxt::new(infcx);
             ocx.register_obligation(obligation);
 
             let errors = ocx.select_all_or_error();
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 60712ad05f1..8fd77335074 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -500,10 +500,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
         // to make sure we don't forget to fold the substs regardless.
 
         match kind {
-            // This is really important. While we *can* handle this, this has
-            // severe performance implications for large opaque types with
-            // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque if !data.substs.has_escaping_bound_vars() => {
+            ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.super_fold_with(self),
@@ -529,7 +526,6 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
                     }
                 }
             }
-            ty::Opaque => ty.super_fold_with(self),
 
             ty::Projection if !data.has_escaping_bound_vars() => {
                 // This branch is *mostly* just an optimization: when we don't
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index c93c30b7053..e29e1b25919 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -80,7 +80,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
 
         if self.next_trait_solver() {
             self.probe(|snapshot| {
-                let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
+                let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self);
                 fulfill_cx.register_predicate_obligation(self, obligation.clone());
                 // True errors
                 // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK?
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 1b6e92946c4..edad519cec2 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -211,10 +211,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
 
         // Wrap this in a closure so we don't accidentally return from the outer function
         let res = match kind {
-            // This is really important. While we *can* handle this, this has
-            // severe performance implications for large opaque types with
-            // late-bound regions. See `issue-88862` benchmark.
-            ty::Opaque if !data.substs.has_escaping_bound_vars() => {
+            ty::Opaque => {
                 // Only normalize `impl Trait` outside of type inference, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty.try_super_fold_with(self)?,
@@ -255,8 +252,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                 }
             }
 
-            ty::Opaque => ty.try_super_fold_with(self)?,
-
             ty::Projection | ty::Inherent | ty::Weak => {
                 // See note in `rustc_trait_selection::traits::project`
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 8b0973021bc..5420caee329 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -82,7 +82,7 @@ where
     );
 
     let value = infcx.commit_if_ok(|_| {
-        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let ocx = ObligationCtxt::new(infcx);
         let value = op(&ocx).map_err(|_| {
             infcx.tcx.sess.delay_span_bug(span, format!("error performing operation: {name}"))
         })?;
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 7406b47e327..7cf8479b803 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -606,7 +606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>,
     ) -> Result<EvaluationResult, OverflowError> {
-        let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
+        let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self.infcx);
         fulfill_cx.register_predicate_obligations(self.infcx, predicates);
         // True errors
         // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK?
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index fee38aed0e2..96f1287416f 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -238,7 +238,7 @@ fn fulfill_implication<'tcx>(
 
     // Needs to be `in_snapshot` because this function is used to rebase
     // substitutions, which may happen inside of a select within a probe.
-    let ocx = ObligationCtxt::new_in_snapshot(infcx);
+    let ocx = ObligationCtxt::new(infcx);
     // attempt to prove all of the predicates for impl2 given those for impl1
     // (which are packed up in penv)
     ocx.register_obligations(obligations.chain(more_obligations));
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index dfd6fbff7c9..189f72d478e 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -11,9 +11,9 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-chalk-ir = "0.87.0"
-chalk-engine = "0.87.0"
-chalk-solve = "0.87.0"
+chalk-ir = "0.92.0"
+chalk-engine = "0.92.0"
+chalk-solve = "0.92.0"
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 rustc_infer = { path = "../rustc_infer" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 6948151c644..0435cd63e80 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -572,6 +572,8 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
             DiscriminantKind => lang_items.discriminant_kind_trait(),
             DispatchFromDyn => lang_items.dispatch_from_dyn_trait(),
             Tuple => lang_items.tuple_trait(),
+            Pointee => lang_items.pointee_trait(),
+            FnPtr => lang_items.fn_ptr_trait(),
         };
         def_id.map(chalk_ir::TraitId)
     }
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 5f84acc8a04..ef50fa23caf 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -5,7 +5,7 @@
 
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
-use rustc_middle::traits::{CodegenObligationError, DefiningAnchor};
+use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::{
@@ -29,13 +29,7 @@ pub fn codegen_select_candidate<'tcx>(
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let infcx = tcx
-        .infer_ctxt()
-        .ignoring_regions()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
-        .build();
-    //~^ HACK `Bubble` is required for
-    // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
+    let infcx = tcx.infer_ctxt().ignoring_regions().build();
     let mut selcx = SelectionContext::new(&infcx);
 
     let obligation_cause = ObligationCause::dummy();
@@ -79,10 +73,5 @@ pub fn codegen_select_candidate<'tcx>(
     let impl_source = infcx.resolve_vars_if_possible(impl_source);
     let impl_source = infcx.tcx.erase_regions(impl_source);
 
-    // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
-    // as they will get constrained elsewhere, too.
-    // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
-    let _ = infcx.take_opaque_types();
-
     Ok(&*tcx.arena.alloc(impl_source))
 }
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 6b718be7b15..be434eb7d00 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -192,8 +192,8 @@ pub(crate) mod rustc {
         TypeError(ErrorGuaranteed),
     }
 
-    impl<'tcx> From<LayoutError<'tcx>> for Err {
-        fn from(err: LayoutError<'tcx>) -> Self {
+    impl<'tcx> From<&LayoutError<'tcx>> for Err {
+        fn from(err: &LayoutError<'tcx>) -> Self {
             match err {
                 LayoutError::Unknown(..) => Self::UnknownLayout,
                 err => unimplemented!("{:?}", err),
@@ -221,7 +221,7 @@ pub(crate) mod rustc {
     }
 
     impl LayoutSummary {
-        fn from_ty<'tcx>(ty: Ty<'tcx>, ctx: TyCtxt<'tcx>) -> Result<Self, LayoutError<'tcx>> {
+        fn from_ty<'tcx>(ty: Ty<'tcx>, ctx: TyCtxt<'tcx>) -> Result<Self, &'tcx LayoutError<'tcx>> {
             use rustc_middle::ty::ParamEnvAnd;
             use rustc_target::abi::{TyAndLayout, Variants};
 
@@ -482,7 +482,7 @@ pub(crate) mod rustc {
     fn layout_of<'tcx>(
         ctx: TyCtxt<'tcx>,
         ty: Ty<'tcx>,
-    ) -> Result<alloc::Layout, LayoutError<'tcx>> {
+    ) -> Result<alloc::Layout, &'tcx LayoutError<'tcx>> {
         use rustc_middle::ty::ParamEnvAnd;
         use rustc_target::abi::TyAndLayout;
 
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 5b3ffc9fc36..8e2a79dd4d4 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -202,7 +202,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
 fn fn_abi_of_fn_ptr<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
     let (param_env, (sig, extra_args)) = query.into_parts();
 
     let cx = LayoutCx { tcx, param_env };
@@ -212,7 +212,7 @@ fn fn_abi_of_fn_ptr<'tcx>(
 fn fn_abi_of_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
     let (param_env, (instance, extra_args)) = query.into_parts();
 
     let sig = fn_sig_for_fn_abi(tcx, instance, param_env);
@@ -331,7 +331,7 @@ fn fn_abi_new_uncached<'tcx>(
     fn_def_id: Option<DefId>,
     // FIXME(eddyb) replace this with something typed, like an `enum`.
     force_thin_self_ptr: bool,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
     let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
 
     let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
@@ -376,7 +376,7 @@ fn fn_abi_new_uncached<'tcx>(
     let is_drop_in_place =
         fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn();
 
-    let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
+    let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
         let span = tracing::debug_span!("arg_of");
         let _entered = span.enter();
         let is_return = arg_idx.is_none();
@@ -386,7 +386,8 @@ fn fn_abi_new_uncached<'tcx>(
             _ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty),
         });
 
-        let layout = cx.layout_of(ty)?;
+        let layout =
+            cx.layout_of(ty).map_err(|err| &*cx.tcx.arena.alloc(FnAbiError::Layout(*err)))?;
         let layout = if force_thin_self_ptr && arg_idx == Some(0) {
             // Don't pass the vtable, it's not an argument of the virtual fn.
             // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -454,7 +455,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
     fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
     abi: SpecAbi,
     fn_def_id: Option<DefId>,
-) -> Result<(), FnAbiError<'tcx>> {
+) -> Result<(), &'tcx FnAbiError<'tcx>> {
     if abi == SpecAbi::Unadjusted {
         return Ok(());
     }
@@ -548,7 +549,9 @@ fn fn_abi_adjust_for_abi<'tcx>(
             fixup(arg, Some(arg_idx));
         }
     } else {
-        fn_abi.adjust_for_foreign_abi(cx, abi)?;
+        fn_abi
+            .adjust_for_foreign_abi(cx, abi)
+            .map_err(|err| &*cx.tcx.arena.alloc(FnAbiError::AdjustForForeignAbi(err)))?;
     }
 
     Ok(())
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 5b731641e9d..b59458bbf35 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -340,12 +340,6 @@ fn associated_type_for_impl_trait_in_trait(
         }
     });
 
-    // There are no predicates for the synthesized associated type.
-    trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
-        parent: Some(trait_def_id.to_def_id()),
-        predicates: &[],
-    });
-
     // There are no inferred outlives for the synthesized associated type.
     trait_assoc_ty.inferred_outlives_of(&[]);
 
@@ -424,12 +418,6 @@ fn associated_type_for_impl_trait_in_impl(
         }
     });
 
-    // There are no predicates for the synthesized associated type.
-    impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
-        parent: Some(impl_local_def_id.to_def_id()),
-        predicates: &[],
-    });
-
     // There are no inferred outlives for the synthesized associated type.
     impl_assoc_ty.inferred_outlives_of(&[]);
 
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index c8c2c8286b0..ac015ddcb49 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -31,7 +31,7 @@ pub fn provide(providers: &mut Providers) {
 fn layout_of<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
+) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
     let (param_env, ty) = query.into_parts();
     debug!(?ty);
 
@@ -45,7 +45,9 @@ fn layout_of<'tcx>(
     let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
         Ok(t) => t,
         Err(normalization_error) => {
-            return Err(LayoutError::NormalizationFailure(ty, normalization_error));
+            return Err(tcx
+                .arena
+                .alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
         }
     };
 
@@ -66,27 +68,34 @@ fn layout_of<'tcx>(
     Ok(layout)
 }
 
+fn error<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    err: LayoutError<'tcx>,
+) -> &'tcx LayoutError<'tcx> {
+    cx.tcx.arena.alloc(err)
+}
+
 fn univariant_uninterned<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     ty: Ty<'tcx>,
     fields: &IndexSlice<FieldIdx, Layout<'_>>,
     repr: &ReprOptions,
     kind: StructKind,
-) -> Result<LayoutS, LayoutError<'tcx>> {
+) -> Result<LayoutS, &'tcx LayoutError<'tcx>> {
     let dl = cx.data_layout();
     let pack = repr.pack;
     if pack.is_some() && repr.align.is_some() {
         cx.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
-        return Err(LayoutError::Unknown(ty));
+        return Err(cx.tcx.arena.alloc(LayoutError::Unknown(ty)));
     }
 
-    cx.univariant(dl, fields, repr, kind).ok_or(LayoutError::SizeOverflow(ty))
+    cx.univariant(dl, fields, repr, kind).ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))
 }
 
 fn layout_of_uncached<'tcx>(
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     ty: Ty<'tcx>,
-) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
+) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
     let tcx = cx.tcx;
     let param_env = cx.param_env;
     let dl = cx.data_layout();
@@ -170,7 +179,7 @@ fn layout_of_uncached<'tcx>(
                                 err = better_err;
                             }
                         }
-                        return Err(LayoutError::NormalizationFailure(pointee, err));
+                        return Err(error(cx, LayoutError::NormalizationFailure(pointee, err)));
                     },
                 };
 
@@ -181,7 +190,7 @@ fn layout_of_uncached<'tcx>(
                 }
 
                 let Abi::Scalar(metadata) = metadata_layout.abi else {
-                    return Err(LayoutError::Unknown(pointee));
+                    return Err(error(cx, LayoutError::Unknown(pointee)));
                 };
 
                 metadata
@@ -199,7 +208,7 @@ fn layout_of_uncached<'tcx>(
                         vtable
                     }
                     _ => {
-                        return Err(LayoutError::Unknown(pointee));
+                        return Err(error(cx, LayoutError::Unknown(pointee)));
                     }
                 }
             };
@@ -221,14 +230,18 @@ fn layout_of_uncached<'tcx>(
             if count.has_projections() {
                 count = tcx.normalize_erasing_regions(param_env, count);
                 if count.has_projections() {
-                    return Err(LayoutError::Unknown(ty));
+                    return Err(error(cx, LayoutError::Unknown(ty)));
                 }
             }
 
-            let count =
-                count.try_eval_target_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
+            let count = count
+                .try_eval_target_usize(tcx, param_env)
+                .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
             let element = cx.layout_of(element)?;
-            let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?;
+            let size = element
+                .size
+                .checked_mul(count, dl)
+                .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
 
             let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) {
                 Abi::Uninhabited
@@ -316,7 +329,7 @@ fn layout_of_uncached<'tcx>(
                     DUMMY_SP,
                     "#[repr(simd)] was applied to an ADT that is not a struct",
                 );
-                return Err(LayoutError::Unknown(ty));
+                return Err(error(cx, LayoutError::Unknown(ty)));
             }
 
             let fields = &def.non_enum_variant().fields;
@@ -346,7 +359,7 @@ fn layout_of_uncached<'tcx>(
                         DUMMY_SP,
                         "#[repr(simd)] was applied to an ADT with heterogeneous field type",
                     );
-                    return Err(LayoutError::Unknown(ty));
+                    return Err(error(cx, LayoutError::Unknown(ty)));
                 }
             }
 
@@ -368,7 +381,7 @@ fn layout_of_uncached<'tcx>(
 
                 // Extract the number of elements from the layout of the array field:
                 let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else {
-                    return Err(LayoutError::Unknown(ty));
+                    return Err(error(cx, LayoutError::Unknown(ty)));
                 };
 
                 (*e_ty, *count, true)
@@ -397,7 +410,10 @@ fn layout_of_uncached<'tcx>(
             };
 
             // Compute the size and alignment of the vector:
-            let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow(ty))?;
+            let size = e_ly
+                .size
+                .checked_mul(e_len, dl)
+                .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
             let align = dl.vector_align(size);
             let size = size.align_to(align.abi);
 
@@ -438,11 +454,12 @@ fn layout_of_uncached<'tcx>(
                         tcx.def_span(def.did()),
                         "union cannot be packed and aligned",
                     );
-                    return Err(LayoutError::Unknown(ty));
+                    return Err(error(cx, LayoutError::Unknown(ty)));
                 }
 
                 return Ok(tcx.mk_layout(
-                    cx.layout_of_union(&def.repr(), &variants).ok_or(LayoutError::Unknown(ty))?,
+                    cx.layout_of_union(&def.repr(), &variants)
+                        .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
                 ));
             }
 
@@ -476,7 +493,7 @@ fn layout_of_uncached<'tcx>(
                             }
                     },
                 )
-                .ok_or(LayoutError::SizeOverflow(ty))?,
+                .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?,
             )
         }
 
@@ -484,7 +501,7 @@ fn layout_of_uncached<'tcx>(
         ty::Alias(..) => {
             // NOTE(eddyb) `layout_of` query should've normalized these away,
             // if that was possible, so there's no reason to try again here.
-            return Err(LayoutError::Unknown(ty));
+            return Err(error(cx, LayoutError::Unknown(ty)));
         }
 
         ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => {
@@ -492,7 +509,7 @@ fn layout_of_uncached<'tcx>(
         }
 
         ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => {
-            return Err(LayoutError::Unknown(ty));
+            return Err(error(cx, LayoutError::Unknown(ty)));
         }
     })
 }
@@ -628,13 +645,13 @@ fn generator_layout<'tcx>(
     ty: Ty<'tcx>,
     def_id: hir::def_id::DefId,
     substs: SubstsRef<'tcx>,
-) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
+) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
     use SavedLocalEligibility::*;
     let tcx = cx.tcx;
     let subst_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).subst(tcx, substs);
 
     let Some(info) = tcx.generator_layout(def_id) else {
-        return Err(LayoutError::Unknown(ty));
+        return Err(error(cx, LayoutError::Unknown(ty)));
     };
     let (ineligible_locals, assignments) = generator_saved_local_eligibility(&info);
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 2daab520a2f..2b391f94a63 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -131,7 +131,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
     | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
     {
-        predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Should not need to add the predicates
+        // from the parent fn to our assumptions
+        predicates.extend(tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates);
     }
 
     // Finally, we have to normalize the bounds in the environment, in
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index f99395c72aa..62856fc9a49 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -888,7 +888,7 @@ impl From<&CStr> for Arc<CStr> {
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
     /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> by moving the [`CString`]
-    /// data into a new [`Arc`] buffer.
+    /// data into a new [`Rc`] buffer.
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index ef4f8be6f19..598ecf05e82 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -560,22 +560,20 @@ impl<T> Vec<T> {
     /// Using memory that was allocated elsewhere:
     ///
     /// ```rust
-    /// #![feature(allocator_api)]
-    ///
-    /// use std::alloc::{AllocError, Allocator, Global, Layout};
+    /// use std::alloc::{alloc, Layout};
     ///
     /// fn main() {
     ///     let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
     ///
     ///     let vec = unsafe {
-    ///         let mem = match Global.allocate(layout) {
-    ///             Ok(mem) => mem.cast::<u32>().as_ptr(),
-    ///             Err(AllocError) => return,
-    ///         };
+    ///         let mem = alloc(layout).cast::<u32>();
+    ///         if mem.is_null() {
+    ///             return;
+    ///         }
     ///
     ///         mem.write(1_000_000);
     ///
-    ///         Vec::from_raw_parts_in(mem, 1, 16, Global)
+    ///         Vec::from_raw_parts(mem, 1, 16)
     ///     };
     ///
     ///     assert_eq!(vec, &[1_000_000]);
@@ -758,19 +756,22 @@ impl<T, A: Allocator> Vec<T, A> {
     /// Using memory that was allocated elsewhere:
     ///
     /// ```rust
-    /// use std::alloc::{alloc, Layout};
+    /// #![feature(allocator_api)]
+    ///
+    /// use std::alloc::{AllocError, Allocator, Global, Layout};
     ///
     /// fn main() {
     ///     let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
+    ///
     ///     let vec = unsafe {
-    ///         let mem = alloc(layout).cast::<u32>();
-    ///         if mem.is_null() {
-    ///             return;
-    ///         }
+    ///         let mem = match Global.allocate(layout) {
+    ///             Ok(mem) => mem.cast::<u32>().as_ptr(),
+    ///             Err(AllocError) => return,
+    ///         };
     ///
     ///         mem.write(1_000_000);
     ///
-    ///         Vec::from_raw_parts(mem, 1, 16)
+    ///         Vec::from_raw_parts_in(mem, 1, 16, Global)
     ///     };
     ///
     ///     assert_eq!(vec, &[1_000_000]);
diff --git a/library/backtrace b/library/backtrace
-Subproject 4245978ca8169c40c088ff733825e4527f7b914
+Subproject e1c49fbd6124a1b626cdf19871aff68c362bdf0
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 799085e9a83..ff5a4c913b7 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -532,7 +532,7 @@ pub trait Into<T>: Sized {
 #[rustc_diagnostic_item = "From"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(on(
-    all(_Self = "&str", T = "std::string::String"),
+    all(_Self = "&str", any(T = "alloc::string::String", T = "std::string::String")),
     note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
 ))]
 pub trait From<T>: Sized {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 50c7516b7fe..3de9188baf6 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -241,7 +241,7 @@ impl CStr {
     /// ```
     ///
     /// ```
-    /// #![feature(const_cstr_methods)]
+    /// #![feature(const_cstr_from_ptr)]
     ///
     /// use std::ffi::{c_char, CStr};
     ///
@@ -256,7 +256,7 @@ impl CStr {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+    #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")]
     pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
         // SAFETY: The caller has provided a pointer that points to a valid C
         // string with a NUL terminator of size less than `isize::MAX`, whose
@@ -377,7 +377,7 @@ impl CStr {
     /// assert!(cstr.is_err());
     /// ```
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-    #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
     pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
         let nul_pos = memchr::memchr(0, bytes);
         match nul_pos {
@@ -561,10 +561,12 @@ impl CStr {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_bytes(&self) -> &[u8] {
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn to_bytes(&self) -> &[u8] {
         let bytes = self.to_bytes_with_nul();
+        // FIXME(const-hack) replace with range index
         // SAFETY: to_bytes_with_nul returns slice with length at least 1
-        unsafe { bytes.get_unchecked(..bytes.len() - 1) }
+        unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
     }
 
     /// Converts this C string to a byte slice containing the trailing 0 byte.
@@ -588,7 +590,7 @@ impl CStr {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
     pub const fn to_bytes_with_nul(&self) -> &[u8] {
         // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
         // is safe on all supported targets.
@@ -612,7 +614,8 @@ impl CStr {
     /// assert_eq!(cstr.to_str(), Ok("foo"));
     /// ```
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
-    pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
         // N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
         // instead of in `from_ptr()`, it may be worth considering if this should
         // be rewritten to do the UTF-8 check inline with the length calculation
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 9b8612485ac..5a9a7013a19 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2657,7 +2657,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-#[inline]
+#[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
@@ -2748,7 +2748,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-#[inline]
+#[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
@@ -2821,7 +2821,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules]
 #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
-#[inline]
+#[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
     extern "rust-intrinsic" {
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 2568aaf34f3..d3e45456351 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -310,7 +310,7 @@ where
 /// Real logic of both `Flatten` and `FlatMap` which simply delegate to
 /// this type.
 #[derive(Clone, Debug)]
-#[unstable(feature = "trusted_len", issue = "37572")]
+#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
 struct FlattenCompat<I, U> {
     iter: Fuse<I>,
     frontiter: Option<U>,
@@ -464,7 +464,7 @@ where
     }
 }
 
-#[unstable(feature = "trusted_len", issue = "37572")]
+#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
 impl<I, U> Iterator for FlattenCompat<I, U>
 where
     I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -579,7 +579,7 @@ where
     }
 }
 
-#[unstable(feature = "trusted_len", issue = "37572")]
+#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
 impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
 where
     I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -649,7 +649,7 @@ where
     }
 }
 
-#[unstable(feature = "trusted_len", issue = "37572")]
+#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
 unsafe impl<const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter>
 where
@@ -657,7 +657,7 @@ where
 {
 }
 
-#[unstable(feature = "trusted_len", issue = "37572")]
+#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
 unsafe impl<'a, const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter>
 where
@@ -665,7 +665,7 @@ where
 {
 }
 
-#[unstable(feature = "trusted_len", issue = "37572")]
+#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
 unsafe impl<'a, const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter>
 where
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index dabfce14474..98835228308 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -26,13 +26,13 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
-        _Self = "std::ops::RangeTo<Idx>",
+        any(_Self = "core::ops::RangeTo<Idx>", _Self = "std::ops::RangeTo<Idx>"),
         label = "if you meant to iterate until a value, add a starting value",
         note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
               bounded `Range`: `0..end`"
     ),
     on(
-        _Self = "std::ops::RangeToInclusive<Idx>",
+        any(_Self = "core::ops::RangeToInclusive<Idx>", _Self = "std::ops::RangeToInclusive<Idx>"),
         label = "if you meant to iterate until a value (including it), add a starting value",
         note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
               to have a bounded `RangeInclusive`: `0..=end`"
@@ -43,7 +43,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
     ),
     on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
     on(
-        _Self = "std::vec::Vec<T, A>",
+        any(_Self = "alloc::vec::Vec<T, A>", _Self = "std::vec::Vec<T, A>"),
         label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
     ),
     on(
@@ -51,7 +51,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
         label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
     ),
     on(
-        _Self = "std::string::String",
+        any(_Self = "alloc::string::String", _Self = "std::string::String"),
         label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
     ),
     on(
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 6c419eb16f3..05876f5fc58 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -113,7 +113,6 @@
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_char_from_u32_unchecked)]
-#![feature(const_cstr_methods)]
 #![feature(const_discriminant)]
 #![feature(const_eval_select)]
 #![feature(const_exact_div)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 760e58276fc..e251015dd86 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -575,59 +575,59 @@ impl<T: ?Sized> Copy for &T {}
 #[lang = "sync"]
 #[rustc_on_unimplemented(
     on(
-        _Self = "std::cell::OnceCell<T>",
+        any(_Self = "core::cell:OnceCell<T>", _Self = "std::cell::OnceCell<T>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead"
     ),
     on(
-        _Self = "std::cell::Cell<u8>",
+        any(_Self = "core::cell::Cell<u8>", _Self = "std::cell::Cell<u8>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead",
     ),
     on(
-        _Self = "std::cell::Cell<u16>",
+        any(_Self = "core::cell::Cell<u16>", _Self = "std::cell::Cell<u16>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU16` instead",
     ),
     on(
-        _Self = "std::cell::Cell<u32>",
+        any(_Self = "core::cell::Cell<u32>", _Self = "std::cell::Cell<u32>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU32` instead",
     ),
     on(
-        _Self = "std::cell::Cell<u64>",
+        any(_Self = "core::cell::Cell<u64>", _Self = "std::cell::Cell<u64>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU64` instead",
     ),
     on(
-        _Self = "std::cell::Cell<usize>",
+        any(_Self = "core::cell::Cell<usize>", _Self = "std::cell::Cell<usize>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicUsize` instead",
     ),
     on(
-        _Self = "std::cell::Cell<i8>",
+        any(_Self = "core::cell::Cell<i8>", _Self = "std::cell::Cell<i8>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI8` instead",
     ),
     on(
-        _Self = "std::cell::Cell<i16>",
+        any(_Self = "core::cell::Cell<i16>", _Self = "std::cell::Cell<i16>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI16` instead",
     ),
     on(
-        _Self = "std::cell::Cell<i32>",
+        any(_Self = "core::cell::Cell<i32>", _Self = "std::cell::Cell<i32>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead",
     ),
     on(
-        _Self = "std::cell::Cell<i64>",
+        any(_Self = "core::cell::Cell<i64>", _Self = "std::cell::Cell<i64>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI64` instead",
     ),
     on(
-        _Self = "std::cell::Cell<isize>",
+        any(_Self = "core::cell::Cell<isize>", _Self = "std::cell::Cell<isize>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicIsize` instead",
     ),
     on(
-        _Self = "std::cell::Cell<bool>",
+        any(_Self = "core::cell::Cell<bool>", _Self = "std::cell::Cell<bool>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead",
     ),
     on(
-        _Self = "std::cell::Cell<T>",
+        any(_Self = "core::cell::Cell<T>", _Self = "std::cell::Cell<T>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`",
     ),
     on(
-        _Self = "std::cell::RefCell<T>",
+        any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
     ),
     message = "`{Self}` cannot be shared between threads safely",
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index 1f1784ec9b2..f4649be54d5 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -153,7 +153,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
 see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
     ),
     on(
-        _Self = "std::string::String",
+        any(_Self = "alloc::string::String", _Self = "std::string::String"),
         note = "you can use `.chars().nth()` or `.bytes().nth()`
 see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
     ),
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index b4f69d0b213..17625daccbc 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -226,8 +226,14 @@ pub trait Try: FromResidual {
     on(
         all(
             from_desugaring = "QuestionMark",
-            _Self = "std::result::Result<T, E>",
-            R = "std::option::Option<std::convert::Infallible>"
+            any(
+                _Self = "core::result::Result<T, E>",
+                _Self = "std::result::Result<T, E>",
+            ),
+            any(
+                R = "core::option::Option<core::convert::Infallible>",
+                R = "std::option::Option<std::convert::Infallible>",
+            )
         ),
         message = "the `?` operator can only be used on `Result`s, not `Option`s, \
             in {ItemContext} that returns `Result`",
@@ -237,7 +243,10 @@ pub trait Try: FromResidual {
     on(
         all(
             from_desugaring = "QuestionMark",
-            _Self = "std::result::Result<T, E>",
+            any(
+                _Self = "core::result::Result<T, E>",
+                _Self = "std::result::Result<T, E>",
+            )
         ),
         // There's a special error message in the trait selection code for
         // `From` in `?`, so this is not shown for result-in-result errors,
@@ -250,8 +259,14 @@ pub trait Try: FromResidual {
     on(
         all(
             from_desugaring = "QuestionMark",
-            _Self = "std::option::Option<T>",
-            R = "std::result::Result<T, E>",
+            any(
+                _Self = "core::option::Option<T>",
+                _Self = "std::option::Option<T>",
+            ),
+            any(
+                R = "core::result::Result<T, E>",
+                R = "std::result::Result<T, E>",
+            )
         ),
         message = "the `?` operator can only be used on `Option`s, not `Result`s, \
             in {ItemContext} that returns `Option`",
@@ -261,7 +276,10 @@ pub trait Try: FromResidual {
     on(
         all(
             from_desugaring = "QuestionMark",
-            _Self = "std::option::Option<T>",
+            any(
+                _Self = "core::option::Option<T>",
+                _Self = "std::option::Option<T>",
+            )
         ),
         // `Option`-in-`Option` always works, as there's only one possible
         // residual, so this can also be phrased strongly.
@@ -273,8 +291,14 @@ pub trait Try: FromResidual {
     on(
         all(
             from_desugaring = "QuestionMark",
-            _Self = "std::ops::ControlFlow<B, C>",
-            R = "std::ops::ControlFlow<B, C>",
+            any(
+                _Self = "core::ops::ControlFlow<B, C>",
+                _Self = "std::ops::ControlFlow<B, C>",
+            ),
+            any(
+                R = "core::ops::ControlFlow<B, C>",
+                R = "std::ops::ControlFlow<B, C>",
+            )
         ),
         message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
             can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
@@ -285,7 +309,10 @@ pub trait Try: FromResidual {
     on(
         all(
             from_desugaring = "QuestionMark",
-            _Self = "std::ops::ControlFlow<B, C>",
+            any(
+                _Self = "core::ops::ControlFlow<B, C>",
+                _Self = "std::ops::ControlFlow<B, C>",
+            )
             // `R` is not a `ControlFlow`, as that case was matched previously
         ),
         message = "the `?` operator can only be used on `ControlFlow`s \
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 6ef9f9c95e8..e1e3bcc05e7 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -152,7 +152,10 @@ mod private_slice_index {
 #[rustc_on_unimplemented(
     on(T = "str", label = "string indices are ranges of `usize`",),
     on(
-        all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"),
+        all(
+            any(T = "str", T = "&str", T = "alloc::string::String", T = "std::string::String"),
+            _Self = "{integer}"
+        ),
         note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
                 for more information, see chapter 8 in The Book: \
                 <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index ef05b25fdd0..9a93bb72903 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -144,8 +144,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let len = "foo".len();
     /// assert_eq!(3, len);
@@ -165,8 +163,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let s = "";
     /// assert!(s.is_empty());
@@ -311,8 +307,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let bytes = "bors".as_bytes();
     /// assert_eq!(b"bors", bytes);
@@ -387,8 +381,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let s = "Hello";
     /// let ptr = s.as_ptr();
@@ -570,8 +562,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let s = "Löwe 老虎 Léopard";
     ///
@@ -649,8 +639,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let s = "Per Martin-Löf";
     ///
@@ -691,8 +679,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let mut s = "Per Martin-Löf".to_string();
     /// {
@@ -840,8 +826,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let mut bytes = "bors".bytes();
     ///
@@ -1020,8 +1004,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let text = "Zażółć gęślą jaźń";
     ///
@@ -1050,8 +1032,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let bananas = "bananas";
     ///
@@ -1077,8 +1057,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let bananas = "bananas";
     ///
@@ -1103,8 +1081,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let bananas = "bananas";
     ///
@@ -1463,8 +1439,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
     /// assert_eq!(v, ["A", "B"]);
@@ -1696,8 +1670,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
     /// assert_eq!(v, ["abc", "abc", "abc"]);
@@ -1732,8 +1704,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
     /// assert_eq!(v, ["abc", "abc", "abc"]);
@@ -1775,8 +1745,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
     /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
@@ -1817,8 +1785,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
     /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
@@ -1845,8 +1811,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// let s = "\n Hello\tworld\t\n";
     ///
@@ -2085,8 +2049,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
     /// assert_eq!("123foo1bar123".trim_start_matches(char::is_numeric), "foo1bar123");
@@ -2232,8 +2194,6 @@ impl str {
     ///
     /// # Examples
     ///
-    /// Basic usage:
-    ///
     /// ```
     /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
     /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 151809b2df5..77b657fd868 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,18 +18,19 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
 libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true }
-compiler_builtins = { version = "0.1.93" }
+# FIXME(Nilstrieb): https://github.com/rust-lang/compiler-builtins/pull/532/files#r1249354225
+compiler_builtins = { version = "=0.1.93" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
 std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
 
 # Dependencies of the `backtrace` crate
-addr2line = { version = "0.19.0", optional = true, default-features = false }
+addr2line = { version = "0.20.0", optional = true, default-features = false }
 rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
-miniz_oxide = { version = "0.6.0", optional = true, default-features = false, public = false }
+miniz_oxide = { version = "0.7.0", optional = true, default-features = false, public = false }
 [dependencies.object]
-version = "0.30.0"
+version = "0.31.1"
 optional = true
 default-features = false
 features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index f3316d97c5f..a083b65604d 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2543,12 +2543,12 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// ```
     /// use std::collections::HashMap;
     ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    /// let s = "hoho".to_string();
+    /// let mut map = HashMap::new();
+    /// let value = "hoho";
     ///
-    /// map.entry("poneyland").or_insert_with(|| s);
+    /// map.entry("poneyland").or_insert_with(|| value);
     ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
+    /// assert_eq!(map["poneyland"], "hoho");
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index 11836b7b694..e39254aa434 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -13,9 +13,10 @@ use crate::sync::{Condvar, Mutex};
 /// use std::sync::{Arc, Barrier};
 /// use std::thread;
 ///
-/// let mut handles = Vec::with_capacity(10);
-/// let barrier = Arc::new(Barrier::new(10));
-/// for _ in 0..10 {
+/// let n = 10;
+/// let mut handles = Vec::with_capacity(n);
+/// let barrier = Arc::new(Barrier::new(n));
+/// for _ in 0..n {
 ///     let c = Arc::clone(&barrier);
 ///     // The same messages will be printed together.
 ///     // You will NOT see any interleaving.
@@ -105,9 +106,10 @@ impl Barrier {
     /// use std::sync::{Arc, Barrier};
     /// use std::thread;
     ///
-    /// let mut handles = Vec::with_capacity(10);
-    /// let barrier = Arc::new(Barrier::new(10));
-    /// for _ in 0..10 {
+    /// let n = 10;
+    /// let mut handles = Vec::with_capacity(n);
+    /// let barrier = Arc::new(Barrier::new(n));
+    /// for _ in 0..n {
     ///     let c = Arc::clone(&barrier);
     ///     // The same messages will be printed together.
     ///     // You will NOT see any interleaving.
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index 7eee4ca2361..bbeb944e8b1 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -199,7 +199,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
         let TestDescAndFn { desc, testfn } = test;
 
         let fntype = match testfn {
-            StaticTestFn(..) | DynTestFn(..) => {
+            StaticTestFn(..) | DynTestFn(..) | StaticBenchAsTestFn(..) | DynBenchAsTestFn(..) => {
                 st.tests += 1;
                 "test"
             }
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index e76d6716b94..b40b6009ea4 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -92,6 +92,7 @@ use time::TestExecTime;
 const ERROR_EXIT_CODE: i32 = 101;
 
 const SECONDARY_TEST_INVOKER_VAR: &str = "__RUST_TEST_INVOKE";
+const SECONDARY_TEST_BENCH_BENCHMARKS_VAR: &str = "__RUST_TEST_BENCH_BENCHMARKS";
 
 // The default console test runner. It accepts the command line
 // arguments and a vector of test_descs.
@@ -171,18 +172,32 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
     // will then exit the process.
     if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) {
         env::remove_var(SECONDARY_TEST_INVOKER_VAR);
+
+        // Convert benchmarks to tests if we're not benchmarking.
+        let mut tests = tests.iter().map(make_owned_test).collect::<Vec<_>>();
+        if env::var(SECONDARY_TEST_BENCH_BENCHMARKS_VAR).is_ok() {
+            env::remove_var(SECONDARY_TEST_BENCH_BENCHMARKS_VAR);
+        } else {
+            tests = convert_benchmarks_to_tests(tests);
+        };
+
         let test = tests
-            .iter()
+            .into_iter()
             .filter(|test| test.desc.name.as_slice() == name)
-            .map(make_owned_test)
             .next()
             .unwrap_or_else(|| panic!("couldn't find a test with the provided name '{name}'"));
         let TestDescAndFn { desc, testfn } = test;
-        let testfn = match testfn {
-            StaticTestFn(f) => f,
-            _ => panic!("only static tests are supported"),
-        };
-        run_test_in_spawned_subprocess(desc, Box::new(testfn));
+        match testfn.into_runnable() {
+            Runnable::Test(runnable_test) => {
+                if runnable_test.is_dynamic() {
+                    panic!("only static tests are supported");
+                }
+                run_test_in_spawned_subprocess(desc, runnable_test);
+            }
+            Runnable::Bench(_) => {
+                panic!("benchmarks should not be executed into child processes")
+            }
+        }
     }
 
     let args = env::args().collect::<Vec<_>>();
@@ -234,16 +249,6 @@ impl FilteredTests {
         self.tests.push((TestId(self.next_id), test));
         self.next_id += 1;
     }
-    fn add_bench_as_test(
-        &mut self,
-        desc: TestDesc,
-        benchfn: impl Fn(&mut Bencher) -> Result<(), String> + Send + 'static,
-    ) {
-        let testfn = DynTestFn(Box::new(move || {
-            bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
-        }));
-        self.add_test(desc, testfn);
-    }
     fn total_len(&self) -> usize {
         self.tests.len() + self.benches.len()
     }
@@ -301,14 +306,14 @@ where
                 if opts.bench_benchmarks {
                     filtered.add_bench(desc, DynBenchFn(benchfn));
                 } else {
-                    filtered.add_bench_as_test(desc, benchfn);
+                    filtered.add_test(desc, DynBenchAsTestFn(benchfn));
                 }
             }
             StaticBenchFn(benchfn) => {
                 if opts.bench_benchmarks {
                     filtered.add_bench(desc, StaticBenchFn(benchfn));
                 } else {
-                    filtered.add_bench_as_test(desc, benchfn);
+                    filtered.add_test(desc, StaticBenchAsTestFn(benchfn));
                 }
             }
             testfn => {
@@ -519,12 +524,8 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
         .into_iter()
         .map(|x| {
             let testfn = match x.testfn {
-                DynBenchFn(benchfn) => DynTestFn(Box::new(move || {
-                    bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
-                })),
-                StaticBenchFn(benchfn) => DynTestFn(Box::new(move || {
-                    bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
-                })),
+                DynBenchFn(benchfn) => DynBenchAsTestFn(benchfn),
+                StaticBenchFn(benchfn) => StaticBenchAsTestFn(benchfn),
                 f => f,
             };
             TestDescAndFn { desc: x.desc, testfn }
@@ -553,99 +554,69 @@ pub fn run_test(
         return None;
     }
 
-    struct TestRunOpts {
-        pub strategy: RunStrategy,
-        pub nocapture: bool,
-        pub time: Option<time::TestTimeOptions>,
-    }
+    match testfn.into_runnable() {
+        Runnable::Test(runnable_test) => {
+            if runnable_test.is_dynamic() {
+                match strategy {
+                    RunStrategy::InProcess => (),
+                    _ => panic!("Cannot run dynamic test fn out-of-process"),
+                };
+            }
 
-    fn run_test_inner(
-        id: TestId,
-        desc: TestDesc,
-        monitor_ch: Sender<CompletedTest>,
-        testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
-        opts: TestRunOpts,
-    ) -> Option<thread::JoinHandle<()>> {
-        let name = desc.name.clone();
-
-        let runtest = move || match opts.strategy {
-            RunStrategy::InProcess => run_test_in_process(
-                id,
-                desc,
-                opts.nocapture,
-                opts.time.is_some(),
-                testfn,
-                monitor_ch,
-                opts.time,
-            ),
-            RunStrategy::SpawnPrimary => spawn_test_subprocess(
-                id,
-                desc,
-                opts.nocapture,
-                opts.time.is_some(),
-                monitor_ch,
-                opts.time,
-            ),
-        };
+            let name = desc.name.clone();
+            let nocapture = opts.nocapture;
+            let time_options = opts.time_options;
+            let bench_benchmarks = opts.bench_benchmarks;
+
+            let runtest = move || match strategy {
+                RunStrategy::InProcess => run_test_in_process(
+                    id,
+                    desc,
+                    nocapture,
+                    time_options.is_some(),
+                    runnable_test,
+                    monitor_ch,
+                    time_options,
+                ),
+                RunStrategy::SpawnPrimary => spawn_test_subprocess(
+                    id,
+                    desc,
+                    nocapture,
+                    time_options.is_some(),
+                    monitor_ch,
+                    time_options,
+                    bench_benchmarks,
+                ),
+            };
 
-        // If the platform is single-threaded we're just going to run
-        // the test synchronously, regardless of the concurrency
-        // level.
-        let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm");
-        if supports_threads {
-            let cfg = thread::Builder::new().name(name.as_slice().to_owned());
-            let mut runtest = Arc::new(Mutex::new(Some(runtest)));
-            let runtest2 = runtest.clone();
-            match cfg.spawn(move || runtest2.lock().unwrap().take().unwrap()()) {
-                Ok(handle) => Some(handle),
-                Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
-                    // `ErrorKind::WouldBlock` means hitting the thread limit on some
-                    // platforms, so run the test synchronously here instead.
-                    Arc::get_mut(&mut runtest).unwrap().get_mut().unwrap().take().unwrap()();
-                    None
+            // If the platform is single-threaded we're just going to run
+            // the test synchronously, regardless of the concurrency
+            // level.
+            let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm");
+            if supports_threads {
+                let cfg = thread::Builder::new().name(name.as_slice().to_owned());
+                let mut runtest = Arc::new(Mutex::new(Some(runtest)));
+                let runtest2 = runtest.clone();
+                match cfg.spawn(move || runtest2.lock().unwrap().take().unwrap()()) {
+                    Ok(handle) => Some(handle),
+                    Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
+                        // `ErrorKind::WouldBlock` means hitting the thread limit on some
+                        // platforms, so run the test synchronously here instead.
+                        Arc::get_mut(&mut runtest).unwrap().get_mut().unwrap().take().unwrap()();
+                        None
+                    }
+                    Err(e) => panic!("failed to spawn thread to run test: {e}"),
                 }
-                Err(e) => panic!("failed to spawn thread to run test: {e}"),
+            } else {
+                runtest();
+                None
             }
-        } else {
-            runtest();
-            None
         }
-    }
-
-    let test_run_opts =
-        TestRunOpts { strategy, nocapture: opts.nocapture, time: opts.time_options };
-
-    match testfn {
-        DynBenchFn(benchfn) => {
+        Runnable::Bench(runnable_bench) => {
             // Benchmarks aren't expected to panic, so we run them all in-process.
-            crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn);
+            runnable_bench.run(id, &desc, &monitor_ch, opts.nocapture);
             None
         }
-        StaticBenchFn(benchfn) => {
-            // Benchmarks aren't expected to panic, so we run them all in-process.
-            crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn);
-            None
-        }
-        DynTestFn(f) => {
-            match strategy {
-                RunStrategy::InProcess => (),
-                _ => panic!("Cannot run dynamic test fn out-of-process"),
-            };
-            run_test_inner(
-                id,
-                desc,
-                monitor_ch,
-                Box::new(move || __rust_begin_short_backtrace(f)),
-                test_run_opts,
-            )
-        }
-        StaticTestFn(f) => run_test_inner(
-            id,
-            desc,
-            monitor_ch,
-            Box::new(move || __rust_begin_short_backtrace(f)),
-            test_run_opts,
-        ),
     }
 }
 
@@ -663,7 +634,7 @@ fn run_test_in_process(
     desc: TestDesc,
     nocapture: bool,
     report_time: bool,
-    testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
+    runnable_test: RunnableTest,
     monitor_ch: Sender<CompletedTest>,
     time_opts: Option<time::TestTimeOptions>,
 ) {
@@ -675,7 +646,7 @@ fn run_test_in_process(
     }
 
     let start = report_time.then(Instant::now);
-    let result = fold_err(catch_unwind(AssertUnwindSafe(testfn)));
+    let result = fold_err(catch_unwind(AssertUnwindSafe(|| runnable_test.run())));
     let exec_time = start.map(|start| {
         let duration = start.elapsed();
         TestExecTime(duration)
@@ -712,6 +683,7 @@ fn spawn_test_subprocess(
     report_time: bool,
     monitor_ch: Sender<CompletedTest>,
     time_opts: Option<time::TestTimeOptions>,
+    bench_benchmarks: bool,
 ) {
     let (result, test_output, exec_time) = (|| {
         let args = env::args().collect::<Vec<_>>();
@@ -719,6 +691,9 @@ fn spawn_test_subprocess(
 
         let mut command = Command::new(current_exe);
         command.env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice());
+        if bench_benchmarks {
+            command.env(SECONDARY_TEST_BENCH_BENCHMARKS_VAR, "1");
+        }
         if nocapture {
             command.stdout(process::Stdio::inherit());
             command.stderr(process::Stdio::inherit());
@@ -760,10 +735,7 @@ fn spawn_test_subprocess(
     monitor_ch.send(message).unwrap();
 }
 
-fn run_test_in_spawned_subprocess(
-    desc: TestDesc,
-    testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
-) -> ! {
+fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
     let builtin_panic_hook = panic::take_hook();
     let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
         let test_result = match panic_info {
@@ -789,7 +761,7 @@ fn run_test_in_spawned_subprocess(
     });
     let record_result2 = record_result.clone();
     panic::set_hook(Box::new(move |info| record_result2(Some(info))));
-    if let Err(message) = testfn() {
+    if let Err(message) = runnable_test.run() {
         panic!("{}", message);
     }
     record_result(None);
diff --git a/library/test/src/types.rs b/library/test/src/types.rs
index e79914dbf4b..504ceee7fce 100644
--- a/library/test/src/types.rs
+++ b/library/test/src/types.rs
@@ -2,8 +2,11 @@
 
 use std::borrow::Cow;
 use std::fmt;
+use std::sync::mpsc::Sender;
 
+use super::__rust_begin_short_backtrace;
 use super::bench::Bencher;
+use super::event::CompletedTest;
 use super::options;
 
 pub use NamePadding::*;
@@ -82,8 +85,10 @@ impl fmt::Display for TestName {
 pub enum TestFn {
     StaticTestFn(fn() -> Result<(), String>),
     StaticBenchFn(fn(&mut Bencher) -> Result<(), String>),
+    StaticBenchAsTestFn(fn(&mut Bencher) -> Result<(), String>),
     DynTestFn(Box<dyn FnOnce() -> Result<(), String> + Send>),
     DynBenchFn(Box<dyn Fn(&mut Bencher) -> Result<(), String> + Send>),
+    DynBenchAsTestFn(Box<dyn Fn(&mut Bencher) -> Result<(), String> + Send>),
 }
 
 impl TestFn {
@@ -91,8 +96,21 @@ impl TestFn {
         match *self {
             StaticTestFn(..) => PadNone,
             StaticBenchFn(..) => PadOnRight,
+            StaticBenchAsTestFn(..) => PadNone,
             DynTestFn(..) => PadNone,
             DynBenchFn(..) => PadOnRight,
+            DynBenchAsTestFn(..) => PadNone,
+        }
+    }
+
+    pub(crate) fn into_runnable(self) -> Runnable {
+        match self {
+            StaticTestFn(f) => Runnable::Test(RunnableTest::Static(f)),
+            StaticBenchFn(f) => Runnable::Bench(RunnableBench::Static(f)),
+            StaticBenchAsTestFn(f) => Runnable::Test(RunnableTest::StaticBenchAsTest(f)),
+            DynTestFn(f) => Runnable::Test(RunnableTest::Dynamic(f)),
+            DynBenchFn(f) => Runnable::Bench(RunnableBench::Dynamic(f)),
+            DynBenchAsTestFn(f) => Runnable::Test(RunnableTest::DynamicBenchAsTest(f)),
         }
     }
 }
@@ -102,12 +120,74 @@ impl fmt::Debug for TestFn {
         f.write_str(match *self {
             StaticTestFn(..) => "StaticTestFn(..)",
             StaticBenchFn(..) => "StaticBenchFn(..)",
+            StaticBenchAsTestFn(..) => "StaticBenchAsTestFn(..)",
             DynTestFn(..) => "DynTestFn(..)",
             DynBenchFn(..) => "DynBenchFn(..)",
+            DynBenchAsTestFn(..) => "DynBenchAsTestFn(..)",
         })
     }
 }
 
+pub(crate) enum Runnable {
+    Test(RunnableTest),
+    Bench(RunnableBench),
+}
+
+pub(crate) enum RunnableTest {
+    Static(fn() -> Result<(), String>),
+    Dynamic(Box<dyn FnOnce() -> Result<(), String> + Send>),
+    StaticBenchAsTest(fn(&mut Bencher) -> Result<(), String>),
+    DynamicBenchAsTest(Box<dyn Fn(&mut Bencher) -> Result<(), String> + Send>),
+}
+
+impl RunnableTest {
+    pub(crate) fn run(self) -> Result<(), String> {
+        match self {
+            RunnableTest::Static(f) => __rust_begin_short_backtrace(f),
+            RunnableTest::Dynamic(f) => __rust_begin_short_backtrace(f),
+            RunnableTest::StaticBenchAsTest(f) => {
+                crate::bench::run_once(|b| __rust_begin_short_backtrace(|| f(b)))
+            }
+            RunnableTest::DynamicBenchAsTest(f) => {
+                crate::bench::run_once(|b| __rust_begin_short_backtrace(|| f(b)))
+            }
+        }
+    }
+
+    pub(crate) fn is_dynamic(&self) -> bool {
+        match self {
+            RunnableTest::Static(_) => false,
+            RunnableTest::StaticBenchAsTest(_) => false,
+            RunnableTest::Dynamic(_) => true,
+            RunnableTest::DynamicBenchAsTest(_) => true,
+        }
+    }
+}
+
+pub(crate) enum RunnableBench {
+    Static(fn(&mut Bencher) -> Result<(), String>),
+    Dynamic(Box<dyn Fn(&mut Bencher) -> Result<(), String> + Send>),
+}
+
+impl RunnableBench {
+    pub(crate) fn run(
+        self,
+        id: TestId,
+        desc: &TestDesc,
+        monitor_ch: &Sender<CompletedTest>,
+        nocapture: bool,
+    ) {
+        match self {
+            RunnableBench::Static(f) => {
+                crate::bench::benchmark(id, desc.clone(), monitor_ch.clone(), nocapture, f)
+            }
+            RunnableBench::Dynamic(f) => {
+                crate::bench::benchmark(id, desc.clone(), monitor_ch.clone(), nocapture, f)
+            }
+        }
+    }
+}
+
 // A unique integer associated with each test.
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct TestId(pub usize);
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index 7ce4599c424..30dfa81c6f7 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -5,9 +5,11 @@
 //! parent directory, and otherwise documentation can be found throughout the `build`
 //! directory in each respective module.
 
-use std::fs::OpenOptions;
+#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
 use std::io::Write;
-use std::{env, fs, process};
+#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
+use std::process;
+use std::{env, fs};
 
 #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
 use bootstrap::t;
@@ -32,7 +34,7 @@ fn main() {
         };
 
         build_lock =
-            fd_lock::RwLock::new(t!(OpenOptions::new().write(true).create(true).open(&path)));
+            fd_lock::RwLock::new(t!(fs::OpenOptions::new().write(true).create(true).open(&path)));
         _build_lock_guard = match build_lock.try_write() {
             Ok(mut lock) => {
                 t!(lock.write(&process::id().to_string().as_ref()));
@@ -85,7 +87,7 @@ fn main() {
     // HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not.
     // We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime.
     // Instead, look for this comment, which is almost certainly not in any custom hook.
-    if std::fs::read_to_string(pre_commit).map_or(false, |contents| {
+    if fs::read_to_string(pre_commit).map_or(false, |contents| {
         contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
     }) {
         println!(
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 1294ca9df0d..3c91e403df3 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -1,6 +1,6 @@
 """Bootstrap tests
 
-Run these with `x test bootstrap`, or `python -m unittest bootstrap_test.py`."""
+Run these with `x test bootstrap`, or `python -m unittest src/bootstrap/bootstrap_test.py`."""
 
 from __future__ import absolute_import, division, print_function
 import os
@@ -12,6 +12,10 @@ import sys
 
 from shutil import rmtree
 
+# Allow running this from the top-level directory.
+bootstrap_dir = os.path.dirname(os.path.abspath(__file__))
+# For the import below, have Python search in src/bootstrap first.
+sys.path.insert(0, bootstrap_dir)
 import bootstrap
 import configure
 
@@ -131,8 +135,13 @@ class BuildBootstrap(unittest.TestCase):
 
         parsed = bootstrap.parse_args(args)
         build = serialize_and_parse(configure_args, parsed)
-        build.build_dir = os.environ["BUILD_DIR"]
-        build.build = os.environ["BUILD_PLATFORM"]
+        # Make these optional so that `python -m unittest` works when run manually.
+        build_dir = os.environ.get("BUILD_DIR")
+        if build_dir is not None:
+            build.build_dir = build_dir
+        build_platform = os.environ.get("BUILD_PLATFORM")
+        if build_platform is not None:
+            build.build = build_platform
         return build.build_bootstrap_cmd(env), env
 
     def test_cargoflags(self):
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 7c8e3536df5..05b66f94727 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -686,6 +686,7 @@ impl<'a> Builder<'a> {
                 test::Tidy,
                 test::Ui,
                 test::RunPassValgrind,
+                test::RunCoverage,
                 test::MirOpt,
                 test::Codegen,
                 test::CodegenUnits,
@@ -694,6 +695,7 @@ impl<'a> Builder<'a> {
                 test::Debuginfo,
                 test::UiFullDeps,
                 test::Rustdoc,
+                test::RunCoverageRustdoc,
                 test::Pretty,
                 test::Crate,
                 test::CrateLibrustc,
@@ -1205,7 +1207,7 @@ impl<'a> Builder<'a> {
             assert_eq!(target, compiler.host);
         }
 
-        if self.config.rust_optimize {
+        if self.config.rust_optimize.is_release() {
             // FIXME: cargo bench/install do not accept `--release`
             if cmd != "bench" && cmd != "install" {
                 cargo.arg("--release");
@@ -1261,7 +1263,7 @@ impl<'a> Builder<'a> {
         }
 
         let profile_var = |name: &str| {
-            let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
+            let profile = if self.config.rust_optimize.is_release() { "RELEASE" } else { "DEV" };
             format!("CARGO_PROFILE_{}_{}", profile, name)
         };
 
@@ -1650,6 +1652,9 @@ impl<'a> Builder<'a> {
             }
         };
         cargo.env(profile_var("DEBUG"), debuginfo_level.to_string());
+        if let Some(opt_level) = &self.config.rust_optimize.get_opt_level() {
+            cargo.env(profile_var("OPT_LEVEL"), opt_level);
+        }
         if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz")
         {
             rustflags.arg("-Clink-arg=-gz");
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index b91275e73e9..5f5f7ea25fb 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -202,7 +202,7 @@ pub struct Config {
     pub llvm_use_libcxx: bool,
 
     // rust codegen options
-    pub rust_optimize: bool,
+    pub rust_optimize: RustOptimize,
     pub rust_codegen_units: Option<u32>,
     pub rust_codegen_units_std: Option<u32>,
     pub rust_debug_assertions: bool,
@@ -875,17 +875,55 @@ impl Default for StringOrBool {
     }
 }
 
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
+#[serde(untagged)]
+pub enum RustOptimize {
+    #[serde(deserialize_with = "deserialize_and_validate_opt_level")]
+    String(String),
+    Bool(bool),
+}
+
+impl Default for RustOptimize {
+    fn default() -> RustOptimize {
+        RustOptimize::Bool(false)
+    }
+}
+
+fn deserialize_and_validate_opt_level<'de, D>(d: D) -> Result<String, D::Error>
+where
+    D: serde::de::Deserializer<'de>,
+{
+    let v = String::deserialize(d)?;
+    if ["0", "1", "2", "3", "s", "z"].iter().find(|x| **x == v).is_some() {
+        Ok(v)
+    } else {
+        Err(format!(r#"unrecognized option for rust optimize: "{}", expected one of "0", "1", "2", "3", "s", "z""#, v)).map_err(serde::de::Error::custom)
+    }
+}
+
+impl RustOptimize {
+    pub(crate) fn is_release(&self) -> bool {
+        if let RustOptimize::Bool(true) | RustOptimize::String(_) = &self { true } else { false }
+    }
+
+    pub(crate) fn get_opt_level(&self) -> Option<String> {
+        match &self {
+            RustOptimize::String(s) => Some(s.clone()),
+            RustOptimize::Bool(_) => None,
+        }
+    }
+}
+
 #[derive(Deserialize)]
 #[serde(untagged)]
 enum StringOrInt<'a> {
     String(&'a str),
     Int(i64),
 }
-
 define_config! {
     /// TOML representation of how the Rust build is configured.
     struct Rust {
-        optimize: Option<bool> = "optimize",
+        optimize: Option<RustOptimize> = "optimize",
         debug: Option<bool> = "debug",
         codegen_units: Option<u32> = "codegen-units",
         codegen_units_std: Option<u32> = "codegen-units-std",
@@ -971,7 +1009,7 @@ impl Config {
         config.ninja_in_file = true;
         config.llvm_static_stdcpp = false;
         config.backtrace = true;
-        config.rust_optimize = true;
+        config.rust_optimize = RustOptimize::Bool(true);
         config.rust_optimize_tests = true;
         config.submodules = None;
         config.docs = true;
@@ -1546,7 +1584,7 @@ impl Config {
         config.llvm_assertions = llvm_assertions.unwrap_or(false);
         config.llvm_tests = llvm_tests.unwrap_or(false);
         config.llvm_plugins = llvm_plugins.unwrap_or(false);
-        config.rust_optimize = optimize.unwrap_or(true);
+        config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true));
 
         let default = debug == Some(true);
         config.rust_debug_assertions = debug_assertions.unwrap_or(default);
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 3bee659abd1..732df54cdac 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -178,3 +178,18 @@ fn profile_user_dist() {
     }
     Config::parse_inner(&["check".to_owned()], get_toml);
 }
+
+#[test]
+fn rust_optimize() {
+    assert_eq!(parse("").rust_optimize.is_release(), true);
+    assert_eq!(parse("rust.optimize = false").rust_optimize.is_release(), false);
+    assert_eq!(parse("rust.optimize = true").rust_optimize.is_release(), true);
+    assert_eq!(parse("rust.optimize = \"1\"").rust_optimize.get_opt_level(), Some("1".to_string()));
+    assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string()));
+}
+
+#[test]
+#[should_panic]
+fn invalid_rust_optimize() {
+    parse("rust.optimize = \"a\"");
+}
diff --git a/src/bootstrap/defaults/config.dist.toml b/src/bootstrap/defaults/config.dist.toml
index 25d9e649f23..44efdf50b96 100644
--- a/src/bootstrap/defaults/config.dist.toml
+++ b/src/bootstrap/defaults/config.dist.toml
@@ -12,6 +12,9 @@ extended = true
 [llvm]
 download-ci-llvm = false
 [rust]
+# We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`).
+# Make sure they don't get set when installing from source.
+channel = "nightly"
 download-rustc = false
 
 [dist]
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index a34a594f137..4522819f996 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1601,9 +1601,7 @@ impl Step for Extended {
             prepare("cargo");
             prepare("rust-analysis");
             prepare("rust-std");
-            prepare("clippy");
-            prepare("rust-analyzer");
-            for tool in &["rust-docs", "rust-demangler", "miri"] {
+            for tool in &["clippy", "rust-analyzer", "rust-docs", "rust-demangler", "miri"] {
                 if built_tools.contains(tool) {
                     prepare(tool);
                 }
@@ -1689,40 +1687,44 @@ impl Step for Extended {
                     .arg("-out")
                     .arg(exe.join("StdGroup.wxs")),
             );
-            builder.run(
-                Command::new(&heat)
-                    .current_dir(&exe)
-                    .arg("dir")
-                    .arg("rust-analyzer")
-                    .args(&heat_flags)
-                    .arg("-cg")
-                    .arg("RustAnalyzerGroup")
-                    .arg("-dr")
-                    .arg("RustAnalyzer")
-                    .arg("-var")
-                    .arg("var.RustAnalyzerDir")
-                    .arg("-out")
-                    .arg(exe.join("RustAnalyzerGroup.wxs"))
-                    .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
-            builder.run(
-                Command::new(&heat)
-                    .current_dir(&exe)
-                    .arg("dir")
-                    .arg("clippy")
-                    .args(&heat_flags)
-                    .arg("-cg")
-                    .arg("ClippyGroup")
-                    .arg("-dr")
-                    .arg("Clippy")
-                    .arg("-var")
-                    .arg("var.ClippyDir")
-                    .arg("-out")
-                    .arg(exe.join("ClippyGroup.wxs"))
-                    .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
+            if built_tools.contains("rust-analyzer") {
+                builder.run(
+                    Command::new(&heat)
+                        .current_dir(&exe)
+                        .arg("dir")
+                        .arg("rust-analyzer")
+                        .args(&heat_flags)
+                        .arg("-cg")
+                        .arg("RustAnalyzerGroup")
+                        .arg("-dr")
+                        .arg("RustAnalyzer")
+                        .arg("-var")
+                        .arg("var.RustAnalyzerDir")
+                        .arg("-out")
+                        .arg(exe.join("RustAnalyzerGroup.wxs"))
+                        .arg("-t")
+                        .arg(etc.join("msi/remove-duplicates.xsl")),
+                );
+            }
+            if built_tools.contains("clippy") {
+                builder.run(
+                    Command::new(&heat)
+                        .current_dir(&exe)
+                        .arg("dir")
+                        .arg("clippy")
+                        .args(&heat_flags)
+                        .arg("-cg")
+                        .arg("ClippyGroup")
+                        .arg("-dr")
+                        .arg("Clippy")
+                        .arg("-var")
+                        .arg("var.ClippyDir")
+                        .arg("-out")
+                        .arg(exe.join("ClippyGroup.wxs"))
+                        .arg("-t")
+                        .arg(etc.join("msi/remove-duplicates.xsl")),
+                );
+            }
             if built_tools.contains("rust-demangler") {
                 builder.run(
                     Command::new(&heat)
@@ -1806,7 +1808,6 @@ impl Step for Extended {
                     .arg("-dCargoDir=cargo")
                     .arg("-dStdDir=rust-std")
                     .arg("-dAnalysisDir=rust-analysis")
-                    .arg("-dClippyDir=clippy")
                     .arg("-arch")
                     .arg(&arch)
                     .arg("-out")
@@ -1814,6 +1815,9 @@ impl Step for Extended {
                     .arg(&input);
                 add_env(builder, &mut cmd, target);
 
+                if built_tools.contains("clippy") {
+                    cmd.arg("-dClippyDir=clippy");
+                }
                 if built_tools.contains("rust-docs") {
                     cmd.arg("-dDocsDir=rust-docs");
                 }
@@ -1840,7 +1844,9 @@ impl Step for Extended {
             }
             candle("CargoGroup.wxs".as_ref());
             candle("StdGroup.wxs".as_ref());
-            candle("ClippyGroup.wxs".as_ref());
+            if built_tools.contains("clippy") {
+                candle("ClippyGroup.wxs".as_ref());
+            }
             if built_tools.contains("miri") {
                 candle("MiriGroup.wxs".as_ref());
             }
@@ -1877,9 +1883,11 @@ impl Step for Extended {
                 .arg("CargoGroup.wixobj")
                 .arg("StdGroup.wixobj")
                 .arg("AnalysisGroup.wixobj")
-                .arg("ClippyGroup.wixobj")
                 .current_dir(&exe);
 
+            if built_tools.contains("clippy") {
+                cmd.arg("ClippyGroup.wixobj");
+            }
             if built_tools.contains("miri") {
                 cmd.arg("MiriGroup.wixobj");
             }
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 1ac52dffe58..5ebfe0995a8 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -751,7 +751,15 @@ impl Step for Rustc {
 }
 
 macro_rules! tool_doc {
-    ($tool: ident, $should_run: literal, $path: literal, $(rustc_tool = $rustc_tool:literal, )? $(in_tree = $in_tree:literal, )? [$($krate: literal),+ $(,)?] $(,)?) => {
+    (
+        $tool: ident,
+        $should_run: literal,
+        $path: literal,
+        $(rustc_tool = $rustc_tool:literal, )?
+        $(in_tree = $in_tree:literal, )?
+        [$($extra_arg: literal),+ $(,)?]
+        $(,)?
+    ) => {
         #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
         pub struct $tool {
             target: TargetSelection,
@@ -832,9 +840,9 @@ macro_rules! tool_doc {
                 cargo.arg("-Zskip-rustdoc-fingerprint");
                 // Only include compiler crates, no dependencies of those, such as `libc`.
                 cargo.arg("--no-deps");
-                cargo.arg("--lib");
+
                 $(
-                    cargo.arg("-p").arg($krate);
+                    cargo.arg($extra_arg);
                 )+
 
                 cargo.rustdocflag("--document-private-items");
@@ -850,15 +858,20 @@ macro_rules! tool_doc {
     }
 }
 
-tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"],);
+tool_doc!(
+    Rustdoc,
+    "rustdoc-tool",
+    "src/tools/rustdoc",
+    ["-p", "rustdoc", "-p", "rustdoc-json-types"]
+);
 tool_doc!(
     Rustfmt,
     "rustfmt-nightly",
     "src/tools/rustfmt",
-    ["rustfmt-nightly", "rustfmt-config_proc_macro"],
+    ["-p", "rustfmt-nightly", "-p", "rustfmt-config_proc_macro"],
 );
-tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);
-tool_doc!(Miri, "miri", "src/tools/miri", ["miri"]);
+tool_doc!(Clippy, "clippy", "src/tools/clippy", ["-p", "clippy_utils"]);
+tool_doc!(Miri, "miri", "src/tools/miri", ["-p", "miri"]);
 tool_doc!(
     Cargo,
     "cargo",
@@ -866,25 +879,44 @@ tool_doc!(
     rustc_tool = false,
     in_tree = false,
     [
+        "-p",
         "cargo",
+        "-p",
         "cargo-platform",
+        "-p",
         "cargo-util",
+        "-p",
         "crates-io",
+        "-p",
         "cargo-test-macro",
+        "-p",
         "cargo-test-support",
+        "-p",
         "cargo-credential",
+        "-p",
         "cargo-credential-1password",
+        "-p",
         "mdman",
         // FIXME: this trips a license check in tidy.
+        // "-p",
         // "resolver-tests",
         // FIXME: we should probably document these, but they're different per-platform so we can't use `tool_doc`.
+        // "-p",
         // "cargo-credential-gnome-secret",
+        // "-p",
         // "cargo-credential-macos-keychain",
+        // "-p",
         // "cargo-credential-wincred",
     ]
 );
-tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["tidy"]);
-tool_doc!(Bootstrap, "bootstrap", "src/bootstrap", rustc_tool = false, ["bootstrap"]);
+tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["-p", "tidy"]);
+tool_doc!(
+    Bootstrap,
+    "bootstrap",
+    "src/bootstrap",
+    rustc_tool = false,
+    ["--lib", "-p", "bootstrap"]
+);
 
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index c960053d7a0..6a51450a777 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -785,7 +785,7 @@ impl Build {
     /// Component directory that Cargo will produce output into (e.g.
     /// release/debug)
     fn cargo_dir(&self) -> &'static str {
-        if self.config.rust_optimize { "release" } else { "debug" }
+        if self.config.rust_optimize.is_release() { "release" } else { "debug" }
     }
 
     fn tools_dir(&self, compiler: Compiler) -> PathBuf {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index ec447a1cd73..75e7bd6aa24 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -379,7 +379,9 @@ impl Step for RustAnalyzer {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::RustAnalyzer { compiler, target: self.host }).expect("in-tree tool");
+        // We don't need to build the whole Rust Analyzer for the proc-macro-srv test suite,
+        // but we do need the standard library to be present.
+        builder.ensure(compile::Std::new(compiler, host));
 
         let workspace_path = "src/tools/rust-analyzer";
         // until the whole RA test suite runs on `i686`, we only run
@@ -788,27 +790,15 @@ impl Step for Clippy {
         cargo.add_rustc_lib_path(builder, compiler);
         let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder);
 
+        // propagate --bless
+        if builder.config.cmd.bless() {
+            cargo.env("BLESS", "Gesundheit");
+        }
+
         if builder.try_run(&mut cargo).is_ok() {
             // The tests succeeded; nothing to do.
             return;
         }
-
-        if !builder.config.cmd.bless() {
-            crate::detail_exit_macro!(1);
-        }
-
-        let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run");
-        cargo.arg("-p").arg("clippy_dev");
-        // clippy_dev gets confused if it can't find `clippy/Cargo.toml`
-        cargo.current_dir(&builder.src.join("src").join("tools").join("clippy"));
-        if builder.config.rust_optimize {
-            cargo.env("PROFILE", "release");
-        } else {
-            cargo.env("PROFILE", "debug");
-        }
-        cargo.arg("--");
-        cargo.arg("bless");
-        builder.run(&mut cargo.into());
     }
 }
 
@@ -1319,6 +1309,13 @@ host_test!(RunMakeFullDeps {
 
 default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" });
 
+host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" });
+host_test!(RunCoverageRustdoc {
+    path: "tests/run-coverage-rustdoc",
+    mode: "run-coverage",
+    suite: "run-coverage-rustdoc"
+});
+
 // For the mir-opt suite we do not use macros, as we need custom behavior when blessing.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct MirOpt {
@@ -1503,6 +1500,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             || (mode == "ui" && is_rustdoc)
             || mode == "js-doc-test"
             || mode == "rustdoc-json"
+            || suite == "run-coverage-rustdoc"
         {
             cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
         }
@@ -1516,7 +1514,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }));
         }
 
-        if mode == "run-make" {
+        if mode == "run-make" || mode == "run-coverage" {
             let rust_demangler = builder
                 .ensure(tool::RustDemangler {
                     compiler,
@@ -1703,17 +1701,21 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cmd);
             }
 
-            // Only pass correct values for these flags for the `run-make` suite as it
-            // requires that a C++ compiler was configured which isn't always the case.
-            if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") {
+            if !builder.config.dry_run()
+                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage")
+            {
                 // The llvm/bin directory contains many useful cross-platform
                 // tools. Pass the path to run-make tests so they can use them.
+                // (The run-coverage tests also need these tools to process
+                // coverage reports.)
                 let llvm_bin_path = llvm_config
                     .parent()
                     .expect("Expected llvm-config to be contained in directory");
                 assert!(llvm_bin_path.is_dir());
                 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
+            }
 
+            if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") {
                 // If LLD is available, add it to the PATH
                 if builder.config.lld_enabled {
                     let lld_install_root =
@@ -2670,8 +2672,9 @@ impl Step for Bootstrap {
             .args(["-m", "unittest", "bootstrap_test.py"])
             .env("BUILD_DIR", &builder.out)
             .env("BUILD_PLATFORM", &builder.build.build.triple)
-            .current_dir(builder.src.join("src/bootstrap/"))
-            .args(builder.config.test_args());
+            .current_dir(builder.src.join("src/bootstrap/"));
+        // NOTE: we intentionally don't pass test_args here because the args for unittest and cargo test are mutually incompatible.
+        // Use `python -m unittest` manually if you want to pass arguments.
         try_run(builder, &mut check_bootstrap).unwrap();
 
         let host = builder.config.build;
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 75aa0c2b2a2..b31629ad605 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.16.7
\ No newline at end of file
+0.16.8
\ No newline at end of file
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 8907d643182..cb12042c117 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -299,9 +299,10 @@ defaults:
     shell: bash
 
 concurrency:
-  # For a given workflow, if we push to the same PR, cancel all previous builds on that PR.
-  # If the push is not attached to a PR, we will cancel all builds related to the same commit SHA.
-  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  # For a given workflow, if we push to the same branch, cancel all previous builds on that branch.
+  # We add an exception for try builds (try branch) and unrolled rollup builds (try-perf), which
+  # are all triggered on the same branch, but which should be able to run concurrently.
+  group: ${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }}
   cancel-in-progress: true
 
 jobs:
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index 3f30b69e8f4..8640a3e0f34 100755
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -840,6 +840,11 @@ def run_tests(pipeline: Pipeline):
     cargo_path = cargo_dir / "bin" / f"cargo{pipeline.executable_extension()}"
     assert cargo_path.is_file()
 
+    # Specify path to a LLVM config so that LLVM is not rebuilt.
+    # It doesn't really matter which LLVM config we choose, because no sysroot will be compiled.
+    llvm_config = pipeline.build_artifacts() / "llvm" / "bin" / f"llvm-config{pipeline.executable_extension()}"
+    assert llvm_config.is_file()
+
     config_content = f"""profile = "user"
 changelog-seen = 2
 
@@ -847,8 +852,8 @@ changelog-seen = 2
 rustc = "{rustc_path.as_posix()}"
 cargo = "{cargo_path.as_posix()}"
 
-[llvm]
-download-ci-llvm = true
+[target.{PGO_HOST}]
+llvm-config = "{llvm_config.as_posix()}"
 """
     logging.info(f"Using following `config.toml` for running tests:\n{config_content}")
 
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
index 55cce8ab570..9deb7009cfe 100644
--- a/src/doc/rustdoc/src/how-to-read-rustdoc.md
+++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md
@@ -110,6 +110,11 @@ Function signature searches also support arrays and slices. The explicit name
 or array of bytes, while square brackets `[u8]` will match either one. Empty
 square brackets, `[]`, will match any slice regardless of what it contains.
 
+Paths are supported as well, you can look for `Vec::new` or `Option::Some` or
+even `module::module_child::another_child::struct::field`. Whitespace characters
+are considered the same as `::`, so if you write `Vec    new`, it will be
+considered the same as `Vec::new`.
+
 ### Shortcuts
 
 Pressing `S` while focused elsewhere on the page will move focus to the
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index ae180439d23..013b93e0129 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -310,6 +310,8 @@ the source.
 
 ### `--show-type-layout`: add a section to each type's docs describing its memory layout
 
+* Tracking issue: [#113248](https://github.com/rust-lang/rust/issues/113248)
+
 Using this flag looks like this:
 
 ```bash
diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md
index 75013bb3df9..b8aa64ba14f 100644
--- a/src/doc/style-guide/src/README.md
+++ b/src/doc/style-guide/src/README.md
@@ -186,6 +186,11 @@ For attributes with argument lists, format like functions.
 ```rust
 #[repr(C)]
 #[foo(foo, bar)]
+#[long_multi_line_attribute(
+    split,
+    across,
+    lines,
+)]
 struct CRepr {
     #![repr(C)]
     x: f32,
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 8271b42da4c..f5e37b6c46f 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -288,7 +288,8 @@ and other assignment operators such as `+=` or `*=`).
 
 For comparison operators, because for `T op U`, `&T op &U` is also implemented:
 if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general,
-within expressions, prefer dereferencing to taking references.
+within expressions, prefer dereferencing to taking references, unless necessary
+(e.g. to avoid an unnecessarily expensive operation).
 
 Use parentheses liberally, do not necessarily elide them due to precedence.
 Tools should not automatically insert or remove parentheses. Do not use spaces
diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md
index 9bc521e1c7b..a5cd6da1061 100644
--- a/src/doc/style-guide/src/statements.md
+++ b/src/doc/style-guide/src/statements.md
@@ -159,8 +159,8 @@ before the `else`.
 
 If the initializer expression is multi-line, the `else` keyword and opening
 brace of the block (i.e. `else {`) should be put on the same line as the end of
-the initializer expression, with a space between them, if all the following are
-true:
+the initializer expression, with a space between them, if and only if all the
+following are true:
 
 * The initializer expression ends with one or more closing
   parentheses, square brackets, and/or braces
@@ -209,6 +209,28 @@ fn main() {
     else {
         return;
     };
+
+    let LongStructName(AnotherStruct {
+        multi,
+        line,
+        pattern,
+    }) = slice.as_ref()
+    else {
+        return;
+    };
+
+    let LongStructName(AnotherStruct {
+        multi,
+        line,
+        pattern,
+    }) = multi_line_function_call(
+        arg1,
+        arg2,
+        arg3,
+        arg4,
+    ) else {
+        return;
+    };
 }
 ```
 
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index 0807e0492c1..c9e1a2733fd 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -5,7 +5,7 @@
 # and remove it from .git/hooks to deactivate.
 #
 
-set -Eeuo pipefail
+set -Euo pipefail
 
 # https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570
 unset GIT_DIR
@@ -15,3 +15,7 @@ echo "Running pre-push script $ROOT_DIR/x test tidy"
 
 cd "$ROOT_DIR"
 ./x test tidy --set build.locked-deps=true
+if [ $? -ne 0 ]; then
+    echo "You may use \`git push --no-verify\` to skip this check."
+    exit 1
+fi
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b4aba2993c7..54c0cd2ef7f 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1459,7 +1459,7 @@ impl clean::FnDecl {
         Ok(())
     }
 
-    pub(crate) fn print_output<'a, 'tcx: 'a>(
+    fn print_output<'a, 'tcx: 'a>(
         &'a self,
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index c9b95b1e645..0bc32ea5a20 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -17,7 +17,7 @@ use crate::html::render::Context;
 #[template(path = "type_layout.html")]
 struct TypeLayout<'cx> {
     variants: Vec<(Symbol, TypeLayoutSize)>,
-    type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>,
+    type_layout_size: Result<TypeLayoutSize, &'cx LayoutError<'cx>>,
 }
 
 #[derive(Template)]
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b6d90091bba..ccfd4cc5b87 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -8,6 +8,7 @@
 
 :root {
 	--nav-sub-mobile-padding: 8px;
+	--search-typename-width: 6.75rem;
 }
 
 /* See FiraSans-LICENSE.txt for the Fira Sans license. */
@@ -869,14 +870,11 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	gap: 1em;
 }
 
-.search-results > a > div {
-	flex: 1;
-}
-
 .search-results > a > div.desc {
 	white-space: nowrap;
 	text-overflow: ellipsis;
 	overflow: hidden;
+	flex: 2;
 }
 
 .search-results a:hover,
@@ -884,6 +882,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	background-color: var(--search-result-link-focus-background-color);
 }
 
+.search-results .result-name {
+	display: flex;
+	align-items: center;
+	justify-content: start;
+	flex: 3;
+}
 .search-results .result-name span.alias {
 	color: var(--search-results-alias-color);
 }
@@ -891,10 +895,14 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	color: var(--search-results-grey-color);
 }
 .search-results .result-name .typename {
-	display: inline-block;
 	color: var(--search-results-grey-color);
 	font-size: 0.875rem;
-	width: 6.25rem;
+	width: var(--search-typename-width);
+}
+.search-results .result-name .path {
+	word-break: break-all;
+	max-width: calc(100% - var(--search-typename-width));
+	display: inline-block;
 }
 
 .popover {
@@ -1730,6 +1738,16 @@ in source-script.js
 	.search-results > a > div.desc, .item-table > li > div.desc {
 		padding-left: 2em;
 	}
+	.search-results .result-name {
+		display: block;
+	}
+	.search-results .result-name .typename {
+		width: initial;
+		margin-right: 0;
+	}
+	.search-results .result-name .typename, .search-results .result-name .path {
+		display: inline;
+	}
 
 	.source-sidebar-expanded .source .sidebar {
 		max-width: 100vw;
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index b8cc0a6db71..51d8e81ca86 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -290,7 +290,7 @@ function initSearch(rawSearchIndex) {
     }
 
     function isStopCharacter(c) {
-        return isWhitespace(c) || isEndCharacter(c);
+        return isEndCharacter(c);
     }
 
     function isErrorCharacter(c) {
@@ -386,18 +386,69 @@ function initSearch(rawSearchIndex) {
      * @return {boolean}
      */
     function isSeparatorCharacter(c) {
-        return c === "," || isWhitespaceCharacter(c);
+        return c === ",";
     }
 
-    /**
-     * Returns `true` if the given `c` character is a whitespace.
+/**
+     * Returns `true` if the given `c` character is a path separator. For example
+     * `:` in `a::b` or a whitespace in `a b`.
      *
      * @param {string} c
      *
      * @return {boolean}
      */
-    function isWhitespaceCharacter(c) {
-        return c === " " || c === "\t";
+    function isPathSeparator(c) {
+        return c === ":" || isWhitespace(c);
+    }
+
+    /**
+     * Returns `true` if the previous character is `lookingFor`.
+     *
+     * @param {ParserState} parserState
+     * @param {String} lookingFor
+     *
+     * @return {boolean}
+     */
+    function prevIs(parserState, lookingFor) {
+        let pos = parserState.pos;
+        while (pos > 0) {
+            const c = parserState.userQuery[pos - 1];
+            if (c === lookingFor) {
+                return true;
+            } else if (!isWhitespace(c)) {
+                break;
+            }
+            pos -= 1;
+        }
+        return false;
+    }
+
+    /**
+     * Returns `true` if the last element in the `elems` argument has generics.
+     *
+     * @param {Array<QueryElement>} elems
+     * @param {ParserState} parserState
+     *
+     * @return {boolean}
+     */
+    function isLastElemGeneric(elems, parserState) {
+        return (elems.length > 0 && elems[elems.length - 1].generics.length > 0) ||
+            prevIs(parserState, ">");
+    }
+
+    /**
+     * Increase current parser position until it doesn't find a whitespace anymore.
+     *
+     * @param {ParserState} parserState
+     */
+    function skipWhitespace(parserState) {
+        while (parserState.pos < parserState.userQuery.length) {
+            const c = parserState.userQuery[parserState.pos];
+            if (!isWhitespace(c)) {
+                break;
+            }
+            parserState.pos += 1;
+        }
     }
 
     /**
@@ -409,11 +460,14 @@ function initSearch(rawSearchIndex) {
      * @return {QueryElement}                - The newly created `QueryElement`.
      */
     function createQueryElement(query, parserState, name, generics, isInGenerics) {
-        if (name === "*" || (name.length === 0 && generics.length === 0)) {
-            return;
+        const path = name.trim();
+        if (path.length === 0 && generics.length === 0) {
+            throw ["Unexpected ", parserState.userQuery[parserState.pos]];
+        } else if (path === "*") {
+            throw ["Unexpected ", "*"];
         }
         if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
-            throw ["You cannot have more than one element if you use quotes"];
+            throw ["Cannot have more than one element if you use quotes"];
         }
         const typeFilter = parserState.typeFilter;
         parserState.typeFilter = null;
@@ -444,38 +498,40 @@ function initSearch(rawSearchIndex) {
                 typeFilter: "primitive",
             };
         }
-        const pathSegments = name.split("::");
-        if (pathSegments.length > 1) {
-            for (let i = 0, len = pathSegments.length; i < len; ++i) {
-                const pathSegment = pathSegments[i];
-
-                if (pathSegment.length === 0) {
-                    if (i === 0) {
-                        throw ["Paths cannot start with ", "::"];
-                    } else if (i + 1 === len) {
-                        throw ["Paths cannot end with ", "::"];
-                    }
-                    throw ["Unexpected ", "::::"];
-                }
-
-                if (pathSegment === "!") {
-                    pathSegments[i] = "never";
-                    if (i !== 0) {
-                        throw ["Never type ", "!", " is not associated item"];
-                    }
-                }
-            }
-        }
+        if (path.startsWith("::")) {
+            throw ["Paths cannot start with ", "::"];
+        } else if (path.endsWith("::")) {
+            throw ["Paths cannot end with ", "::"];
+        } else if (path.includes("::::")) {
+            throw ["Unexpected ", "::::"];
+        } else if (path.includes(" ::")) {
+            throw ["Unexpected ", " ::"];
+        } else if (path.includes(":: ")) {
+            throw ["Unexpected ", ":: "];
+        }
+        const pathSegments = path.split(/::|\s+/);
         // In case we only have something like `<p>`, there is no name.
         if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
-            throw ["Found generics without a path"];
+            if (generics.length > 0 || prevIs(parserState, ">")) {
+                throw ["Found generics without a path"];
+            } else {
+                throw ["Unexpected ", parserState.userQuery[parserState.pos]];
+            }
+        }
+        for (const [i, pathSegment] of pathSegments.entries()) {
+            if (pathSegment === "!") {
+                if (i !== 0) {
+                    throw ["Never type ", "!", " is not associated item"];
+                }
+                pathSegments[i] = "never";
+            }
         }
         parserState.totalElems += 1;
         if (isInGenerics) {
             parserState.genericsElems += 1;
         }
         return {
-            name: name,
+            name: name.trim(),
             id: -1,
             fullPath: pathSegments,
             pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
@@ -511,15 +567,21 @@ function initSearch(rawSearchIndex) {
                     foundExclamation = parserState.pos;
                 } else if (isErrorCharacter(c)) {
                     throw ["Unexpected ", c];
-                } else if (
-                    isStopCharacter(c) ||
-                    isSpecialStartCharacter(c) ||
-                    isSeparatorCharacter(c)
-                ) {
-                    break;
-                } else if (c === ":") { // If we allow paths ("str::string" for example).
-                    if (!isPathStart(parserState)) {
-                        break;
+                } else if (isPathSeparator(c)) {
+                    if (c === ":") {
+                        if (!isPathStart(parserState)) {
+                            break;
+                        }
+                        // Skip current ":".
+                        parserState.pos += 1;
+                    } else {
+                        while (parserState.pos + 1 < parserState.length) {
+                            const next_c = parserState.userQuery[parserState.pos + 1];
+                            if (!isWhitespace(next_c)) {
+                                break;
+                            }
+                            parserState.pos += 1;
+                        }
                     }
                     if (foundExclamation !== -1) {
                         if (foundExclamation !== start &&
@@ -532,8 +594,13 @@ function initSearch(rawSearchIndex) {
                             foundExclamation = -1;
                         }
                     }
-                    // Skip current ":".
-                    parserState.pos += 1;
+                } else if (
+                    c === "[" ||
+                    isStopCharacter(c) ||
+                    isSpecialStartCharacter(c) ||
+                    isSeparatorCharacter(c)
+                ) {
+                    break;
                 } else {
                     throw ["Unexpected ", c];
                 }
@@ -571,6 +638,7 @@ function initSearch(rawSearchIndex) {
     function getNextElem(query, parserState, elems, isInGenerics) {
         const generics = [];
 
+        skipWhitespace(parserState);
         let start = parserState.pos;
         let end;
         if (parserState.userQuery[parserState.pos] === "[") {
@@ -601,8 +669,9 @@ function initSearch(rawSearchIndex) {
                 typeFilter: "primitive",
             });
         } else {
+            const isStringElem = parserState.userQuery[start] === "\"";
             // We handle the strings on their own mostly to make code easier to follow.
-            if (parserState.userQuery[parserState.pos] === "\"") {
+            if (isStringElem) {
                 start += 1;
                 getStringElem(query, parserState, isInGenerics);
                 end = parserState.pos - 1;
@@ -618,6 +687,9 @@ function initSearch(rawSearchIndex) {
                 parserState.pos += 1;
                 getItemsBefore(query, parserState, generics, ">");
             }
+            if (isStringElem) {
+                skipWhitespace(parserState);
+            }
             if (start >= end && generics.length === 0) {
                 return;
             }
@@ -682,7 +754,7 @@ function initSearch(rawSearchIndex) {
                 if (elems.length === 0) {
                     throw ["Expected type filter before ", ":"];
                 } else if (query.literalSearch) {
-                    throw ["You cannot use quotes on type filter"];
+                    throw ["Cannot use quotes on type filter"];
                 }
                 // The type filter doesn't count as an element since it's a modifier.
                 const typeFilterElem = elems.pop();
@@ -697,23 +769,27 @@ function initSearch(rawSearchIndex) {
                 throw ["Unexpected ", c, " after ", extra];
             }
             if (!foundStopChar) {
+                let extra = [];
+                if (isLastElemGeneric(query.elems, parserState)) {
+                    extra = [" after ", ">"];
+                } else if (prevIs(parserState, "\"")) {
+                    throw ["Cannot have more than one element if you use quotes"];
+                }
                 if (endChar !== "") {
                     throw [
                         "Expected ",
-                        ",", // comma
-                        ", ",
-                        "&nbsp;", // whitespace
+                        ",",
                         " or ",
                         endChar,
+                        ...extra,
                         ", found ",
                         c,
                     ];
                 }
                 throw [
                     "Expected ",
-                    ",", // comma
-                    " or ",
-                    "&nbsp;", // whitespace
+                    ",",
+                    ...extra,
                     ", found ",
                     c,
                 ];
@@ -749,11 +825,17 @@ function initSearch(rawSearchIndex) {
      * @param {ParserState} parserState
      */
     function checkExtraTypeFilterCharacters(start, parserState) {
-        const query = parserState.userQuery;
+        const query = parserState.userQuery.slice(start, parserState.pos).trim();
 
-        for (let pos = start; pos < parserState.pos; ++pos) {
-            if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
-                throw ["Unexpected ", query[pos], " in type filter"];
+        for (const c in query) {
+            if (!isIdentCharacter(query[c])) {
+                throw [
+                    "Unexpected ",
+                    query[c],
+                    " in type filter (before ",
+                    ":",
+                    ")",
+                ];
             }
         }
     }
@@ -785,12 +867,17 @@ function initSearch(rawSearchIndex) {
                 throw ["Unexpected ", c];
             } else if (c === ":" && !isPathStart(parserState)) {
                 if (parserState.typeFilter !== null) {
-                    throw ["Unexpected ", ":"];
-                }
-                if (query.elems.length === 0) {
+                    throw [
+                        "Unexpected ",
+                        ":",
+                        " (expected path after type filter ",
+                        parserState.typeFilter + ":",
+                        ")",
+                    ];
+                } else if (query.elems.length === 0) {
                     throw ["Expected type filter before ", ":"];
                 } else if (query.literalSearch) {
-                    throw ["You cannot use quotes on type filter"];
+                    throw ["Cannot use quotes on type filter"];
                 }
                 // The type filter doesn't count as an element since it's a modifier.
                 const typeFilterElem = query.elems.pop();
@@ -801,29 +888,36 @@ function initSearch(rawSearchIndex) {
                 query.literalSearch = false;
                 foundStopChar = true;
                 continue;
+            } else if (isWhitespace(c)) {
+                skipWhitespace(parserState);
+                continue;
             }
             if (!foundStopChar) {
+                let extra = "";
+                if (isLastElemGeneric(query.elems, parserState)) {
+                    extra = [" after ", ">"];
+                } else if (prevIs(parserState, "\"")) {
+                    throw ["Cannot have more than one element if you use quotes"];
+                }
                 if (parserState.typeFilter !== null) {
                     throw [
                         "Expected ",
-                        ",", // comma
-                        ", ",
-                        "&nbsp;", // whitespace
+                        ",",
                         " or ",
-                        "->", // arrow
+                        "->",
+                        ...extra,
                         ", found ",
                         c,
                     ];
                 }
                 throw [
                     "Expected ",
-                    ",", // comma
+                    ",",
                     ", ",
-                    "&nbsp;", // whitespace
-                    ", ",
-                    ":", // colon
+                    ":",
                     " or ",
-                    "->", // arrow
+                    "->",
+                    ...extra,
                     ", found ",
                     c,
                 ];
@@ -838,11 +932,18 @@ function initSearch(rawSearchIndex) {
             foundStopChar = false;
         }
         if (parserState.typeFilter !== null) {
-            throw ["Unexpected ", ":", " (expected path after type filter)"];
+            throw [
+                "Unexpected ",
+                ":",
+                " (expected path after type filter ",
+                parserState.typeFilter + ":",
+                ")",
+            ];
         }
         while (parserState.pos < parserState.length) {
             if (isReturnArrow(parserState)) {
                 parserState.pos += 2;
+                skipWhitespace(parserState);
                 // Get returned elements.
                 getItemsBefore(query, parserState, query.returned, "");
                 // Nothing can come afterward!
@@ -917,10 +1018,10 @@ function initSearch(rawSearchIndex) {
      * The supported syntax by this parser is as follow:
      *
      * ident = *(ALPHA / DIGIT / "_")
-     * path = ident *(DOUBLE-COLON ident) [!]
+     * path = ident *(DOUBLE-COLON/{WS} ident) [!]
      * slice = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET
      * arg = [type-filter *WS COLON *WS] (path [generics] / slice)
-     * type-sep = COMMA/WS *(COMMA/WS)
+     * type-sep = *WS COMMA *(COMMA)
      * nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep)
      * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list ] *(type-sep)
      *            CLOSE-ANGLE-BRACKET
@@ -2024,9 +2125,11 @@ function initSearch(rawSearchIndex) {
 
                 resultName.insertAdjacentHTML(
                     "beforeend",
-                    `<span class="typename">${typeName}</span>`
-                    + ` ${item.displayPath}<span class="${type}">${name}</span>`
-                );
+                    `\
+<span class="typename">${typeName}</span>\
+<div class="path">\
+ ${item.displayPath}<span class="${type}">${name}</span>\
+</div>`);
                 link.appendChild(resultName);
 
                 const description = document.createElement("div");
@@ -2138,7 +2241,7 @@ function initSearch(rawSearchIndex) {
             error.forEach((value, index) => {
                 value = value.split("<").join("&lt;").split(">").join("&gt;");
                 if (index % 2 !== 0) {
-                    error[index] = `<code>${value}</code>`;
+                    error[index] = `<code>${value.replaceAll(" ", "&nbsp;")}</code>`;
                 } else {
                     error[index] = value;
                 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index c31ba3304b0..0dd9e590b9b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -398,6 +398,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             .doc_link_resolutions(module_id)
             .get(&(Symbol::intern(path_str), ns))
             .copied()
+            // NOTE: do not remove this panic! Missing links should be recorded as `Res::Err`; if
+            // `doc_link_resolutions` is missing a `path_str`, that means that there are valid links
+            // that are being missed. To fix the ICE, change
+            // `rustc_resolve::rustdoc::attrs_to_preprocessed_links` to cache the link.
             .unwrap_or_else(|| panic!("no resolution for {:?} {:?} {:?}", path_str, ns, module_id))
             .and_then(|res| res.try_into().ok())
             .or_else(|| resolve_primitive(path_str, ns));
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 03bc66b55c290324bd46eb22e369c8fae1908f9
+Subproject 5b377cece0e0dd0af686cf53ce4637d5d85c2a1
diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml
index 4d80d3ce63d..48a63e48568 100644
--- a/src/tools/clippy/.cargo/config.toml
+++ b/src/tools/clippy/.cargo/config.toml
@@ -1,5 +1,7 @@
 [alias]
 uitest = "test --test compile-test"
+uibless = "test --test compile-test -- -- --bless"
+bless = "test -- -- --bless"
 dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
 lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml  -- "
 collect-metadata = "test --test dogfood --features internal -- run_metadata_collection_lint --ignored"
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index a9d42159c4b..c582c28cd3c 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -25,7 +25,6 @@ env:
   CARGO_TARGET_DIR: '${{ github.workspace }}/target'
   NO_FMT_TEST: 1
   CARGO_INCREMENTAL: 0
-  CARGO_UNSTABLE_SPARSE_REGISTRY: true
 
 jobs:
   base:
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 30a156c925b..d5ab313ba0e 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -11,7 +11,6 @@ env:
   CARGO_TARGET_DIR: '${{ github.workspace }}/target'
   NO_FMT_TEST: 1
   CARGO_INCREMENTAL: 0
-  CARGO_UNSTABLE_SPARSE_REGISTRY: true
 
 defaults:
   run:
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 514706d64c8..0f0e3f2db92 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -16,7 +16,6 @@ on:
 env:
   RUST_BACKTRACE: 1
   CARGO_INCREMENTAL: 0
-  CARGO_UNSTABLE_SPARSE_REGISTRY: true
 
 jobs:
   clippy_dev:
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 8b609b47d81..14d822083d8 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -10,9 +10,9 @@ document.
 
 ## Rust 1.70
 
-Current beta, released 2023-06-01
+Current stable, released 2023-06-01
 
-[149392b0...83e42a23](https://github.com/rust-lang/rust-clippy/compare/149392b0...83e42a23)
+[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+)
 
 ### New Lints
 
@@ -95,7 +95,7 @@ Current beta, released 2023-06-01
   [#10375](https://github.com/rust-lang/rust-clippy/pull/10375)
 * [`mem_replace_option_with_none`]: No longer lints on field expressions
   [#10594](https://github.com/rust-lang/rust-clippy/pull/10594)
-* [`items_after_statements`]: No longer lints on times from macros
+* [`items_after_statements`]: No longer lints on items from macros
   [#10542](https://github.com/rust-lang/rust-clippy/pull/10542)
 * [`print_literal`], [`write_literal`]: No longer lint strings coming from the `file!()` macro
   [#10573](https://github.com/rust-lang/rust-clippy/pull/10573)
@@ -135,9 +135,9 @@ Current beta, released 2023-06-01
 
 ## Rust 1.69
 
-Current stable, released 2023-04-20
+Released 2023-04-20
 
-[7f27e2e7...149392b0](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...149392b0)
+[**View 86 PRs merged since 1.68**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-03-09..2023-04-20+base%3Amaster+sort%3Amerged-desc+)
 
 ### New Lints
 
@@ -252,7 +252,7 @@ Current stable, released 2023-04-20
 
 Released 2023-03-09
 
-[d822110d...7f27e2e7](https://github.com/rust-lang/rust-clippy/compare/d822110d...7f27e2e7)
+[**View 85 PRs merged since 1.67**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-01-26..2023-03-09+base%3Amaster+sort%3Amerged-desc+)
 
 ### New Lints
 
@@ -399,7 +399,7 @@ Released 2023-03-09
 
 Released 2023-01-26
 
-[4f142aa1...d822110d](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...d822110d)
+[**View 68 PRs merged since 1.66**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-12-15..2023-01-26+base%3Amaster+sort%3Amerged-desc+)
 
 ### New Lints
 
@@ -590,7 +590,8 @@ Released 2023-01-26
 
 Released 2022-12-15
 
-[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
+[**View 93 PRs merged since 1.65**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-11-03..2022-12-15+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -761,7 +762,8 @@ Released 2022-12-15
 
 Released 2022-11-03
 
-[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523)
+[**View 129 PRs merged since 1.64**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-09-22..2022-11-03+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### Important Changes
 
@@ -905,7 +907,8 @@ Released 2022-11-03
 
 Released 2022-09-22
 
-[d7b5cbf0...3c7e7dbc](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...3c7e7dbc)
+[**View 92 PRs merged since 1.63**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-08-11..2022-09-22+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -1055,7 +1058,8 @@ Released 2022-09-22
 
 Released 2022-08-11
 
-[7c21f91b...d7b5cbf0](https://github.com/rust-lang/rust-clippy/compare/7c21f91b...d7b5cbf0)
+[**View 100 PRs merged since 1.62**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-06-30..2022-08-11+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -1201,7 +1205,8 @@ Released 2022-08-11
 
 Released 2022-06-30
 
-[d0cf3481...7c21f91b](https://github.com/rust-lang/rust-clippy/compare/d0cf3481...7c21f91b)
+[**View 104 PRs merged since 1.61**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-05-19..2022-06-30+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -1358,7 +1363,8 @@ Released 2022-06-30
 
 Released 2022-05-19
 
-[57b3c4b...d0cf3481](https://github.com/rust-lang/rust-clippy/compare/57b3c4b...d0cf3481)
+[**View 93 PRs merged since 1.60**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-04-07..2022-05-19+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -1459,7 +1465,8 @@ Released 2022-05-19
 
 Released 2022-04-07
 
-[0eff589...57b3c4b](https://github.com/rust-lang/rust-clippy/compare/0eff589...57b3c4b)
+[**View 75 PRs merged since 1.59**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-02-24..2022-04-07+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -1591,7 +1598,8 @@ Released 2022-04-07
 
 Released 2022-02-24
 
-[e181011...0eff589](https://github.com/rust-lang/rust-clippy/compare/e181011...0eff589)
+[**View 63 PRs merged since 1.58**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2022-01-13..2022-02-24+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -1755,7 +1763,8 @@ Released 2022-02-24
 
 Released 2022-01-13
 
-[00e31fa...e181011](https://github.com/rust-lang/rust-clippy/compare/00e31fa...e181011)
+[**View 73 PRs merged since 1.57**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-12-02..2022-01-13+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### Rust 1.58.1
 
@@ -1876,7 +1885,8 @@ Released 2022-01-13
 
 Released 2021-12-02
 
-[7bfc26e...00e31fa](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...00e31fa)
+[**View 92 PRs merged since 1.56**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-10-21..2021-12-02+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -2027,7 +2037,7 @@ Released 2021-12-02
 
 Released 2021-10-21
 
-[74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e)
+[**View 92 PRs merged since 1.55**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-09-09..2021-10-21+base%3Amaster+sort%3Amerged-desc+)
 
 ### New Lints
 
@@ -2093,7 +2103,7 @@ Released 2021-10-21
 
 Released 2021-09-09
 
-[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
+[**View 61 PRs merged since 1.54**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-07-29..2021-09-09+base%3Amaster+sort%3Amerged-desc+)
 
 ### Important Changes
 
@@ -2211,7 +2221,8 @@ Released 2021-09-09
 
 Released 2021-07-29
 
-[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf)
+[**View 68 PRs merged since 1.53**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-06-17..2021-07-29+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -2339,7 +2350,7 @@ Released 2021-07-29
 
 Released 2021-06-17
 
-[6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c)
+[**View 80 PRs merged since 1.52**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-05-06..2021-06-17+base%3Amaster+sort%3Amerged-desc+)
 
 ### New Lints
 
@@ -2523,7 +2534,8 @@ Released 2021-06-17
 
 Released 2021-05-06
 
-[3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e)
+[**View 113 PRs merged since 1.51**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-03-25..2021-05-06+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -2658,7 +2670,8 @@ Released 2021-05-06
 
 Released 2021-03-25
 
-[4911ab1...3e41797](https://github.com/rust-lang/rust-clippy/compare/4911ab1...3e41797)
+[**View 117 PRs merged since 1.50**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2021-02-11..2021-03-25+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -2773,7 +2786,8 @@ Released 2021-03-25
 
 Released 2021-02-11
 
-[b20d4c1...4bd77a1](https://github.com/rust-lang/rust-clippy/compare/b20d4c1...4bd77a1)
+[**View 90 PRs merged since 1.49**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-12-31..2021-02-11+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -2902,7 +2916,8 @@ Released 2021-02-11
 
 Released 2020-12-31
 
-[e636b88...b20d4c1](https://github.com/rust-lang/rust-clippy/compare/e636b88...b20d4c1)
+[**View 85 PRs merged since 1.48**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-11-19..2020-12-31+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New Lints
 
@@ -3008,7 +3023,7 @@ Released 2020-12-31
 
 Released 2020-11-19
 
-[09bd400...e636b88](https://github.com/rust-lang/rust-clippy/compare/09bd400...e636b88)
+[**View 112 PRs merged since 1.47**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-10-08..2020-11-19+base%3Amaster+sort%3Amerged-desc+)
 
 ### New lints
 
@@ -3126,7 +3141,8 @@ Released 2020-11-19
 
 Released 2020-10-08
 
-[c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400)
+[**View 80 PRs merged since 1.46**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-08-27..2020-10-08+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New lints
 
@@ -3228,7 +3244,8 @@ Released 2020-10-08
 
 Released 2020-08-27
 
-[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa)
+[**View 93 PRs merged since 1.45**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-07-16..2020-08-27+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New lints
 
@@ -3290,7 +3307,8 @@ Released 2020-08-27
 
 Released 2020-07-16
 
-[891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1)
+[**View 65 PRs merged since 1.44**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-06-04..2020-07-16+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New lints
 
@@ -3367,7 +3385,8 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565
 
 Released 2020-06-04
 
-[204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8)
+[**View 88 PRs merged since 1.43**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-04-23..2020-06-04+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New lints
 
@@ -3450,7 +3469,8 @@ Released 2020-06-04
 
 Released 2020-04-23
 
-[4ee1206...204bb9b](https://github.com/rust-lang/rust-clippy/compare/4ee1206...204bb9b)
+[**View 121 PRs merged since 1.42**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-03-12..2020-04-23+base%3Amaster+sort%3Amerged-desc+)
+
 
 ### New lints
 
@@ -3508,7 +3528,7 @@ Released 2020-04-23
 
 Released 2020-03-12
 
-[69f99e7...4ee1206](https://github.com/rust-lang/rust-clippy/compare/69f99e7...4ee1206)
+[**View 106 PRs merged since 1.41**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2020-01-30..2020-03-12+base%3Amaster+sort%3Amerged-desc+)
 
 ### New lints
 
@@ -3575,7 +3595,7 @@ Released 2020-03-12
 
 Released 2020-01-30
 
-[c8e3cfb...69f99e7](https://github.com/rust-lang/rust-clippy/compare/c8e3cfb...69f99e7)
+[**View 107 PRs merged since 1.40**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-12-19..2020-01-30+base%3Amaster+sort%3Amerged-desc+)
 
 * New Lints:
   * [`exit`] [#4697](https://github.com/rust-lang/rust-clippy/pull/4697)
@@ -3620,7 +3640,8 @@ Released 2020-01-30
 
 Released 2019-12-19
 
-[4e7e71b...c8e3cfb](https://github.com/rust-lang/rust-clippy/compare/4e7e71b...c8e3cfb)
+[**View 69 😺 PRs merged since 1.39**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-11-07..2019-12-19+base%3Amaster+sort%3Amerged-desc+)
+
 
 * New Lints:
   * [`unneeded_wildcard_pattern`] [#4537](https://github.com/rust-lang/rust-clippy/pull/4537)
@@ -3662,7 +3683,7 @@ Released 2019-12-19
 
 Released 2019-11-07
 
-[3aea860...4e7e71b](https://github.com/rust-lang/rust-clippy/compare/3aea860...4e7e71b)
+[**View 84 PRs merged since 1.38**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-09-26..2019-11-07+base%3Amaster+sort%3Amerged-desc+)
 
 * New Lints:
   * [`uninit_assumed_init`] [#4479](https://github.com/rust-lang/rust-clippy/pull/4479)
@@ -3706,7 +3727,7 @@ Released 2019-11-07
 
 Released 2019-09-26
 
-[e3cb40e...3aea860](https://github.com/rust-lang/rust-clippy/compare/e3cb40e...3aea860)
+[**View 102 PRs merged since 1.37**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-08-15..2019-09-26+base%3Amaster+sort%3Amerged-desc+)
 
 * New Lints:
   * [`main_recursion`] [#4203](https://github.com/rust-lang/rust-clippy/pull/4203)
@@ -3736,7 +3757,7 @@ Released 2019-09-26
 
 Released 2019-08-15
 
-[082cfa7...e3cb40e](https://github.com/rust-lang/rust-clippy/compare/082cfa7...e3cb40e)
+[**View 83 PRs merged since 1.36**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-07-04..2019-08-15+base%3Amaster+sort%3Amerged-desc+)
 
 * New Lints:
   * [`checked_conversions`] [#4088](https://github.com/rust-lang/rust-clippy/pull/4088)
@@ -3760,7 +3781,8 @@ Released 2019-08-15
 
 Released 2019-07-04
 
-[eb9f9b1...082cfa7](https://github.com/rust-lang/rust-clippy/compare/eb9f9b1...082cfa7)
+[**View 75 PRs merged since 1.35**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-05-20..2019-07-04+base%3Amaster+sort%3Amerged-desc+)
+
 
 * New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039)
 * New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954)
@@ -3791,7 +3813,8 @@ Released 2019-07-04
 
 Released 2019-05-20
 
-[1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e)
+[**View 90 PRs merged since 1.34**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-04-10..2019-05-20+base%3Amaster+sort%3Amerged-desc+)
+
 
 * New lint: `drop_bounds` to detect `T: Drop` bounds
 * Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101)
@@ -3819,7 +3842,8 @@ Released 2019-05-20
 
 Released 2019-04-10
 
-[1b89724...1fac380](https://github.com/rust-lang/rust-clippy/compare/1b89724...1fac380)
+[**View 66 PRs merged since 1.33**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-02-26..2019-04-10+base%3Amaster+sort%3Amerged-desc+)
+
 
 * New lint: [`assertions_on_constants`] to detect for example `assert!(true)`
 * New lint: [`dbg_macro`] to detect uses of the `dbg!` macro
@@ -3849,7 +3873,7 @@ Released 2019-04-10
 
 Released 2019-02-26
 
-[b2601be...1b89724](https://github.com/rust-lang/rust-clippy/compare/b2601be...1b89724)
+[**View 83 PRs merged since 1.32**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2019-01-17..2019-02-26+base%3Amaster+sort%3Amerged-desc+)
 
 * New lints: [`implicit_return`], [`vec_box`], [`cast_ref_to_mut`]
 * The `rust-clippy` repository is now part of the `rust-lang` org.
@@ -3882,7 +3906,7 @@ Released 2019-02-26
 
 Released 2019-01-17
 
-[2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be)
+[**View 106 PRs merged since 1.31**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-12-06..2019-01-17+base%3Amaster+sort%3Amerged-desc+)
 
 * New lints: [`slow_vector_initialization`], `mem_discriminant_non_enum`,
   [`redundant_clone`], [`wildcard_dependencies`],
@@ -3912,7 +3936,8 @@ Released 2019-01-17
 
 Released 2018-12-06
 
-[125907ad..2e26fdc2](https://github.com/rust-lang/rust-clippy/compare/125907ad..2e26fdc2)
+[**View 85 PRs merged since 1.30**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-10-25..2018-12-06+base%3Amaster+sort%3Amerged-desc+)
+
 
 * Clippy has been relicensed under a dual MIT / Apache license.
   See [#3093](https://github.com/rust-lang/rust-clippy/issues/3093) for more
@@ -3952,7 +3977,8 @@ Released 2018-12-06
 
 Released 2018-10-25
 
-[14207503...125907ad](https://github.com/rust-lang/rust-clippy/compare/14207503...125907ad)
+[**View 106 PRs merged since 1.29**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2018-09-13..2018-10-25+base%3Amaster+sort%3Amerged-desc+)
+
 
 * Deprecate `assign_ops` lint
 * New lints: [`mistyped_literal_suffixes`], [`ptr_offset_with_cast`],
@@ -4628,6 +4654,7 @@ Released 2018-09-13
 [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
 [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
 [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
+[`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync
 [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
 [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
 [`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut
@@ -4641,6 +4668,7 @@ Released 2018-09-13
 [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock
 [`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref
 [`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
+[`big_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#big_endian_bytes
 [`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map
 [`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name
 [`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints
@@ -4735,6 +4763,7 @@ Released 2018-09-13
 [`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use
 [`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg
 [`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens
+[`drain_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#drain_collect
 [`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds
 [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy
 [`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop
@@ -4757,6 +4786,7 @@ Released 2018-09-13
 [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op
 [`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect
 [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence
+[`excessive_nesting`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting
 [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision
 [`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums
 [`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs
@@ -4811,6 +4841,7 @@ Released 2018-09-13
 [`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first
 [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len
 [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap
+[`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes
 [`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion
 [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op
 [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex
@@ -4829,6 +4860,7 @@ Released 2018-09-13
 [`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
 [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
 [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor
+[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type
 [`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice
 [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
 [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
@@ -4879,6 +4911,7 @@ Released 2018-09-13
 [`large_futures`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_futures
 [`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file
 [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
+[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames
 [`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value
 [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
 [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
@@ -4892,6 +4925,7 @@ Released 2018-09-13
 [`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore
 [`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok
 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
+[`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_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
@@ -4915,6 +4949,7 @@ Released 2018-09-13
 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
+[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns
 [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
 [`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain
 [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
@@ -4924,6 +4959,7 @@ Released 2018-09-13
 [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new
 [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip
 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
+[`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold
 [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
 [`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some
 [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
@@ -4947,11 +4983,13 @@ Released 2018-09-13
 [`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm
 [`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants
 [`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter
+[`maybe_misused_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_misused_cfg
 [`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum
 [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget
 [`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none
 [`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default
 [`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit
+[`min_ident_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars
 [`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max
 [`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute
 [`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os
@@ -5002,6 +5040,7 @@ Released 2018-09-13
 [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main
 [`needless_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_else
 [`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each
+[`needless_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_if
 [`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init
 [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
 [`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match
@@ -5009,8 +5048,11 @@ Released 2018-09-13
 [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take
 [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals
 [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
+[`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self
 [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
 [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop
+[`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes
+[`needless_raw_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_strings
 [`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
 [`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn
 [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update
@@ -5081,6 +5123,8 @@ Released 2018-09-13
 [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
 [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
 [`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use
+[`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_with_shorthand
+[`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_without_shorthand
 [`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
 [`question_mark_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark_used
 [`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one
@@ -5094,6 +5138,7 @@ Released 2018-09-13
 [`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl
 [`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
 [`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_async_block
+[`redundant_at_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_at_rest_pattern
 [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
 [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
 [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
@@ -5106,6 +5151,7 @@ Released 2018-09-13
 [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
 [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
 [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
+[`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
@@ -5146,6 +5192,7 @@ Released 2018-09-13
 [`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee
 [`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening
 [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
+[`single_call_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn
 [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str
 [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names
 [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
@@ -5154,6 +5201,7 @@ Released 2018-09-13
 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop
 [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
+[`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_range_in_vec_init
 [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
 [`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
 [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
@@ -5216,6 +5264,7 @@ Released 2018-09-13
 [`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex
 [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref
 [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
+[`tuple_array_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions
 [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
 [`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
 [`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction
@@ -5238,6 +5287,7 @@ Released 2018-09-13
 [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
 [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join
 [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations
+[`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap
 [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed
 [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation
 [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings
@@ -5311,3 +5361,65 @@ Released 2018-09-13
 [`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
 [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
 <!-- end autogenerated links to lint list -->
+<!-- begin autogenerated links to configuration documentation -->
+[`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed
+[`arithmetic-side-effects-allowed-binary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-binary
+[`arithmetic-side-effects-allowed-unary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-unary
+[`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api
+[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv
+[`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold
+[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold
+[`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names
+[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline
+[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline
+[`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents
+[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold
+[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold
+[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold
+[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack
+[`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold
+[`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold
+[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold
+[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
+[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit
+[`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit
+[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold
+[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold
+[`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold
+[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold
+[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds
+[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools
+[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools
+[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports
+[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros
+[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods
+[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types
+[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions
+[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive
+[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
+[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish
+[`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces
+[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames
+[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts
+[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send
+[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length
+[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types
+[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size
+[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests
+[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests
+[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests
+[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests
+[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
+[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
+[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args
+[`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const
+[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items
+[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
+[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size
+[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception
+[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
+[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
+[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement
+[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes
+[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
+<!-- end autogenerated links to configuration documentation -->
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index ca8bf9fac91..76c804f935e 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -27,27 +27,14 @@ tempfile = { version = "3.2", optional = true }
 termize = "0.1"
 
 [dev-dependencies]
-compiletest_rs = { version = "0.10", features = ["tmp"] }
+ui_test = "0.11.5"
 tester = "0.9"
 regex = "1.5"
 toml = "0.7.3"
 walkdir = "2.3"
 # This is used by the `collect-metadata` alias.
 filetime = "0.2"
-
-# UI test dependencies
-clap = { version = "4.1.4", features = ["derive"] }
-clippy_utils = { path = "clippy_utils" }
-derive-new = "0.5"
-if_chain = "1.0"
 itertools = "0.10.1"
-quote = "1.0"
-serde = { version = "1.0.125", features = ["derive"] }
-syn = { version = "2.0", features = ["full"] }
-futures = "0.3"
-parking_lot = "0.12"
-tokio = { version = "1", features = ["io-util"] }
-rustc-semver = "1.1"
 
 [build-dependencies]
 rustc_tools_util = "0.3.0"
@@ -60,3 +47,7 @@ internal = ["clippy_lints/internal", "tempfile"]
 [package.metadata.rust-analyzer]
 # This package uses #[feature(rustc_private)]
 rustc_private = true
+
+[[test]]
+name = "compile-test"
+harness = false
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index c26aa883eba..a0db8089250 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -122,20 +122,17 @@ fn main() {
 }
 ```
 
-Now we can run the test with `TESTNAME=foo_functions cargo uitest`, currently
+Now we can run the test with `TESTNAME=foo_functions cargo uibless`, currently
 this test is meaningless though.
 
 While we are working on implementing our lint, we can keep running the UI test.
-That allows us to check if the output is turning into what we want.
+That allows us to check if the output is turning into what we want by checking the
+`.stderr` file that gets updated on every test run.
 
-Once we are satisfied with the output, we need to run `cargo dev bless` to
-update the `.stderr` file for our lint. Please note that, we should run
-`TESTNAME=foo_functions cargo uitest` every time before running `cargo dev
-bless`. Running `TESTNAME=foo_functions cargo uitest` should pass then. When we
+Running `TESTNAME=foo_functions cargo uitest` should pass on its own. When we
 commit our lint, we need to commit the generated `.stderr` files, too. In
-general, you should only commit files changed by `cargo dev bless` for the
-specific lint you are creating/editing. Note that if the generated files are
-empty, they should be removed.
+general, you should only commit files changed by `cargo bless` for the
+specific lint you are creating/editing.
 
 > _Note:_ you can run multiple test files by specifying a comma separated list:
 > `TESTNAME=foo_functions,test2,test3`.
@@ -169,7 +166,7 @@ additionally run [rustfix] for that test. Rustfix will apply the suggestions
 from the lint to the code of the test file and compare that to the contents of a
 `.fixed` file.
 
-Use `cargo dev bless` to automatically generate the `.fixed` file after running
+Use `cargo bless` to automatically generate the `.fixed` file while running
 the tests.
 
 [rustfix]: https://github.com/rust-lang/rustfix
@@ -417,7 +414,7 @@ fn is_foo_fn(fn_kind: FnKind<'_>) -> bool {
 
 Now we should also run the full test suite with `cargo test`. At this point
 running `cargo test` should produce the expected output. Remember to run `cargo
-dev bless` to update the `.stderr` file.
+bless` to update the `.stderr` file.
 
 `cargo test` (as opposed to `cargo uitest`) will also ensure that our lint
 implementation is not violating any Clippy lints itself.
diff --git a/src/tools/clippy/book/src/development/basics.md b/src/tools/clippy/book/src/development/basics.md
index 7615dc12f9e..f4c109ff119 100644
--- a/src/tools/clippy/book/src/development/basics.md
+++ b/src/tools/clippy/book/src/development/basics.md
@@ -66,7 +66,7 @@ If the output of a [UI test] differs from the expected output, you can update
 the reference file with:
 
 ```bash
-cargo dev bless
+cargo bless
 ```
 
 For example, this is necessary if you fix a typo in an error message of a lint,
diff --git a/src/tools/clippy/book/src/development/infrastructure/changelog_update.md b/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
index df9b1bbe18f..52445494436 100644
--- a/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
+++ b/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
@@ -56,6 +56,28 @@ and open that file in your editor of choice.
 When updating the changelog it's also a good idea to make sure that `commit1` is
 already correct in the current changelog.
 
+#### PR ranges
+
+We developed the concept of PR ranges to help the user understand the size of a new update. To create a PR range,
+get the current release date and the date that the last version was released (YYYY-MM-DD) and use the following link:
+
+```
+[**View <NUMBER OF PRs> PRs merged since 1.<LAST VERSION NUM>**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A<LAST VERSION DATE>..<CURRENT VERSION DATE>+base%3Amaster+sort%3Amerged-desc+)
+```
+
+> Note: Be sure to check click the link and check how many PRs got merged between
+
+Example:
+
+```
+[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+)
+```
+
+Which renders to:
+[**View 85 PRs merged since 1.69**](https://github.com/rust-lang/rust-clippy/pulls?q=is%3Apr+is%3Aclosed+merged%3A2023-04-20..2023-06-01+base%3Amaster+sort%3Amerged-desc+)
+
+Note that **commit ranges should not be included**, only PR ranges.
+
 ### 3. Authoring the final changelog
 
 The above script should have dumped all the relevant PRs to the file you
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 5646c9b1520..60d7ce6e615 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -3,63 +3,14 @@ This file is generated by `cargo collect-metadata`.
 Please use that command to update the file and do not edit it by hand.
 -->
 
-## Lint Configuration Options
-| <div style="width:290px">Option</div> | Default Value |
-|--|--|
-| [arithmetic-side-effects-allowed](#arithmetic-side-effects-allowed) | `{}` |
-| [arithmetic-side-effects-allowed-binary](#arithmetic-side-effects-allowed-binary) | `[]` |
-| [arithmetic-side-effects-allowed-unary](#arithmetic-side-effects-allowed-unary) | `{}` |
-| [avoid-breaking-exported-api](#avoid-breaking-exported-api) | `true` |
-| [msrv](#msrv) | `None` |
-| [cognitive-complexity-threshold](#cognitive-complexity-threshold) | `25` |
-| [disallowed-names](#disallowed-names) | `["foo", "baz", "quux"]` |
-| [semicolon-inside-block-ignore-singleline](#semicolon-inside-block-ignore-singleline) | `false` |
-| [semicolon-outside-block-ignore-multiline](#semicolon-outside-block-ignore-multiline) | `false` |
-| [doc-valid-idents](#doc-valid-idents) | `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` |
-| [too-many-arguments-threshold](#too-many-arguments-threshold) | `7` |
-| [type-complexity-threshold](#type-complexity-threshold) | `250` |
-| [single-char-binding-names-threshold](#single-char-binding-names-threshold) | `4` |
-| [too-large-for-stack](#too-large-for-stack) | `200` |
-| [enum-variant-name-threshold](#enum-variant-name-threshold) | `3` |
-| [enum-variant-size-threshold](#enum-variant-size-threshold) | `200` |
-| [verbose-bit-mask-threshold](#verbose-bit-mask-threshold) | `1` |
-| [literal-representation-threshold](#literal-representation-threshold) | `16384` |
-| [trivial-copy-size-limit](#trivial-copy-size-limit) | `None` |
-| [pass-by-value-size-limit](#pass-by-value-size-limit) | `256` |
-| [too-many-lines-threshold](#too-many-lines-threshold) | `100` |
-| [array-size-threshold](#array-size-threshold) | `512000` |
-| [vec-box-size-threshold](#vec-box-size-threshold) | `4096` |
-| [max-trait-bounds](#max-trait-bounds) | `3` |
-| [max-struct-bools](#max-struct-bools) | `3` |
-| [max-fn-params-bools](#max-fn-params-bools) | `3` |
-| [warn-on-all-wildcard-imports](#warn-on-all-wildcard-imports) | `false` |
-| [disallowed-macros](#disallowed-macros) | `[]` |
-| [disallowed-methods](#disallowed-methods) | `[]` |
-| [disallowed-types](#disallowed-types) | `[]` |
-| [unreadable-literal-lint-fractions](#unreadable-literal-lint-fractions) | `true` |
-| [upper-case-acronyms-aggressive](#upper-case-acronyms-aggressive) | `false` |
-| [matches-for-let-else](#matches-for-let-else) | `WellKnownTypes` |
-| [cargo-ignore-publish](#cargo-ignore-publish) | `false` |
-| [standard-macro-braces](#standard-macro-braces) | `[]` |
-| [enforced-import-renames](#enforced-import-renames) | `[]` |
-| [allowed-scripts](#allowed-scripts) | `["Latin"]` |
-| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` |
-| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` |
-| [await-holding-invalid-types](#await-holding-invalid-types) | `[]` |
-| [max-include-file-size](#max-include-file-size) | `1000000` |
-| [allow-expect-in-tests](#allow-expect-in-tests) | `false` |
-| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` |
-| [allow-dbg-in-tests](#allow-dbg-in-tests) | `false` |
-| [allow-print-in-tests](#allow-print-in-tests) | `false` |
-| [large-error-threshold](#large-error-threshold) | `128` |
-| [ignore-interior-mutability](#ignore-interior-mutability) | `["bytes::Bytes"]` |
-| [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` |
-| [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` |
-| [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` |
-| [future-size-threshold](#future-size-threshold) | `16384` |
-| [unnecessary-box-size](#unnecessary-box-size) | `128` |
-
-### arithmetic-side-effects-allowed
+# Lint Configuration Options
+
+The following list shows each configuration option, along with a description, its default value, an example
+and lints affected.
+
+---
+
+## `arithmetic-side-effects-allowed`
 Suppress checking of the passed type names in all types of operations.
 
 If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
@@ -77,10 +28,12 @@ A type, say `SomeType`, listed in this configuration has the same behavior of
 
 **Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
 
-* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
+---
+**Affected lints:**
+* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
 
 
-### arithmetic-side-effects-allowed-binary
+## `arithmetic-side-effects-allowed-binary`
 Suppress checking of the passed type pair names in binary operations like addition or
 multiplication.
 
@@ -98,10 +51,12 @@ arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType",
 
 **Default Value:** `[]` (`Vec<[String; 2]>`)
 
-* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
+---
+**Affected lints:**
+* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
 
 
-### arithmetic-side-effects-allowed-unary
+## `arithmetic-side-effects-allowed-unary`
 Suppress checking of the passed type names in unary operations like "negation" (`-`).
 
 #### Example
@@ -112,116 +67,145 @@ arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
 
 **Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
 
-* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
+---
+**Affected lints:**
+* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
 
 
-### avoid-breaking-exported-api
+## `avoid-breaking-exported-api`
 Suppress lints whenever the suggested change would cause breakage for other crates.
 
 **Default Value:** `true` (`bool`)
 
-* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
-* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
-* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
-* [unnecessary_wraps](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps)
-* [unused_self](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self)
-* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
-* [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention)
-* [box_collection](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection)
-* [redundant_allocation](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation)
-* [rc_buffer](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer)
-* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
-* [option_option](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
-* [linkedlist](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
-* [rc_mutex](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
-* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
-
-
-### msrv
+---
+**Affected lints:**
+* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
+* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
+* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
+* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps)
+* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self)
+* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
+* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention)
+* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection)
+* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation)
+* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer)
+* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
+* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
+* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
+* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
+* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
+* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn)
+
+
+## `msrv`
 The minimum rust version that the project supports
 
 **Default Value:** `None` (`Option<String>`)
 
-* [manual_split_once](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once)
-* [manual_str_repeat](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat)
-* [cloned_instead_of_copied](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
-* [redundant_field_names](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
-* [redundant_static_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
-* [filter_map_next](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next)
-* [checked_conversions](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
-* [manual_range_contains](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
-* [use_self](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
-* [mem_replace_with_default](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default)
-* [manual_non_exhaustive](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
-* [option_as_ref_deref](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
-* [map_unwrap_or](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or)
-* [match_like_matches_macro](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro)
-* [manual_strip](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
-* [missing_const_for_fn](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn)
-* [unnested_or_patterns](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
-* [from_over_into](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
-* [ptr_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
-* [if_then_some_else_none](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
-* [approx_constant](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
-* [deprecated_cfg_attr](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
-* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
-* [map_clone](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone)
-* [borrow_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
-* [manual_bits](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
-* [err_expect](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect)
-* [cast_abs_to_unsigned](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
-* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
-* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
-* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
-* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
-* [collapsible_str_replace](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
-* [seek_from_current](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
-* [seek_rewind](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
-* [unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
-* [transmute_ptr_to_ref](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
-* [almost_complete_range](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
-* [needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)
-* [derivable_impls](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
-* [manual_is_ascii_check](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
-* [manual_rem_euclid](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
-* [manual_retain](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
-
-
-### cognitive-complexity-threshold
+---
+**Affected lints:**
+* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once)
+* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat)
+* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
+* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
+* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or)
+* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
+* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next)
+* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
+* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
+* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
+* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default)
+* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
+* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
+* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or)
+* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro)
+* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
+* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn)
+* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
+* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
+* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
+* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
+* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
+* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
+* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
+* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone)
+* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
+* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
+* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect)
+* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
+* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
+* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
+* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
+* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
+* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
+* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
+* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
+* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
+* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
+* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
+* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)
+* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
+* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
+* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
+* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
+* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
+* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions)
+* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold)
+
+
+## `cognitive-complexity-threshold`
 The maximum cognitive complexity a function can have
 
 **Default Value:** `25` (`u64`)
 
-* [cognitive_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity)
+---
+**Affected lints:**
+* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity)
+
+
+## `excessive-nesting-threshold`
+The maximum amount of nesting a block can reside in
 
+**Default Value:** `0` (`u64`)
 
-### disallowed-names
+---
+**Affected lints:**
+* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting)
+
+
+## `disallowed-names`
 The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
 `".."` 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:** `["foo", "baz", "quux"]` (`Vec<String>`)
 
-* [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
+---
+**Affected lints:**
+* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
 
 
-### semicolon-inside-block-ignore-singleline
+## `semicolon-inside-block-ignore-singleline`
 Whether to lint only if it's multiline.
 
 **Default Value:** `false` (`bool`)
 
-* [semicolon_inside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block)
+---
+**Affected lints:**
+* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block)
 
 
-### semicolon-outside-block-ignore-multiline
+## `semicolon-outside-block-ignore-multiline`
 Whether to lint only if it's singleline.
 
 **Default Value:** `false` (`bool`)
 
-* [semicolon_outside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block)
+---
+**Affected lints:**
+* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block)
 
 
-### doc-valid-idents
+## `doc-valid-idents`
 The list of words this lint should not consider as identifiers needing ticks. The value
 `".."` 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. For example:
@@ -230,207 +214,267 @@ default configuration of Clippy. By default, any configuration will replace the
 
 Default list:
 
-**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec<String>`)
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec<String>`)
 
-* [doc_markdown](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown)
+---
+**Affected lints:**
+* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown)
 
 
-### too-many-arguments-threshold
+## `too-many-arguments-threshold`
 The maximum number of argument a function or method can have
 
 **Default Value:** `7` (`u64`)
 
-* [too_many_arguments](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments)
+---
+**Affected lints:**
+* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments)
 
 
-### type-complexity-threshold
+## `type-complexity-threshold`
 The maximum complexity a type can have
 
 **Default Value:** `250` (`u64`)
 
-* [type_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity)
+---
+**Affected lints:**
+* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity)
 
 
-### single-char-binding-names-threshold
+## `single-char-binding-names-threshold`
 The maximum number of single char bindings a scope may have
 
 **Default Value:** `4` (`u64`)
 
-* [many_single_char_names](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
+---
+**Affected lints:**
+* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
 
 
-### too-large-for-stack
+## `too-large-for-stack`
 The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
 
 **Default Value:** `200` (`u64`)
 
-* [boxed_local](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local)
-* [useless_vec](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
+---
+**Affected lints:**
+* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local)
+* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
 
 
-### enum-variant-name-threshold
+## `enum-variant-name-threshold`
 The minimum number of enum variants for the lints about variant names to trigger
 
 **Default Value:** `3` (`u64`)
 
-* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
+---
+**Affected lints:**
+* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
 
 
-### enum-variant-size-threshold
+## `enum-variant-size-threshold`
 The maximum size of an enum's variant to avoid box suggestion
 
 **Default Value:** `200` (`u64`)
 
-* [large_enum_variant](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
+---
+**Affected lints:**
+* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
 
 
-### verbose-bit-mask-threshold
+## `verbose-bit-mask-threshold`
 The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
 
 **Default Value:** `1` (`u64`)
 
-* [verbose_bit_mask](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask)
+---
+**Affected lints:**
+* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask)
 
 
-### literal-representation-threshold
+## `literal-representation-threshold`
 The lower bound for linting decimal literals
 
 **Default Value:** `16384` (`u64`)
 
-* [decimal_literal_representation](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation)
+---
+**Affected lints:**
+* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation)
 
 
-### trivial-copy-size-limit
+## `trivial-copy-size-limit`
 The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
 
 **Default Value:** `None` (`Option<u64>`)
 
-* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
+---
+**Affected lints:**
+* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
 
 
-### pass-by-value-size-limit
+## `pass-by-value-size-limit`
 The minimum size (in bytes) to consider a type for passing by reference instead of by value.
 
 **Default Value:** `256` (`u64`)
 
-* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
+---
+**Affected lints:**
+* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
 
 
-### too-many-lines-threshold
+## `too-many-lines-threshold`
 The maximum number of lines a function or method can have
 
 **Default Value:** `100` (`u64`)
 
-* [too_many_lines](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
+---
+**Affected lints:**
+* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
 
 
-### array-size-threshold
+## `array-size-threshold`
 The maximum allowed size for arrays on the stack
 
 **Default Value:** `512000` (`u64`)
 
-* [large_stack_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
-* [large_const_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
+---
+**Affected lints:**
+* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
+* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
+
+
+## `stack-size-threshold`
+The maximum allowed stack size for functions in bytes
+
+**Default Value:** `512000` (`u64`)
+
+---
+**Affected lints:**
+* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames)
 
 
-### vec-box-size-threshold
+## `vec-box-size-threshold`
 The size of the boxed type in bytes, where boxing in a `Vec` is allowed
 
 **Default Value:** `4096` (`u64`)
 
-* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
+---
+**Affected lints:**
+* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
 
 
-### max-trait-bounds
+## `max-trait-bounds`
 The maximum number of bounds a trait can have to be linted
 
 **Default Value:** `3` (`u64`)
 
-* [type_repetition_in_bounds](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
+---
+**Affected lints:**
+* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
 
 
-### max-struct-bools
+## `max-struct-bools`
 The maximum number of bool fields a struct can have
 
 **Default Value:** `3` (`u64`)
 
-* [struct_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools)
+---
+**Affected lints:**
+* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools)
 
 
-### max-fn-params-bools
+## `max-fn-params-bools`
 The maximum number of bool parameters a function can have
 
 **Default Value:** `3` (`u64`)
 
-* [fn_params_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools)
+---
+**Affected lints:**
+* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools)
 
 
-### warn-on-all-wildcard-imports
+## `warn-on-all-wildcard-imports`
 Whether to allow certain wildcard imports (prelude, super in tests).
 
 **Default Value:** `false` (`bool`)
 
-* [wildcard_imports](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
+---
+**Affected lints:**
+* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
 
 
-### disallowed-macros
+## `disallowed-macros`
 The list of disallowed macros, written as fully qualified paths.
 
 **Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
 
-* [disallowed_macros](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros)
+---
+**Affected lints:**
+* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros)
 
 
-### disallowed-methods
+## `disallowed-methods`
 The list of disallowed methods, written as fully qualified paths.
 
 **Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
 
-* [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods)
+---
+**Affected lints:**
+* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods)
 
 
-### disallowed-types
+## `disallowed-types`
 The list of disallowed types, written as fully qualified paths.
 
 **Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
 
-* [disallowed_types](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types)
+---
+**Affected lints:**
+* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types)
 
 
-### unreadable-literal-lint-fractions
+## `unreadable-literal-lint-fractions`
 Should the fraction of a decimal be linted to include separators.
 
 **Default Value:** `true` (`bool`)
 
-* [unreadable_literal](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal)
+---
+**Affected lints:**
+* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal)
 
 
-### upper-case-acronyms-aggressive
+## `upper-case-acronyms-aggressive`
 Enables verbose mode. Triggers if there is more than one uppercase char next to each other
 
 **Default Value:** `false` (`bool`)
 
-* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
+---
+**Affected lints:**
+* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
 
 
-### matches-for-let-else
+## `matches-for-let-else`
 Whether the matches should be considered by the lint, and whether there should
 be filtering for common types.
 
 **Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`)
 
-* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
+---
+**Affected lints:**
+* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
 
 
-### cargo-ignore-publish
+## `cargo-ignore-publish`
 For internal testing only, ignores the current `publish` settings in the Cargo manifest.
 
 **Default Value:** `false` (`bool`)
 
-* [_cargo_common_metadata](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata)
+---
+**Affected lints:**
+* [`_cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata)
 
 
-### standard-macro-braces
+## `standard-macro-braces`
 Enforce the named macros always use the braces specified.
 
 A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
@@ -439,119 +483,147 @@ could be used with a full path two `MacroMatcher`s have to be added one with the
 
 **Default Value:** `[]` (`Vec<crate::nonstandard_macro_braces::MacroMatcher>`)
 
-* [nonstandard_macro_braces](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
+---
+**Affected lints:**
+* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
 
 
-### enforced-import-renames
+## `enforced-import-renames`
 The list of imports to always rename, a fully qualified path followed by the rename.
 
 **Default Value:** `[]` (`Vec<crate::utils::conf::Rename>`)
 
-* [missing_enforced_import_renames](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames)
+---
+**Affected lints:**
+* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames)
 
 
-### allowed-scripts
+## `allowed-scripts`
 The list of unicode scripts allowed to be used in the scope.
 
 **Default Value:** `["Latin"]` (`Vec<String>`)
 
-* [disallowed_script_idents](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents)
+---
+**Affected lints:**
+* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents)
 
 
-### enable-raw-pointer-heuristic-for-send
+## `enable-raw-pointer-heuristic-for-send`
 Whether to apply the raw pointer heuristic to determine if a type is `Send`.
 
 **Default Value:** `true` (`bool`)
 
-* [non_send_fields_in_send_ty](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty)
+---
+**Affected lints:**
+* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty)
 
 
-### max-suggested-slice-pattern-length
+## `max-suggested-slice-pattern-length`
 When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
 the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
 For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
 
 **Default Value:** `3` (`u64`)
 
-* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
+---
+**Affected lints:**
+* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
 
 
-### await-holding-invalid-types
+## `await-holding-invalid-types`
 
 
 **Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
 
-* [await_holding_invalid_type](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type)
+---
+**Affected lints:**
+* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type)
 
 
-### max-include-file-size
+## `max-include-file-size`
 The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
 
 **Default Value:** `1000000` (`u64`)
 
-* [large_include_file](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file)
+---
+**Affected lints:**
+* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file)
 
 
-### allow-expect-in-tests
+## `allow-expect-in-tests`
 Whether `expect` should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
-* [expect_used](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
+---
+**Affected lints:**
+* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
 
 
-### allow-unwrap-in-tests
+## `allow-unwrap-in-tests`
 Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
-* [unwrap_used](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
+---
+**Affected lints:**
+* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
 
 
-### allow-dbg-in-tests
+## `allow-dbg-in-tests`
 Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
-* [dbg_macro](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro)
+---
+**Affected lints:**
+* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro)
 
 
-### allow-print-in-tests
+## `allow-print-in-tests`
 Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
-* [print_stdout](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout)
-* [print_stderr](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr)
+---
+**Affected lints:**
+* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout)
+* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr)
 
 
-### large-error-threshold
+## `large-error-threshold`
 The maximum size of the `Err`-variant in a `Result` returned from a function
 
 **Default Value:** `128` (`u64`)
 
-* [result_large_err](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
+---
+**Affected lints:**
+* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
 
 
-### ignore-interior-mutability
+## `ignore-interior-mutability`
 A list of paths to types that should be treated like `Arc`, i.e. ignored but
 for the generic parameters for determining interior mutability
 
 **Default Value:** `["bytes::Bytes"]` (`Vec<String>`)
 
-* [mutable_key_type](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)
-* [ifs_same_cond](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond)
+---
+**Affected lints:**
+* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)
+* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond)
 
 
-### allow-mixed-uninlined-format-args
+## `allow-mixed-uninlined-format-args`
 Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
 
 **Default Value:** `true` (`bool`)
 
-* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
+---
+**Affected lints:**
+* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
 
 
-### suppress-restriction-lint-in-const
+## `suppress-restriction-lint-in-const`
 Whether to suppress a restriction lint in constant code. In same
 cases the restructured operation might not be unavoidable, as the
 suggested counterparts are unavailable in constant code. This
@@ -560,32 +632,101 @@ if no suggestion can be made.
 
 **Default Value:** `false` (`bool`)
 
-* [indexing_slicing](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
+---
+**Affected lints:**
+* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
 
 
-### missing-docs-in-crate-items
+## `missing-docs-in-crate-items`
 Whether to **only** check for missing documentation in items visible within the current
 crate. For example, `pub(crate)` items.
 
 **Default Value:** `false` (`bool`)
 
-* [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
+---
+**Affected lints:**
+* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
 
 
-### future-size-threshold
+## `future-size-threshold`
 The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
 
 **Default Value:** `16384` (`u64`)
 
-* [large_futures](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures)
+---
+**Affected lints:**
+* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures)
 
 
-### unnecessary-box-size
+## `unnecessary-box-size`
 The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
 
 **Default Value:** `128` (`u64`)
 
-* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
+---
+**Affected lints:**
+* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
+
+
+## `allow-private-module-inception`
+Whether to allow module inception if it's not public.
+
+**Default Value:** `false` (`bool`)
+
+---
+**Affected lints:**
+* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception)
+
+
+## `allowed-idents-below-min-chars`
+Allowed names below the minimum allowed characters. The value `".."` 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:** `{"j", "z", "i", "y", "n", "x", "w"}` (`rustc_data_structures::fx::FxHashSet<String>`)
+
+---
+**Affected lints:**
+* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
+
+
+## `min-ident-chars-threshold`
+Minimum chars an ident can have, anything below or equal to this will be linted.
+
+**Default Value:** `1` (`u64`)
+
+---
+**Affected lints:**
+* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
+
+
+## `accept-comment-above-statement`
+Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
+
+**Default Value:** `false` (`bool`)
+
+---
+**Affected lints:**
+* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
+
+
+## `accept-comment-above-attributes`
+Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
+
+**Default Value:** `false` (`bool`)
+
+---
+**Affected lints:**
+* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
+
+
+## `allow-one-hash-in-raw-strings`
+Whether to allow `r#""#` when `r""` can be used
+
+**Default Value:** `false` (`bool`)
 
+---
+**Affected lints:**
+* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes)
 
 
diff --git a/src/tools/clippy/clippy_dev/src/bless.rs b/src/tools/clippy/clippy_dev/src/bless.rs
deleted file mode 100644
index 92b2771f3fe..00000000000
--- a/src/tools/clippy/clippy_dev/src/bless.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//! `bless` updates the reference files in the repo with changed output files
-//! from the last test run.
-
-use crate::cargo_clippy_path;
-use std::ffi::OsStr;
-use std::fs;
-use std::path::{Path, PathBuf};
-use std::sync::LazyLock;
-use walkdir::{DirEntry, WalkDir};
-
-static CLIPPY_BUILD_TIME: LazyLock<Option<std::time::SystemTime>> =
-    LazyLock::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
-
-/// # Panics
-///
-/// Panics if the path to a test file is broken
-pub fn bless(ignore_timestamp: bool) {
-    let extensions = ["stdout", "stderr", "fixed"].map(OsStr::new);
-
-    WalkDir::new(build_dir())
-        .into_iter()
-        .map(Result::unwrap)
-        .filter(|entry| entry.path().extension().map_or(false, |ext| extensions.contains(&ext)))
-        .for_each(|entry| update_reference_file(&entry, ignore_timestamp));
-}
-
-fn update_reference_file(test_output_entry: &DirEntry, ignore_timestamp: bool) {
-    let test_output_path = test_output_entry.path();
-
-    let reference_file_name = test_output_entry.file_name().to_str().unwrap().replace(".stage-id", "");
-    let reference_file_path = Path::new("tests")
-        .join(test_output_path.strip_prefix(build_dir()).unwrap())
-        .with_file_name(reference_file_name);
-
-    // If the test output was not updated since the last clippy build, it may be outdated
-    if !ignore_timestamp && !updated_since_clippy_build(test_output_entry).unwrap_or(true) {
-        return;
-    }
-
-    let test_output_file = fs::read(test_output_path).expect("Unable to read test output file");
-    let reference_file = fs::read(&reference_file_path).unwrap_or_default();
-
-    if test_output_file != reference_file {
-        // If a test run caused an output file to change, update the reference file
-        println!("updating {}", reference_file_path.display());
-        fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file");
-    }
-}
-
-fn updated_since_clippy_build(entry: &DirEntry) -> Option<bool> {
-    let clippy_build_time = (*CLIPPY_BUILD_TIME)?;
-    let modified = entry.metadata().ok()?.modified().ok()?;
-    Some(modified >= clippy_build_time)
-}
-
-fn build_dir() -> PathBuf {
-    let mut path = std::env::current_exe().unwrap();
-    path.set_file_name("test");
-    path
-}
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 25623144181..ee559d45dd1 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -35,6 +35,7 @@ struct FmtContext {
 }
 
 // the "main" function of cargo dev fmt
+#[allow(clippy::missing_panics_doc)]
 pub fn run(check: bool, verbose: bool) {
     fn try_run(context: &FmtContext) -> Result<bool, CliError> {
         let mut success = true;
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 56a269288c0..4624451cff4 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -14,7 +14,6 @@ use std::io;
 use std::path::PathBuf;
 use std::process::{self, ExitStatus};
 
-pub mod bless;
 pub mod dogfood;
 pub mod fmt;
 pub mod lint;
@@ -29,6 +28,10 @@ static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
 static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
 
 /// Returns the path to the `cargo-clippy` binary
+///
+/// # Panics
+///
+/// Panics if the path of current executable could not be retrieved.
 #[must_use]
 pub fn cargo_clippy_path() -> PathBuf {
     let mut path = std::env::current_exe().expect("failed to get current executable name");
@@ -61,6 +64,8 @@ pub fn clippy_project_root() -> PathBuf {
     panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
 }
 
+/// # Panics
+/// Panics if given command result was failed.
 pub fn exit_if_err(status: io::Result<ExitStatus>) {
     match status.expect("failed to run command").code() {
         Some(0) => {},
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index c03fbe9d275..43eaccdf5a3 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -3,7 +3,7 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
 use clap::{Arg, ArgAction, ArgMatches, Command};
-use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints};
+use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints};
 use indoc::indoc;
 use std::convert::Infallible;
 
@@ -11,8 +11,8 @@ fn main() {
     let matches = get_clap_config();
 
     match matches.subcommand() {
-        Some(("bless", matches)) => {
-            bless::bless(matches.get_flag("ignore-timestamp"));
+        Some(("bless", _)) => {
+            eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run");
         },
         Some(("dogfood", matches)) => {
             dogfood::dogfood(
@@ -35,7 +35,7 @@ fn main() {
         },
         Some(("new_lint", matches)) => {
             match new_lint::create(
-                matches.get_one::<String>("pass"),
+                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),
@@ -176,7 +176,7 @@ fn get_clap_config() -> ArgMatches {
                         .help("Specify whether the lint runs during the early or late pass")
                         .value_parser(["early", "late"])
                         .conflicts_with("type")
-                        .required_unless_present("type"),
+                        .default_value("late"),
                     Arg::new("name")
                         .short('n')
                         .long("name")
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 13a27703427..f11aa547bd7 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -36,8 +36,9 @@ impl<T> Context for io::Result<T> {
 /// # Errors
 ///
 /// This function errors out if the files couldn't be created or written to.
+#[allow(clippy::missing_panics_doc)]
 pub fn create(
-    pass: Option<&String>,
+    pass: &String,
     lint_name: Option<&String>,
     category: Option<&str>,
     mut ty: Option<&str>,
@@ -49,7 +50,7 @@ pub fn create(
     }
 
     let lint = LintData {
-        pass: pass.map_or("", String::as_str),
+        pass,
         name: lint_name.expect("`name` argument is validated by clap"),
         category: category.expect("`category` argument is validated by clap"),
         ty,
@@ -63,6 +64,14 @@ pub fn create(
         add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?;
     }
 
+    if pass == "early" {
+        println!(
+            "\n\
+            NOTE: Use a late pass unless you need something specific from\
+            an early pass, as they lack many features and utilities"
+        );
+    }
+
     Ok(())
 }
 
@@ -87,7 +96,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
 
         path.push("src");
         fs::create_dir(&path)?;
-        let header = format!("// compile-flags: --crate-name={lint_name}");
+        let header = format!("//@compile-flags: --crate-name={lint_name}");
         write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?;
 
         Ok(())
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index be9261a4704..c23054443bb 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
 tempfile = { version = "3.3.0", optional = true }
 toml = "0.7.3"
+regex = { version = "1.5", optional = true }
 unicode-normalization = "0.1"
 unicode-script = { version = "0.5", default-features = false }
 semver = "1.0"
@@ -31,7 +32,7 @@ url = "2.2"
 [features]
 deny-warnings = ["clippy_utils/deny-warnings"]
 # build clippy with internal lints enabled, off by default
-internal = ["clippy_utils/internal", "serde_json", "tempfile"]
+internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"]
 
 [package.metadata.rust-analyzer]
 # This crate uses #[feature(rustc_private)]
diff --git a/src/tools/clippy/clippy_lints/src/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/allow_attributes.rs
index 554efdc58e1..eb21184713e 100644
--- a/src/tools/clippy/clippy_lints/src/allow_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/allow_attributes.rs
@@ -1,5 +1,5 @@
-use ast::AttrStyle;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use ast::{AttrStyle, Attribute};
+use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro};
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -50,13 +50,14 @@ declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]);
 
 impl LateLintPass<'_> for AllowAttribute {
     // Separate each crate's features.
-    fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
+    fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) {
         if_chain! {
             if !in_external_macro(cx.sess(), attr.span);
             if cx.tcx.features().lint_reasons;
             if let AttrStyle::Outer = attr.style;
             if let Some(ident) = attr.ident();
             if ident.name == rustc_span::symbol::sym::allow;
+            if !is_from_proc_macro(cx, &attr);
             then {
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
new file mode 100644
index 00000000000..a1e44668e1a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
@@ -0,0 +1,72 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::last_path_segment;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use if_chain::if_chain;
+
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_lint::LateLintPass;
+use rustc_middle::ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::sym;
+
+declare_clippy_lint! {
+    /// ### What it does.
+    /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`.
+    ///
+    /// ### Why is this bad?
+    /// Wrapping a type in Arc doesn't add thread safety to the underlying data, so data races
+    /// could occur when touching the underlying data.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::cell::RefCell;
+    /// # use std::sync::Arc;
+    ///
+    /// fn main() {
+    ///     // This is safe, as `i32` implements `Send` and `Sync`.
+    ///     let a = Arc::new(42);
+    ///
+    ///     // This is not safe, as `RefCell` does not implement `Sync`.
+    ///     let b = Arc::new(RefCell::new(42));
+    /// }
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub ARC_WITH_NON_SEND_SYNC,
+    correctness,
+    "using `Arc` with a type that does not implement `Send` or `Sync`"
+}
+declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]);
+
+impl LateLintPass<'_> for ArcWithNonSendSync {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let ty = cx.typeck_results().expr_ty(expr);
+        if_chain! {
+            if is_type_diagnostic_item(cx, ty, sym::Arc);
+            if let ExprKind::Call(func, [arg]) = expr.kind;
+            if let ExprKind::Path(func_path) = func.kind;
+            if last_path_segment(&func_path).ident.name == sym::new;
+            if let arg_ty = cx.typeck_results().expr_ty(arg);
+            if !matches!(arg_ty.kind(), ty::Param(_));
+            if !cx.tcx
+                .lang_items()
+                .sync_trait()
+                .map_or(false, |id| implements_trait(cx, arg_ty, id, &[])) ||
+                !cx.tcx
+                .get_diagnostic_item(sym::Send)
+                .map_or(false, |id| implements_trait(cx, arg_ty, id, &[]));
+
+            then {
+                span_lint_and_help(
+                    cx,
+                    ARC_WITH_NON_SEND_SYNC,
+                    expr.span,
+                    "usage of `Arc<T>` where `T` is not `Send` or `Sync`",
+                    None,
+                    "consider using `Rc<T>` instead or wrapping `T` in a std::sync type like \
+                    `Mutex<T>`",
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs
index c7a76e5f907..b9dda49ca41 100644
--- a/src/tools/clippy/clippy_lints/src/as_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use clippy_utils::is_from_proc_macro;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -45,9 +46,9 @@ declare_clippy_lint! {
 
 declare_lint_pass!(AsConversions => [AS_CONVERSIONS]);
 
-impl EarlyLintPass for AsConversions {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess(), expr.span) {
+impl<'tcx> LateLintPass<'tcx> for AsConversions {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if in_external_macro(cx.sess(), expr.span) || is_from_proc_macro(cx, expr) {
             return;
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 897495ba108..2ba78f99569 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -1,9 +1,12 @@
 //! checks for attributes
 
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::macros::{is_panic, macro_backtrace};
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
+use clippy_utils::{
+    diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then},
+    is_from_proc_macro,
+};
 use if_chain::if_chain;
 use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_errors::Applicability;
@@ -362,6 +365,32 @@ declare_clippy_lint! {
     "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[cfg(features = "...")]` and suggests to replace it with
+    /// `#[cfg(feature = "...")]`.
+    ///
+    /// ### Why is this bad?
+    /// Misspelling `feature` as `features` can be sometimes hard to spot. It
+    /// may cause conditional compilation not work quitely.
+    ///
+    /// ### Example
+    /// ```rust
+    /// #[cfg(features = "some-feature")]
+    /// fn conditional() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// #[cfg(feature = "some-feature")]
+    /// fn conditional() { }
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub MAYBE_MISUSED_CFG,
+    suspicious,
+    "prevent from misusing the wrong attr name"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -540,7 +569,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe
     }
 }
 
-fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) {
+fn check_lint_reason<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) {
     // Check for the feature
     if !cx.tcx.features().lint_reasons {
         return;
@@ -555,7 +584,7 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem
     }
 
     // Check if the attribute is in an external macro and therefore out of the developer's control
-    if in_external_macro(cx.sess(), attr.span) {
+    if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) {
         return;
     }
 
@@ -676,6 +705,7 @@ impl_lint_pass!(EarlyAttributes => [
     EMPTY_LINE_AFTER_OUTER_ATTR,
     EMPTY_LINE_AFTER_DOC_COMMENTS,
     NON_MINIMAL_CFG,
+    MAYBE_MISUSED_CFG,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
@@ -687,6 +717,7 @@ impl EarlyLintPass for EarlyAttributes {
         check_deprecated_cfg_attr(cx, attr, &self.msrv);
         check_mismatched_target_os(cx, attr);
         check_minimal_cfg_condition(cx, attr);
+        check_misused_cfg(cx, attr);
     }
 
     extract_msrv_attr!(EarlyContext);
@@ -777,7 +808,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
 }
 
 fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
-    for item in items.iter() {
+    for item in items {
         if let NestedMetaItem::MetaItem(meta) = item {
             if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
                 continue;
@@ -810,6 +841,27 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
     }
 }
 
+fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+    for item in items {
+        if let NestedMetaItem::MetaItem(meta) = item {
+            if meta.has_name(sym!(features)) && let Some(val) = meta.value_str() {
+                span_lint_and_sugg(
+                    cx,
+                    MAYBE_MISUSED_CFG,
+                    meta.span,
+                    "feature may misspelled as features",
+                    "use",
+                    format!("feature = \"{val}\""),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            if let MetaItemKind::List(list) = &meta.kind {
+                check_nested_misused_cfg(cx, list);
+            }
+        }
+    }
+}
+
 fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
     if attr.has_name(sym::cfg) &&
         let Some(items) = attr.meta_item_list()
@@ -818,6 +870,14 @@ fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
     }
 }
 
+fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg) &&
+        let Some(items) = attr.meta_item_list()
+    {
+        check_nested_misused_cfg(cx, &items);
+    }
+}
+
 fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
     fn find_os(name: &str) -> Option<&'static str> {
         UNIX_SYSTEMS
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index ff0102255a0..04cca9e3177 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -440,7 +440,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
                             diag.span_suggestions(
                                 e.span,
                                 "try",
-                                suggestions.into_iter(),
+                                suggestions,
                                 // nonminimal_bool can produce minimal but
                                 // not human readable expressions (#3141)
                                 Applicability::Unspecified,
diff --git a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
index 294d22d34de..b7256dd2eae 100644
--- a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -4,6 +4,7 @@ use clippy_utils::source::snippet_with_context;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::adjustment::Adjust;
 
 use super::BORROW_AS_PTR;
 
@@ -23,6 +24,15 @@ pub(super) fn check<'tcx>(
         };
         let mut app = Applicability::MachineApplicable;
         let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0;
+        // Fix #9884
+        if !e.is_place_expr(|base| {
+            cx.typeck_results()
+                .adjustments()
+                .get(base.hir_id)
+                .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
+        }) {
+            return;
+        }
 
         span_lint_and_sugg(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
index 28ecdea7ea0..ffa571abb39 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -1,41 +1,90 @@
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::is_isize_or_usize;
 use rustc_hir::Expr;
-use rustc_lint::LateContext;
+use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty::Ty;
 
 use super::{utils, CAST_POSSIBLE_WRAP};
 
+// this should be kept in sync with the allowed bit widths of `usize` and `isize`
+const ALLOWED_POINTER_SIZES: [u64; 3] = [16, 32, 64];
+
+// whether the lint should be emitted, and the required pointer size, if it matters
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum EmitState {
+    NoLint,
+    LintAlways,
+    LintOnPtrSize(u64),
+}
+
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     if !(cast_from.is_integral() && cast_to.is_integral()) {
         return;
     }
 
-    let arch_64_suffix = " on targets with 64-bit wide pointers";
-    let arch_32_suffix = " on targets with 32-bit wide pointers";
-    let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed();
+    // emit a lint if a cast is:
+    // 1. unsigned to signed
+    // and
+    // 2. either:
+    //
+    //    2a. between two types of constant size that are always the same size
+    //    2b. between one target-dependent size and one constant size integer,
+    //        and the constant integer is in the allowed set of target dependent sizes
+    //        (the ptr size could be chosen to be the same as the constant size)
+
+    if cast_from.is_signed() || !cast_to.is_signed() {
+        return;
+    }
+
     let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
     let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
 
-    let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
-        (true, true) | (false, false) => (to_nbits == from_nbits && cast_unsigned_to_signed, ""),
-        (true, false) => (to_nbits <= 32 && cast_unsigned_to_signed, arch_32_suffix),
-        (false, true) => (
-            cast_unsigned_to_signed,
-            if from_nbits == 64 {
-                arch_64_suffix
+    let should_lint = match (cast_from.is_ptr_sized_integral(), cast_to.is_ptr_sized_integral()) {
+        (true, true) => {
+            // casts between two ptr sized integers are trivially always the same size
+            // so do not depend on any specific pointer size to be the same
+            EmitState::LintAlways
+        },
+        (true, false) => {
+            // the first type is `usize` and the second is a constant sized signed integer
+            if ALLOWED_POINTER_SIZES.contains(&to_nbits) {
+                EmitState::LintOnPtrSize(to_nbits)
+            } else {
+                EmitState::NoLint
+            }
+        },
+        (false, true) => {
+            // the first type is a constant sized unsigned integer, and the second is `isize`
+            if ALLOWED_POINTER_SIZES.contains(&from_nbits) {
+                EmitState::LintOnPtrSize(from_nbits)
+            } else {
+                EmitState::NoLint
+            }
+        },
+        (false, false) => {
+            // the types are both a constant known size
+            // and do not depend on any specific pointer size to be the same
+            if from_nbits == to_nbits {
+                EmitState::LintAlways
             } else {
-                arch_32_suffix
-            },
+                EmitState::NoLint
+            }
+        },
+    };
+
+    let message = match should_lint {
+        EmitState::NoLint => return,
+        EmitState::LintAlways => format!("casting `{cast_from}` to `{cast_to}` may wrap around the value"),
+        EmitState::LintOnPtrSize(ptr_size) => format!(
+            "casting `{cast_from}` to `{cast_to}` may wrap around the value on targets with {ptr_size}-bit wide pointers",
         ),
     };
 
-    if should_lint {
-        span_lint(
-            cx,
-            CAST_POSSIBLE_WRAP,
-            expr.span,
-            &format!("casting `{cast_from}` to `{cast_to}` may wrap around the value{suffix}",),
-        );
-    }
+    cx.struct_span_lint(CAST_POSSIBLE_WRAP, expr.span, message, |diag| {
+        if let EmitState::LintOnPtrSize(16) = should_lint {
+            diag
+            .note("`usize` and `isize` may be as small as 16 bits on some platforms")
+            .note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types")
+        } else {
+            diag
+        }
+    });
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index b90dab07a27..0ac6ef6496a 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -118,9 +118,10 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for casts from an unsigned type to a signed type of
-    /// the same size. Performing such a cast is a 'no-op' for the compiler,
-    /// i.e., nothing is changed at the bit level, and the binary representation of
-    /// the value is reinterpreted. This can cause wrapping if the value is too big
+    /// the same size, or possibly smaller due to target dependent integers.
+    /// Performing such a cast is a 'no-op' for the compiler, i.e., nothing is
+    /// changed at the bit level, and the binary representation of the value is
+    /// reinterpreted. This can cause wrapping if the value is too big
     /// for the target signed type. However, the cast works as defined, so this lint
     /// is `Allow` by default.
     ///
@@ -174,8 +175,8 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for casts to the same type, casts of int literals to integer types
-    /// and casts of float literals to float types.
+    /// Checks for casts to the same type, casts of int literals to integer types, casts of float
+    /// literals to float types and casts between raw pointers without changing type or constness.
     ///
     /// ### Why is this bad?
     /// It's just unnecessary.
@@ -522,7 +523,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Check for the usage of `as _` conversion using inferred type.
+    /// Checks for the usage of `as _` conversion using inferred type.
     ///
     /// ### Why is this bad?
     /// The conversion might include lossy conversion and dangerous cast that might go
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
index ab015f8822e..f0c1df01430 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -9,20 +9,21 @@ use rustc_middle::ty::{self, Ty, TypeAndMut};
 
 use super::PTR_CAST_CONSTNESS;
 
-pub(super) fn check(
+pub(super) fn check<'tcx>(
     cx: &LateContext<'_>,
     expr: &Expr<'_>,
     cast_expr: &Expr<'_>,
-    cast_from: Ty<'_>,
-    cast_to: Ty<'_>,
+    cast_from: Ty<'tcx>,
+    cast_to: Ty<'tcx>,
     msrv: &Msrv,
 ) {
     if_chain! {
         if msrv.meets(POINTER_CAST_CONSTNESS);
-        if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind();
-        if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind();
+        if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind();
+        if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind();
         if matches!((from_mutbl, to_mutbl),
             (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not));
+        if from_ty == to_ty;
         then {
             let sugg = Sugg::hir(cx, cast_expr, "_");
             let constness = match *to_mutbl {
@@ -34,7 +35,7 @@ pub(super) fn check(
                 cx,
                 PTR_CAST_CONSTNESS,
                 expr.span,
-                "`as` casting between raw pointers while changing its constness",
+                "`as` casting between raw pointers while changing only its constness",
                 &format!("try `pointer::cast_{constness}`, a safer alternative"),
                 format!("{}.cast_{constness}()", sugg.maybe_par()),
                 Applicability::MachineApplicable,
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index 804ae841100..71cf2aea0f8 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,18 +1,21 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::NumericLiteral;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::{get_parent_expr, path_to_local};
+use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
 use if_chain::if_chain;
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
-use rustc_hir::{Expr, ExprKind, Lit, QPath, TyKind, UnOp};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, InferTy, Ty};
+use std::ops::ControlFlow;
 
 use super::UNNECESSARY_CAST;
 
+#[expect(clippy::too_many_lines)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &Expr<'tcx>,
@@ -20,19 +23,84 @@ pub(super) fn check<'tcx>(
     cast_from: Ty<'tcx>,
     cast_to: Ty<'tcx>,
 ) -> bool {
-    // skip non-primitive type cast
+    let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
+
+    if_chain! {
+        if let ty::RawPtr(..) = cast_from.kind();
+        // check both mutability and type are the same
+        if cast_from.kind() == cast_to.kind();
+        if let ExprKind::Cast(_, cast_to_hir) = expr.kind;
+        // Ignore casts to e.g. type aliases and infer types
+        // - p as pointer_alias
+        // - p as _
+        if let TyKind::Ptr(to_pointee) = cast_to_hir.kind;
+        then {
+            match to_pointee.ty.kind {
+                // Ignore casts to pointers that are aliases or cfg dependant, e.g.
+                // - p as *const std::ffi::c_char (alias)
+                // - p as *const std::os::raw::c_char (cfg dependant)
+                TyKind::Path(qpath) => {
+                    if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) {
+                        return false;
+                    }
+                },
+                // Ignore `p as *const _`
+                TyKind::Infer => return false,
+                _ => {},
+            }
+
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_CAST,
+                expr.span,
+                &format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"),
+                "try",
+                cast_str.clone(),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
+    // skip cast of local that is a type alias
+    if let ExprKind::Cast(inner, ..) = expr.kind
+        && let ExprKind::Path(qpath) = inner.kind
+        && let QPath::Resolved(None, Path { res, .. }) = qpath
+        && let Res::Local(hir_id) = res
+        && let parent = cx.tcx.hir().get_parent(*hir_id)
+        && let Node::Local(local) = parent
+    {
+        if let Some(ty) = local.ty
+            && let TyKind::Path(qpath) = ty.kind
+            && is_ty_alias(&qpath)
+        {
+            return false;
+        }
+
+        if let Some(expr) = local.init
+            && let ExprKind::Cast(.., cast_to) = expr.kind
+            && let TyKind::Path(qpath) = cast_to.kind
+            && is_ty_alias(&qpath)
+        {
+            return false;
+        }
+    }
+
+    // skip cast of fn call that returns type alias
+    if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) {
+        return false;
+    }
+
+    // skip cast to non-primitive type
     if_chain! {
         if let ExprKind::Cast(_, cast_to) = expr.kind;
         if let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind;
         if let Res::PrimTy(_) = path.res;
         then {}
         else {
-            return false
+            return false;
         }
     }
 
-    let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
-
     if let Some(lit) = get_numeric_literal(cast_expr) {
         let literal_str = &cast_str;
 
@@ -162,3 +230,61 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
         _ => 0,
     }
 }
+
+/// Finds whether an `Expr` returns a type alias.
+///
+/// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark,
+/// dark path reimplementing this (or something similar).
+fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>, cast_from: Ty<'tcx>) -> bool {
+    for_each_expr(expr, |expr| {
+        // Calls are a `Path`, and usage of locals are a `Path`. So, this checks
+        // - call() as i32
+        // - local as i32
+        if let ExprKind::Path(qpath) = expr.kind {
+            let res = cx.qpath_res(&qpath, expr.hir_id);
+            // Function call
+            if let Res::Def(DefKind::Fn, def_id) = res {
+                let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else {
+                    return ControlFlow::Continue(());
+                };
+                // This is the worst part of this entire function. This is the only way I know of to
+                // check whether a function returns a type alias. Sure, you can get the return type
+                // from a function in the current crate as an hir ty, but how do you get it for
+                // external functions?? Simple: It's impossible. So, we check whether a part of the
+                // function's declaration snippet is exactly equal to the `Ty`. That way, we can
+                // see whether it's a type alias.
+                //
+                // Will this work for more complex types? Probably not!
+                if !snippet
+                    .split("->")
+                    .skip(0)
+                    .map(|s| {
+                        s.trim() == cast_from.to_string()
+                            || s.split("where").any(|ty| ty.trim() == cast_from.to_string())
+                    })
+                    .any(|a| a)
+                {
+                    return ControlFlow::Break(());
+                }
+            // Local usage
+            } else if let Res::Local(hir_id) = res
+                && let Some(parent) = get_parent_node(cx.tcx, hir_id)
+                && let Node::Local(l) = parent
+            {
+                if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) {
+                    return ControlFlow::Break::<()>(());
+                }
+
+                if let Some(ty) = l.ty
+                    && let TyKind::Path(qpath) = ty.kind
+                    && is_ty_alias(&qpath)
+                {
+                    return ControlFlow::Break::<()>(());
+                }
+            }
+        }
+
+        ControlFlow::Continue(())
+    })
+    .is_some()
+}
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index f1d1355123a..9d9ee6ba307 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -4,6 +4,8 @@
 
 pub(crate) static LINTS: &[&crate::LintInfo] = &[
     #[cfg(feature = "internal")]
+    crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
+    #[cfg(feature = "internal")]
     crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
     #[cfg(feature = "internal")]
     crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO,
@@ -38,6 +40,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::allow_attributes::ALLOW_ATTRIBUTES_INFO,
     crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
     crate::approx_const::APPROX_CONSTANT_INFO,
+    crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO,
     crate::as_conversions::AS_CONVERSIONS_INFO,
     crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
     crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO,
@@ -51,6 +54,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
+    crate::attrs::MAYBE_MISUSED_CFG_INFO,
     crate::attrs::MISMATCHED_TARGET_OS_INFO,
     crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::USELESS_ATTRIBUTE_INFO,
@@ -136,11 +140,15 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::double_parens::DOUBLE_PARENS_INFO,
     crate::drop_forget_ref::DROP_NON_DROP_INFO,
     crate::drop_forget_ref::FORGET_NON_DROP_INFO,
+    crate::drop_forget_ref::MEM_FORGET_INFO,
     crate::duplicate_mod::DUPLICATE_MOD_INFO,
     crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
     crate::empty_drop::EMPTY_DROP_INFO,
     crate::empty_enum::EMPTY_ENUM_INFO,
     crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
+    crate::endian_bytes::BIG_ENDIAN_BYTES_INFO,
+    crate::endian_bytes::HOST_ENDIAN_BYTES_INFO,
+    crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO,
     crate::entry::MAP_ENTRY_INFO,
     crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO,
     crate::enum_variants::ENUM_VARIANT_NAMES_INFO,
@@ -152,6 +160,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS_INFO,
     crate::excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS_INFO,
     crate::excessive_bools::STRUCT_EXCESSIVE_BOOLS_INFO,
+    crate::excessive_nesting::EXCESSIVE_NESTING_INFO,
     crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO,
     crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
     crate::exit::EXIT_INFO,
@@ -197,6 +206,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
     crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
     crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
+    crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO,
     crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO,
     crate::indexing_slicing::INDEXING_SLICING_INFO,
     crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO,
@@ -219,6 +229,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::large_futures::LARGE_FUTURES_INFO,
     crate::large_include_file::LARGE_INCLUDE_FILE_INFO,
     crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO,
+    crate::large_stack_frames::LARGE_STACK_FRAMES_INFO,
     crate::len_zero::COMPARISON_TO_EMPTY_INFO,
     crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
     crate::len_zero::LEN_ZERO_INFO,
@@ -266,6 +277,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::manual_let_else::MANUAL_LET_ELSE_INFO,
     crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO,
     crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
+    crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_INFO,
     crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO,
     crate::manual_retain::MANUAL_RETAIN_INFO,
     crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO,
@@ -299,7 +311,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::matches::TRY_ERR_INFO,
     crate::matches::WILDCARD_ENUM_MATCH_ARM_INFO,
     crate::matches::WILDCARD_IN_OR_PATTERNS_INFO,
-    crate::mem_forget::MEM_FORGET_INFO,
     crate::mem_replace::MEM_REPLACE_OPTION_WITH_NONE_INFO,
     crate::mem_replace::MEM_REPLACE_WITH_DEFAULT_INFO,
     crate::mem_replace::MEM_REPLACE_WITH_UNINIT_INFO,
@@ -314,6 +325,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::CLONE_ON_COPY_INFO,
     crate::methods::CLONE_ON_REF_PTR_INFO,
     crate::methods::COLLAPSIBLE_STR_REPLACE_INFO,
+    crate::methods::DRAIN_COLLECT_INFO,
     crate::methods::ERR_EXPECT_INFO,
     crate::methods::EXPECT_FUN_CALL_INFO,
     crate::methods::EXPECT_USED_INFO,
@@ -352,6 +364,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
     crate::methods::MANUAL_SPLIT_ONCE_INFO,
     crate::methods::MANUAL_STR_REPEAT_INFO,
+    crate::methods::MANUAL_TRY_FOLD_INFO,
     crate::methods::MAP_CLONE_INFO,
     crate::methods::MAP_COLLECT_RESULT_UNIT_INFO,
     crate::methods::MAP_ERR_IGNORE_INFO,
@@ -398,6 +411,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::UNNECESSARY_FOLD_INFO,
     crate::methods::UNNECESSARY_JOIN_INFO,
     crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO,
+    crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO,
     crate::methods::UNNECESSARY_SORT_BY_INFO,
     crate::methods::UNNECESSARY_TO_OWNED_INFO,
     crate::methods::UNWRAP_OR_ELSE_DEFAULT_INFO,
@@ -407,6 +421,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::VERBOSE_FILE_READS_INFO,
     crate::methods::WRONG_SELF_CONVENTION_INFO,
     crate::methods::ZST_OFFSET_INFO,
+    crate::min_ident_chars::MIN_IDENT_CHARS_INFO,
     crate::minmax::MIN_MAX_INFO,
     crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
     crate::misc::TOPLEVEL_REF_ARG_INFO,
@@ -416,6 +431,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::misc_early::DOUBLE_NEG_INFO,
     crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
     crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO,
+    crate::misc_early::REDUNDANT_AT_REST_PATTERN_INFO,
     crate::misc_early::REDUNDANT_PATTERN_INFO,
     crate::misc_early::SEPARATED_LITERAL_SUFFIX_INFO,
     crate::misc_early::UNNEEDED_FIELD_PATTERN_INFO,
@@ -450,6 +466,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::needless_continue::NEEDLESS_CONTINUE_INFO,
     crate::needless_else::NEEDLESS_ELSE_INFO,
     crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
+    crate::needless_if::NEEDLESS_IF_INFO,
     crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
     crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
     crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,
@@ -524,6 +541,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::ranges::RANGE_MINUS_ONE_INFO,
     crate::ranges::RANGE_PLUS_ONE_INFO,
     crate::ranges::REVERSED_EMPTY_RANGES_INFO,
+    crate::raw_strings::NEEDLESS_RAW_STRINGS_INFO,
+    crate::raw_strings::NEEDLESS_RAW_STRING_HASHES_INFO,
     crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO,
     crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO,
     crate::redundant_async_block::REDUNDANT_ASYNC_BLOCK_INFO,
@@ -535,6 +554,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::redundant_slicing::DEREF_BY_SLICING_INFO,
     crate::redundant_slicing::REDUNDANT_SLICING_INFO,
     crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
+    crate::redundant_type_annotations::REDUNDANT_TYPE_ANNOTATIONS_INFO,
     crate::ref_option_ref::REF_OPTION_REF_INFO,
     crate::ref_patterns::REF_PATTERNS_INFO,
     crate::reference::DEREF_ADDROF_INFO,
@@ -553,8 +573,10 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::shadow::SHADOW_SAME_INFO,
     crate::shadow::SHADOW_UNRELATED_INFO,
     crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO,
+    crate::single_call_fn::SINGLE_CALL_FN_INFO,
     crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
     crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
+    crate::single_range_in_vec_init::SINGLE_RANGE_IN_VEC_INIT_INFO,
     crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
     crate::size_of_ref::SIZE_OF_REF_INFO,
     crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
@@ -602,6 +624,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO,
     crate::transmute::USELESS_TRANSMUTE_INFO,
     crate::transmute::WRONG_TRANSMUTE_INFO,
+    crate::tuple_array_conversions::TUPLE_ARRAY_CONVERSIONS_INFO,
     crate::types::BORROWED_BOX_INFO,
     crate::types::BOX_COLLECTION_INFO,
     crate::types::LINKEDLIST_INFO,
@@ -644,6 +667,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::useless_conversion::USELESS_CONVERSION_INFO,
     crate::vec::USELESS_VEC_INFO,
     crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO,
+    crate::visibility::NEEDLESS_PUB_SELF_INFO,
+    crate::visibility::PUB_WITHOUT_SHORTHAND_INFO,
+    crate::visibility::PUB_WITH_SHORTHAND_INFO,
     crate::wildcard_imports::ENUM_GLOB_USE_INFO,
     crate::wildcard_imports::WILDCARD_IMPORTS_INFO,
     crate::write::PRINTLN_EMPTY_STRING_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index fb037bbcbf3..ca9514ccc7d 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Check for construction on unit struct using `default`.
+    /// Checks for construction on unit struct using `default`.
     ///
     /// ### Why is this bad?
     /// This adds code complexity and an unnecessary function call.
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 4e1a6cd4d73..e53a9877b20 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -161,7 +161,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
                         let fields_def = &variant.fields;
 
                         // Push field type then visit each field expr.
-                        for field in fields.iter() {
+                        for field in *fields {
                             let bound =
                                 fields_def
                                     .iter()
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 1ecaa1a123c..73556c1053e 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -56,9 +56,11 @@ declare_clippy_lint! {
     /// let b = &*a;
     /// ```
     ///
-    /// This lint excludes:
+    /// This lint excludes all of:
     /// ```rust,ignore
     /// let _ = d.unwrap().deref();
+    /// let _ = Foo::deref(&foo);
+    /// let _ = <Foo as Deref>::deref(&foo);
     /// ```
     #[clippy::version = "1.44.0"]
     pub EXPLICIT_DEREF_METHODS,
@@ -355,15 +357,17 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                         //    start auto-deref.
                         // 4. If the chain of non-user-defined derefs ends with a mutable re-borrow, and re-borrow
                         //    adjustments will not be inserted automatically, then leave one further reference to avoid
-                        //    moving a mutable borrow.
-                        //    e.g.
-                        //        fn foo<T>(x: &mut Option<&mut T>, y: &mut T) {
-                        //            let x = match x {
-                        //                // Removing the borrow will cause `x` to be moved
-                        //                Some(x) => &mut *x,
-                        //                None => y
-                        //            };
-                        //        }
+                        //    moving a mutable borrow. e.g.
+                        //
+                        //    ```rust
+                        //    fn foo<T>(x: &mut Option<&mut T>, y: &mut T) {
+                        //        let x = match x {
+                        //            // Removing the borrow will cause `x` to be moved
+                        //            Some(x) => &mut *x,
+                        //            None => y
+                        //        };
+                        //    }
+                        //    ```
                         let deref_msg =
                             "this expression creates a reference which is immediately dereferenced by the compiler";
                         let borrow_msg = "this expression borrows a value the compiler would automatically borrow";
@@ -1481,7 +1485,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             target_mut,
         } => {
             let mut app = Applicability::MachineApplicable;
-            let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
+            let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
             let ty = cx.typeck_results().expr_ty(expr);
             let (_, ref_count) = peel_mid_ty_refs(ty);
             let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
@@ -1504,11 +1508,20 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
                 "&"
             };
 
-            let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
-                format!("({expr_str})")
+            // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
+            // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
+            /*
+            expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
+                Cow::Owned(format!("({expr_str})"))
             } else {
-                expr_str.into_owned()
+                expr_str
             };
+            */
+
+            // Fix #10850, do not lint if it's `Foo::deref` instead of `foo.deref()`.
+            if is_final_ufcs {
+                return;
+            }
 
             span_lint_and_sugg(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 8f68f90a2a1..ec0ca50cfec 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -4,11 +4,13 @@ use clippy_utils::source::indent_of;
 use clippy_utils::{is_default_equivalent, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{
+    self as hir,
     def::{CtorKind, CtorOf, DefKind, Res},
-    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
+    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Adt, AdtDef, SubstsRef};
+use rustc_middle::ty::adjustment::{Adjust, PointerCast};
+use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, Ty, TypeckResults};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::sym;
 
@@ -75,13 +77,23 @@ fn is_path_self(e: &Expr<'_>) -> bool {
     }
 }
 
+fn contains_trait_object(ty: Ty<'_>) -> bool {
+    match ty.kind() {
+        ty::Ref(_, ty, _) => contains_trait_object(*ty),
+        ty::Adt(def, substs) => def.is_box() && substs[0].as_type().map_or(false, contains_trait_object),
+        ty::Dynamic(..) => true,
+        _ => false,
+    }
+}
+
 fn check_struct<'tcx>(
     cx: &LateContext<'tcx>,
     item: &'tcx Item<'_>,
-    self_ty: &Ty<'_>,
+    self_ty: &hir::Ty<'_>,
     func_expr: &Expr<'_>,
     adt_def: AdtDef<'_>,
     substs: SubstsRef<'_>,
+    typeck_results: &'tcx TypeckResults<'tcx>,
 ) {
     if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
         if let Some(PathSegment { args, .. }) = p.segments.last() {
@@ -96,10 +108,23 @@ fn check_struct<'tcx>(
             }
         }
     }
+
+    // the default() call might unsize coerce to a trait object (e.g. Box<T> to Box<dyn Trait>),
+    // which would not be the same if derived (see #10158).
+    // this closure checks both if the expr is equivalent to a `default()` call and does not
+    // have such coercions.
+    let is_default_without_adjusts = |expr| {
+        is_default_equivalent(cx, expr)
+            && typeck_results.expr_adjustments(expr).iter().all(|adj| {
+                !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize)
+                    if contains_trait_object(adj.target))
+            })
+    };
+
     let should_emit = match peel_blocks(func_expr).kind {
-        ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
-        ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
-        ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
+        ExprKind::Tup(fields) => fields.iter().all(is_default_without_adjusts),
+        ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(is_default_without_adjusts),
+        ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_without_adjusts(ef.expr)),
         _ => false,
     };
 
@@ -197,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
 
             then {
                 if adt_def.is_struct() {
-                    check_struct(cx, item, self_ty, func_expr, adt_def, substs);
+                    check_struct(cx, item, self_ty, func_expr, adt_def, substs, cx.tcx.typeck_body(*b));
                 } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
                     check_enum(cx, item, func_expr, adt_def);
                 }
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 10a2f0cb1e7..a005a360e9c 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
-    self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv,
-    ToPredicate, TraitPredicate, Ty, TyCtxt,
+    self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate,
+    TraitPredicate, Ty, TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
@@ -520,7 +520,8 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
                     trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
                     constness: BoundConstness::NotConst,
                     polarity: ImplPolarity::Positive,
-                }).to_predicate(tcx)
+                })
+                .to_predicate(tcx)
             }),
         )),
         Reveal::UserFacing,
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index 384aca7fead..87d88f70752 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -571,6 +571,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut in_link = None;
     let mut in_heading = false;
     let mut is_rust = false;
+    let mut no_test = false;
     let mut edition = None;
     let mut ticks_unbalanced = false;
     let mut text_to_check: Vec<(CowStr<'_>, Span)> = Vec::new();
@@ -584,6 +585,8 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                         if item == "ignore" {
                             is_rust = false;
                             break;
+                        } else if item == "no_test" {
+                            no_test = true;
                         }
                         if let Some(stripped) = item.strip_prefix("edition") {
                             is_rust = true;
@@ -648,7 +651,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 headers.errors |= in_heading && trimmed_text == "Errors";
                 headers.panics |= in_heading && trimmed_text == "Panics";
                 if in_code {
-                    if is_rust {
+                    if is_rust && !no_test {
                         let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
                         check_code(cx, &text, edition, span);
                     }
@@ -906,15 +909,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
             if is_panic(self.cx, macro_call.def_id)
                 || matches!(
                     self.cx.tcx.item_name(macro_call.def_id).as_str(),
-                    "assert" | "assert_eq" | "assert_ne" | "todo"
+                    "assert" | "assert_eq" | "assert_ne"
                 )
             {
                 self.panic_span = Some(macro_call.span);
             }
         }
 
-        // check for `unwrap`
-        if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
+        // check for `unwrap` and `expect` for both `Option` and `Result`
+        if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) {
             let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
             if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
                 || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 7a4b9a87aeb..976ce47e869 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -6,6 +6,7 @@ use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
+use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -47,6 +48,27 @@ declare_clippy_lint! {
     "call to `std::mem::forget` with a value which does not implement `Drop`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `std::mem::forget(t)` where `t` is
+    /// `Drop` or has a field that implements `Drop`.
+    ///
+    /// ### Why is this bad?
+    /// `std::mem::forget(t)` prevents `t` from running its
+    /// destructor, possibly causing leaks.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::mem;
+    /// # use std::rc::Rc;
+    /// mem::forget(Rc::new(55))
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub MEM_FORGET,
+    restriction,
+    "`mem::forget` usage on `Drop` types, likely to cause memory leaks"
+}
+
 const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \
                                  Dropping such a type only extends its contained lifetimes";
 const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \
@@ -55,6 +77,7 @@ const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value t
 declare_lint_pass!(DropForgetRef => [
     DROP_NON_DROP,
     FORGET_NON_DROP,
+    MEM_FORGET,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
@@ -67,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
             let arg_ty = cx.typeck_results().expr_ty(arg);
             let is_copy = is_copy(cx, arg_ty);
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
-            let (lint, msg) = match fn_name {
+            let (lint, msg, note_span) = match fn_name {
                 // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types
                 sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
                 sym::mem_forget if arg_ty.is_ref() => return,
@@ -81,19 +104,34 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                         || drop_is_single_call_in_arm
                         ) =>
                 {
-                    (DROP_NON_DROP, DROP_NON_DROP_SUMMARY)
-                },
-                sym::mem_forget if !arg_ty.needs_drop(cx.tcx, cx.param_env) => {
-                    (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY)
+                    (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span))
                 },
+                sym::mem_forget => {
+                    if arg_ty.needs_drop(cx.tcx, cx.param_env) {
+                        (
+                            MEM_FORGET,
+                            Cow::Owned(format!(
+                                "usage of `mem::forget` on {}",
+                                if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) {
+                                    "`Drop` type"
+                                } else {
+                                    "type with `Drop` fields"
+                                }
+                            )),
+                            None,
+                        )
+                    } else {
+                        (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY.into(), Some(arg.span))
+                    }
+                }
                 _ => return,
             };
             span_lint_and_note(
                 cx,
                 lint,
                 expr.span,
-                msg,
-                Some(arg.span),
+                &msg,
+                note_span,
                 &format!("argument has type `{arg_ty}`"),
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/endian_bytes.rs b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
new file mode 100644
index 00000000000..f470987833e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
@@ -0,0 +1,216 @@
+use crate::Lint;
+use clippy_utils::{diagnostics::span_lint_and_then, is_lint_allowed};
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::{lint::in_external_macro, ty::Ty};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Symbol;
+use std::borrow::Cow;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`.
+    ///
+    /// ### Why is this bad?
+    /// It's not, but some may prefer to specify the target endianness explicitly.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// let _x = 2i32.to_ne_bytes();
+    /// let _y = 2i64.to_ne_bytes();
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub HOST_ENDIAN_BYTES,
+    restriction,
+    "disallows usage of the `to_ne_bytes` method"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`.
+    ///
+    /// ### Why is this bad?
+    /// It's not, but some may wish to lint usage of this method, either to suggest using the host
+    /// endianness or big endian.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// let _x = 2i32.to_le_bytes();
+    /// let _y = 2i64.to_le_bytes();
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub LITTLE_ENDIAN_BYTES,
+    restriction,
+    "disallows usage of the `to_le_bytes` method"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`.
+    ///
+    /// ### Why is this bad?
+    /// It's not, but some may wish to lint usage of this method, either to suggest using the host
+    /// endianness or little endian.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// let _x = 2i32.to_be_bytes();
+    /// let _y = 2i64.to_be_bytes();
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub BIG_ENDIAN_BYTES,
+    restriction,
+    "disallows usage of the `to_be_bytes` method"
+}
+
+declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]);
+
+const HOST_NAMES: [&str; 2] = ["from_ne_bytes", "to_ne_bytes"];
+const LITTLE_NAMES: [&str; 2] = ["from_le_bytes", "to_le_bytes"];
+const BIG_NAMES: [&str; 2] = ["from_be_bytes", "to_be_bytes"];
+
+#[derive(Clone, Debug)]
+enum LintKind {
+    Host,
+    Little,
+    Big,
+}
+
+#[derive(Clone, Copy, PartialEq)]
+enum Prefix {
+    From,
+    To,
+}
+
+impl LintKind {
+    fn allowed(&self, cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+        is_lint_allowed(cx, self.as_lint(), expr.hir_id)
+    }
+
+    fn as_lint(&self) -> &'static Lint {
+        match self {
+            LintKind::Host => HOST_ENDIAN_BYTES,
+            LintKind::Little => LITTLE_ENDIAN_BYTES,
+            LintKind::Big => BIG_ENDIAN_BYTES,
+        }
+    }
+
+    fn as_name(&self, prefix: Prefix) -> &str {
+        let index = usize::from(prefix == Prefix::To);
+
+        match self {
+            LintKind::Host => HOST_NAMES[index],
+            LintKind::Little => LITTLE_NAMES[index],
+            LintKind::Big => BIG_NAMES[index],
+        }
+    }
+}
+
+impl LateLintPass<'_> for EndianBytes {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if in_external_macro(cx.sess(), expr.span) {
+            return;
+        }
+
+        if_chain! {
+            if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind;
+            if args.is_empty();
+            let ty = cx.typeck_results().expr_ty(receiver);
+            if ty.is_primitive_ty();
+            if maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty);
+            then {
+                return;
+            }
+        }
+
+        if_chain! {
+            if let ExprKind::Call(function, ..) = expr.kind;
+            if let ExprKind::Path(qpath) = function.kind;
+            if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id();
+            if let Some(function_name) = cx.get_def_path(def_id).last();
+            let ty = cx.typeck_results().expr_ty(expr);
+            if ty.is_primitive_ty();
+            then {
+                maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty);
+            }
+        }
+    }
+}
+
+fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix, name: Symbol, ty: Ty<'_>) -> bool {
+    let ne = LintKind::Host.as_name(prefix);
+    let le = LintKind::Little.as_name(prefix);
+    let be = LintKind::Big.as_name(prefix);
+
+    let (lint, other_lints) = match name.as_str() {
+        name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]),
+        name if name == le => ((&LintKind::Little), [(&LintKind::Host), (&LintKind::Big)]),
+        name if name == be => ((&LintKind::Big), [(&LintKind::Host), (&LintKind::Little)]),
+        _ => return false,
+    };
+
+    let mut help = None;
+
+    'build_help: {
+        // all lints disallowed, don't give help here
+        if [&[lint], other_lints.as_slice()]
+            .concat()
+            .iter()
+            .all(|lint| !lint.allowed(cx, expr))
+        {
+            break 'build_help;
+        }
+
+        // ne_bytes and all other lints allowed
+        if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) {
+            help = Some(Cow::Borrowed("specify the desired endianness explicitly"));
+            break 'build_help;
+        }
+
+        // le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but
+        // le_bytes is not
+        if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) {
+            help = Some(Cow::Borrowed("use the native endianness instead"));
+            break 'build_help;
+        }
+
+        let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr));
+        let len = allowed_lints.clone().count();
+
+        let mut help_str = "use ".to_owned();
+
+        for (i, lint) in allowed_lints.enumerate() {
+            let only_one = len == 1;
+            if !only_one {
+                help_str.push_str("either of ");
+            }
+
+            help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));
+
+            if i != len && !only_one {
+                help_str.push_str("or ");
+            }
+        }
+
+        help = Some(Cow::Owned(help_str + "instead"));
+    }
+
+    span_lint_and_then(
+        cx,
+        lint.as_lint(),
+        expr.span,
+        &format!(
+            "usage of the {}`{ty}::{}`{}",
+            if prefix == Prefix::From { "function " } else { "" },
+            lint.as_name(prefix),
+            if prefix == Prefix::To { " method" } else { "" },
+        ),
+        move |diag| {
+            if let Some(help) = help {
+                diag.help(help);
+            }
+        },
+    );
+
+    true
+}
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index e275efaba25..d85650712db 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
                         .const_eval_poly(def_id.to_def_id())
                         .ok()
                         .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty));
-                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
+                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
                         if let ty::Adt(adt, _) = ty.kind() {
                             if adt.is_enum() {
                                 ty = adt.repr().discr_type().to_ty(cx.tcx);
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index faac6340419..d4df6f7aa2d 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -3,7 +3,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
 use clippy_utils::source::is_present_in_source;
 use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start};
-use rustc_hir::{EnumDef, Item, ItemKind, Variant};
+use rustc_hir::{EnumDef, Item, ItemKind, OwnerId, Variant};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
@@ -105,18 +105,20 @@ declare_clippy_lint! {
 }
 
 pub struct EnumVariantNames {
-    modules: Vec<(Symbol, String)>,
+    modules: Vec<(Symbol, String, OwnerId)>,
     threshold: u64,
     avoid_breaking_exported_api: bool,
+    allow_private_module_inception: bool,
 }
 
 impl EnumVariantNames {
     #[must_use]
-    pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
+    pub fn new(threshold: u64, avoid_breaking_exported_api: bool, allow_private_module_inception: bool) -> Self {
         Self {
             modules: Vec::new(),
             threshold,
             avoid_breaking_exported_api,
+            allow_private_module_inception,
         }
     }
 }
@@ -252,18 +254,19 @@ impl LateLintPass<'_> for EnumVariantNames {
         let item_name = item.ident.name.as_str();
         let item_camel = to_camel_case(item_name);
         if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
-            if let Some((mod_name, mod_camel)) = self.modules.last() {
+            if let [.., (mod_name, mod_camel, owner_id)] = &*self.modules {
                 // constants don't have surrounding modules
                 if !mod_camel.is_empty() {
-                    if mod_name == &item.ident.name {
-                        if let ItemKind::Mod(..) = item.kind {
-                            span_lint(
-                                cx,
-                                MODULE_INCEPTION,
-                                item.span,
-                                "module has the same name as its containing module",
-                            );
-                        }
+                    if mod_name == &item.ident.name
+                        && let ItemKind::Mod(..) = item.kind
+                        && (!self.allow_private_module_inception || cx.tcx.visibility(owner_id.def_id).is_public())
+                    {
+                        span_lint(
+                            cx,
+                            MODULE_INCEPTION,
+                            item.span,
+                            "module has the same name as its containing module",
+                        );
                     }
                     // The `module_name_repetitions` lint should only trigger if the item has the module in its
                     // name. Having the same name is accepted.
@@ -302,6 +305,6 @@ impl LateLintPass<'_> for EnumVariantNames {
                 check_variant(cx, self.threshold, def, item_name, item.span);
             }
         }
-        self.modules.push((item.ident.name, item_camel));
+        self.modules.push((item.ident.name, item_camel, item.owner_id));
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index c919b4de65d..58e62d1f3d3 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -120,6 +120,13 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc);
             if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc);
             if let ty::Closure(_, substs) = *closure_ty.kind();
+            // Don't lint if this is an inclusive range expression.
+            // They desugar to a call to `RangeInclusiveNew` which would have odd suggestions. (#10684)
+            if !matches!(higher::Range::hir(body.value), Some(higher::Range {
+                start: Some(_),
+                end: Some(_),
+                limits: rustc_ast::RangeLimits::Closed
+            }));
             then {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
                     if let Some(mut snippet) = snippet_opt(cx, callee.span) {
@@ -136,6 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                                 // Mutable closure is used after current expr; we cannot consume it.
                                 snippet = format!("&mut {snippet}");
                         }
+
                         diag.span_suggestion(
                             expr.span,
                             "replace the closure with the function itself",
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
new file mode 100644
index 00000000000..d04d833e630
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -0,0 +1,181 @@
+use clippy_utils::{diagnostics::span_lint_and_help, source::snippet};
+use rustc_ast::{
+    node_id::NodeSet,
+    visit::{walk_block, walk_item, Visitor},
+    Block, Crate, Inline, Item, ItemKind, ModKind, NodeId,
+};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for blocks which are nested beyond a certain threshold.
+    ///
+    /// Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file.
+    ///
+    /// ### Why is this bad?
+    /// It can severely hinder readability.
+    ///
+    /// ### Example
+    /// An example clippy.toml configuration:
+    /// ```toml
+    /// # clippy.toml
+    /// excessive-nesting-threshold = 3
+    /// ```
+    /// ```rust,ignore
+    /// // lib.rs
+    /// pub mod a {
+    ///     pub struct X;
+    ///     impl X {
+    ///         pub fn run(&self) {
+    ///             if true {
+    ///                 // etc...
+    ///             }
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// // a.rs
+    /// fn private_run(x: &X) {
+    ///     if true {
+    ///         // etc...
+    ///     }
+    /// }
+    ///
+    /// pub struct X;
+    /// impl X {
+    ///     pub fn run(&self) {
+    ///         private_run(self);
+    ///     }
+    /// }
+    /// ```
+    /// ```rust,ignore
+    /// // lib.rs
+    /// pub mod a;
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub EXCESSIVE_NESTING,
+    complexity,
+    "checks for blocks nested beyond a certain threshold"
+}
+impl_lint_pass!(ExcessiveNesting => [EXCESSIVE_NESTING]);
+
+#[derive(Clone)]
+pub struct ExcessiveNesting {
+    pub excessive_nesting_threshold: u64,
+    pub nodes: NodeSet,
+}
+
+impl ExcessiveNesting {
+    pub fn check_node_id(&self, cx: &EarlyContext<'_>, span: Span, node_id: NodeId) {
+        if self.nodes.contains(&node_id) {
+            span_lint_and_help(
+                cx,
+                EXCESSIVE_NESTING,
+                span,
+                "this block is too nested",
+                None,
+                "try refactoring your code to minimize nesting",
+            );
+        }
+    }
+}
+
+impl EarlyLintPass for ExcessiveNesting {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
+        if self.excessive_nesting_threshold == 0 {
+            return;
+        }
+
+        let mut visitor = NestingVisitor {
+            conf: self,
+            cx,
+            nest_level: 0,
+        };
+
+        for item in &krate.items {
+            visitor.visit_item(item);
+        }
+    }
+
+    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
+        self.check_node_id(cx, block.span, block.id);
+    }
+
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+        self.check_node_id(cx, item.span, item.id);
+    }
+}
+
+struct NestingVisitor<'conf, 'cx> {
+    conf: &'conf mut ExcessiveNesting,
+    cx: &'cx EarlyContext<'cx>,
+    nest_level: u64,
+}
+
+impl NestingVisitor<'_, '_> {
+    fn check_indent(&mut self, span: Span, id: NodeId) -> bool {
+        if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) {
+            self.conf.nodes.insert(id);
+
+            return true;
+        }
+
+        false
+    }
+}
+
+impl<'conf, 'cx> Visitor<'_> for NestingVisitor<'conf, 'cx> {
+    fn visit_block(&mut self, block: &Block) {
+        if block.span.from_expansion() {
+            return;
+        }
+
+        // TODO: This should be rewritten using `LateLintPass` so we can use `is_from_proc_macro` instead,
+        // but for now, this is fine.
+        let snippet = snippet(self.cx, block.span, "{}").trim().to_owned();
+        if !snippet.starts_with('{') || !snippet.ends_with('}') {
+            return;
+        }
+
+        self.nest_level += 1;
+
+        if !self.check_indent(block.span, block.id) {
+            walk_block(self, block);
+        }
+
+        self.nest_level -= 1;
+    }
+
+    fn visit_item(&mut self, item: &Item) {
+        if item.span.from_expansion() {
+            return;
+        }
+
+        match &item.kind {
+            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
+                self.nest_level += 1;
+
+                if !self.check_indent(item.span, item.id) {
+                    walk_item(self, item);
+                }
+
+                self.nest_level -= 1;
+            },
+            // Reset nesting level for non-inline modules (since these are in another file)
+            ItemKind::Mod(..) => walk_item(
+                &mut NestingVisitor {
+                    conf: self.conf,
+                    cx: self.cx,
+                    nest_level: 0,
+                },
+                item,
+            ),
+            _ => walk_item(self, item),
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index eeb4de8b58f..126bed6789c 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::trait_ref_of_method;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
@@ -265,6 +266,7 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let ItemKind::Fn(_, generics, body_id) = item.kind
             && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id)
+            && !is_from_proc_macro(cx, item)
         {
             let mut walker = TypeWalker::new(cx, generics);
             walk_item(&mut walker, item);
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 93bf50fd5e7..d182bb62195 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -82,19 +82,24 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                     LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
                     LitFloatType::Unsuffixed => None
                 };
-                let (is_whole, mut float_str) = match fty {
+                let (is_whole, is_inf, mut float_str) = match fty {
                     FloatTy::F32 => {
                         let value = sym_str.parse::<f32>().unwrap();
 
-                        (value.fract() == 0.0, formatter.format(value))
+                        (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
                     },
                     FloatTy::F64 => {
                         let value = sym_str.parse::<f64>().unwrap();
 
-                        (value.fract() == 0.0, formatter.format(value))
+
+                        (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
                     },
                 };
 
+                if is_inf {
+                    return;
+                }
+
                 if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') {
                     // Normalize the literal by stripping the fractional portion
                     if sym_str.split('.').next().unwrap() != float_str {
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 3c55a563af4..5e0fcd74339 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -215,7 +215,7 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
 // ranges [-16777215, 16777216) for type f32 as whole number floats outside
 // this range are lossy and ambiguous.
 #[expect(clippy::cast_possible_truncation)]
-fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
+fn get_integer_from_float_constant(value: &Constant<'_>) -> Option<i32> {
     match value {
         F32(num) if num.fract() == 0.0 => {
             if (-16_777_215.0..16_777_216.0).contains(num) {
diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs
index 68c5c3673fe..45f67020c2d 100644
--- a/src/tools/clippy/clippy_lints/src/format_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{match_def_path, paths, peel_hir_expr_refs};
-use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem};
+use clippy_utils::{higher, match_def_path, paths};
+use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -44,10 +44,24 @@ fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     is_type_lang_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), LangItem::String)
 }
 fn is_format(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    if let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id {
+    let e = e.peel_blocks().peel_borrows();
+
+    if e.span.from_expansion()
+        && let Some(macro_def_id) = e.span.ctxt().outer_expn_data().macro_def_id
+    {
         cx.tcx.get_diagnostic_name(macro_def_id) == Some(sym::format_macro)
+    } else if let Some(higher::If { then, r#else, .. }) = higher::If::hir(e) {
+        is_format(cx, then) || r#else.is_some_and(|e| is_format(cx, e))
     } else {
-        false
+        match higher::IfLetOrMatch::parse(cx, e) {
+            Some(higher::IfLetOrMatch::Match(_, arms, MatchSource::Normal)) => {
+                arms.iter().any(|arm| is_format(cx, arm.body))
+            },
+            Some(higher::IfLetOrMatch::IfLet(_, _, then, r#else)) => {
+                is_format(cx, then) ||r#else.is_some_and(|e| is_format(cx, e))
+            },
+            _ => false,
+        }
     }
 }
 
@@ -68,7 +82,6 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString {
             },
             _ => return,
         };
-        let (arg, _) = peel_hir_expr_refs(arg);
         if is_format(cx, arg) {
             span_lint_and_help(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index 4762b354392..d03480c2108 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -236,6 +236,12 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
                 }
             }
 
+            // Don't warn if the only thing inside post_else_post_eol is a comment block.
+            let trimmed_post_else_post_eol = post_else_post_eol.trim();
+            if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") {
+                return
+            }
+
             let else_desc = if is_if(else_) { "if" } else { "{..}" };
             span_lint_and_note(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 10ce2a0f0c7..92d67ef359d 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -134,9 +134,10 @@ impl<'a, 'tcx> Visitor<'tcx> for SelfFinder<'a, 'tcx> {
                 kw::SelfUpper => self.upper.push(segment.ident.span),
                 _ => continue,
             }
+
+            self.invalid |= segment.ident.span.from_expansion();
         }
 
-        self.invalid |= path.span.from_expansion();
         if !self.invalid {
             walk_path(self, path);
         }
@@ -156,6 +157,11 @@ fn convert_to_from(
     self_ty: &Ty<'_>,
     impl_item_ref: &ImplItemRef,
 ) -> Option<Vec<(Span, String)>> {
+    if !target_ty.find_self_aliases().is_empty() {
+        // It's tricky to expand self-aliases correctly, we'll ignore it to not cause a
+        // bad suggestion/fix.
+        return None;
+    }
     let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
     let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind else { return None };
     let body = cx.tcx.hir().body(body_id);
diff --git a/src/tools/clippy/clippy_lints/src/incorrect_impls.rs b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs
new file mode 100644
index 00000000000..13cc0b23ba3
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/incorrect_impls.rs
@@ -0,0 +1,124 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait};
+use rustc_errors::Applicability;
+use rustc_hir::{ExprKind, ImplItem, ImplItemKind, ItemKind, Node, UnOp};
+use rustc_hir_analysis::hir_ty_to_ty;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::EarlyBinder;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{sym, symbol};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for manual implementations of `Clone` when `Copy` is already implemented.
+    ///
+    /// ### Why is this bad?
+    /// If both `Clone` and `Copy` are implemented, they must agree. This is done by dereferencing
+    /// `self` in `Clone`'s implementation. Anything else is incorrect.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// #[derive(Eq, PartialEq)]
+    /// struct A(u32);
+    ///
+    /// impl Clone for A {
+    ///     fn clone(&self) -> Self {
+    ///         Self(self.0)
+    ///     }
+    /// }
+    ///
+    /// impl Copy for A {}
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// #[derive(Eq, PartialEq)]
+    /// struct A(u32);
+    ///
+    /// impl Clone for A {
+    ///     fn clone(&self) -> Self {
+    ///         *self
+    ///     }
+    /// }
+    ///
+    /// impl Copy for A {}
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+    correctness,
+    "manual implementation of `Clone` on a `Copy` type"
+}
+declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE]);
+
+impl LateLintPass<'_> for IncorrectImpls {
+    #[expect(clippy::needless_return)]
+    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
+        let node = get_parent_node(cx.tcx, impl_item.hir_id());
+        let Some(Node::Item(item)) = node else {
+            return;
+        };
+        let ItemKind::Impl(imp) = item.kind else {
+            return;
+        };
+        let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else {
+            return;
+        };
+        let trait_impl_def_id = trait_impl.def_id;
+        if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) {
+            return;
+        }
+        let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else {
+            return;
+        };
+        let body = cx.tcx.hir().body(impl_item_id);
+        let ExprKind::Block(block, ..) = body.value.kind else {
+            return;
+        };
+        // Above is duplicated from the `duplicate_manual_partial_ord_impl` branch.
+        // Remove it while solving conflicts once that PR is merged.
+
+        // Actual implementation; remove this comment once aforementioned PR is merged
+        if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id)
+            && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy)
+            && implements_trait(
+                    cx,
+                    hir_ty_to_ty(cx.tcx, imp.self_ty),
+                    copy_def_id,
+                    trait_impl.substs,
+                )
+        {
+            if impl_item.ident.name == sym::clone {
+                if block.stmts.is_empty()
+                    && let Some(expr) = block.expr
+                    && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind
+                    && let ExprKind::Path(qpath) = inner.kind
+                    && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower
+                {} else {
+                    span_lint_and_sugg(
+                        cx,
+                        INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+                        block.span,
+                        "incorrect implementation of `clone` on a `Copy` type",
+                        "change this to",
+                        "{ *self }".to_owned(),
+                        Applicability::MaybeIncorrect,
+                    );
+
+                    return;
+                }
+            }
+
+            if impl_item.ident.name == sym::clone_from {
+                span_lint_and_sugg(
+                    cx,
+                    INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+                    impl_item.span,
+                    "incorrect implementation of `clone_from` on a `Copy` type",
+                    "remove this",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+
+                return;
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
index b992d689aa9..40378ee8205 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
@@ -1,4 +1,4 @@
-use clippy_utils::{diagnostics::span_lint_and_help, is_in_cfg_test};
+use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, is_in_cfg_test};
 use rustc_hir::{HirId, ItemId, ItemKind, Mod};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -59,6 +59,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
             if !matches!(item.kind, ItemKind::Mod(_));
             if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself
             if !in_external_macro(cx.sess(), item.span);
+            if !is_from_proc_macro(cx, item);
 
             then {
                 span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined");
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
new file mode 100644
index 00000000000..9c0cc978a39
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs
@@ -0,0 +1,162 @@
+use std::ops::AddAssign;
+
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::fn_has_unsatisfiable_preds;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::Body;
+use rustc_hir::FnDecl;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_tool_lint;
+use rustc_session::impl_lint_pass;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for functions that use a lot of stack space.
+    ///
+    /// This often happens when constructing a large type, such as an array with a lot of elements,
+    /// or constructing *many* smaller-but-still-large structs, or copying around a lot of large types.
+    ///
+    /// This lint is a more general version of [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/#large_stack_arrays)
+    /// that is intended to look at functions as a whole instead of only individual array expressions inside of a function.
+    ///
+    /// ### Why is this bad?
+    /// The stack region of memory is very limited in size (usually *much* smaller than the heap) and attempting to
+    /// use too much will result in a stack overflow and crash the program.
+    /// To avoid this, you should consider allocating large types on the heap instead (e.g. by boxing them).
+    ///
+    /// Keep in mind that the code path to construction of large types does not even need to be reachable;
+    /// it purely needs to *exist* inside of the function to contribute to the stack size.
+    /// For example, this causes a stack overflow even though the branch is unreachable:
+    /// ```rust,ignore
+    /// fn main() {
+    ///     if false {
+    ///         let x = [0u8; 10000000]; // 10 MB stack array
+    ///         black_box(&x);
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// ### Known issues
+    /// False positives. The stack size that clippy sees is an estimated value and can be vastly different
+    /// from the actual stack usage after optimizations passes have run (especially true in release mode).
+    /// Modern compilers are very smart and are able to optimize away a lot of unnecessary stack allocations.
+    /// In debug mode however, it is usually more accurate.
+    ///
+    /// This lint works by summing up the size of all variables that the user typed, variables that were
+    /// implicitly introduced by the compiler for temporaries, function arguments and the return value,
+    /// and comparing them against a (configurable, but high-by-default).
+    ///
+    /// ### Example
+    /// This function creates four 500 KB arrays on the stack. Quite big but just small enough to not trigger `large_stack_arrays`.
+    /// However, looking at the function as a whole, it's clear that this uses a lot of stack space.
+    /// ```rust
+    /// struct QuiteLargeType([u8; 500_000]);
+    /// fn foo() {
+    ///     // ... some function that uses a lot of stack space ...
+    ///     let _x1 = QuiteLargeType([0; 500_000]);
+    ///     let _x2 = QuiteLargeType([0; 500_000]);
+    ///     let _x3 = QuiteLargeType([0; 500_000]);
+    ///     let _x4 = QuiteLargeType([0; 500_000]);
+    /// }
+    /// ```
+    ///
+    /// Instead of doing this, allocate the arrays on the heap.
+    /// This currently requires going through a `Vec` first and then converting it to a `Box`:
+    /// ```rust
+    /// struct NotSoLargeType(Box<[u8]>);
+    ///
+    /// fn foo() {
+    ///     let _x1 = NotSoLargeType(vec![0; 500_000].into_boxed_slice());
+    /// //                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  Now heap allocated.
+    /// //                                                                The size of `NotSoLargeType` is 16 bytes.
+    /// //  ...
+    /// }
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub LARGE_STACK_FRAMES,
+    nursery,
+    "checks for functions that allocate a lot of stack space"
+}
+
+pub struct LargeStackFrames {
+    maximum_allowed_size: u64,
+}
+
+impl LargeStackFrames {
+    #[must_use]
+    pub fn new(size: u64) -> Self {
+        Self {
+            maximum_allowed_size: size,
+        }
+    }
+}
+
+impl_lint_pass!(LargeStackFrames => [LARGE_STACK_FRAMES]);
+
+#[derive(Copy, Clone)]
+enum Space {
+    Used(u64),
+    Overflow,
+}
+
+impl Space {
+    pub fn exceeds_limit(self, limit: u64) -> bool {
+        match self {
+            Self::Used(used) => used > limit,
+            Self::Overflow => true,
+        }
+    }
+}
+
+impl AddAssign<u64> for Space {
+    fn add_assign(&mut self, rhs: u64) {
+        if let Self::Used(lhs) = self {
+            match lhs.checked_add(rhs) {
+                Some(sum) => *self = Self::Used(sum),
+                None => *self = Self::Overflow,
+            }
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        _: FnKind<'tcx>,
+        _: &'tcx FnDecl<'tcx>,
+        _: &'tcx Body<'tcx>,
+        span: Span,
+        local_def_id: LocalDefId,
+    ) {
+        let def_id = local_def_id.to_def_id();
+        // Building MIR for `fn`s with unsatisfiable preds results in ICE.
+        if fn_has_unsatisfiable_preds(cx, def_id) {
+            return;
+        }
+
+        let mir = cx.tcx.optimized_mir(def_id);
+        let param_env = cx.tcx.param_env(def_id);
+
+        let mut frame_size = Space::Used(0);
+
+        for local in &mir.local_decls {
+            if let Ok(layout) = cx.tcx.layout_of(param_env.and(local.ty)) {
+                frame_size += layout.size.bytes();
+            }
+        }
+
+        if frame_size.exceeds_limit(self.maximum_allowed_size) {
+            span_lint_and_note(
+                cx,
+                LARGE_STACK_FRAMES,
+                span,
+                "this function allocates a large amount of stack space",
+                None,
+                "allocating large amounts of stack space can overflow the stack",
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
index 2f10e3d2581..4e9d77ea156 100644
--- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet;
 use rustc_hir::{Local, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
@@ -25,14 +26,21 @@ declare_clippy_lint! {
 declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]);
 
 impl LateLintPass<'_> for UnderscoreTyped {
-    fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
+    fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
         if_chain! {
             if !in_external_macro(cx.tcx.sess, local.span);
             if let Some(ty) = local.ty; // Ensure that it has a type defined
             if let TyKind::Infer = &ty.kind; // that type is '_'
             if local.span.ctxt() == ty.span.ctxt();
             then {
-                span_lint_and_help(cx,
+                // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized,
+                // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty`
+                if snippet(cx, ty.span, "_").trim() != "_" {
+                    return;
+                }
+
+                span_lint_and_help(
+                    cx,
                     LET_WITH_TYPE_UNDERSCORE,
                     local.span,
                     "variable declared with type underscore",
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 4a23edb58aa..87329ee5e14 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -68,6 +68,7 @@ mod renamed_lints;
 mod allow_attributes;
 mod almost_complete_range;
 mod approx_const;
+mod arc_with_non_send_sync;
 mod as_conversions;
 mod asm_syntax;
 mod assertions_on_constants;
@@ -114,6 +115,7 @@ mod else_if_without_else;
 mod empty_drop;
 mod empty_enum;
 mod empty_structs_with_brackets;
+mod endian_bytes;
 mod entry;
 mod enum_clike;
 mod enum_variants;
@@ -121,6 +123,7 @@ mod equatable_if_let;
 mod escape;
 mod eta_reduction;
 mod excessive_bools;
+mod excessive_nesting;
 mod exhaustive_items;
 mod exit;
 mod explicit_write;
@@ -147,6 +150,7 @@ mod implicit_return;
 mod implicit_saturating_add;
 mod implicit_saturating_sub;
 mod inconsistent_struct_constructor;
+mod incorrect_impls;
 mod index_refutable_slice;
 mod indexing_slicing;
 mod infinite_iter;
@@ -165,6 +169,7 @@ mod large_enum_variant;
 mod large_futures;
 mod large_include_file;
 mod large_stack_arrays;
+mod large_stack_frames;
 mod len_zero;
 mod let_if_seq;
 mod let_underscore;
@@ -183,6 +188,7 @@ mod manual_is_ascii_check;
 mod manual_let_else;
 mod manual_main_separator_str;
 mod manual_non_exhaustive;
+mod manual_range_patterns;
 mod manual_rem_euclid;
 mod manual_retain;
 mod manual_slice_size_calculation;
@@ -191,9 +197,9 @@ mod manual_strip;
 mod map_unit_fn;
 mod match_result_ok;
 mod matches;
-mod mem_forget;
 mod mem_replace;
 mod methods;
+mod min_ident_chars;
 mod minmax;
 mod misc;
 mod misc_early;
@@ -220,6 +226,7 @@ mod needless_borrowed_ref;
 mod needless_continue;
 mod needless_else;
 mod needless_for_each;
+mod needless_if;
 mod needless_late_init;
 mod needless_parens_on_range_literals;
 mod needless_pass_by_value;
@@ -256,6 +263,7 @@ mod pub_use;
 mod question_mark;
 mod question_mark_used;
 mod ranges;
+mod raw_strings;
 mod rc_clone_in_vec_init;
 mod read_zero_byte_vec;
 mod redundant_async_block;
@@ -266,6 +274,7 @@ mod redundant_field_names;
 mod redundant_pub_crate;
 mod redundant_slicing;
 mod redundant_static_lifetimes;
+mod redundant_type_annotations;
 mod ref_option_ref;
 mod ref_patterns;
 mod reference;
@@ -279,8 +288,10 @@ mod semicolon_if_nothing_returned;
 mod serde_api;
 mod shadow;
 mod significant_drop_tightening;
+mod single_call_fn;
 mod single_char_lifetime_names;
 mod single_component_path_imports;
+mod single_range_in_vec_init;
 mod size_of_in_element_count;
 mod size_of_ref;
 mod slow_vector_initialization;
@@ -300,6 +311,7 @@ mod to_digit_is_some;
 mod trailing_empty_array;
 mod trait_bounds;
 mod transmute;
+mod tuple_array_conversions;
 mod types;
 mod undocumented_unsafe_blocks;
 mod unicode;
@@ -327,6 +339,7 @@ mod use_self;
 mod useless_conversion;
 mod vec;
 mod vec_init_then_push;
+mod visibility;
 mod wildcard_imports;
 mod write;
 mod zero_div_zero;
@@ -486,26 +499,27 @@ pub(crate) struct LintInfo {
     explanation: &'static str,
 }
 
-pub fn explain(name: &str) {
+pub fn explain(name: &str) -> i32 {
     let target = format!("clippy::{}", name.to_ascii_uppercase());
-    match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
-        Some(info) => {
-            println!("{}", info.explanation);
-            // Check if the lint has configuration
-            let mdconf = get_configuration_metadata();
-            if let Some(config_vec_positions) = mdconf
-                .iter()
-                .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
-            {
-                // If it has, print it
-                println!("### Configuration for {}:\n", info.lint.name_lower());
-                for position in config_vec_positions {
-                    let conf = &mdconf[position];
-                    println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
-                }
+    if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
+        println!("{}", info.explanation);
+        // Check if the lint has configuration
+        let mdconf = get_configuration_metadata();
+        if let Some(config_vec_positions) = mdconf
+            .iter()
+            .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
+        {
+            // If it has, print it
+            println!("### Configuration for {}:\n", info.lint.name_lower());
+            for position in config_vec_positions {
+                let conf = &mdconf[position];
+                println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
             }
-        },
-        None => println!("unknown lint: {name}"),
+        }
+        0
+    } else {
+        println!("unknown lint: {name}");
+        1
     }
 }
 
@@ -564,6 +578,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         store.register_late_pass(|_| Box::<utils::internal_lints::unnecessary_def_path::UnnecessaryDefPath>::default());
         store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass));
         store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl));
+        store.register_late_pass(|_| {
+            Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new())
+        });
     }
 
     let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
@@ -672,7 +689,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     store.register_late_pass(|_| Box::<shadow::Shadow>::default());
     store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
-    store.register_late_pass(|_| Box::new(loops::Loops));
+    store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv())));
     store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
     store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
     store.register_late_pass(|_| Box::new(entry::HashMapPass));
@@ -693,7 +710,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     let too_large_for_stack = conf.too_large_for_stack;
     store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack }));
-    store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack }));
+    store.register_late_pass(move |_| {
+        Box::new(vec::UselessVec {
+            too_large_for_stack,
+            msrv: msrv(),
+        })
+    });
     store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
     store.register_late_pass(|_| Box::new(strings::StringLitAsBytes));
     store.register_late_pass(|_| Box::new(derive::Derive));
@@ -725,7 +747,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     let missing_docs_in_crate_items = conf.missing_docs_in_crate_items;
     store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
     store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply));
-    store.register_late_pass(|_| Box::new(mem_forget::MemForget));
     store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
     store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
     store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(missing_docs_in_crate_items)));
@@ -751,7 +772,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::<useless_conversion::UselessConversion>::default());
     store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher));
     store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom));
-    store.register_late_pass(|_| Box::new(question_mark::QuestionMark));
+    store.register_late_pass(|_| Box::<question_mark::QuestionMark>::default());
     store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed));
     store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings));
     store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl));
@@ -773,7 +794,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates));
     store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString));
     let max_trait_bounds = conf.max_trait_bounds;
-    store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
+    store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv())));
     store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
     let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
     store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
@@ -785,7 +806,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
     store.register_early_pass(|| Box::new(formatting::Formatting));
     store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints));
-    store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
     store.register_late_pass(|_| Box::new(returns::Return));
@@ -810,10 +830,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     let enum_variant_name_threshold = conf.enum_variant_name_threshold;
+    let allow_private_module_inception = conf.allow_private_module_inception;
     store.register_late_pass(move |_| {
         Box::new(enum_variants::EnumVariantNames::new(
             enum_variant_name_threshold,
             avoid_breaking_exported_api,
+            allow_private_module_inception,
         ))
     });
     store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
@@ -833,7 +855,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
     store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
     store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
-    store.register_early_pass(|| Box::new(as_conversions::AsConversions));
+    store.register_late_pass(|_| Box::new(as_conversions::AsConversions));
     store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
     store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default());
     let max_fn_params_bools = conf.max_fn_params_bools;
@@ -909,7 +931,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             enable_raw_pointer_heuristic_for_send,
         ))
     });
-    store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
+    let accept_comment_above_statement = conf.accept_comment_above_statement;
+    let accept_comment_above_attributes = conf.accept_comment_above_attributes;
+    store.register_late_pass(move |_| {
+        Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(
+            accept_comment_above_statement,
+            accept_comment_above_attributes,
+        ))
+    });
     let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args;
     store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined)));
     store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
@@ -1002,11 +1031,49 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
     store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
     store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
+    let excessive_nesting_threshold = conf.excessive_nesting_threshold;
+    store.register_early_pass(move || {
+        Box::new(excessive_nesting::ExcessiveNesting {
+            excessive_nesting_threshold,
+            nodes: rustc_ast::node_id::NodeSet::new(),
+        })
+    });
     store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
     store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
     store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
     store.register_early_pass(|| Box::new(needless_else::NeedlessElse));
     store.register_late_pass(|_| Box::new(missing_fields_in_debug::MissingFieldsInDebug));
+    store.register_late_pass(|_| Box::new(endian_bytes::EndianBytes));
+    store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations));
+    store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync));
+    store.register_late_pass(|_| Box::new(needless_if::NeedlessIf));
+    let allowed_idents_below_min_chars = conf.allowed_idents_below_min_chars.clone();
+    let min_ident_chars_threshold = conf.min_ident_chars_threshold;
+    store.register_late_pass(move |_| {
+        Box::new(min_ident_chars::MinIdentChars {
+            allowed_idents_below_min_chars: allowed_idents_below_min_chars.clone(),
+            min_ident_chars_threshold,
+        })
+    });
+    let stack_size_threshold = conf.stack_size_threshold;
+    store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold)));
+    store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit));
+    store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls));
+    store.register_late_pass(move |_| {
+        Box::new(single_call_fn::SingleCallFn {
+            avoid_breaking_exported_api,
+            def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(),
+        })
+    });
+    let needless_raw_string_hashes_allow_one = conf.allow_one_hash_in_raw_strings;
+    store.register_early_pass(move || {
+        Box::new(raw_strings::RawStrings {
+            needless_raw_string_hashes_allow_one,
+        })
+    });
+    store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns));
+    store.register_early_pass(|| Box::new(visibility::Visibility));
+    store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() }));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 986ffcad883..852f6736585 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
+use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
@@ -201,7 +202,19 @@ fn check_fn_inner<'tcx>(
         span_lint_and_then(
             cx,
             NEEDLESS_LIFETIMES,
-            span.with_hi(sig.decl.output.span().hi()),
+            elidable_lts
+                .iter()
+                .map(|&lt| cx.tcx.def_span(lt))
+                .chain(usages.iter().filter_map(|usage| {
+                    if let LifetimeName::Param(def_id) = usage.res
+                        && elidable_lts.contains(&def_id)
+                    {
+                        return Some(usage.ident.span);
+                    }
+
+                    None
+                }))
+                .collect_vec(),
             &format!("the following explicit lifetimes could be elided: {lts}"),
             |diag| {
                 if sig.header.is_async() {
@@ -562,7 +575,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
                 // if the bounds define new lifetimes, they are fine to occur
                 let allowed_lts = allowed_lts_from(pred.bound_generic_params);
                 // now walk the bounds
-                for bound in pred.bounds.iter() {
+                for bound in pred.bounds {
                     walk_param_bound(&mut visitor, bound);
                 }
                 // and check that all lifetimes are allowed
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
index 175e2b382e3..93d6b808646 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_into_iter_loop.rs
@@ -5,15 +5,76 @@ use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
+use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_span::symbol::sym;
 
+#[derive(Clone, Copy)]
+enum AdjustKind {
+    None,
+    Borrow,
+    BorrowMut,
+    Reborrow,
+    ReborrowMut,
+}
+impl AdjustKind {
+    fn borrow(mutbl: AutoBorrowMutability) -> Self {
+        match mutbl {
+            AutoBorrowMutability::Not => Self::Borrow,
+            AutoBorrowMutability::Mut { .. } => Self::BorrowMut,
+        }
+    }
+
+    fn reborrow(mutbl: AutoBorrowMutability) -> Self {
+        match mutbl {
+            AutoBorrowMutability::Not => Self::Reborrow,
+            AutoBorrowMutability::Mut { .. } => Self::ReborrowMut,
+        }
+    }
+
+    fn display(self) -> &'static str {
+        match self {
+            Self::None => "",
+            Self::Borrow => "&",
+            Self::BorrowMut => "&mut ",
+            Self::Reborrow => "&*",
+            Self::ReborrowMut => "&mut *",
+        }
+    }
+}
+
 pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>) {
-    let self_ty = cx.typeck_results().expr_ty(self_arg);
-    let self_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg);
-    if !(self_ty == self_ty_adjusted && is_trait_method(cx, call_expr, sym::IntoIterator)) {
+    if !is_trait_method(cx, call_expr, sym::IntoIterator) {
         return;
     }
 
+    let typeck = cx.typeck_results();
+    let self_ty = typeck.expr_ty(self_arg);
+    let adjust = match typeck.expr_adjustments(self_arg) {
+        [] => AdjustKind::None,
+        &[
+            Adjustment {
+                kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                ..
+            },
+        ] => AdjustKind::borrow(mutbl),
+        &[
+            Adjustment {
+                kind: Adjust::Deref(_), ..
+            },
+            Adjustment {
+                kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                target,
+            },
+        ] => {
+            if self_ty == target && matches!(mutbl, AutoBorrowMutability::Not) {
+                AdjustKind::None
+            } else {
+                AdjustKind::reborrow(mutbl)
+            }
+        },
+        _ => return,
+    };
+
     let mut applicability = Applicability::MachineApplicable;
     let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability);
     span_lint_and_sugg(
@@ -23,7 +84,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<
         "it is more concise to loop over containers instead of using explicit \
             iteration methods",
         "to write this more concisely, try",
-        object.to_string(),
+        format!("{}{object}", adjust.display()),
         applicability,
     );
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 151c7f1d5d2..f3347e33077 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -1,75 +1,235 @@
 use super::EXPLICIT_ITER_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_trait_method;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{
+    implements_trait, implements_trait_with_env, is_copy, make_normalized_projection,
+    make_normalized_projection_with_regions, normalize_with_regions,
+};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
+use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut};
 use rustc_span::sym;
 
-pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, method_name: &str) {
-    let should_lint = match method_name {
-        "iter" | "iter_mut" => is_ref_iterable_type(cx, self_arg),
-        "into_iter" if is_trait_method(cx, arg, sym::IntoIterator) => {
-            let receiver_ty = cx.typeck_results().expr_ty(self_arg);
-            let receiver_ty_adjusted = cx.typeck_results().expr_ty_adjusted(self_arg);
-            let ref_receiver_ty = cx.tcx.mk_ref(
-                cx.tcx.lifetimes.re_erased,
-                ty::TypeAndMut {
-                    ty: receiver_ty,
-                    mutbl: Mutability::Not,
-                },
-            );
-            receiver_ty_adjusted == ref_receiver_ty
-        },
-        _ => false,
-    };
-
-    if !should_lint {
+pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, msrv: &Msrv) {
+    let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr) else {
         return;
+    };
+    if let ty::Array(_, count) = *ty.peel_refs().kind() {
+        if !ty.is_ref() {
+            if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) {
+                return;
+            }
+        } else if count
+            .try_eval_target_usize(cx.tcx, cx.param_env)
+            .map_or(true, |x| x > 32)
+            && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN)
+        {
+            return;
+        }
     }
 
     let mut applicability = Applicability::MachineApplicable;
     let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability);
-    let muta = if method_name == "iter_mut" { "mut " } else { "" };
     span_lint_and_sugg(
         cx,
         EXPLICIT_ITER_LOOP,
-        arg.span,
+        call_expr.span,
         "it is more concise to loop over references to containers instead of using explicit \
          iteration methods",
         "to write this more concisely, try",
-        format!("&{muta}{object}"),
+        format!("{}{object}", adjust.display()),
         applicability,
     );
 }
 
-/// Returns `true` if the type of expr is one that provides `IntoIterator` impls
-/// for `&T` and `&mut T`, such as `Vec`.
-#[rustfmt::skip]
-fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    // no walk_ptrs_ty: calling iter() on a reference can make sense because it
-    // will allow further borrows afterwards
-    let ty = cx.typeck_results().expr_ty(e);
-    is_iterable_array(ty, cx) ||
-    is_type_diagnostic_item(cx, ty, sym::Vec) ||
-    is_type_diagnostic_item(cx, ty, sym::LinkedList) ||
-    is_type_diagnostic_item(cx, ty, sym::HashMap) ||
-    is_type_diagnostic_item(cx, ty, sym::HashSet) ||
-    is_type_diagnostic_item(cx, ty, sym::VecDeque) ||
-    is_type_diagnostic_item(cx, ty, sym::BinaryHeap) ||
-    is_type_diagnostic_item(cx, ty, sym::BTreeMap) ||
-    is_type_diagnostic_item(cx, ty, sym::BTreeSet)
+#[derive(Clone, Copy)]
+enum AdjustKind {
+    None,
+    Borrow,
+    BorrowMut,
+    Deref,
+    Reborrow,
+    ReborrowMut,
 }
+impl AdjustKind {
+    fn borrow(mutbl: Mutability) -> Self {
+        match mutbl {
+            Mutability::Not => Self::Borrow,
+            Mutability::Mut => Self::BorrowMut,
+        }
+    }
 
-fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
-    // IntoIterator is currently only implemented for array sizes <= 32 in rustc
-    match ty.kind() {
-        ty::Array(_, n) => n
-            .try_eval_target_usize(cx.tcx, cx.param_env)
-            .map_or(false, |val| (0..=32).contains(&val)),
-        _ => false,
+    fn auto_borrow(mutbl: AutoBorrowMutability) -> Self {
+        match mutbl {
+            AutoBorrowMutability::Not => Self::Borrow,
+            AutoBorrowMutability::Mut { .. } => Self::BorrowMut,
+        }
+    }
+
+    fn reborrow(mutbl: Mutability) -> Self {
+        match mutbl {
+            Mutability::Not => Self::Reborrow,
+            Mutability::Mut => Self::ReborrowMut,
+        }
+    }
+
+    fn auto_reborrow(mutbl: AutoBorrowMutability) -> Self {
+        match mutbl {
+            AutoBorrowMutability::Not => Self::Reborrow,
+            AutoBorrowMutability::Mut { .. } => Self::ReborrowMut,
+        }
+    }
+
+    fn display(self) -> &'static str {
+        match self {
+            Self::None => "",
+            Self::Borrow => "&",
+            Self::BorrowMut => "&mut ",
+            Self::Deref => "*",
+            Self::Reborrow => "&*",
+            Self::ReborrowMut => "&mut *",
+        }
+    }
+}
+
+/// Checks if an `iter` or `iter_mut` call returns `IntoIterator::IntoIter`. Returns how the
+/// argument needs to be adjusted.
+#[expect(clippy::too_many_lines)]
+fn is_ref_iterable<'tcx>(
+    cx: &LateContext<'tcx>,
+    self_arg: &Expr<'_>,
+    call_expr: &Expr<'_>,
+) -> Option<(AdjustKind, Ty<'tcx>)> {
+    let typeck = cx.typeck_results();
+    if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
+        && let Some(fn_id) = typeck.type_dependent_def_id(call_expr.hir_id)
+        && let sig = cx.tcx.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
+        && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
+        && let param_env = cx.tcx.param_env(fn_id)
+        && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, [])
+        && let Some(into_iter_ty) =
+            make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
+        && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)
+        && into_iter_ty == req_res_ty
+    {
+        let adjustments = typeck.expr_adjustments(self_arg);
+        let self_ty = typeck.expr_ty(self_arg);
+        let self_is_copy = is_copy(cx, self_ty);
+
+        if adjustments.is_empty() && self_is_copy {
+            // Exact type match, already checked earlier
+            return Some((AdjustKind::None, self_ty));
+        }
+
+        let res_ty = cx.tcx.erase_regions(EarlyBinder::bind(req_res_ty)
+            .subst(cx.tcx, typeck.node_substs(call_expr.hir_id)));
+        let mutbl = if let ty::Ref(_, _, mutbl) = *req_self_ty.kind() {
+            Some(mutbl)
+        } else {
+            None
+        };
+
+        if !adjustments.is_empty() {
+            if self_is_copy {
+                // Using by value won't consume anything
+                if implements_trait(cx, self_ty, trait_id, &[])
+                    && let Some(ty) =
+                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
+                    && ty == res_ty
+                {
+                    return Some((AdjustKind::None, self_ty));
+                }
+            } else if let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
+                && let Some(mutbl) = mutbl
+            {
+                // Attempt to reborrow the mutable reference
+                let self_ty = if mutbl.is_mut() {
+                    self_ty
+                } else {
+                    cx.tcx.mk_ref(region, TypeAndMut { ty, mutbl })
+                };
+                if implements_trait(cx, self_ty, trait_id, &[])
+                    && let Some(ty) =
+                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
+                    && ty == res_ty
+                {
+                    return Some((AdjustKind::reborrow(mutbl), self_ty));
+                }
+            }
+        }
+        if let Some(mutbl) = mutbl
+            && !self_ty.is_ref()
+        {
+            // Attempt to borrow
+            let self_ty = cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, TypeAndMut {
+                ty: self_ty,
+                mutbl,
+            });
+            if implements_trait(cx, self_ty, trait_id, &[])
+                && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
+                && ty == res_ty
+            {
+                return Some((AdjustKind::borrow(mutbl), self_ty));
+            }
+        }
+
+        match adjustments {
+            [] => Some((AdjustKind::None, self_ty)),
+            &[
+                Adjustment { kind: Adjust::Deref(_), ..},
+                Adjustment {
+                    kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                    target,
+                },
+                ..
+            ] => {
+                if target != self_ty
+                    && implements_trait(cx, target, trait_id, &[])
+                    && let Some(ty) =
+                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
+                    && ty == res_ty
+                {
+                    Some((AdjustKind::auto_reborrow(mutbl), target))
+                } else {
+                    None
+                }
+            }
+            &[Adjustment { kind: Adjust::Deref(_), target }, ..] => {
+                if is_copy(cx, target)
+                    && implements_trait(cx, target, trait_id, &[])
+                    && let Some(ty) =
+                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
+                    && ty == res_ty
+                {
+                    Some((AdjustKind::Deref, target))
+                } else {
+                    None
+                }
+            }
+            &[
+                Adjustment {
+                    kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
+                    target,
+                },
+                ..
+            ] => {
+                if self_ty.is_ref()
+                    && implements_trait(cx, target, trait_id, &[])
+                    && let Some(ty) =
+                        make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
+                    && ty == res_ty
+                {
+                    Some((AdjustKind::auto_borrow(mutbl), target))
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    } else {
+        None
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index d4c3f76b864..7d1f8ef29c8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -51,7 +51,7 @@ pub(super) fn check<'tcx>(
                 iter_b = Some(get_assignment(body));
             }
 
-            let assignments = iter_a.into_iter().flatten().chain(iter_b.into_iter());
+            let assignments = iter_a.into_iter().flatten().chain(iter_b);
 
             let big_sugg = assignments
                 // The only statements in the for loops can be indexed assignments from
@@ -402,7 +402,7 @@ fn get_assignments<'a, 'tcx>(
             StmtKind::Local(..) | StmtKind::Item(..) => None,
             StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e),
         })
-        .chain((*expr).into_iter())
+        .chain(*expr)
         .filter(move |e| {
             if let ExprKind::AssignOp(_, place, _) = e.kind {
                 path_to_local(place).map_or(false, |id| {
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index f83ad388a74..529189b52ac 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -20,9 +20,10 @@ mod while_let_loop;
 mod while_let_on_iterator;
 
 use clippy_utils::higher;
+use clippy_utils::msrvs::Msrv;
 use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor};
 
@@ -479,7 +480,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Check for unnecessary `if let` usage in a for loop
+    /// Checks for unnecessary `if let` usage in a for loop
     /// where only the `Some` or `Ok` variant of the iterator element is used.
     ///
     /// ### Why is this bad?
@@ -511,7 +512,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Check for empty spin loops
+    /// Checks for empty spin loops
     ///
     /// ### Why is this bad?
     /// The loop body should have something like `thread::park()` or at least
@@ -547,7 +548,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Check for manual implementations of Iterator::find
+    /// Checks for manual implementations of Iterator::find
     ///
     /// ### Why is this bad?
     /// It doesn't affect performance, but using `find` is shorter and easier to read.
@@ -606,7 +607,15 @@ declare_clippy_lint! {
     "checking for emptiness of a `Vec` in the loop condition and popping an element in the body"
 }
 
-declare_lint_pass!(Loops => [
+pub struct Loops {
+    msrv: Msrv,
+}
+impl Loops {
+    pub fn new(msrv: Msrv) -> Self {
+        Self { msrv }
+    }
+}
+impl_lint_pass!(Loops => [
     MANUAL_MEMCPY,
     MANUAL_FLATTEN,
     NEEDLESS_RANGE_LOOP,
@@ -645,7 +654,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
             if body.span.from_expansion() {
                 return;
             }
-            check_for_loop(cx, pat, arg, body, expr, span);
+            self.check_for_loop(cx, pat, arg, body, expr, span);
             if let ExprKind::Block(block, _) = body.kind {
                 never_loop::check(cx, block, loop_id, span, for_loop.as_ref());
             }
@@ -678,46 +687,48 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
             manual_while_let_some::check(cx, condition, body, span);
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
-fn check_for_loop<'tcx>(
-    cx: &LateContext<'tcx>,
-    pat: &'tcx Pat<'_>,
-    arg: &'tcx Expr<'_>,
-    body: &'tcx Expr<'_>,
-    expr: &'tcx Expr<'_>,
-    span: Span,
-) {
-    let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr);
-    if !is_manual_memcpy_triggered {
-        needless_range_loop::check(cx, pat, arg, body, expr);
-        explicit_counter_loop::check(cx, pat, arg, body, expr);
+impl Loops {
+    fn check_for_loop<'tcx>(
+        &self,
+        cx: &LateContext<'tcx>,
+        pat: &'tcx Pat<'_>,
+        arg: &'tcx Expr<'_>,
+        body: &'tcx Expr<'_>,
+        expr: &'tcx Expr<'_>,
+        span: Span,
+    ) {
+        let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr);
+        if !is_manual_memcpy_triggered {
+            needless_range_loop::check(cx, pat, arg, body, expr);
+            explicit_counter_loop::check(cx, pat, arg, body, expr);
+        }
+        self.check_for_loop_arg(cx, pat, arg);
+        for_kv_map::check(cx, pat, arg, body);
+        mut_range_bound::check(cx, arg, body);
+        single_element_loop::check(cx, pat, arg, body, expr);
+        same_item_push::check(cx, pat, arg, body, expr);
+        manual_flatten::check(cx, pat, arg, body, span);
+        manual_find::check(cx, pat, arg, body, span, expr);
     }
-    check_for_loop_arg(cx, pat, arg);
-    for_kv_map::check(cx, pat, arg, body);
-    mut_range_bound::check(cx, arg, body);
-    single_element_loop::check(cx, pat, arg, body, expr);
-    same_item_push::check(cx, pat, arg, body, expr);
-    manual_flatten::check(cx, pat, arg, body, span);
-    manual_find::check(cx, pat, arg, body, span, expr);
-}
 
-fn check_for_loop_arg(cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) {
-    if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
-        let method_name = method.ident.as_str();
-        // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
-        match method_name {
-            "iter" | "iter_mut" => {
-                explicit_iter_loop::check(cx, self_arg, arg, method_name);
-            },
-            "into_iter" => {
-                explicit_iter_loop::check(cx, self_arg, arg, method_name);
-                explicit_into_iter_loop::check(cx, self_arg, arg);
-            },
-            "next" => {
-                iter_next_loop::check(cx, arg);
-            },
-            _ => {},
+    fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) {
+        if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
+            match method.ident.as_str() {
+                "iter" | "iter_mut" => {
+                    explicit_iter_loop::check(cx, self_arg, arg, &self.msrv);
+                },
+                "into_iter" => {
+                    explicit_into_iter_loop::check(cx, self_arg, arg);
+                },
+                "next" => {
+                    iter_next_loop::check(cx, arg);
+                },
+                _ => {},
+            }
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 10b5e1edf92..ee338c6beb0 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -1,22 +1,23 @@
 use super::utils::make_iterator_snippet;
 use super::NEVER_LOOP;
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::consts::constant;
 use clippy_utils::higher::ForLoop;
 use clippy_utils::source::snippet;
+use clippy_utils::{consts::Constant, diagnostics::span_lint_and_then};
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 use std::iter::{once, Iterator};
 
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    block: &Block<'_>,
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    block: &Block<'tcx>,
     loop_id: HirId,
     span: Span,
     for_loop: Option<&ForLoop<'_>>,
 ) {
-    match never_loop_block(block, &mut Vec::new(), loop_id) {
+    match never_loop_block(cx, block, &mut Vec::new(), loop_id) {
         NeverLoopResult::AlwaysBreak => {
             span_lint_and_then(cx, NEVER_LOOP, span, "this loop never actually loops", |diag| {
                 if let Some(ForLoop {
@@ -95,7 +96,12 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult, ignore_ids: &[HirI
     }
 }
 
-fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
+fn never_loop_block<'tcx>(
+    cx: &LateContext<'tcx>,
+    block: &Block<'tcx>,
+    ignore_ids: &mut Vec<HirId>,
+    main_loop_id: HirId,
+) -> NeverLoopResult {
     let iter = block
         .stmts
         .iter()
@@ -103,10 +109,10 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id
         .chain(block.expr.map(|expr| (expr, None)));
 
     iter.map(|(e, els)| {
-        let e = never_loop_expr(e, ignore_ids, main_loop_id);
+        let e = never_loop_expr(cx, e, ignore_ids, main_loop_id);
         // els is an else block in a let...else binding
         els.map_or(e, |els| {
-            combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id), ignore_ids)
+            combine_branches(e, never_loop_block(cx, els, ignore_ids, main_loop_id), ignore_ids)
         })
     })
     .fold(NeverLoopResult::Otherwise, combine_seq)
@@ -122,7 +128,12 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t
 }
 
 #[allow(clippy::too_many_lines)]
-fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
+fn never_loop_expr<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'tcx>,
+    ignore_ids: &mut Vec<HirId>,
+    main_loop_id: HirId,
+) -> NeverLoopResult {
     match expr.kind {
         ExprKind::Unary(_, e)
         | ExprKind::Cast(e, _)
@@ -130,45 +141,51 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
         | ExprKind::Field(e, _)
         | ExprKind::AddrOf(_, _, e)
         | ExprKind::Repeat(e, _)
-        | ExprKind::DropTemps(e) => never_loop_expr(e, ignore_ids, main_loop_id),
-        ExprKind::Let(let_expr) => never_loop_expr(let_expr.init, ignore_ids, main_loop_id),
-        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(&mut es.iter(), ignore_ids, main_loop_id),
+        | ExprKind::DropTemps(e) => never_loop_expr(cx, e, ignore_ids, main_loop_id),
+        ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, ignore_ids, main_loop_id),
+        ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, &mut es.iter(), ignore_ids, main_loop_id),
         ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all(
+            cx,
             &mut std::iter::once(receiver).chain(es.iter()),
             ignore_ids,
             main_loop_id,
         ),
         ExprKind::Struct(_, fields, base) => {
-            let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id);
+            let fields = never_loop_expr_all(cx, &mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id);
             if let Some(base) = base {
-                combine_seq(fields, never_loop_expr(base, ignore_ids, main_loop_id))
+                combine_seq(fields, never_loop_expr(cx, base, ignore_ids, main_loop_id))
             } else {
                 fields
             }
         },
-        ExprKind::Call(e, es) => never_loop_expr_all(&mut once(e).chain(es.iter()), ignore_ids, main_loop_id),
+        ExprKind::Call(e, es) => never_loop_expr_all(cx, &mut once(e).chain(es.iter()), ignore_ids, main_loop_id),
         ExprKind::Binary(_, e1, e2)
         | ExprKind::Assign(e1, e2, _)
         | ExprKind::AssignOp(_, e1, e2)
-        | ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), ignore_ids, main_loop_id),
+        | ExprKind::Index(e1, e2) => never_loop_expr_all(cx, &mut [e1, e2].iter().copied(), ignore_ids, main_loop_id),
         ExprKind::Loop(b, _, _, _) => {
             // Break can come from the inner loop so remove them.
-            absorb_break(never_loop_block(b, ignore_ids, main_loop_id))
+            absorb_break(never_loop_block(cx, b, ignore_ids, main_loop_id))
         },
         ExprKind::If(e, e2, e3) => {
-            let e1 = never_loop_expr(e, ignore_ids, main_loop_id);
-            let e2 = never_loop_expr(e2, ignore_ids, main_loop_id);
+            let e1 = never_loop_expr(cx, e, ignore_ids, main_loop_id);
+            let e2 = never_loop_expr(cx, e2, ignore_ids, main_loop_id);
+            // If we know the `if` condition evaluates to `true`, don't check everything past it; it
+            // should just return whatever's evaluated for `e1` and `e2` since `e3` is unreachable
+            if let Some(Constant::Bool(true)) = constant(cx, cx.typeck_results(), e) {
+                return combine_seq(e1, e2);
+            }
             let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| {
-                never_loop_expr(e, ignore_ids, main_loop_id)
+                never_loop_expr(cx, e, ignore_ids, main_loop_id)
             });
             combine_seq(e1, combine_branches(e2, e3, ignore_ids))
         },
         ExprKind::Match(e, arms, _) => {
-            let e = never_loop_expr(e, ignore_ids, main_loop_id);
+            let e = never_loop_expr(cx, e, ignore_ids, main_loop_id);
             if arms.is_empty() {
                 e
             } else {
-                let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id);
+                let arms = never_loop_expr_branch(cx, &mut arms.iter().map(|a| a.body), ignore_ids, main_loop_id);
                 combine_seq(e, arms)
             }
         },
@@ -176,7 +193,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
             if l.is_some() {
                 ignore_ids.push(b.hir_id);
             }
-            let ret = never_loop_block(b, ignore_ids, main_loop_id);
+            let ret = never_loop_block(cx, b, ignore_ids, main_loop_id);
             if l.is_some() {
                 ignore_ids.pop();
             }
@@ -198,31 +215,30 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
         // checks if break targets a block instead of a loop
         ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e
             .map_or(NeverLoopResult::IgnoreUntilEnd(t), |e| {
-                never_loop_expr(e, ignore_ids, main_loop_id)
+                never_loop_expr(cx, e, ignore_ids, main_loop_id)
             }),
         ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| {
             combine_seq(
-                never_loop_expr(e, ignore_ids, main_loop_id),
+                never_loop_expr(cx, e, ignore_ids, main_loop_id),
                 NeverLoopResult::AlwaysBreak,
             )
         }),
-        ExprKind::Become(e) => {
-            combine_seq(
-                never_loop_expr(e, ignore_ids, main_loop_id),
-                NeverLoopResult::AlwaysBreak,
-            )
-        }
+        ExprKind::Become(e) => combine_seq(
+            never_loop_expr(cx, e, ignore_ids, main_loop_id),
+            NeverLoopResult::AlwaysBreak,
+        ),
         ExprKind::InlineAsm(asm) => asm
             .operands
             .iter()
             .map(|(o, _)| match o {
                 InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
-                    never_loop_expr(expr, ignore_ids, main_loop_id)
+                    never_loop_expr(cx, expr, ignore_ids, main_loop_id)
                 },
                 InlineAsmOperand::Out { expr, .. } => {
-                    never_loop_expr_all(&mut expr.iter().copied(), ignore_ids, main_loop_id)
+                    never_loop_expr_all(cx, &mut expr.iter().copied(), ignore_ids, main_loop_id)
                 },
                 InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => never_loop_expr_all(
+                    cx,
                     &mut once(*in_expr).chain(out_expr.iter().copied()),
                     ignore_ids,
                     main_loop_id,
@@ -242,22 +258,24 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
     }
 }
 
-fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(
+fn never_loop_expr_all<'tcx, T: Iterator<Item = &'tcx Expr<'tcx>>>(
+    cx: &LateContext<'tcx>,
     es: &mut T,
     ignore_ids: &mut Vec<HirId>,
     main_loop_id: HirId,
 ) -> NeverLoopResult {
-    es.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
+    es.map(|e| never_loop_expr(cx, e, ignore_ids, main_loop_id))
         .fold(NeverLoopResult::Otherwise, combine_seq)
 }
 
-fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
+fn never_loop_expr_branch<'tcx, T: Iterator<Item = &'tcx Expr<'tcx>>>(
+    cx: &LateContext<'tcx>,
     e: &mut T,
     ignore_ids: &mut Vec<HirId>,
     main_loop_id: HirId,
 ) -> NeverLoopResult {
     e.fold(NeverLoopResult::AlwaysBreak, |a, b| {
-        combine_branches(a, never_loop_expr(b, ignore_ids, main_loop_id), ignore_ids)
+        combine_branches(a, never_loop_expr(cx, b, ignore_ids, main_loop_id), ignore_ids)
     })
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index 9d9341559ac..f7b3b2358a0 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -148,7 +148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
     }
 
     fn visit_block(&mut self, b: &'tcx Block<'_>) {
-        for stmt in b.stmts.iter() {
+        for stmt in b.stmts {
             self.visit_stmt(stmt);
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index e2e6a87a301..8e322a97907 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
             });
             if !id.is_local();
             then {
-                for kid in cx.tcx.module_children(id).iter() {
+                for kid in cx.tcx.module_children(id) {
                     if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
                         let span = mac_attr.span;
                         let def_path = cx.tcx.def_path_str(mac_id);
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 389b0a4a62d..59e421c1622 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -6,17 +6,18 @@ use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::{Descend, Visitable};
 use if_chain::if_chain;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use serde::Deserialize;
 use std::ops::ControlFlow;
+use std::slice;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -81,11 +82,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
         {
             match if_let_or_match {
                 IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
-                    if expr_is_simple_identity(let_pat, if_then);
+                    if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then);
                     if let Some(if_else) = if_else;
                     if expr_diverges(cx, if_else);
                     then {
-                        emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
+                        emit_manual_let_else(cx, stmt.span, if_let_expr, &ident_map, let_pat, if_else);
                     }
                 },
                 IfLetOrMatch::Match(match_expr, arms, source) => {
@@ -118,11 +119,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                         return;
                     }
                     let pat_arm = &arms[1 - idx];
-                    if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) {
-                        return;
-                    }
+                    let Some(ident_map) = expr_simple_identity_map(local.pat, pat_arm.pat, pat_arm.body) else {
+                        return
+                    };
 
-                    emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
+                    emit_manual_let_else(cx, stmt.span, match_expr, &ident_map, pat_arm.pat, diverging_arm.body);
                 },
             }
         };
@@ -135,7 +136,7 @@ fn emit_manual_let_else(
     cx: &LateContext<'_>,
     span: Span,
     expr: &Expr<'_>,
-    local: &Pat<'_>,
+    ident_map: &FxHashMap<Symbol, &Pat<'_>>,
     pat: &Pat<'_>,
     else_body: &Expr<'_>,
 ) {
@@ -146,8 +147,8 @@ fn emit_manual_let_else(
         "this could be rewritten as `let...else`",
         |diag| {
             // This is far from perfect, for example there needs to be:
-            // * tracking for multi-binding cases: let (foo, bar) = if let (Some(foo), Ok(bar)) = ...
-            // * renamings of the bindings for many `PatKind`s like structs, slices, etc.
+            // * renamings of the bindings for many `PatKind`s like slices, etc.
+            // * limitations in the existing replacement algorithms
             // * unused binding collision detection with existing ones
             // for this to be machine applicable.
             let mut app = Applicability::HasPlaceholders;
@@ -159,57 +160,126 @@ fn emit_manual_let_else(
             } else {
                 format!("{{ {sn_else} }}")
             };
-            let sn_bl = replace_in_pattern(cx, span, local, pat, &mut app);
+            let sn_bl = replace_in_pattern(cx, span, ident_map, pat, &mut app, true);
             let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
             diag.span_suggestion(span, "consider writing", sugg, app);
         },
     );
 }
 
-// replaces the locals in the pattern
+/// Replaces the locals in the pattern
+///
+/// For this example:
+///
+/// ```ignore
+/// let (a, FooBar { b, c }) = if let Bar { Some(a_i), b_i } = ex { (a_i, b_i) } else { return };
+/// ```
+///
+/// We have:
+///
+/// ```ignore
+/// pat: Bar { Some(a_i), b_i }
+/// ident_map: (a_i) -> (a), (b_i) -> (FooBar { b, c })
+/// ```
+///
+/// We return:
+///
+/// ```ignore
+/// Bar { Some(a), b_i: FooBar { b, c } }
+/// ```
 fn replace_in_pattern(
     cx: &LateContext<'_>,
     span: Span,
-    local: &Pat<'_>,
+    ident_map: &FxHashMap<Symbol, &Pat<'_>>,
     pat: &Pat<'_>,
     app: &mut Applicability,
+    top_level: bool,
 ) -> String {
-    let mut bindings_count = 0;
-    pat.each_binding_or_first(&mut |_, _, _, _| bindings_count += 1);
-    // If the pattern creates multiple bindings, exit early,
-    // as otherwise we might paste the pattern to the positions of multiple bindings.
-    if bindings_count > 1 {
-        let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app);
-        return sn_pat.into_owned();
-    }
+    // We put a labeled block here so that we can implement the fallback in this function.
+    // As the function has multiple call sites, implementing the fallback via an Option<T>
+    // return type and unwrap_or_else would cause repetition. Similarly, the function also
+    // invokes the fall back multiple times.
+    'a: {
+        // If the ident map is empty, there is no replacement to do.
+        // The code following this if assumes a non-empty ident_map.
+        if ident_map.is_empty() {
+            break 'a;
+        }
 
-    match pat.kind {
-        PatKind::Binding(..) => {
-            let (sn_bdg, _) = snippet_with_context(cx, local.span, span.ctxt(), "", app);
-            return sn_bdg.to_string();
-        },
-        PatKind::Or(pats) => {
-            let patterns = pats
-                .iter()
-                .map(|pat| replace_in_pattern(cx, span, local, pat, app))
-                .collect::<Vec<_>>();
-            let or_pat = patterns.join(" | ");
-            return format!("({or_pat})");
-        },
-        // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
-        PatKind::TupleStruct(ref w, args, dot_dot_pos) => {
-            let mut args = args
-                .iter()
-                .map(|pat| replace_in_pattern(cx, span, local, pat, app))
-                .collect::<Vec<_>>();
-            if let Some(pos) = dot_dot_pos.as_opt_usize() {
-                args.insert(pos, "..".to_owned());
-            }
-            let args = args.join(", ");
-            let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
-            return format!("{sn_wrapper}({args})");
-        },
-        _ => {},
+        match pat.kind {
+            PatKind::Binding(_ann, _id, binding_name, opt_subpt) => {
+                let Some(pat_to_put) = ident_map.get(&binding_name.name) else { break 'a };
+                let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app);
+                if let Some(subpt) = opt_subpt {
+                    let subpt = replace_in_pattern(cx, span, ident_map, subpt, app, false);
+                    return format!("{sn_ptp} @ {subpt}");
+                }
+                return sn_ptp.to_string();
+            },
+            PatKind::Or(pats) => {
+                let patterns = pats
+                    .iter()
+                    .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false))
+                    .collect::<Vec<_>>();
+                let or_pat = patterns.join(" | ");
+                if top_level {
+                    return format!("({or_pat})");
+                }
+                return or_pat;
+            },
+            PatKind::Struct(path, fields, has_dot_dot) => {
+                let fields = fields
+                    .iter()
+                    .map(|fld| {
+                        if let PatKind::Binding(_, _, name, None) = fld.pat.kind &&
+                            let Some(pat_to_put) = ident_map.get(&name.name)
+                        {
+                            let (sn_fld_name, _) = snippet_with_context(cx, fld.ident.span, span.ctxt(), "", app);
+                            let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app);
+                            // TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is
+                            // a PatKind::Binding but that is also hard to get right.
+                            if sn_fld_name == sn_ptp {
+                                // Field init shorthand
+                                return format!("{sn_fld_name}");
+                            }
+                            return format!("{sn_fld_name}: {sn_ptp}");
+                        }
+                        let (sn_fld, _) = snippet_with_context(cx, fld.span, span.ctxt(), "", app);
+                        sn_fld.into_owned()
+                    })
+                    .collect::<Vec<_>>();
+                let fields_string = fields.join(", ");
+
+                let dot_dot_str = if has_dot_dot { " .." } else { "" };
+                let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app);
+                return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}");
+            },
+            // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
+            PatKind::TupleStruct(ref w, args, dot_dot_pos) => {
+                let mut args = args
+                    .iter()
+                    .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false))
+                    .collect::<Vec<_>>();
+                if let Some(pos) = dot_dot_pos.as_opt_usize() {
+                    args.insert(pos, "..".to_owned());
+                }
+                let args = args.join(", ");
+                let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
+                return format!("{sn_wrapper}({args})");
+            },
+            PatKind::Tuple(args, dot_dot_pos) => {
+                let mut args = args
+                    .iter()
+                    .map(|pat| replace_in_pattern(cx, span, ident_map, pat, app, false))
+                    .collect::<Vec<_>>();
+                if let Some(pos) = dot_dot_pos.as_opt_usize() {
+                    args.insert(pos, "..".to_owned());
+                }
+                let args = args.join(", ");
+                return format!("({args})");
+            },
+            _ => {},
+        }
     }
     let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", app);
     sn_pat.into_owned()
@@ -353,37 +423,74 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: boo
     !has_disallowed
 }
 
-/// Checks if the passed block is a simple identity referring to bindings created by the pattern
-fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool {
-    // We support patterns with multiple bindings and tuples, like:
-    //   let ... = if let (Some(foo), bar) = g() { (foo, bar) } else { ... }
+/// Checks if the passed block is a simple identity referring to bindings created by the pattern,
+/// and if yes, returns a mapping between the relevant sub-pattern and the identifier it corresponds
+/// to.
+///
+/// We support patterns with multiple bindings and tuples, e.g.:
+///
+/// ```ignore
+/// let (foo_o, bar_o) = if let (Some(foo), bar) = g() { (foo, bar) } else { ... }
+/// ```
+///
+/// The expected params would be:
+///
+/// ```ignore
+/// local_pat: (foo_o, bar_o)
+/// let_pat: (Some(foo), bar)
+/// expr: (foo, bar)
+/// ```
+///
+/// We build internal `sub_pats` so that it looks like `[foo_o, bar_o]` and `paths` so that it looks
+/// like `[foo, bar]`. Then we turn that into `FxHashMap [(foo) -> (foo_o), (bar) -> (bar_o)]` which
+/// we return.
+fn expr_simple_identity_map<'a, 'hir>(
+    local_pat: &'a Pat<'hir>,
+    let_pat: &'_ Pat<'hir>,
+    expr: &'_ Expr<'hir>,
+) -> Option<FxHashMap<Symbol, &'a Pat<'hir>>> {
     let peeled = peel_blocks(expr);
-    let paths = match peeled.kind {
-        ExprKind::Tup(exprs) | ExprKind::Array(exprs) => exprs,
-        ExprKind::Path(_) => std::slice::from_ref(peeled),
-        _ => return false,
+    let (sub_pats, paths) = match (local_pat.kind, peeled.kind) {
+        (PatKind::Tuple(pats, _), ExprKind::Tup(exprs)) | (PatKind::Slice(pats, ..), ExprKind::Array(exprs)) => {
+            (pats, exprs)
+        },
+        (_, ExprKind::Path(_)) => (slice::from_ref(local_pat), slice::from_ref(peeled)),
+        _ => return None,
     };
+
+    // There is some length mismatch, which indicates usage of .. in the patterns above e.g.:
+    // let (a, ..) = if let [a, b, _c] = ex { (a, b) } else { ... };
+    // We bail in these cases as they should be rare.
+    if paths.len() != sub_pats.len() {
+        return None;
+    }
+
     let mut pat_bindings = FxHashSet::default();
-    pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| {
+    let_pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| {
         pat_bindings.insert(ident);
     });
     if pat_bindings.len() < paths.len() {
-        return false;
+        // This rebinds some bindings from the outer scope, or it repeats some copy-able bindings multiple
+        // times. We don't support these cases so we bail here. E.g.:
+        // let foo = 0;
+        // let (new_foo, bar, bar_copied) = if let Some(bar) = Some(0) { (foo, bar, bar) } else { .. };
+        return None;
     }
-    for path in paths {
-        if_chain! {
-            if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind;
-            if let [path_seg] = path.segments;
-            then {
-                if !pat_bindings.remove(&path_seg.ident) {
-                    return false;
-                }
-            } else {
-                return false;
+    let mut ident_map = FxHashMap::default();
+    for (sub_pat, path) in sub_pats.iter().zip(paths.iter()) {
+        if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind &&
+            let [path_seg] = path.segments
+        {
+            let ident = path_seg.ident;
+            if !pat_bindings.remove(&ident) {
+                return None;
             }
+            ident_map.insert(ident.name, sub_pat);
+        } else {
+            return None;
         }
     }
-    true
+    Some(ident_map)
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)]
diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
new file mode 100644
index 00000000000..65ff555209a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
@@ -0,0 +1,123 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::LitKind;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_hir::ExprKind;
+use rustc_hir::PatKind;
+use rustc_hir::RangeEnd;
+use rustc_lint::LintContext;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Looks for combined OR patterns that are all contained in a specific range,
+    /// e.g. `6 | 4 | 5 | 9 | 7 | 8` can be rewritten as `4..=9`.
+    ///
+    /// ### Why is this bad?
+    /// Using an explicit range is more concise and easier to read.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let x = 6;
+    /// let foo = matches!(x, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let x = 6;
+    /// let foo = matches!(x, 1..=10);
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub MANUAL_RANGE_PATTERNS,
+    complexity,
+    "manually writing range patterns using a combined OR pattern (`|`)"
+}
+declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
+
+fn expr_as_u128(expr: &Expr<'_>) -> Option<u128> {
+    if let ExprKind::Lit(lit) = expr.kind
+        && let LitKind::Int(num, _) = lit.node
+    {
+        Some(num)
+    } else {
+        None
+    }
+}
+
+impl LateLintPass<'_> for ManualRangePatterns {
+    fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) {
+        if in_external_macro(cx.sess(), pat.span) {
+            return;
+        }
+
+        // a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives
+        if let PatKind::Or(pats) = pat.kind
+            && pats.len() >= 3
+        {
+            let mut min = u128::MAX;
+            let mut max = 0;
+            let mut numbers_found = FxHashSet::default();
+            let mut ranges_found = Vec::new();
+
+            for pat in pats {
+                if let PatKind::Lit(lit) = pat.kind
+                    && let Some(num) = expr_as_u128(lit)
+                {
+                    numbers_found.insert(num);
+
+                    min = min.min(num);
+                    max = max.max(num);
+                } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind
+                    && let Some(left) = expr_as_u128(left)
+                    && let Some(right) = expr_as_u128(right)
+                    && right >= left
+                {
+                    min = min.min(left);
+                    max = max.max(right);
+                    ranges_found.push(left..=match end {
+                        RangeEnd::Included => right,
+                        RangeEnd::Excluded => right - 1,
+                    });
+                } else {
+                    return;
+                }
+            }
+
+            let contains_whole_range = 'contains: {
+                let mut num = min;
+                while num <= max {
+                    if numbers_found.contains(&num) {
+                        num += 1;
+                    }
+                    // Given a list of (potentially overlapping) ranges like:
+                    // 1..=5, 3..=7, 6..=10
+                    // We want to find the range with the highest end that still contains the current number
+                    else if let Some(range) = ranges_found
+                        .iter()
+                        .filter(|range| range.contains(&num))
+                        .max_by_key(|range| range.end())
+                    {
+                        num = range.end() + 1;
+                    } else {
+                        break 'contains false;
+                    }
+                }
+                break 'contains true;
+            };
+
+            if contains_whole_range {
+                span_lint_and_sugg(
+                    cx,
+                    MANUAL_RANGE_PATTERNS,
+                    pat.span,
+                    "this OR pattern can be rewritten using a range",
+                    "try",
+                    format!("{min}..={max}"),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
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 ae8262ace96..3d2fbea63f5 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,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{path_to_local, search_same, SpanlessEq, SpanlessHash};
+use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash};
 use core::cmp::Ordering;
 use core::iter;
 use core::slice;
@@ -9,6 +9,7 @@ use rustc_ast::ast::LitKind;
 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_middle::ty;
 use rustc_span::Symbol;
@@ -103,17 +104,21 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
     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) {
-            span_lint_and_then(
-                cx,
-                MATCH_SAME_ARMS,
-                arm1.span,
-                "this match arm has an identical body to the `_` wildcard arm",
-                |diag| {
-                    diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect)
-                        .help("or try changing either arm body")
-                        .span_note(arm2.span, "`_` wildcard arm here");
-                },
-            );
+            if !cx.tcx.features().non_exhaustive_omitted_patterns_lint
+                || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id)
+            {
+                span_lint_and_then(
+                    cx,
+                    MATCH_SAME_ARMS,
+                    arm1.span,
+                    "this match arm has an identical body to the `_` wildcard arm",
+                    |diag| {
+                        diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect)
+                            .help("or try changing either arm body")
+                            .span_note(arm2.span, "`_` wildcard arm here");
+                    },
+                );
+            }
         } else {
             let back_block = backwards_blocking_idxs[j];
             let (keep_arm, move_arm) = if back_block < i || (back_block == 0 && forwards_blocking_idxs[i] <= j) {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index 6424ac31d9f..de911f7a028 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -25,7 +25,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
                     let mut ident_bind_name = kw::Underscore;
                     if !matching_wild {
                         // Looking for unused bindings (i.e.: `_e`)
-                        for pat in inner.iter() {
+                        for pat in inner {
                             if let PatKind::Binding(_, id, ident, None) = pat.kind {
                                 if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) {
                                     ident_bind_name = ident.name;
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 0d91051632a..00fa3eb9bfe 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -38,6 +38,11 @@ declare_clippy_lint! {
     /// Checks for matches with a single arm where an `if let`
     /// will usually suffice.
     ///
+    /// This intentionally does not lint if there are comments
+    /// inside of the other arm, so as to allow the user to document
+    /// why having another explicit pattern with an empty body is necessary,
+    /// or because the comments need to be preserved for other reasons.
+    ///
     /// ### Why is this bad?
     /// Just readability – `if let` nests less than a `match`.
     ///
@@ -559,6 +564,9 @@ declare_clippy_lint! {
     /// ### What it does
     /// Checks for `match` with identical arm bodies.
     ///
+    /// Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is
+    /// enabled and disallowed.
+    ///
     /// ### Why is this bad?
     /// This is probably a copy & paste error. If arm bodies
     /// are the same on purpose, you can factor them
@@ -777,7 +785,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Check for temporaries returned from function calls in a match scrutinee that have the
+    /// Checks for temporaries returned from function calls in a match scrutinee that have the
     /// `clippy::has_significant_drop` attribute.
     ///
     /// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index abf2525a61c..8be3c178a29 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -41,7 +41,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                                 cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
                                 ty,
                             );
-                            miri_to_const(cx.tcx, min_constant)?
+                            miri_to_const(cx, min_constant)?
                         },
                     };
                     let rhs_const = match rhs {
@@ -52,7 +52,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                                 cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
                                 ty,
                             );
-                            miri_to_const(cx.tcx, max_constant)?
+                            miri_to_const(cx, max_constant)?
                         },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
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 93ef07d36ae..37528d9f7f2 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
@@ -140,7 +140,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
                     }
                 }
 
-                for generic_arg in b.iter() {
+                for generic_arg in *b {
                     if let GenericArgKind::Type(ty) = generic_arg.unpack() {
                         if self.has_sig_drop_attr(cx, ty) {
                             return true;
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index ad47c13896c..35627d6c649 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{expr_block, snippet};
+use clippy_utils::source::{expr_block, get_source_text, snippet};
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
 use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs};
 use core::cmp::max;
@@ -7,10 +7,26 @@ use rustc_errors::Applicability;
 use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::sym;
+use rustc_span::{sym, Span};
 
 use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
 
+/// Checks if there are comments contained within a span.
+/// This is a very "naive" check, as it just looks for the literal characters // and /* in the
+/// source text. This won't be accurate if there are potentially expressions contained within the
+/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
+/// match arms.
+fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
+    if let Some(ff) = get_source_text(cx, span)
+        && let Some(text) = ff.as_str()
+    {
+        text.as_bytes().windows(2)
+            .any(|w| w == b"//" || w == b"/*")
+    } else {
+        false
+    }
+}
+
 #[rustfmt::skip]
 pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
@@ -25,7 +41,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
             return;
         }
         let els = arms[1].body;
-        let els = if is_unit_expr(peel_blocks(els)) {
+        let els = if is_unit_expr(peel_blocks(els)) && !empty_arm_has_comment(cx, els.span) {
             None
         } else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind {
             if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() {
@@ -35,7 +51,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
             // block with 2+ statements or 1 expr and 1+ statement
             Some(els)
         } else {
-            // not a block, don't lint
+            // not a block or an emtpy block w/ comments, don't lint
             return;
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
index 704c34c32bf..3a7f1e034f3 100644
--- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
@@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
 /// Finds function return type by examining return expressions in match arms.
 fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> Option<Ty<'tcx>> {
     if let ExprKind::Match(_, arms, MatchSource::TryDesugar) = expr {
-        for arm in arms.iter() {
+        for arm in *arms {
             if let ExprKind::Ret(Some(ret)) = arm.body.kind {
                 return Some(cx.typeck_results().expr_ty(ret));
             }
diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs
deleted file mode 100644
index d6c235b5a69..00000000000
--- a/src/tools/clippy/clippy_lints/src/mem_forget.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for usage of `std::mem::forget(t)` where `t` is
-    /// `Drop`.
-    ///
-    /// ### Why is this bad?
-    /// `std::mem::forget(t)` prevents `t` from running its
-    /// destructor, possibly causing leaks.
-    ///
-    /// ### Example
-    /// ```rust
-    /// # use std::mem;
-    /// # use std::rc::Rc;
-    /// mem::forget(Rc::new(55))
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub MEM_FORGET,
-    restriction,
-    "`mem::forget` usage on `Drop` types, likely to cause memory leaks"
-}
-
-declare_lint_pass!(MemForget => [MEM_FORGET]);
-
-impl<'tcx> LateLintPass<'tcx> for MemForget {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind {
-            if let ExprKind::Path(ref qpath) = path_expr.kind {
-                if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
-                    if cx.tcx.is_diagnostic_item(sym::mem_forget, def_id) {
-                        let forgot_ty = cx.typeck_results().expr_ty(first_arg);
-
-                        if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) {
-                            span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type");
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs b/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
new file mode 100644
index 00000000000..d0c79dc11b0
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
@@ -0,0 +1,85 @@
+use crate::methods::DRAIN_COLLECT;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_range_full;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_lang_item;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_hir::ExprKind;
+use rustc_hir::LangItem;
+use rustc_hir::Path;
+use rustc_hir::QPath;
+use rustc_lint::LateContext;
+use rustc_middle::query::Key;
+use rustc_middle::ty;
+use rustc_middle::ty::Ty;
+use rustc_span::sym;
+use rustc_span::Symbol;
+
+/// Checks if both types match the given diagnostic item, e.g.:
+///
+/// `vec![1,2].drain(..).collect::<Vec<_>>()`
+///  ^^^^^^^^^                     ^^^^^^   true
+/// `vec![1,2].drain(..).collect::<HashSet<_>>()`
+///  ^^^^^^^^^                     ^^^^^^^^^^  false
+fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool {
+    if let Some(expr_adt_did) = expr.ty_adt_id()
+        && let Some(recv_adt_did) = recv.ty_adt_id()
+    {
+        cx.tcx.is_diagnostic_item(sym, expr_adt_did) && cx.tcx.is_diagnostic_item(sym, recv_adt_did)
+    } else {
+        false
+    }
+}
+
+/// Checks `std::{vec::Vec, collections::VecDeque}`.
+fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool {
+    (types_match_diagnostic_item(cx, expr, recv, sym::Vec)
+        || types_match_diagnostic_item(cx, expr, recv, sym::VecDeque))
+        && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path)))
+}
+
+/// Checks `std::string::String`
+fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool {
+    is_type_lang_item(cx, expr, LangItem::String)
+        && is_type_lang_item(cx, recv, LangItem::String)
+        && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path)))
+}
+
+/// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`.
+fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option<&'static str> {
+    types_match_diagnostic_item(cx, expr, recv, sym::HashSet)
+        .then_some("HashSet")
+        .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::HashMap).then_some("HashMap"))
+        .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::BinaryHeap).then_some("BinaryHeap"))
+}
+
+pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, recv: &Expr<'_>) {
+    let expr_ty = cx.typeck_results().expr_ty(expr);
+    let recv_ty = cx.typeck_results().expr_ty(recv);
+    let recv_ty_no_refs = recv_ty.peel_refs();
+
+    if let ExprKind::Path(QPath::Resolved(_, recv_path)) = recv.kind
+        && let Some(typename) = check_vec(cx, args, expr_ty, recv_ty_no_refs, recv_path)
+            .then_some("Vec")
+            .or_else(|| check_string(cx, args, expr_ty, recv_ty_no_refs, recv_path).then_some("String"))
+            .or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs))
+    {
+        let recv = snippet(cx, recv.span, "<expr>");
+        let sugg = if let ty::Ref(..) = recv_ty.kind() {
+            format!("std::mem::take({recv})")
+        } else {
+            format!("std::mem::take(&mut {recv})")
+        };
+
+        span_lint_and_sugg(
+            cx,
+            DRAIN_COLLECT,
+            expr.span,
+            &format!("you seem to be trying to move all elements into a new `{typename}`"),
+            "consider using `mem::take`",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
index ffc3a4d780e..e35fb12ed79 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -23,21 +22,15 @@ pub(super) fn check<'tcx>(
     let mut applicability = Applicability::MachineApplicable;
     let expr_ty = cx.typeck_results().expr_ty(recv);
     let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability);
-    let mut needs_ref;
     let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() {
-        needs_ref = get_args_str.parse::<usize>().is_ok();
         "slice"
     } else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) {
-        needs_ref = get_args_str.parse::<usize>().is_ok();
         "Vec"
     } else if is_type_diagnostic_item(cx, expr_ty, sym::VecDeque) {
-        needs_ref = get_args_str.parse::<usize>().is_ok();
         "VecDeque"
     } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::HashMap) {
-        needs_ref = true;
         "HashMap"
     } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::BTreeMap) {
-        needs_ref = true;
         "BTreeMap"
     } else {
         return; // caller is not a type that we want to lint
@@ -45,18 +38,24 @@ pub(super) fn check<'tcx>(
 
     let mut span = expr.span;
 
-    // Handle the case where the result is immediately dereferenced
-    // by not requiring ref and pulling the dereference into the
-    // suggestion.
-    if_chain! {
-        if needs_ref;
-        if let Some(parent) = get_parent_expr(cx, expr);
-        if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind;
-        then {
-            needs_ref = false;
+    // Handle the case where the result is immediately dereferenced,
+    // either directly be the user, or as a result of a method call or the like
+    // by not requiring an explicit reference
+    let needs_ref = if let Some(parent) = get_parent_expr(cx, expr)
+        && let hir::ExprKind::Unary(hir::UnOp::Deref, _)
+            | hir::ExprKind::MethodCall(..)
+            | hir::ExprKind::Field(..)
+            | hir::ExprKind::Index(..) = parent.kind
+    {
+        if let hir::ExprKind::Unary(hir::UnOp::Deref, _) = parent.kind {
+            // if the user explicitly dereferences the result, we can adjust
+            // the span to also include the deref part
             span = parent.span;
         }
-    }
+        false
+    } else {
+        true
+    };
 
     let mut_str = if is_mut { "_mut" } else { "" };
     let borrow_str = if !needs_ref {
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
index ceee12784cb..12104310405 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
@@ -20,9 +20,9 @@ pub(super) fn check<'tcx>(
     let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() {
         "slice"
     } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::Vec) {
-        "Vec"
+        "`Vec`"
     } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) {
-        "VecDeque"
+        "`VecDeque`"
     } else {
         iter_nth_zero::check(cx, expr, nth_recv, nth_arg);
         return; // caller is not a type that we want to lint
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index d1609eebfdc..e1f950d5a4a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -1,8 +1,8 @@
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_trait_method;
 use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
+use clippy_utils::{is_lang_item_or_ctor, is_trait_method};
+use hir::{LangItem, OwnerNode};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -11,20 +11,21 @@ use rustc_span::sym;
 use super::ITER_NTH_ZERO;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
-    if_chain! {
-        if is_trait_method(cx, expr, sym::Iterator);
-        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            span_lint_and_sugg(
-                cx,
-                ITER_NTH_ZERO,
-                expr.span,
-                "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
-                "try calling `.next()` instead of `.nth(0)`",
-                format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut applicability)),
-                applicability,
-            );
-        }
+    if let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id))
+        && let def_id = item.owner_id.to_def_id()
+        && is_trait_method(cx, expr, sym::Iterator)
+        && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg)
+        && !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext)
+    {
+        let mut app = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            ITER_NTH_ZERO,
+            expr.span,
+            "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
+            "try calling `.next()` instead of `.nth(0)`",
+            format!("{}.next()", snippet_with_applicability(cx, recv.span, "..", &mut app)),
+            app,
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
new file mode 100644
index 00000000000..576a58499b1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
@@ -0,0 +1,55 @@
+use clippy_utils::{
+    diagnostics::span_lint_and_sugg,
+    is_from_proc_macro,
+    msrvs::{Msrv, ITERATOR_TRY_FOLD},
+    source::snippet_opt,
+    ty::implements_trait,
+};
+use rustc_errors::Applicability;
+use rustc_hir::{
+    def::{DefKind, Res},
+    Expr, ExprKind,
+};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_span::Span;
+
+use super::MANUAL_TRY_FOLD;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'tcx>,
+    init: &Expr<'_>,
+    acc: &Expr<'_>,
+    fold_span: Span,
+    msrv: &Msrv,
+) {
+    if !in_external_macro(cx.sess(), fold_span)
+        && msrv.meets(ITERATOR_TRY_FOLD)
+        && let init_ty = cx.typeck_results().expr_ty(init)
+        && let Some(try_trait) = cx.tcx.lang_items().try_trait()
+        && implements_trait(cx, init_ty, try_trait, &[])
+        && let ExprKind::Call(path, [first, rest @ ..]) = init.kind
+        && let ExprKind::Path(qpath) = path.kind
+        && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id)
+        && let ExprKind::Closure(closure) = acc.kind
+        && !is_from_proc_macro(cx, expr)
+        && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span))
+    {
+        let init_snip = rest
+            .is_empty()
+            .then_some(first.span)
+            .and_then(|span| snippet_opt(cx, span))
+            .unwrap_or("...".to_owned());
+
+        span_lint_and_sugg(
+            cx,
+            MANUAL_TRY_FOLD,
+            fold_span,
+            "usage of `Iterator::fold` on a type that implements `Try`",
+            "use `try_fold` instead",
+            format!("try_fold({init_snip}, {args_snip} ...)", ),
+            Applicability::HasPlaceholders,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 88cbefbb5d3..24dbe8c1d75 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -14,6 +14,7 @@ mod clone_on_copy;
 mod clone_on_ref_ptr;
 mod cloned_instead_of_copied;
 mod collapsible_str_replace;
+mod drain_collect;
 mod err_expect;
 mod expect_fun_call;
 mod expect_used;
@@ -49,6 +50,7 @@ mod manual_next_back;
 mod manual_ok_or;
 mod manual_saturating_arithmetic;
 mod manual_str_repeat;
+mod manual_try_fold;
 mod map_clone;
 mod map_collect_result_unit;
 mod map_err_ignore;
@@ -93,6 +95,7 @@ mod unnecessary_fold;
 mod unnecessary_iter_cloned;
 mod unnecessary_join;
 mod unnecessary_lazy_eval;
+mod unnecessary_literal_unwrap;
 mod unnecessary_sort_by;
 mod unnecessary_to_owned;
 mod unwrap_or_else_default;
@@ -275,6 +278,32 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for `.unwrap()` related calls on `Result`s and `Option`s that are constructed.
+    ///
+    /// ### Why is this bad?
+    /// It is better to write the value directly without the indirection.
+    ///
+    /// ### Examples
+    /// ```rust
+    /// let val1 = Some(1).unwrap();
+    /// let val2 = Ok::<_, ()>(1).unwrap();
+    /// let val3 = Err::<(), _>(1).unwrap_err();
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// let val1 = 1;
+    /// let val2 = 1;
+    /// let val3 = 1;
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub UNNECESSARY_LITERAL_UNWRAP,
+    complexity,
+    "using `unwrap()` related calls on `Result` and `Option` constructors"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s.
     ///
     /// ### Why is this bad?
@@ -485,6 +514,7 @@ declare_clippy_lint! {
     /// # let result: Result<usize, ()> = Ok(1);
     /// # fn some_function(foo: ()) -> usize { 1 }
     /// option.map(|a| a + 1).unwrap_or(0);
+    /// option.map(|a| a > 10).unwrap_or(false);
     /// result.map(|a| a + 1).unwrap_or_else(some_function);
     /// ```
     ///
@@ -494,6 +524,7 @@ declare_clippy_lint! {
     /// # let result: Result<usize, ()> = Ok(1);
     /// # fn some_function(foo: ()) -> usize { 1 }
     /// option.map_or(0, |a| a + 1);
+    /// option.is_some_and(|a| a > 10);
     /// result.map_or_else(some_function, |a| a + 1);
     /// ```
     #[clippy::version = "1.45.0"]
@@ -3220,6 +3251,71 @@ declare_clippy_lint! {
     "manual reverse iteration of `DoubleEndedIterator`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`.
+    ///
+    /// > "Collection" in this context refers to any type with a `drain` method:
+    /// > `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String`
+    ///
+    /// ### Why is this bad?
+    /// Using `mem::take` is faster as it avoids the allocation.
+    /// When using `mem::take`, the old collection is replaced with an empty one and ownership of
+    /// the old collection is returned.
+    ///
+    /// ### Known issues
+    /// `mem::take(&mut vec)` is almost equivalent to `vec.drain(..).collect()`, except that
+    /// it also moves the **capacity**. The user might have explicitly written it this way
+    /// to keep the capacity on the original `Vec`.
+    ///
+    /// ### Example
+    /// ```rust
+    /// fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
+    ///     v.drain(..).collect()
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// use std::mem;
+    /// fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
+    ///     mem::take(v)
+    /// }
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub DRAIN_COLLECT,
+    perf,
+    "calling `.drain(..).collect()` to move all elements into a new collection"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `Iterator::fold` with a type that implements `Try`.
+    ///
+    /// ### Why is this bad?
+    /// The code should use `try_fold` instead, which short-circuits on failure, thus opening the
+    /// door for additional optimizations not possible with `fold` as rustc can guarantee the
+    /// function is never called on `None`, `Err`, etc., alleviating otherwise necessary checks. It's
+    /// also slightly more idiomatic.
+    ///
+    /// ### Known issues
+    /// This lint doesn't take into account whether a function does something on the failure case,
+    /// i.e., whether short-circuiting will affect behavior. Refactoring to `try_fold` is not
+    /// desirable in those cases.
+    ///
+    /// ### Example
+    /// ```rust
+    /// vec![1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i));
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// vec![1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i));
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub MANUAL_TRY_FOLD,
+    perf,
+    "checks for usage of `Iterator::fold` with a type that implements `Try`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3349,6 +3445,9 @@ impl_lint_pass!(Methods => [
     SUSPICIOUS_COMMAND_ARG_SPACE,
     CLEAR_WITH_DRAIN,
     MANUAL_NEXT_BACK,
+    UNNECESSARY_LITERAL_UNWRAP,
+    DRAIN_COLLECT,
+    MANUAL_TRY_FOLD,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3578,6 +3677,9 @@ impl Methods {
                                 manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
                             }
                         },
+                        Some(("drain", recv, args, ..)) => {
+                            drain_collect::check(cx, args, expr, recv);
+                        }
                         _ => {},
                     }
                 },
@@ -3606,12 +3708,18 @@ impl Methods {
                         case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
                     }
                 },
-                ("expect", [_]) => match method_call(recv) {
-                    Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv),
-                    Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv),
-                    _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
+                ("expect", [_]) => {
+                    match method_call(recv) {
+                        Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv),
+                        Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv),
+                        _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
+                    }
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
+                },
+                ("expect_err", [_]) => {
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
+                    expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests);
                 },
-                ("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests),
                 ("extend", [arg]) => {
                     string_extend_chars::check(cx, expr, recv, arg);
                     extend_with_drain::check(cx, expr, recv, arg);
@@ -3632,7 +3740,10 @@ impl Methods {
                     Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
                     _ => {},
                 },
-                ("fold", [init, acc]) => unnecessary_fold::check(cx, expr, init, acc, span),
+                ("fold", [init, acc]) => {
+                    manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv);
+                    unnecessary_fold::check(cx, expr, init, acc, span);
+                },
                 ("for_each", [_]) => {
                     if let Some(("inspect", _, [_], span2, _)) = method_call(recv) {
                         inspect_for_each::check(cx, expr, span2);
@@ -3816,28 +3927,41 @@ impl Methods {
                         },
                         _ => {},
                     }
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                     unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests);
                 },
-                ("unwrap_err", []) => unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests),
-                ("unwrap_or", [u_arg]) => match method_call(recv) {
-                    Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => {
-                        manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
-                    },
-                    Some(("map", m_recv, [m_arg], span, _)) => {
-                        option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
-                    },
-                    Some(("then_some", t_recv, [t_arg], _, _)) => {
-                        obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg);
-                    },
-                    _ => {},
+                ("unwrap_err", []) => {
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
+                    unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests);
                 },
-                ("unwrap_or_else", [u_arg]) => match method_call(recv) {
-                    Some(("map", recv, [map_arg], _, _))
-                        if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {},
-                    _ => {
-                        unwrap_or_else_default::check(cx, expr, recv, u_arg);
-                        unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
-                    },
+                ("unwrap_or", [u_arg]) => {
+                    match method_call(recv) {
+                        Some((arith @ ("checked_add" | "checked_sub" | "checked_mul"), lhs, [rhs], _, _)) => {
+                            manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
+                        },
+                        Some(("map", m_recv, [m_arg], span, _)) => {
+                            option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv);
+                        },
+                        Some(("then_some", t_recv, [t_arg], _, _)) => {
+                            obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg);
+                        },
+                        _ => {},
+                    }
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
+                },
+                ("unwrap_or_default", []) => {
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
+                }
+                ("unwrap_or_else", [u_arg]) => {
+                    match method_call(recv) {
+                        Some(("map", recv, [map_arg], _, _))
+                            if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {},
+                        _ => {
+                            unwrap_or_else_default::check(cx, expr, recv, u_arg);
+                            unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
+                        },
+                    }
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
                 ("zip", [arg]) => {
                     if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 0699997d0d2..ac209d01406 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -322,7 +322,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> {
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // Check function calls on our collection
-        if let ExprKind::MethodCall(method_name, recv, [args @ ..], _) = &expr.kind {
+        if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind {
             if method_name.ident.name == sym!(collect) && is_trait_method(self.cx, expr, sym::Iterator) {
                 self.current_mutably_captured_ids = get_captured_ids(self.cx, self.cx.typeck_results().expr_ty(recv));
                 self.visit_expr(recv);
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 4c6328481e4..f4f158c0439 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -1,19 +1,26 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_copy;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
+use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::ExprKind;
+use rustc_hir::Node;
+use rustc_hir::PatKind;
+use rustc_hir::QPath;
 use rustc_hir::{self, HirId, Path};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_span::source_map::Span;
-use rustc_span::{sym, Symbol};
+use rustc_span::sym;
 
 use super::MAP_UNWRAP_OR;
 
 /// lint use of `map().unwrap_or()` for `Option`s
+#[expect(clippy::too_many_arguments)]
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &rustc_hir::Expr<'_>,
@@ -22,12 +29,27 @@ pub(super) fn check<'tcx>(
     unwrap_recv: &rustc_hir::Expr<'_>,
     unwrap_arg: &'tcx rustc_hir::Expr<'_>,
     map_span: Span,
+    msrv: &Msrv,
 ) {
     // lint if the caller of `map()` is an `Option`
     if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) {
         if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) {
-            // Do not lint if the `map` argument uses identifiers in the `map`
-            // argument that are also used in the `unwrap_or` argument
+            // Replacing `.map(<f>).unwrap_or(<a>)` with `.map_or(<a>, <f>)` can sometimes lead to
+            // borrowck errors, see #10579 for one such instance.
+            // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint:
+            // ```
+            // let x = vec![1, 2];
+            // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x);
+            // ```
+            // This compiles, but changing it to `map_or` will produce a compile error:
+            // ```
+            // let x = vec![1, 2];
+            // x.get(0..1).map_or(x, |s| s.to_vec())
+            //                    ^ moving `x` here
+            // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure)
+            // ```
+            // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!)
+            // before the call to `unwrap_or`.
 
             let mut unwrap_visitor = UnwrapVisitor {
                 cx,
@@ -35,14 +57,18 @@ pub(super) fn check<'tcx>(
             };
             unwrap_visitor.visit_expr(unwrap_arg);
 
-            let mut map_expr_visitor = MapExprVisitor {
+            let mut reference_visitor = ReferenceVisitor {
                 cx,
                 identifiers: unwrap_visitor.identifiers,
-                found_identifier: false,
+                found_reference: false,
+                unwrap_or_span: unwrap_arg.span,
             };
-            map_expr_visitor.visit_expr(map_arg);
 
-            if map_expr_visitor.found_identifier {
+            let map = cx.tcx.hir();
+            let body = map.body(map.body_owned_by(map.enclosing_body_owner(expr.hir_id)));
+            reference_visitor.visit_body(body);
+
+            if reference_visitor.found_reference {
                 return;
             }
         }
@@ -51,16 +77,29 @@ pub(super) fn check<'tcx>(
             return;
         }
 
+        // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead
+        let suggest_is_some_and = msrv.meets(msrvs::OPTION_IS_SOME_AND)
+            && matches!(&unwrap_arg.kind, ExprKind::Lit(lit)
+            if matches!(lit.node, rustc_ast::LitKind::Bool(false)));
+
         let mut applicability = Applicability::MachineApplicable;
         // get snippet for unwrap_or()
         let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability);
         // lint message
         // comparing the snippet from source to raw text ("None") below is safe
         // because we already have checked the type.
-        let arg = if unwrap_snippet == "None" { "None" } else { "<a>" };
+        let arg = if unwrap_snippet == "None" {
+            "None"
+        } else if suggest_is_some_and {
+            "false"
+        } else {
+            "<a>"
+        };
         let unwrap_snippet_none = unwrap_snippet == "None";
         let suggest = if unwrap_snippet_none {
             "and_then(<f>)"
+        } else if suggest_is_some_and {
+            "is_some_and(<f>)"
         } else {
             "map_or(<a>, <f>)"
         };
@@ -75,12 +114,18 @@ pub(super) fn check<'tcx>(
             let mut suggestion = vec![
                 (
                     map_span,
-                    String::from(if unwrap_snippet_none { "and_then" } else { "map_or" }),
+                    String::from(if unwrap_snippet_none {
+                        "and_then"
+                    } else if suggest_is_some_and {
+                        "is_some_and"
+                    } else {
+                        "map_or"
+                    }),
                 ),
                 (expr.span.with_lo(unwrap_recv.span.hi()), String::new()),
             ];
 
-            if !unwrap_snippet_none {
+            if !unwrap_snippet_none && !suggest_is_some_and {
                 suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, ")));
             }
 
@@ -91,14 +136,19 @@ pub(super) fn check<'tcx>(
 
 struct UnwrapVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    identifiers: FxHashSet<Symbol>,
+    identifiers: FxHashSet<HirId>,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
-        self.identifiers.insert(ident(path));
+    fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) {
+        if let Res::Local(local_id) = path.res
+            && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id)
+            && let PatKind::Binding(_, local_id, ..) = pat.kind
+        {
+            self.identifiers.insert(local_id);
+        }
         walk_path(self, path);
     }
 
@@ -107,32 +157,35 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
     }
 }
 
-struct MapExprVisitor<'a, 'tcx> {
+struct ReferenceVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    identifiers: FxHashSet<Symbol>,
-    found_identifier: bool,
+    identifiers: FxHashSet<HirId>,
+    found_reference: bool,
+    unwrap_or_span: Span,
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::All;
-
-    fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
-        if self.identifiers.contains(&ident(path)) {
-            self.found_identifier = true;
-            return;
+    fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) {
+        // If we haven't found a reference yet, check if this references
+        // one of the locals that was moved in the `unwrap_or` argument.
+        // We are only interested in exprs that appear before the `unwrap_or` call.
+        if !self.found_reference {
+            if expr.span < self.unwrap_or_span
+                && let ExprKind::Path(ref path) = expr.kind
+                && let QPath::Resolved(_, path) = path
+                && let Res::Local(local_id) = path.res
+                && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id)
+                && let PatKind::Binding(_, local_id, ..) = pat.kind
+                && self.identifiers.contains(&local_id)
+            {
+                self.found_reference = true;
+            }
+            rustc_hir::intravisit::walk_expr(self, expr);
         }
-        walk_path(self, path);
     }
 
     fn nested_visit_map(&mut self) -> Self::Map {
         self.cx.tcx.hir()
     }
 }
-
-fn ident(path: &Path<'_>) -> Symbol {
-    path.segments
-        .last()
-        .expect("segments should be composed of at least 1 element")
-        .ident
-        .name
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 5ea12c44184..88a3c2620a4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -289,7 +289,7 @@ fn parse_iter_usage<'tcx>(
 ) -> Option<IterUsage> {
     let (kind, span) = match iter.next() {
         Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
-            let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind else {
+            let ExprKind::MethodCall(name, _, args, _) = e.kind else {
                 return None;
             };
             let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index 5a3d12fd790..8ec15a1c1b7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -7,71 +7,120 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::PatKind;
 use rustc_lint::LateContext;
+use rustc_middle::ty;
 use rustc_span::{source_map::Span, sym};
 
 use super::UNNECESSARY_FOLD;
 
-pub(super) fn check(
+/// Do we need to suggest turbofish when suggesting a replacement method?
+/// Changing `fold` to `sum` needs it sometimes when the return type can't be
+/// inferred. This checks for some common cases where it can be safely omitted
+fn needs_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    let parent = cx.tcx.hir().get_parent(expr.hir_id);
+
+    // some common cases where turbofish isn't needed:
+    // - assigned to a local variable with a type annotation
+    if let hir::Node::Local(local) = parent
+        && local.ty.is_some()
+    {
+        return false;
+    }
+
+    // - part of a function call argument, can be inferred from the function signature (provided that
+    //   the parameter is not a generic type parameter)
+    if let hir::Node::Expr(parent_expr) = parent
+        && let hir::ExprKind::Call(recv, args) = parent_expr.kind
+        && let hir::ExprKind::Path(ref qpath) = recv.kind
+        && let Some(fn_def_id) = cx.qpath_res(qpath, recv.hir_id).opt_def_id()
+        && let fn_sig = cx.tcx.fn_sig(fn_def_id).skip_binder().skip_binder()
+        && let Some(arg_pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
+        && let Some(ty) = fn_sig.inputs().get(arg_pos)
+        && !matches!(ty.kind(), ty::Param(_))
+    {
+        return false;
+    }
+
+    // if it's neither of those, stay on the safe side and suggest turbofish,
+    // even if it could work!
+    true
+}
+
+#[derive(Copy, Clone)]
+struct Replacement {
+    method_name: &'static str,
+    has_args: bool,
+    has_generic_return: bool,
+}
+
+fn check_fold_with_op(
     cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
-    init: &hir::Expr<'_>,
     acc: &hir::Expr<'_>,
     fold_span: Span,
+    op: hir::BinOpKind,
+    replacement: Replacement,
 ) {
-    fn check_fold_with_op(
-        cx: &LateContext<'_>,
-        expr: &hir::Expr<'_>,
-        acc: &hir::Expr<'_>,
-        fold_span: Span,
-        op: hir::BinOpKind,
-        replacement_method_name: &str,
-        replacement_has_args: bool,
-    ) {
-        if_chain! {
-            // Extract the body of the closure passed to fold
-            if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind;
-            let closure_body = cx.tcx.hir().body(body);
-            let closure_expr = peel_blocks(closure_body.value);
-
-            // Check if the closure body is of the form `acc <op> some_expr(x)`
-            if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind;
-            if bin_op.node == op;
-
-            // Extract the names of the two arguments to the closure
-            if let [param_a, param_b] = closure_body.params;
-            if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind;
-            if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind;
-
-            if path_to_local_id(left_expr, first_arg_id);
-            if replacement_has_args || path_to_local_id(right_expr, second_arg_id);
-
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let sugg = if replacement_has_args {
-                    format!(
-                        "{replacement_method_name}(|{second_arg_ident}| {r})",
-                        r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
-                    )
-                } else {
-                    format!(
-                        "{replacement_method_name}()",
-                    )
-                };
-
-                span_lint_and_sugg(
-                    cx,
-                    UNNECESSARY_FOLD,
-                    fold_span.with_hi(expr.span.hi()),
-                    // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
-                    "this `.fold` can be written more succinctly using another method",
-                    "try",
-                    sugg,
-                    applicability,
-                );
-            }
+    if_chain! {
+        // Extract the body of the closure passed to fold
+        if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind;
+        let closure_body = cx.tcx.hir().body(body);
+        let closure_expr = peel_blocks(closure_body.value);
+
+        // Check if the closure body is of the form `acc <op> some_expr(x)`
+        if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind;
+        if bin_op.node == op;
+
+        // Extract the names of the two arguments to the closure
+        if let [param_a, param_b] = closure_body.params;
+        if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind;
+        if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind;
+
+        if path_to_local_id(left_expr, first_arg_id);
+        if replacement.has_args || path_to_local_id(right_expr, second_arg_id);
+
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+
+            let turbofish = if replacement.has_generic_return {
+                format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs())
+            } else {
+                String::new()
+            };
+
+            let sugg = if replacement.has_args {
+                format!(
+                    "{method}{turbofish}(|{second_arg_ident}| {r})",
+                    method = replacement.method_name,
+                    r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
+                )
+            } else {
+                format!(
+                    "{method}{turbofish}()",
+                    method = replacement.method_name,
+                )
+            };
+
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_FOLD,
+                fold_span.with_hi(expr.span.hi()),
+                // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
+                "this `.fold` can be written more succinctly using another method",
+                "try",
+                sugg,
+                applicability,
+            );
         }
     }
+}
 
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    init: &hir::Expr<'_>,
+    acc: &hir::Expr<'_>,
+    fold_span: Span,
+) {
     // Check that this is a call to Iterator::fold rather than just some function called fold
     if !is_trait_method(cx, expr, sym::Iterator) {
         return;
@@ -80,11 +129,59 @@ pub(super) fn check(
     // Check if the first argument to .fold is a suitable literal
     if let hir::ExprKind::Lit(lit) = init.kind {
         match lit.node {
-            ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true),
-            ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true),
-            ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false),
+            ast::LitKind::Bool(false) => {
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Or,
+                    Replacement {
+                        has_args: true,
+                        has_generic_return: false,
+                        method_name: "any",
+                    },
+                );
+            },
+            ast::LitKind::Bool(true) => {
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::And,
+                    Replacement {
+                        has_args: true,
+                        has_generic_return: false,
+                        method_name: "all",
+                    },
+                );
+            },
+            ast::LitKind::Int(0, _) => check_fold_with_op(
+                cx,
+                expr,
+                acc,
+                fold_span,
+                hir::BinOpKind::Add,
+                Replacement {
+                    has_args: false,
+                    has_generic_return: needs_turbofish(cx, expr),
+                    method_name: "sum",
+                },
+            ),
             ast::LitKind::Int(1, _) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false);
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Mul,
+                    Replacement {
+                        has_args: false,
+                        has_generic_return: needs_turbofish(cx, expr),
+                        method_name: "product",
+                    },
+                );
             },
             _ => (),
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
new file mode 100644
index 00000000000..7877f6a386c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -0,0 +1,95 @@
+use clippy_utils::{diagnostics::span_lint_and_then, is_res_lang_ctor, last_path_segment, path_res, MaybePath};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+
+use super::UNNECESSARY_LITERAL_UNWRAP;
+
+fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a>> {
+    let args = args?;
+
+    if args.len() <= index {
+        return None;
+    }
+
+    match args[index] {
+        hir::GenericArg::Type(ty) => match ty.kind {
+            hir::TyKind::Infer => None,
+            _ => Some(ty),
+        },
+        _ => None,
+    }
+}
+
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    recv: &hir::Expr<'_>,
+    method: &str,
+    args: &[hir::Expr<'_>],
+) {
+    let init = clippy_utils::expr_or_init(cx, recv);
+
+    let (constructor, call_args, ty) = if let hir::ExprKind::Call(call, call_args) = init.kind {
+        let Some(qpath) = call.qpath_opt() else { return };
+
+        let args = last_path_segment(qpath).args.map(|args| args.args);
+        let res = cx.qpath_res(qpath, call.hir_id());
+
+        if is_res_lang_ctor(cx, res, hir::LangItem::OptionSome) {
+            ("Some", call_args, get_ty_from_args(args, 0))
+        } else if is_res_lang_ctor(cx, res, hir::LangItem::ResultOk) {
+            ("Ok", call_args, get_ty_from_args(args, 0))
+        } else if is_res_lang_ctor(cx, res, hir::LangItem::ResultErr) {
+            ("Err", call_args, get_ty_from_args(args, 1))
+        } else {
+            return;
+        }
+    } else if is_res_lang_ctor(cx, path_res(cx, init), hir::LangItem::OptionNone) {
+        let call_args: &[hir::Expr<'_>] = &[];
+        ("None", call_args, None)
+    } else {
+        return;
+    };
+
+    let help_message = format!("used `{method}()` on `{constructor}` value");
+    let suggestion_message = format!("remove the `{constructor}` and `{method}()`");
+
+    span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| {
+        let suggestions = match (constructor, method, ty) {
+            ("None", "unwrap", _) => Some(vec![(expr.span, "panic!()".to_string())]),
+            ("None", "expect", _) => Some(vec![
+                (expr.span.with_hi(args[0].span.lo()), "panic!(".to_string()),
+                (expr.span.with_lo(args[0].span.hi()), ")".to_string()),
+            ]),
+            (_, _, Some(_)) => None,
+            ("Ok", "unwrap_err", None) | ("Err", "unwrap", None) => Some(vec![
+                (
+                    recv.span.with_hi(call_args[0].span.lo()),
+                    "panic!(\"{:?}\", ".to_string(),
+                ),
+                (expr.span.with_lo(call_args[0].span.hi()), ")".to_string()),
+            ]),
+            ("Ok", "expect_err", None) | ("Err", "expect", None) => Some(vec![
+                (
+                    recv.span.with_hi(call_args[0].span.lo()),
+                    "panic!(\"{1}: {:?}\", ".to_string(),
+                ),
+                (call_args[0].span.with_lo(args[0].span.lo()), ", ".to_string()),
+            ]),
+            (_, _, None) => Some(vec![
+                (recv.span.with_hi(call_args[0].span.lo()), String::new()),
+                (expr.span.with_lo(call_args[0].span.hi()), String::new()),
+            ]),
+        };
+
+        match (init.span == recv.span, suggestions) {
+            (true, Some(suggestions)) => {
+                diag.multipart_suggestion(suggestion_message, suggestions, Applicability::MachineApplicable);
+            },
+            _ => {
+                diag.span_help(init.span, suggestion_message);
+            },
+        }
+    });
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 80eb00a1b42..16ef24bd4e3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -144,6 +144,11 @@ fn check_addr_of_expr(
                 if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
                 if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
                 if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty);
+                // Make sure that it's actually calling the right `.to_string()`, (#10033)
+                // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow)
+                // but that's ok for Cow::into_owned specifically)
+                if cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty
+                    || is_cow_into_owned(cx, method_name, method_def_id);
                 then {
                     if n_receiver_refs > 0 {
                         span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
new file mode 100644
index 00000000000..d49bb0ca6e2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
@@ -0,0 +1,153 @@
+use clippy_utils::{diagnostics::span_lint, is_from_proc_macro};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::{
+    def::{DefKind, Res},
+    intravisit::{walk_item, Visitor},
+    GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind,
+};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+use std::borrow::Cow;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for idents which comprise of a single letter.
+    ///
+    /// Note: This lint can be very noisy when enabled; it may be desirable to only enable it
+    /// temporarily.
+    ///
+    /// ### Why is this bad?
+    /// In many cases it's not, but at times it can severely hinder readability. Some codebases may
+    /// wish to disallow this to improve readability.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// for m in movies {
+    ///	    let title = m.t;
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// for movie in movies {
+    ///     let title = movie.title;
+    /// }
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub MIN_IDENT_CHARS,
+    restriction,
+    "disallows idents that are too short"
+}
+impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]);
+
+#[derive(Clone)]
+pub struct MinIdentChars {
+    pub allowed_idents_below_min_chars: FxHashSet<String>,
+    pub min_ident_chars_threshold: u64,
+}
+
+impl MinIdentChars {
+    #[expect(clippy::cast_possible_truncation)]
+    fn is_ident_too_short(&self, cx: &LateContext<'_>, str: &str, span: Span) -> bool {
+        !in_external_macro(cx.sess(), span)
+            && str.len() <= self.min_ident_chars_threshold as usize
+            && !str.starts_with('_')
+            && !str.is_empty()
+            && self.allowed_idents_below_min_chars.get(&str.to_owned()).is_none()
+    }
+}
+
+impl LateLintPass<'_> for MinIdentChars {
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if self.min_ident_chars_threshold == 0 {
+            return;
+        }
+
+        walk_item(&mut IdentVisitor { conf: self, cx }, item);
+    }
+
+    // This is necessary as `Node::Pat`s are not visited in `visit_id`. :/
+    fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
+        if let PatKind::Binding(_, _, ident, ..) = pat.kind
+            && let str = ident.as_str()
+            && self.is_ident_too_short(cx, str, ident.span)
+        {
+            emit_min_ident_chars(self, cx, str, ident.span);
+        }
+    }
+}
+
+struct IdentVisitor<'cx, 'tcx> {
+    conf: &'cx MinIdentChars,
+    cx: &'cx LateContext<'tcx>,
+}
+
+impl Visitor<'_> for IdentVisitor<'_, '_> {
+    fn visit_id(&mut self, hir_id: HirId) {
+        let Self { conf, cx } = *self;
+        // FIXME(#112534) Reimplementation of `find`, as it uses indexing, which can (and will in
+        // async functions, or really anything async) panic. This should probably be fixed on the
+        // rustc side, this is just a temporary workaround.
+        let node = if hir_id.local_id == ItemLocalId::from_u32(0) {
+            // In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't
+            // reimplement it even if we wanted to
+            cx.tcx.hir().find(hir_id)
+        } else {
+            let Some(owner) = cx.tcx.hir_owner_nodes(hir_id.owner).as_owner() else {
+                return;
+            };
+            owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node)
+        };
+        let Some(node) = node else {
+            return;
+        };
+        let Some(ident) = node.ident() else {
+            return;
+        };
+
+        let str = ident.as_str();
+        if conf.is_ident_too_short(cx, str, ident.span) {
+            if let Node::Item(item) = node && let ItemKind::Use(..) = item.kind {
+                return;
+            }
+            // `struct Awa<T>(T)`
+            //                ^
+            if let Node::PathSegment(path) = node {
+                if let Res::Def(def_kind, ..) = path.res && let DefKind::TyParam = def_kind {
+                    return;
+                }
+                if matches!(path.res, Res::PrimTy(..)) || path.res.opt_def_id().is_some_and(|def_id| !def_id.is_local())
+                {
+                    return;
+                }
+            }
+            // `struct Awa<T>(T)`
+            //             ^
+            if let Node::GenericParam(generic_param) = node
+                && let GenericParamKind::Type { .. } = generic_param.kind
+            {
+                return;
+            }
+
+            if is_from_proc_macro(cx, &ident) {
+                return;
+            }
+
+            emit_min_ident_chars(conf, cx, str, ident.span);
+        }
+    }
+}
+
+fn emit_min_ident_chars(conf: &MinIdentChars, cx: &impl LintContext, ident: &str, span: Span) {
+    let help = if conf.min_ident_chars_threshold == 1 {
+        Cow::Borrowed("this ident consists of a single char")
+    } else {
+        Cow::Owned(format!(
+            "this ident is too short ({} <= {})",
+            ident.len(),
+            conf.min_ident_chars_threshold,
+        ))
+    };
+    span_lint(cx, MIN_IDENT_CHARS, span, &help);
+}
diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs
index 4f967755bfa..e0904f17b8d 100644
--- a/src/tools/clippy/clippy_lints/src/minmax.rs
+++ b/src/tools/clippy/clippy_lints/src/minmax.rs
@@ -66,7 +66,7 @@ enum MinMax {
     Max,
 }
 
-fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
+fn min_max<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> {
     match expr.kind {
         ExprKind::Call(path, args) => {
             if let ExprKind::Path(ref qpath) = path.kind {
@@ -99,12 +99,12 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
     }
 }
 
-fn fetch_const<'a>(
-    cx: &LateContext<'_>,
+fn fetch_const<'a, 'tcx>(
+    cx: &LateContext<'tcx>,
     receiver: Option<&'a Expr<'a>>,
     args: &'a [Expr<'a>],
     m: MinMax,
-) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
+) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> {
     let mut args = receiver.into_iter().chain(args);
     let first_arg = args.next()?;
     let second_arg = args.next()?;
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs
index ddb8b9173a5..9151cc63320 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs
@@ -13,7 +13,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_sni
         return;
     }
     let mut seen = (false, false);
-    for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() {
+    for ch in &lit_snip.as_bytes()[2..=maybe_last_sep_idx] {
         match ch {
             b'a'..=b'f' => seen.0 = true,
             b'A'..=b'F' => seen.1 = true,
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index 78be6b9e23f..b226b878123 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -2,6 +2,7 @@ mod builtin_type_shadow;
 mod double_neg;
 mod literal_suffix;
 mod mixed_case_hex_literals;
+mod redundant_at_rest_pattern;
 mod redundant_pattern;
 mod unneeded_field_pattern;
 mod unneeded_wildcard_pattern;
@@ -318,6 +319,36 @@ declare_clippy_lint! {
     "tuple patterns with a wildcard pattern (`_`) is next to a rest pattern (`..`)"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `[all @ ..]` patterns.
+    ///
+    /// ### Why is this bad?
+    /// In all cases, `all` works fine and can often make code simpler, as you possibly won't need
+    /// to convert from say a `Vec` to a slice by dereferencing.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// if let [all @ ..] = &*v {
+    ///     // NOTE: Type is a slice here
+    ///     println!("all elements: {all:#?}");
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// if let all = v {
+    ///     // NOTE: Type is a `Vec` here
+    ///     println!("all elements: {all:#?}");
+    /// }
+    /// // or
+    /// println!("all elements: {v:#?}");
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub REDUNDANT_AT_REST_PATTERN,
+    complexity,
+    "checks for `[all @ ..]` where `all` would suffice"
+}
+
 declare_lint_pass!(MiscEarlyLints => [
     UNNEEDED_FIELD_PATTERN,
     DUPLICATE_UNDERSCORE_ARGUMENT,
@@ -329,6 +360,7 @@ declare_lint_pass!(MiscEarlyLints => [
     BUILTIN_TYPE_SHADOW,
     REDUNDANT_PATTERN,
     UNNEEDED_WILDCARD_PATTERN,
+    REDUNDANT_AT_REST_PATTERN,
 ]);
 
 impl EarlyLintPass for MiscEarlyLints {
@@ -339,8 +371,13 @@ impl EarlyLintPass for MiscEarlyLints {
     }
 
     fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
+        if in_external_macro(cx.sess(), pat.span) {
+            return;
+        }
+
         unneeded_field_pattern::check(cx, pat);
         redundant_pattern::check(cx, pat);
+        redundant_at_rest_pattern::check(cx, pat);
         unneeded_wildcard_pattern::check(cx, pat);
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs
new file mode 100644
index 00000000000..0c81ee5eced
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs
@@ -0,0 +1,26 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::{Pat, PatKind};
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+
+use super::REDUNDANT_AT_REST_PATTERN;
+
+pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
+    if !in_external_macro(cx.sess(), pat.span)
+        && let PatKind::Slice(slice) = &pat.kind
+        && let [one] = &**slice
+        && let PatKind::Ident(annotation, ident, Some(rest)) = &one.kind
+        && let PatKind::Rest = rest.kind
+    {
+        span_lint_and_sugg(
+            cx,
+            REDUNDANT_AT_REST_PATTERN,
+            pat.span,
+            "using a rest pattern to bind an entire slice to a local",
+            "this is better represented with just the binding",
+            format!("{}{ident}", annotation.prefix_str()),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
index 9de4b56b77b..28e041dee0d 100644
--- a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
+++ b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
             then {
                 // get the name and span of the generic parameters in the Impl
                 let mut impl_params = Vec::new();
-                for p in generic_args.args.iter() {
+                for p in generic_args.args {
                     match p {
                         GenericArg::Type(Ty {kind: TyKind::Path(QPath::Resolved(_, path)), ..}) =>
                             impl_params.push((path.segments[0].ident.to_string(), path.span)),
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index b6f0de7e504..1138d1163a4 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -207,6 +207,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
         if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, items, .. }) = item.kind
             && let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res
             && let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind
+            // don't trigger if self is a generic parameter, e.g. `impl<T> Debug for T`
+            // this can only happen in core itself, where the trait is defined,
+            // but it caused ICEs in the past:
+            // https://github.com/rust-lang/rust-clippy/issues/10887
+            && !matches!(self_path.res, Res::Def(DefKind::TyParam, _))
             && cx.match_def_path(trait_def_id, &[sym::core, sym::fmt, sym::Debug])
             // don't trigger if this impl was derived
             && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived)
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index f0be7771bb1..57ec3a1f1e6 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -114,7 +114,7 @@ struct DivergenceVisitor<'a, 'tcx> {
 impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
     fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
-            ExprKind::Closure { .. } => {},
+            ExprKind::Closure(..) | ExprKind::If(..) | ExprKind::Loop(..) => {},
             ExprKind::Match(e, arms, _) => {
                 self.visit_expr(e);
                 for arm in arms {
@@ -128,6 +128,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
             _ => walk_expr(self, e),
         }
     }
+
     fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) {
         span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges");
     }
@@ -136,6 +137,15 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
+            // fix #10776
+            ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
+                ([], Some(e)) => self.visit_expr(e),
+                ([stmt], None) => match stmt.kind {
+                    StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
+                    _ => {},
+                },
+                _ => {},
+            },
             ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e),
             ExprKind::Call(func, _) => {
                 let typ = self.cx.typeck_results().expr_ty(func);
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 349fcd2274d..439cae812b7 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -2,6 +2,7 @@ use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::{FileName, SourceFile, Span, SyntaxContext};
 use std::ffi::OsStr;
 use std::path::{Component, Path};
@@ -90,7 +91,14 @@ impl EarlyLintPass for ModStyle {
         // `{ foo => path/to/foo.rs, .. }
         let mut file_map = FxHashMap::default();
         for file in files.iter() {
-            if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() {
+            if let FileName::Real(name) = &file.name
+                && let Some(lp) = name.local_path()
+                && file.cnum == LOCAL_CRATE
+            {
+                // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887)
+                // Only check files in the current crate.
+                // Fix false positive that crate dependency in workspace sub directory
+                // is checked unintentionally.
                 let path = if lp.is_relative() {
                     lp
                 } else if let Ok(relative) = lp.strip_prefix(trim_to_src) {
diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs
new file mode 100644
index 00000000000..ad5c3e1dc82
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/needless_if.rs
@@ -0,0 +1,75 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, higher::If, is_from_proc_macro, source::snippet_opt};
+use rustc_errors::Applicability;
+use rustc_hir::{ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for empty `if` branches with no else branch.
+    ///
+    /// ### Why is this bad?
+    /// It can be entirely omitted, and often the condition too.
+    ///
+    /// ### Known issues
+    /// This will usually only suggest to remove the `if` statement, not the condition. Other lints
+    /// such as `no_effect` will take care of removing the condition if it's unnecessary.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// if really_expensive_condition(&i) {}
+    /// if really_expensive_condition_with_side_effects(&mut i) {}
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// // <omitted>
+    /// really_expensive_condition_with_side_effects(&mut i);
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub NEEDLESS_IF,
+    complexity,
+    "checks for empty if branches"
+}
+declare_lint_pass!(NeedlessIf => [NEEDLESS_IF]);
+
+impl LateLintPass<'_> for NeedlessIf {
+    fn check_stmt<'tcx>(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'tcx>) {
+        if let StmtKind::Expr(expr) = stmt.kind
+            && let Some(If {cond, then, r#else: None }) = If::hir(expr)
+            && let ExprKind::Block(block, ..) = then.kind
+            && block.stmts.is_empty()
+            && block.expr.is_none()
+            && !in_external_macro(cx.sess(), expr.span)
+            && !is_from_proc_macro(cx, expr)
+            && let Some(then_snippet) = snippet_opt(cx, then.span)
+            // Ignore
+            // - empty macro expansions
+            // - empty reptitions in macro expansions
+            // - comments
+            // - #[cfg]'d out code
+            && then_snippet.chars().all(|ch| matches!(ch, '{' | '}') || ch.is_ascii_whitespace())
+            && let Some(cond_snippet) = snippet_opt(cx, cond.span)
+        {
+            span_lint_and_sugg(
+                cx,
+                NEEDLESS_IF,
+                stmt.span,
+                "this `if` branch is empty",
+                "you can remove it",
+                if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() {
+                    // `{ foo }` or `{ foo } && bar` placed into a statement position would be
+                    // interpreted as a block statement, force it to be an expression
+                    if cond_snippet.starts_with('{') {
+                        format!("({cond_snippet});")
+                    } else {
+                        format!("{cond_snippet};")
+                    }
+                } else {
+                    String::new()
+                },
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
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 c0970048cdf..ece10474715 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
@@ -7,13 +7,12 @@ use clippy_utils::ty::{
 use clippy_utils::{get_trait_def_id, is_self, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind,
 };
-use rustc_hir::{HirIdMap, HirIdSet, LangItem};
+use rustc_hir::{HirIdSet, LangItem};
 use rustc_hir_typeck::expr_use_visitor as euv;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
@@ -126,9 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
             .filter_map(|pred| {
                 // Note that we do not want to deal with qualified predicates here.
                 match pred.kind().no_bound_vars() {
-                    Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => {
-                        Some(pred)
-                    },
+                    Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => Some(pred),
                     _ => None,
                 }
             })
@@ -136,11 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
 
         // Collect moved variables and spans which will need dereferencings from the
         // function body.
-        let MovedVariablesCtxt {
-            moved_vars,
-            spans_need_deref,
-            ..
-        } = {
+        let MovedVariablesCtxt { moved_vars } = {
             let mut ctx = MovedVariablesCtxt::default();
             let infcx = cx.tcx.infer_ctxt().build();
             euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
@@ -211,7 +204,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                             }
                         }
 
-                        let deref_span = spans_need_deref.get(&canonical_id);
                         if_chain! {
                             if is_type_diagnostic_item(cx, ty, sym::Vec);
                             if let Some(clone_spans) =
@@ -247,7 +239,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                 }
 
                                 // cannot be destructured, no need for `*` suggestion
-                                assert!(deref_span.is_none());
                                 return;
                             }
                         }
@@ -275,23 +266,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                                     );
                                 }
 
-                                assert!(deref_span.is_none());
                                 return;
                             }
                         }
 
-                        let mut spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))];
-
-                        // Suggests adding `*` to dereference the added reference.
-                        if let Some(deref_span) = deref_span {
-                            spans.extend(
-                                deref_span
-                                    .iter()
-                                    .copied()
-                                    .map(|span| (span, format!("*{}", snippet(cx, span, "<expr>")))),
-                            );
-                            spans.sort_by_key(|&(span, _)| span);
-                        }
+                        let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))];
+
                         multispan_sugg(diag, "consider taking a reference instead", spans);
                     };
 
@@ -320,9 +300,6 @@ fn requires_exact_signature(attrs: &[Attribute]) -> bool {
 #[derive(Default)]
 struct MovedVariablesCtxt {
     moved_vars: HirIdSet,
-    /// Spans which need to be prefixed with `*` for dereferencing the
-    /// suggested additional reference.
-    spans_need_deref: HirIdMap<FxHashSet<Span>>,
 }
 
 impl MovedVariablesCtxt {
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index e3712190e67..a4c7da7e48d 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -1,11 +1,16 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
-use clippy_utils::is_lint_allowed;
 use clippy_utils::peel_blocks;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::has_drop;
+use clippy_utils::{get_parent_node, is_lint_allowed};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, PatKind, Stmt, StmtKind, UnsafeSource};
+use rustc_hir::{
+    is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, FnRetTy, ItemKind, Node, PatKind, Stmt, StmtKind,
+    UnsafeSource,
+};
+use rustc_hir_analysis::hir_ty_to_ty;
+use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -86,7 +91,43 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
 fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
     if let StmtKind::Semi(expr) = stmt.kind {
         if has_no_effect(cx, expr) {
-            span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect");
+            span_lint_hir_and_then(
+                cx,
+                NO_EFFECT,
+                expr.hir_id,
+                stmt.span,
+                "statement with no effect",
+                |diag| {
+                    for parent in cx.tcx.hir().parent_iter(stmt.hir_id) {
+                        if let Node::Item(item) = parent.1
+                            && let ItemKind::Fn(sig, ..) = item.kind
+                            && let FnRetTy::Return(ret_ty) = sig.decl.output
+                            && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id)
+                            && let [.., final_stmt] = block.stmts
+                            && final_stmt.hir_id == stmt.hir_id
+                        {
+                            let expr_ty = cx.typeck_results().expr_ty(expr);
+                            let mut ret_ty = hir_ty_to_ty(cx.tcx, ret_ty);
+
+                            // Remove `impl Future<Output = T>` to get `T`
+                            if cx.tcx.ty_is_opaque_future(ret_ty) &&
+                                let Some(true_ret_ty) = cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
+                            {
+                                ret_ty = true_ret_ty;
+                            }
+
+                            if ret_ty == expr_ty {
+                                diag.span_suggestion(
+                                    stmt.span.shrink_to_lo(),
+                                    "did you mean to return it?",
+                                    "return ",
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                },
+            );
             return true;
         }
     } else if let StmtKind::Local(local) = stmt.kind {
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 58590df1fed..75f1e95276a 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -15,12 +15,14 @@ use rustc_hir::{
 };
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass, Lint};
-use rustc_middle::mir;
-use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::adjustment::Adjust;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, InnerSpan, Span};
+use rustc_target::abi::VariantIdx;
+use rustc_middle::mir::interpret::EvalToValTreeResult;
+use rustc_middle::mir::interpret::GlobalId;
 
 // FIXME: this is a correctness problem but there's no suitable
 // warn-by-default category.
@@ -141,21 +143,35 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 
 fn is_value_unfrozen_raw<'tcx>(
     cx: &LateContext<'tcx>,
-    result: Result<ConstValue<'tcx>, ErrorHandled>,
+    result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
     ty: Ty<'tcx>,
 ) -> bool {
-    fn inner<'tcx>(cx: &LateContext<'tcx>, val: mir::ConstantKind<'tcx>) -> bool {
-        match val.ty().kind() {
+    fn inner<'tcx>(cx: &LateContext<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> bool {
+        match *ty.kind() {
             // the fact that we have to dig into every structs to search enums
             // leads us to the point checking `UnsafeCell` directly is the only option.
             ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true,
             // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
             // contained value.
             ty::Adt(def, ..) if def.is_union() => false,
-            ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
-                let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
-                val.fields.iter().any(|field| inner(cx, *field))
+            ty::Array(ty, _)  => {
+                val.unwrap_branch().iter().any(|field| inner(cx, *field, ty))
             },
+            ty::Adt(def, _) if def.is_union() => false,
+            ty::Adt(def, substs) if def.is_enum() => {
+                let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap();
+                let variant_index =
+                    VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
+                fields.iter().copied().zip(
+                    def.variants()[variant_index]
+                        .fields
+                        .iter()
+                        .map(|field| field.ty(cx.tcx, substs))).any(|(field, ty)| inner(cx, field, ty))
+            }
+            ty::Adt(def, substs) => {
+                val.unwrap_branch().iter().zip(def.non_enum_variant().fields.iter().map(|field| field.ty(cx.tcx, substs))).any(|(field, ty)| inner(cx, *field, ty))
+            }
+            ty::Tuple(tys) => val.unwrap_branch().iter().zip(tys).any(|(field, ty)| inner(cx, *field, ty)),
             _ => false,
         }
     }
@@ -166,15 +182,15 @@ fn is_value_unfrozen_raw<'tcx>(
             // have a value that is a frozen variant with a generic param (an example is
             // `declare_interior_mutable_const::enums::BothOfCellAndGeneric::GENERIC_VARIANT`).
             // However, it prevents a number of false negatives that is, I think, important:
-            // 1. assoc consts in trait defs referring to consts of themselves
-            //    (an example is `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`).
-            // 2. a path expr referring to assoc consts whose type is doesn't have
-            //    any frozen variants in trait defs (i.e. without substitute for `Self`).
-            //    (e.g. borrowing `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`)
-            // 3. similar to the false positive above;
-            //    but the value is an unfrozen variant, or the type has no enums. (An example is
-            //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT`
-            //    and `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`).
+            // 1. assoc consts in trait defs referring to consts of themselves (an example is
+            //    `declare_interior_mutable_const::traits::ConcreteTypes::ANOTHER_ATOMIC`).
+            // 2. a path expr referring to assoc consts whose type is doesn't have any frozen variants in trait
+            //    defs (i.e. without substitute for `Self`). (e.g. borrowing
+            //    `borrow_interior_mutable_const::trait::ConcreteTypes::ATOMIC`)
+            // 3. similar to the false positive above; but the value is an unfrozen variant, or the type has no
+            //    enums. (An example is
+            //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::UNFROZEN_VARIANT` and
+            //    `declare_interior_mutable_const::enums::BothOfCellAndGeneric::NO_ENUM`).
             // One might be able to prevent these FNs correctly, and replace this with `false`;
             // e.g. implementing `has_frozen_variant` described above, and not running this function
             // when the type doesn't have any frozen variants would be the 'correct' way for the 2nd
@@ -184,24 +200,44 @@ fn is_value_unfrozen_raw<'tcx>(
             // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
             err == ErrorHandled::TooGeneric
         },
-        |val| inner(cx, mir::ConstantKind::from_value(val, ty)),
+        |val| val.map_or(true, |val| inner(cx, val, ty)),
     )
 }
 
 fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
-    let result = cx.tcx.const_eval_poly(body_id.hir_id.owner.to_def_id());
+    let def_id = body_id.hir_id.owner.to_def_id();
+    let substs = ty::InternalSubsts::identity_for_item(cx.tcx, def_id);
+    let instance = ty::Instance::new(def_id, substs);
+    let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
+    let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
+    let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, None);
     is_value_unfrozen_raw(cx, result, ty)
 }
 
 fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
     let substs = cx.typeck_results().node_substs(hir_id);
 
-    let result = cx
-        .tcx
-        .const_eval_resolve(cx.param_env, mir::UnevaluatedConst::new(def_id, substs), None);
+    let result = const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, substs), None);
     is_value_unfrozen_raw(cx, result, ty)
 }
 
+
+pub fn const_eval_resolve<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ct: ty::UnevaluatedConst<'tcx>,
+    span: Option<Span>,
+) -> EvalToValTreeResult<'tcx> {
+    match ty::Instance::resolve(tcx, param_env, ct.def, ct.substs) {
+        Ok(Some(instance)) => {
+            let cid = GlobalId { instance, promoted: None };
+            tcx.const_eval_global_id_for_typeck(param_env, cid, span)
+        }
+        Ok(None) => Err(ErrorHandled::TooGeneric),
+        Err(err) => Err(ErrorHandled::Reported(err.into())),
+    }
+}
+
 #[derive(Copy, Clone)]
 enum Source {
     Item { item: Span },
diff --git a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
index 67913f7392c..78965b7d6f7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace};
 use clippy_utils::{ast_utils::is_useless_with_eq_exprs, eq_expr_value, is_in_test_function};
 use rustc_hir::{BinOpKind, Expr};
@@ -35,11 +35,16 @@ pub(crate) fn check<'tcx>(
     right: &'tcx Expr<'_>,
 ) {
     if is_useless_with_eq_exprs(op.into()) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) {
-        span_lint(
+        span_lint_and_then(
             cx,
             EQ_OP,
             e.span,
             &format!("equal expressions as operands to `{}`", op.as_str()),
+            |diag| {
+                if let BinOpKind::Ne = op && cx.typeck_results().expr_ty(left).is_floating_point() {
+                    diag.note("if you intended to check if the operand is NaN, use `.is_nan()` instead");
+                }
+            },
         );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index 15dff126be7..f3e0c58a787 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -85,7 +85,7 @@ fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static
     }
 }
 
-fn is_allowed(val: &Constant) -> bool {
+fn is_allowed(val: &Constant<'_>) -> bool {
     match val {
         &Constant::F32(f) => f == 0.0 || f.is_infinite(),
         &Constant::F64(f) => f == 0.0 || f.is_infinite(),
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index aa6d4004268..abdccc47f54 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -140,6 +140,9 @@ fn try_get_option_occurrence<'tcx>(
             let (as_ref, as_mut) = match &expr.kind {
                 ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                 ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
+                _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => {
+                    (mutb == Mutability::Not, mutb == Mutability::Mut)
+                }
                 _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT),
             };
 
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index b8911f10907..866a04466c9 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -5,6 +5,7 @@ use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::expr_sig;
 use clippy_utils::visitors::contains_unsafe_block;
 use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths};
+use hir::LifetimeName;
 use if_chain::if_chain;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::def_id::DefId;
@@ -15,6 +16,7 @@ use rustc_hir::{
     ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind,
     TyKind, Unsafety,
 };
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_lint::{LateContext, LateLintPass};
@@ -166,6 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
                 cx,
                 cx.tcx.fn_sig(item.owner_id).subst_identity().skip_binder().inputs(),
                 sig.decl.inputs,
+                &sig.decl.output,
                 &[],
             )
             .filter(|arg| arg.mutability() == Mutability::Not)
@@ -218,7 +221,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
         check_mut_from_ref(cx, sig, Some(body));
         let decl = sig.decl;
         let sig = cx.tcx.fn_sig(item_id).subst_identity().skip_binder();
-        let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, body.params)
+        let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, &decl.output, body.params)
             .filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not)
             .collect();
         let results = check_ptr_arg_usage(cx, body, &lint_args);
@@ -407,29 +410,27 @@ impl<'tcx> DerefTy<'tcx> {
     }
 }
 
+#[expect(clippy::too_many_lines)]
 fn check_fn_args<'cx, 'tcx: 'cx>(
     cx: &'cx LateContext<'tcx>,
     tys: &'tcx [Ty<'tcx>],
     hir_tys: &'tcx [hir::Ty<'tcx>],
+    ret_ty: &'tcx FnRetTy<'tcx>,
     params: &'tcx [Param<'tcx>],
 ) -> impl Iterator<Item = PtrArg<'tcx>> + 'cx {
     tys.iter()
         .zip(hir_tys.iter())
         .enumerate()
-        .filter_map(|(i, (ty, hir_ty))| {
-            if_chain! {
-                if let ty::Ref(_, ty, mutability) = *ty.kind();
-                if let ty::Adt(adt, substs) = *ty.kind();
-
-                if let TyKind::Ref(lt, ref ty) = hir_ty.kind;
-                if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind;
-
+        .filter_map(move |(i, (ty, hir_ty))| {
+            if let ty::Ref(_, ty, mutability) = *ty.kind()
+                && let  ty::Adt(adt, substs) = *ty.kind()
+                && let TyKind::Ref(lt, ref ty) = hir_ty.kind
+                && let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind
                 // Check that the name as typed matches the actual name of the type.
                 // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec`
-                if let [.., name] = path.segments;
-                if cx.tcx.item_name(adt.did()) == name.ident.name;
-
-                then {
+                && let [.., name] = path.segments
+                && cx.tcx.item_name(adt.did()) == name.ident.name
+            {
                     let emission_id = params.get(i).map_or(hir_ty.hir_id, |param| param.hir_id);
                     let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) {
                         Some(sym::Vec) => (
@@ -454,30 +455,65 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                             DerefTy::Path,
                         ),
                         Some(sym::Cow) if mutability == Mutability::Not => {
-                            let ty_name = name.args
+                            if let Some((lifetime, ty)) = name.args
                                 .and_then(|args| {
-                                    args.args.iter().find_map(|a| match a {
-                                        GenericArg::Type(x) => Some(x),
-                                        _ => None,
-                                    })
+                                    if let [GenericArg::Lifetime(lifetime), ty] = args.args {
+                                        return Some((lifetime, ty));
+                                    }
+                                    None
                                 })
-                                .and_then(|arg| snippet_opt(cx, arg.span))
-                                .unwrap_or_else(|| substs.type_at(1).to_string());
-                            span_lint_hir_and_then(
-                                cx,
-                                PTR_ARG,
-                                emission_id,
-                                hir_ty.span,
-                                "using a reference to `Cow` is not recommended",
-                                |diag| {
-                                    diag.span_suggestion(
-                                        hir_ty.span,
-                                        "change this to",
-                                        format!("&{}{ty_name}", mutability.prefix_str()),
-                                        Applicability::Unspecified,
-                                    );
+                            {
+                                if !lifetime.is_anonymous()
+                                    && let FnRetTy::Return(ret_ty) = ret_ty
+                                    && let ret_ty = hir_ty_to_ty(cx.tcx, ret_ty)
+                                    && ret_ty
+                                        .walk()
+                                        .filter_map(|arg| {
+                                            arg.as_region().and_then(|lifetime| {
+                                                match lifetime.kind() {
+                                                    ty::ReEarlyBound(r) => Some(r.def_id),
+                                                    ty::ReLateBound(_, r) => r.kind.get_id(),
+                                                    ty::ReFree(r) => r.bound_region.get_id(),
+                                                    ty::ReStatic
+                                                    | ty::ReVar(_)
+                                                    | ty::RePlaceholder(_)
+                                                    | ty::ReErased
+                                                    | ty::ReError(_) => None,
+                                                }
+                                            })
+                                        })
+                                        .any(|def_id| {
+                                            matches!(
+                                                lifetime.res,
+                                                LifetimeName::Param(param_def_id) if def_id
+                                                    .as_local()
+                                                    .is_some_and(|def_id| def_id == param_def_id),
+                                            )
+                                        })
+                                {
+                                    // `&Cow<'a, T>` when the return type uses 'a is okay
+                                    return None;
                                 }
-                            );
+
+                                let ty_name =
+                                    snippet_opt(cx, ty.span()).unwrap_or_else(|| substs.type_at(1).to_string());
+
+                                span_lint_hir_and_then(
+                                    cx,
+                                    PTR_ARG,
+                                    emission_id,
+                                    hir_ty.span,
+                                    "using a reference to `Cow` is not recommended",
+                                    |diag| {
+                                        diag.span_suggestion(
+                                            hir_ty.span,
+                                            "change this to",
+                                            format!("&{}{ty_name}", mutability.prefix_str()),
+                                            Applicability::Unspecified,
+                                        );
+                                    }
+                                );
+                            }
                             return None;
                         },
                         _ => return None,
@@ -495,7 +531,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                         },
                         deref_ty,
                     });
-                }
             }
             None
         })
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 5269bbd1f1a..e3d940ad2a4 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -1,19 +1,20 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{
     eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, path_to_local, path_to_local_id,
     peel_blocks, peel_blocks_with_stmt,
 };
+use clippy_utils::{higher, is_path_lang_item};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::declare_tool_lint;
+use rustc_session::impl_lint_pass;
 use rustc_span::{sym, symbol::Symbol};
 
 declare_clippy_lint! {
@@ -41,7 +42,16 @@ declare_clippy_lint! {
     "checks for expressions that could be replaced by the question mark operator"
 }
 
-declare_lint_pass!(QuestionMark => [QUESTION_MARK]);
+#[derive(Default)]
+pub struct QuestionMark {
+    /// Keeps track of how many try blocks we are in at any point during linting.
+    /// This allows us to answer the question "are we inside of a try block"
+    /// very quickly, without having to walk up the parent chain, by simply checking
+    /// if it is greater than zero.
+    /// As for why we need this in the first place: <https://github.com/rust-lang/rust-clippy/issues/8628>
+    try_block_depth_stack: Vec<u32>,
+}
+impl_lint_pass!(QuestionMark => [QUESTION_MARK]);
 
 enum IfBlockType<'hir> {
     /// An `if x.is_xxx() { a } else { b } ` expression.
@@ -68,98 +78,6 @@ enum IfBlockType<'hir> {
     ),
 }
 
-/// Checks if the given expression on the given context matches the following structure:
-///
-/// ```ignore
-/// if option.is_none() {
-///    return None;
-/// }
-/// ```
-///
-/// ```ignore
-/// if result.is_err() {
-///     return result;
-/// }
-/// ```
-///
-/// If it matches, it will suggest to use the question mark operator instead
-fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-    if_chain! {
-        if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
-        if !is_else_clause(cx.tcx, expr);
-        if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind;
-        let caller_ty = cx.typeck_results().expr_ty(caller);
-        let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else);
-        if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
-            let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) &&
-                !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
-            let sugg = if let Some(else_inner) = r#else {
-                if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
-                    format!("Some({receiver_str}?)")
-                } else {
-                    return;
-                }
-            } else {
-                format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
-            };
-
-            span_lint_and_sugg(
-                cx,
-                QUESTION_MARK,
-                expr.span,
-                "this block may be rewritten with the `?` operator",
-                "replace it with",
-                sugg,
-                applicability,
-            );
-        }
-    }
-}
-
-fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-    if_chain! {
-        if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
-        if !is_else_clause(cx.tcx, expr);
-        if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind;
-        if ddpos.as_opt_usize().is_none();
-        if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
-        let caller_ty = cx.typeck_results().expr_ty(let_expr);
-        let if_block = IfBlockType::IfLet(
-            cx.qpath_res(path1, let_pat.hir_id),
-            caller_ty,
-            ident.name,
-            let_expr,
-            if_then,
-            if_else
-        );
-        if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
-            || is_early_return(sym::Result, cx, &if_block);
-        if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
-            let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
-            let sugg = format!(
-                "{receiver_str}{}?{}",
-                if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
-                if requires_semi { ";" } else { "" }
-            );
-            span_lint_and_sugg(
-                cx,
-                QUESTION_MARK,
-                expr.span,
-                "this block may be rewritten with the `?` operator",
-                "replace it with",
-                sugg,
-                applicability,
-            );
-        }
-    }
-}
-
 fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_>) -> bool {
     match *if_block {
         IfBlockType::IfIs(caller, caller_ty, call_sym, if_then, _) => {
@@ -230,11 +148,147 @@ fn expr_return_none_or_err(
     }
 }
 
+impl QuestionMark {
+    fn inside_try_block(&self) -> bool {
+        self.try_block_depth_stack.last() > Some(&0)
+    }
+
+    /// Checks if the given expression on the given context matches the following structure:
+    ///
+    /// ```ignore
+    /// if option.is_none() {
+    ///    return None;
+    /// }
+    /// ```
+    ///
+    /// ```ignore
+    /// if result.is_err() {
+    ///     return result;
+    /// }
+    /// ```
+    ///
+    /// If it matches, it will suggest to use the question mark operator instead
+    fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if_chain! {
+            if !self.inside_try_block();
+            if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
+            if !is_else_clause(cx.tcx, expr);
+            if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind;
+            let caller_ty = cx.typeck_results().expr_ty(caller);
+            let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else);
+            if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block);
+            then {
+                let mut applicability = Applicability::MachineApplicable;
+                let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
+                let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) &&
+                    !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
+                let sugg = if let Some(else_inner) = r#else {
+                    if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
+                        format!("Some({receiver_str}?)")
+                    } else {
+                        return;
+                    }
+                } else {
+                    format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
+                };
+
+                span_lint_and_sugg(
+                    cx,
+                    QUESTION_MARK,
+                    expr.span,
+                    "this block may be rewritten with the `?` operator",
+                    "replace it with",
+                    sugg,
+                    applicability,
+                );
+            }
+        }
+    }
+
+    fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if_chain! {
+            if !self.inside_try_block();
+            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
+            if !is_else_clause(cx.tcx, expr);
+            if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind;
+            if ddpos.as_opt_usize().is_none();
+            if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
+            let caller_ty = cx.typeck_results().expr_ty(let_expr);
+            let if_block = IfBlockType::IfLet(
+                cx.qpath_res(path1, let_pat.hir_id),
+                caller_ty,
+                ident.name,
+                let_expr,
+                if_then,
+                if_else
+            );
+            if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
+                || is_early_return(sym::Result, cx, &if_block);
+            if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
+            then {
+                let mut applicability = Applicability::MachineApplicable;
+                let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
+                let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
+                let sugg = format!(
+                    "{receiver_str}{}?{}",
+                    if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
+                    if requires_semi { ";" } else { "" }
+                );
+                span_lint_and_sugg(
+                    cx,
+                    QUESTION_MARK,
+                    expr.span,
+                    "this block may be rewritten with the `?` operator",
+                    "replace it with",
+                    sugg,
+                    applicability,
+                );
+            }
+        }
+    }
+}
+
+fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool {
+    if let Some(expr) = bl.expr
+        && let rustc_hir::ExprKind::Call(callee, _) = expr.kind
+    {
+        is_path_lang_item(cx, callee, LangItem::TryTraitFromOutput)
+    } else {
+        false
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for QuestionMark {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if !in_constant(cx, expr.hir_id) {
-            check_is_none_or_err_and_early_return(cx, expr);
-            check_if_let_some_or_err_and_early_return(cx, expr);
+            self.check_is_none_or_err_and_early_return(cx, expr);
+            self.check_if_let_some_or_err_and_early_return(cx, expr);
+        }
+    }
+
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) {
+        if is_try_block(cx, block) {
+            *self
+                .try_block_depth_stack
+                .last_mut()
+                .expect("blocks are always part of bodies and must have a depth") += 1;
+        }
+    }
+
+    fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) {
+        self.try_block_depth_stack.push(0);
+    }
+
+    fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) {
+        self.try_block_depth_stack.pop();
+    }
+
+    fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) {
+        if is_try_block(cx, block) {
+            *self
+                .try_block_depth_stack
+                .last_mut()
+                .expect("blocks are always part of bodies and must have a depth") -= 1;
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index dd7ded491e7..d2018aba9e3 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -296,8 +296,8 @@ fn check_possible_range_contains(
     }
 }
 
-struct RangeBounds<'a> {
-    val: Constant,
+struct RangeBounds<'a, 'tcx> {
+    val: Constant<'tcx>,
     expr: &'a Expr<'a>,
     id: HirId,
     name_span: Span,
@@ -309,7 +309,7 @@ struct RangeBounds<'a> {
 // Takes a binary expression such as x <= 2 as input
 // Breaks apart into various pieces, such as the value of the number,
 // hir id of the variable, and direction/inclusiveness of the operator
-fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<RangeBounds<'a>> {
+fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> Option<RangeBounds<'a, 'tcx>> {
     if let ExprKind::Binary(ref op, l, r) = ex.kind {
         let (inclusive, ordering) = match op.node {
             BinOpKind::Gt => (false, Ordering::Greater),
diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs
new file mode 100644
index 00000000000..f45bb1ef3e1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs
@@ -0,0 +1,143 @@
+use std::{iter::once, ops::ControlFlow};
+
+use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet};
+use rustc_ast::{
+    ast::{Expr, ExprKind},
+    token::LitKind,
+};
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for raw string literals where a string literal can be used instead.
+    ///
+    /// ### Why is this bad?
+    /// It's just unnecessary, but there are many cases where using a raw string literal is more
+    /// idiomatic than a string literal, so it's opt-in.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let r = r"Hello, world!";
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let r = "Hello, world!";
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub NEEDLESS_RAW_STRINGS,
+    restriction,
+    "suggests using a string literal when a raw string literal is unnecessary"
+}
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for raw string literals with an unnecessary amount of hashes around them.
+    ///
+    /// ### Why is this bad?
+    /// It's just unnecessary, and makes it look like there's more escaping needed than is actually
+    /// necessary.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let r = r###"Hello, "world"!"###;
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let r = r#"Hello, "world"!"#;
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub NEEDLESS_RAW_STRING_HASHES,
+    style,
+    "suggests reducing the number of hashes around a raw string literal"
+}
+impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]);
+
+pub struct RawStrings {
+    pub needless_raw_string_hashes_allow_one: bool,
+}
+
+impl EarlyLintPass for RawStrings {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
+        if !in_external_macro(cx.sess(), expr.span)
+            && let ExprKind::Lit(lit) = expr.kind
+            && let LitKind::StrRaw(max) | LitKind::ByteStrRaw(max) | LitKind::CStrRaw(max) = lit.kind
+        {
+            let str = lit.symbol.as_str();
+            let prefix = match lit.kind {
+                LitKind::StrRaw(..) => "r",
+                LitKind::ByteStrRaw(..) => "br",
+                LitKind::CStrRaw(..) => "cr",
+                _ => unreachable!(),
+            };
+            if !snippet(cx, expr.span, prefix).trim().starts_with(prefix) {
+                return;
+            }
+
+            if !str.contains(['\\', '"']) {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_RAW_STRINGS,
+                    expr.span,
+                    "unnecessary raw string literal",
+                    "try",
+                    format!("{}\"{}\"", prefix.replace('r', ""), lit.symbol),
+                    Applicability::MachineApplicable,
+                );
+
+                return;
+            }
+
+            let req = {
+                let mut following_quote = false;
+                let mut req = 0;
+                // `once` so a raw string ending in hashes is still checked
+                let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| {
+                    match b {
+                        b'"' => (following_quote, req) = (true, 1),
+                        // I'm a bit surprised the compiler didn't optimize this out, there's no
+                        // branch but it still ends up doing an unnecessary comparison, it's:
+                        // - cmp r9b,1h
+                        // - sbb cl,-1h
+                        // which will add 1 if it's true. With this change, it becomes:
+                        // - add cl,r9b
+                        // isn't that so much nicer?
+                        b'#' => req += u8::from(following_quote),
+                        _ => {
+                            if following_quote {
+                                following_quote = false;
+
+                                if req == max {
+                                    return ControlFlow::Break(req);
+                                }
+
+                                return ControlFlow::Continue(acc.max(req));
+                            }
+                        },
+                    }
+
+                    ControlFlow::Continue(acc)
+                });
+
+                match num {
+                    ControlFlow::Continue(num) | ControlFlow::Break(num) => num,
+                }
+            };
+
+            if req < max {
+                let hashes = "#".repeat(req as usize);
+
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_RAW_STRING_HASHES,
+                    expr.span,
+                    "unnecessary hashes around raw string literal",
+                    "try",
+                    format!(r#"{prefix}{hashes}"{}"{hashes}"#, lit.symbol),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 944a33cc3e5..e36adef555e 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -57,7 +57,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.32.0"]
     pub REDUNDANT_CLONE,
-    perf,
+    nursery,
     "`clone()` of an owned value that is going to be dropped immediately"
 }
 
@@ -320,8 +320,6 @@ fn base_local_and_movability<'tcx>(
     mir: &mir::Body<'tcx>,
     place: mir::Place<'tcx>,
 ) -> (mir::Local, CannotMoveOut) {
-    use rustc_middle::mir::PlaceRef;
-
     // Dereference. You cannot move things out from a borrowed value.
     let mut deref = false;
     // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
@@ -330,17 +328,14 @@ fn base_local_and_movability<'tcx>(
     // underlying type implements Copy
     let mut slice = false;
 
-    let PlaceRef { local, mut projection } = place.as_ref();
-    while let [base @ .., elem] = projection {
-        projection = base;
+    for (base, elem) in place.as_ref().iter_projections() {
+        let base_ty = base.ty(&mir.local_decls, cx.tcx).ty;
         deref |= matches!(elem, mir::ProjectionElem::Deref);
-        field |= matches!(elem, mir::ProjectionElem::Field(..))
-            && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
-        slice |= matches!(elem, mir::ProjectionElem::Index(..))
-            && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
+        field |= matches!(elem, mir::ProjectionElem::Field(..)) && has_drop(cx, base_ty);
+        slice |= matches!(elem, mir::ProjectionElem::Index(..)) && !is_copy(cx, base_ty);
     }
 
-    (local, deref || field || slice)
+    (place.local, deref || field || slice)
 }
 
 #[derive(Default)]
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 2a42e73488f..b6ce4ebc28f 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -1,14 +1,14 @@
+use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::get_parent_expr;
 use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
-use rustc_ast::ast;
-use rustc_ast::visit as ast_visit;
-use rustc_ast::visit::Visitor as AstVisitor;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor as HirVisitor;
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_hir::intravisit::Visitor;
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -51,59 +51,136 @@ impl ReturnVisitor {
     }
 }
 
-impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
-    fn visit_expr(&mut self, ex: &'ast ast::Expr) {
-        if let ast::ExprKind::Ret(_) | ast::ExprKind::Try(_) = ex.kind {
+impl<'tcx> Visitor<'tcx> for ReturnVisitor {
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
+        if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) = ex.kind {
             self.found_return = true;
+        } else {
+            hir_visit::walk_expr(self, ex);
         }
+    }
+}
 
-        ast_visit::walk_expr(self, ex);
+/// Checks if the body is owned by an async closure
+fn is_async_closure(body: &hir::Body<'_>) -> bool {
+    if let hir::ExprKind::Closure(closure) = body.value.kind
+        && let [resume_ty] = closure.fn_decl.inputs
+        && let hir::TyKind::Path(hir::QPath::LangItem(hir::LangItem::ResumeTy, ..)) = resume_ty.kind
+    {
+        true
+    } else {
+        false
     }
 }
 
-impl EarlyLintPass for RedundantClosureCall {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+/// Tries to find the innermost closure:
+/// ```rust,ignore
+/// (|| || || || 42)()()()()
+///  ^^^^^^^^^^^^^^          given this nested closure expression
+///           ^^^^^          we want to return this closure
+/// ```
+/// It also has a parameter for how many steps to go in at most, so as to
+/// not take more closures than there are calls.
+fn find_innermost_closure<'tcx>(
+    cx: &LateContext<'tcx>,
+    mut expr: &'tcx hir::Expr<'tcx>,
+    mut steps: usize,
+) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> {
+    let mut data = None;
+
+    while let hir::ExprKind::Closure(closure) = expr.kind
+        && let body = cx.tcx.hir().body(closure.body)
+        && {
+            let mut visitor = ReturnVisitor::new();
+            visitor.visit_expr(body.value);
+            !visitor.found_return
+        }
+        && steps > 0
+    {
+        expr = body.value;
+        data = Some((body.value, closure.fn_decl, if is_async_closure(body) {
+            hir::IsAsync::Async
+        } else {
+            hir::IsAsync::NotAsync
+        }));
+        steps -= 1;
+    }
+
+    data
+}
+
+/// "Walks up" the chain of calls to find the outermost call expression, and returns the depth:
+/// ```rust,ignore
+/// (|| || || 3)()()()
+///             ^^      this is the call expression we were given
+///                 ^^  this is what we want to return (and the depth is 3)
+/// ```
+fn get_parent_call_exprs<'tcx>(
+    cx: &LateContext<'tcx>,
+    mut expr: &'tcx hir::Expr<'tcx>,
+) -> (&'tcx hir::Expr<'tcx>, usize) {
+    let mut depth = 1;
+    while let Some(parent) = get_parent_expr(cx, expr)
+        && let hir::ExprKind::Call(recv, _) = parent.kind
+        && expr.span == recv.span
+    {
+        expr = parent;
+        depth += 1;
+    }
+    (expr, depth)
+}
+
+impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         if in_external_macro(cx.sess(), expr.span) {
             return;
         }
-        if_chain! {
-            if let ast::ExprKind::Call(ref paren, _) = expr.kind;
-            if let ast::ExprKind::Paren(ref closure) = paren.kind;
-            if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind;
-            then {
-                let mut visitor = ReturnVisitor::new();
-                visitor.visit_expr(body);
-                if !visitor.found_return {
-                    span_lint_and_then(
-                        cx,
-                        REDUNDANT_CLOSURE_CALL,
-                        expr.span,
-                        "try not to call a closure in the expression where it is declared",
-                        |diag| {
-                            if fn_decl.inputs.is_empty() {
-                                let mut app = Applicability::MachineApplicable;
-                                let mut hint = Sugg::ast(cx, body, "..", closure.span.ctxt(), &mut app);
-
-                                if asyncness.is_async() {
-                                    // `async x` is a syntax error, so it becomes `async { x }`
-                                    if !matches!(body.kind, ast::ExprKind::Block(_, _)) {
-                                        hint = hint.blockify();
-                                    }
-
-                                    hint = hint.asyncify();
-                                }
-
-                                diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app);
+
+        if let hir::ExprKind::Call(recv, _) = expr.kind
+            // don't lint if the receiver is a call, too. 
+            // we do this in order to prevent linting multiple times; consider:
+            // `(|| || 1)()()`
+            //           ^^  we only want to lint for this call (but we walk up the calls to consider both calls).
+            // without this check, we'd end up linting twice.
+            && !matches!(recv.kind, hir::ExprKind::Call(..))
+            && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr)
+            && let Some((body, fn_decl, generator_kind)) = find_innermost_closure(cx, recv, call_depth)
+        {
+            span_lint_and_then(
+                cx,
+                REDUNDANT_CLOSURE_CALL,
+                full_expr.span,
+                "try not to call a closure in the expression where it is declared",
+                |diag| {
+                    if fn_decl.inputs.is_empty() {
+                        let mut applicability = Applicability::MachineApplicable;
+                        let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability);
+
+                        if generator_kind.is_async()
+                            && let hir::ExprKind::Closure(closure) = body.kind
+                        {
+                            let async_closure_body = cx.tcx.hir().body(closure.body);
+
+                            // `async x` is a syntax error, so it becomes `async { x }`
+                            if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) {
+                                hint = hint.blockify();
                             }
-                        },
-                    );
+
+                            hint = hint.asyncify();
+                        }
+
+                        diag.span_suggestion(
+                            full_expr.span,
+                            "try doing something like",
+                            hint.maybe_par(),
+                            applicability
+                        );
+                    }
                 }
-            }
+            );
         }
     }
-}
 
-impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
         fn count_closure_usage<'tcx>(
             cx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs
new file mode 100644
index 00000000000..8e9234bba3c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs
@@ -0,0 +1,210 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::LitKind;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Warns about needless / redundant type annotations.
+    ///
+    /// ### Why is this bad?
+    /// Code without type annotations is shorter and in most cases
+    /// more idiomatic and easier to modify.
+    ///
+    /// ### Limitations
+    /// This lint doesn't support:
+    ///
+    /// - Generics
+    /// - Refs returned from anything else than a `MethodCall`
+    /// - Complex types (tuples, arrays, etc...)
+    /// - `Path` to anything else than a primitive type.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let foo: String = String::new();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let foo = String::new();
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub REDUNDANT_TYPE_ANNOTATIONS,
+    restriction,
+    "warns about needless / redundant type annotations."
+}
+declare_lint_pass!(RedundantTypeAnnotations => [REDUNDANT_TYPE_ANNOTATIONS]);
+
+fn is_same_type<'tcx>(cx: &LateContext<'tcx>, ty_resolved_path: hir::def::Res, func_return_type: Ty<'tcx>) -> bool {
+    // type annotation is primitive
+    if let hir::def::Res::PrimTy(primty) = ty_resolved_path
+        && func_return_type.is_primitive()
+        && let Some(func_return_type_sym) = func_return_type.primitive_symbol()
+    {
+        return primty.name() == func_return_type_sym;
+    }
+
+    // type annotation is any other non generic type
+    if let hir::def::Res::Def(_, defid) = ty_resolved_path
+        && let Some(annotation_ty) = cx.tcx.type_of(defid).no_bound_vars()
+    {
+        return annotation_ty == func_return_type;
+    }
+
+    false
+}
+
+fn func_hir_id_to_func_ty<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::hir_id::HirId) -> Option<Ty<'tcx>> {
+    if let Some((defkind, func_defid)) = cx.typeck_results().type_dependent_def(hir_id)
+        && defkind == hir::def::DefKind::AssocFn
+        && let Some(init_ty) = cx.tcx.type_of(func_defid).no_bound_vars()
+    {
+        Some(init_ty)
+    } else {
+        None
+    }
+}
+
+fn func_ty_to_return_type<'tcx>(cx: &LateContext<'tcx>, func_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+    if func_ty.is_fn() {
+        Some(func_ty.fn_sig(cx.tcx).output().skip_binder())
+    } else {
+        None
+    }
+}
+
+/// Extracts the fn Ty, e.g. `fn() -> std::string::String {f}`
+fn extract_fn_ty<'tcx>(
+    cx: &LateContext<'tcx>,
+    call: &hir::Expr<'tcx>,
+    func_return_path: &hir::QPath<'tcx>,
+) -> Option<Ty<'tcx>> {
+    match func_return_path {
+        // let a: String = f(); where f: fn f() -> String
+        hir::QPath::Resolved(_, resolved_path) => {
+            if let hir::def::Res::Def(_, defid) = resolved_path.res
+                && let Some(middle_ty_init) = cx.tcx.type_of(defid).no_bound_vars()
+            {
+                Some(middle_ty_init)
+            } else {
+                None
+            }
+        },
+        // Associated functions like
+        // let a: String = String::new();
+        // let a: String = String::get_string();
+        hir::QPath::TypeRelative(..) => func_hir_id_to_func_ty(cx, call.hir_id),
+        hir::QPath::LangItem(..) => None,
+    }
+}
+
+fn is_redundant_in_func_call<'tcx>(
+    cx: &LateContext<'tcx>,
+    ty_resolved_path: hir::def::Res,
+    call: &hir::Expr<'tcx>,
+) -> bool {
+    if let hir::ExprKind::Path(init_path) = &call.kind {
+        let func_type = extract_fn_ty(cx, call, init_path);
+
+        if let Some(func_type) = func_type
+            && let Some(init_return_type) = func_ty_to_return_type(cx, func_type)
+        {
+            return is_same_type(cx, ty_resolved_path, init_return_type);
+        }
+    }
+
+    false
+}
+
+fn extract_primty(ty_kind: &hir::TyKind<'_>) -> Option<hir::PrimTy> {
+    if let hir::TyKind::Path(ty_path) = ty_kind
+        && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path
+        && let hir::def::Res::PrimTy(primty) = resolved_path_ty.res
+    {
+        Some(primty)
+    } else {
+        None
+    }
+}
+
+impl LateLintPass<'_> for RedundantTypeAnnotations {
+    fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::Local<'tcx>) {
+        // type annotation part
+        if !local.span.from_expansion()
+            && let Some(ty) = &local.ty
+
+            // initialization part
+            && let Some(init) = local.init
+        {
+            match &init.kind {
+                // When the initialization is a call to a function
+                hir::ExprKind::Call(init_call, _) => {
+                    if let hir::TyKind::Path(ty_path) = &ty.kind
+                        && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path
+
+                        && is_redundant_in_func_call(cx, resolved_path_ty.res, init_call) {
+                        span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
+                    }
+                },
+                hir::ExprKind::MethodCall(_, _, _, _) => {
+                    let mut is_ref = false;
+                    let mut ty_kind = &ty.kind;
+
+                    // If the annotation is a ref we "peel" it
+                    if let hir::TyKind::Ref(_, mut_ty) = &ty.kind {
+                        is_ref = true;
+                        ty_kind = &mut_ty.ty.kind;
+                    }
+
+                    if let hir::TyKind::Path(ty_path) = ty_kind
+                        && let hir::QPath::Resolved(_, resolved_path_ty) = ty_path
+                        && let Some(func_ty) = func_hir_id_to_func_ty(cx, init.hir_id)
+                        && let Some(return_type) = func_ty_to_return_type(cx, func_ty)
+                        && is_same_type(cx, resolved_path_ty.res, if is_ref {
+                            return_type.peel_refs()
+                        } else {
+                            return_type
+                        })
+                    {
+                        span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
+                    }
+                },
+                // When the initialization is a path for example u32::MAX
+                hir::ExprKind::Path(init_path) => {
+                    // TODO: check for non primty
+                    if let Some(primty) = extract_primty(&ty.kind)
+
+                        && let hir::QPath::TypeRelative(init_ty, _) = init_path
+                        && let Some(primty_init) = extract_primty(&init_ty.kind)
+
+                        && primty == primty_init
+                    {
+                        span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
+                    }
+                },
+                hir::ExprKind::Lit(init_lit) => {
+                    match init_lit.node {
+                        // In these cases the annotation is redundant
+                        LitKind::Str(..)
+                        | LitKind::ByteStr(..)
+                        | LitKind::Byte(..)
+                        | LitKind::Char(..)
+                        | LitKind::Bool(..)
+                        | LitKind::CStr(..) => {
+                            span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
+                        },
+                        LitKind::Int(..) | LitKind::Float(..) => {
+                            // If the initialization value is a suffixed literal we lint
+                            if init_lit.node.is_suffixed() {
+                                span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
+                            }
+                        },
+                        LitKind::Err => (),
+                    }
+                }
+                _ => ()
+            }
+        };
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 631ecf1428d..958351ad81b 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -25,6 +25,12 @@ declare_clippy_lint! {
     /// It is just extraneous code. Remove it to make your code
     /// more rusty.
     ///
+    /// ### Known problems
+    /// In the case of some temporaries, e.g. locks, eliding the variable binding could lead
+    /// to deadlocks. See [this issue](https://github.com/rust-lang/rust/issues/37612).
+    /// This could become relevant if the code is later changed to use the code that would have been
+    /// bound without first assigning it to a let-binding.
+    ///
     /// ### Example
     /// ```rust
     /// fn foo() -> String {
@@ -286,7 +292,7 @@ fn check_final_expr<'tcx>(
         // (except for unit type functions) so we don't match it
         ExprKind::Match(_, arms, MatchSource::Normal) => {
             let match_ty = cx.typeck_results().expr_ty(peeled_drop_expr);
-            for arm in arms.iter() {
+            for arm in *arms {
                 check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit, Some(match_ty));
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index b930b2c8dd7..fffa8a380c2 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -1,10 +1,10 @@
 use clippy_utils::{
     diagnostics::span_lint_and_then,
-    get_attr,
+    expr_or_init, get_attr, path_to_local,
     source::{indent_of, snippet},
 };
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_errors::Applicability;
 use rustc_hir::{
     self as hir,
     intravisit::{walk_expr, Visitor},
@@ -13,6 +13,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::{subst::GenericArgKind, Ty, TypeAndMut};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{symbol::Ident, Span, DUMMY_SP};
+use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -56,255 +57,102 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
 
 #[derive(Default)]
 pub struct SignificantDropTightening<'tcx> {
+    apas: FxIndexMap<hir::HirId, AuxParamsAttr>,
     /// Auxiliary structure used to avoid having to verify the same type multiple times.
     seen_types: FxHashSet<Ty<'tcx>>,
     type_cache: FxHashMap<Ty<'tcx>, bool>,
 }
 
-impl<'tcx> SignificantDropTightening<'tcx> {
-    /// Unifies the statements of a block with its return expression.
-    fn all_block_stmts<'ret, 'rslt, 'stmts>(
-        block_stmts: &'stmts [hir::Stmt<'tcx>],
-        dummy_ret_stmt: Option<&'ret hir::Stmt<'tcx>>,
-    ) -> impl Iterator<Item = &'rslt hir::Stmt<'tcx>>
-    where
-        'ret: 'rslt,
-        'stmts: 'rslt,
-    {
-        block_stmts.iter().chain(dummy_ret_stmt)
-    }
-
-    /// Searches for at least one statement that could slow down the release of a significant drop.
-    fn at_least_one_stmt_is_expensive<'stmt>(stmts: impl Iterator<Item = &'stmt hir::Stmt<'tcx>>) -> bool
-    where
-        'tcx: 'stmt,
-    {
-        for stmt in stmts {
-            match stmt.kind {
-                hir::StmtKind::Expr(expr) if let hir::ExprKind::Path(_) = expr.kind => {}
-                hir::StmtKind::Local(local) if let Some(expr) = local.init
-                    && let hir::ExprKind::Path(_) = expr.kind => {},
-                _ => return true
-            };
-        }
-        false
-    }
-
-    /// Verifies if the expression is of type `drop(some_lock_path)` to assert that the temporary
-    /// is already being dropped before the end of its scope.
-    fn has_drop(expr: &'tcx hir::Expr<'_>, init_bind_ident: Ident) -> bool {
-        if let hir::ExprKind::Call(fun, args) = expr.kind
-            && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
-            && let [fun_ident, ..] = fun_path.segments
-            && fun_ident.ident.name == rustc_span::sym::drop
-            && let [first_arg, ..] = args
-            && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind
-            && let [first_arg_ps, .. ] = arg_path.segments
-        {
-            first_arg_ps.ident == init_bind_ident
-        }
-        else {
-            false
-        }
-    }
-
-    /// Tries to find types marked with `#[has_significant_drop]` of an expression `expr` that is
-    /// originated from `stmt` and then performs common logic on `sdap`.
-    fn modify_sdap_if_sig_drop_exists(
+impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
+    fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
-        expr: &'tcx hir::Expr<'_>,
-        idx: usize,
-        sdap: &mut SigDropAuxParams,
-        stmt: &hir::Stmt<'_>,
-        cb: impl Fn(&mut SigDropAuxParams),
+        _: hir::intravisit::FnKind<'_>,
+        _: &hir::FnDecl<'_>,
+        body: &'tcx hir::Body<'_>,
+        _: Span,
+        _: hir::def_id::LocalDefId,
     ) {
-        let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types, &mut self.type_cache);
-        sig_drop_finder.visit_expr(expr);
-        if sig_drop_finder.has_sig_drop {
-            cb(sdap);
-            if sdap.number_of_stmts > 0 {
-                sdap.last_use_stmt_idx = idx;
-                sdap.last_use_stmt_span = stmt.span;
-                if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind {
-                    sdap.last_use_method_span = span;
-                }
+        self.apas.clear();
+        let initial_dummy_stmt = dummy_stmt_expr(body.value);
+        let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt);
+        StmtsChecker::new(&mut ap, cx, &mut self.seen_types, &mut self.type_cache).visit_body(body);
+        for apa in ap.apas.values() {
+            if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
+                continue;
             }
-            sdap.number_of_stmts = sdap.number_of_stmts.wrapping_add(1);
-        }
-    }
-
-    /// Shows generic overall messages as well as specialized messages depending on the usage.
-    fn set_suggestions(cx: &LateContext<'tcx>, block_span: Span, diag: &mut Diagnostic, sdap: &SigDropAuxParams) {
-        match sdap.number_of_stmts {
-            0 | 1 => {},
-            2 => {
-                let indent = " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0));
-                let init_method = snippet(cx, sdap.init_method_span, "..");
-                let usage_method = snippet(cx, sdap.last_use_method_span, "..");
-                let stmt = if let Some(last_use_bind_span) = sdap.last_use_bind_span {
-                    format!(
-                        "\n{indent}let {} = {init_method}.{usage_method};",
-                        snippet(cx, last_use_bind_span, ".."),
-                    )
-                } else {
-                    format!("\n{indent}{init_method}.{usage_method};")
-                };
-                diag.span_suggestion_verbose(
-                    sdap.init_stmt_span,
-                    "merge the temporary construction with its single usage",
-                    stmt,
-                    Applicability::MaybeIncorrect,
-                );
-                diag.span_suggestion(
-                    sdap.last_use_stmt_span,
-                    "remove separated single usage",
-                    "",
-                    Applicability::MaybeIncorrect,
-                );
-            },
-            _ => {
-                diag.span_suggestion(
-                    sdap.last_use_stmt_span.shrink_to_hi(),
-                    "drop the temporary after the end of its last usage",
-                    format!(
-                        "\n{}drop({});",
-                        " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)),
-                        sdap.init_bind_ident
-                    ),
-                    Applicability::MaybeIncorrect,
-                );
-            },
-        }
-        diag.note("this might lead to unnecessary resource contention");
-        diag.span_label(
-            block_span,
-            format!(
-                "temporary `{}` is currently being dropped at the end of its contained scope",
-                sdap.init_bind_ident
-            ),
-        );
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
-    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
-        let dummy_ret_stmt = block.expr.map(|expr| hir::Stmt {
-            hir_id: hir::HirId::INVALID,
-            kind: hir::StmtKind::Expr(expr),
-            span: DUMMY_SP,
-        });
-        let mut sdap = SigDropAuxParams::default();
-        for (idx, stmt) in Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).enumerate() {
-            match stmt.kind {
-                hir::StmtKind::Expr(expr) => self.modify_sdap_if_sig_drop_exists(
-                    cx,
-                    expr,
-                    idx,
-                    &mut sdap,
-                    stmt,
-                    |_| {}
-                ),
-                hir::StmtKind::Local(local) if let Some(expr) = local.init => self.modify_sdap_if_sig_drop_exists(
-                    cx,
-                    expr,
-                    idx,
-                    &mut sdap,
-                    stmt,
-                    |local_sdap| {
-                        if local_sdap.number_of_stmts == 0 {
-                            if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
-                                local_sdap.init_bind_ident = ident;
-                            }
-                            if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr.kind {
-                                local_sdap.init_method_span = local_expr.span.to(span);
-                            }
-                            local_sdap.init_stmt_span = stmt.span;
-                        }
-                        else if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
-                            local_sdap.last_use_bind_span = Some(ident.span);
-                        }
-                    }
-                ),
-                hir::StmtKind::Semi(expr) => {
-                    if Self::has_drop(expr, sdap.init_bind_ident) {
-                        return;
-                    }
-                    self.modify_sdap_if_sig_drop_exists(cx, expr, idx, &mut sdap, stmt, |_| {});
-                },
-                _ => {}
-            };
-        }
-
-        let idx = sdap.last_use_stmt_idx.wrapping_add(1);
-        let stmts_after_last_use = Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).skip(idx);
-        if sdap.number_of_stmts > 1 && Self::at_least_one_stmt_is_expensive(stmts_after_last_use) {
             span_lint_and_then(
                 cx,
                 SIGNIFICANT_DROP_TIGHTENING,
-                sdap.init_bind_ident.span,
+                apa.first_bind_ident.span,
                 "temporary with significant `Drop` can be early dropped",
                 |diag| {
-                    Self::set_suggestions(cx, block.span, diag, &sdap);
+                    match apa.counter {
+                        0 | 1 => {},
+                        2 => {
+                            let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0));
+                            let init_method = snippet(cx, apa.first_method_span, "..");
+                            let usage_method = snippet(cx, apa.last_method_span, "..");
+                            let stmt = if apa.last_bind_ident == Ident::empty() {
+                                format!("\n{indent}{init_method}.{usage_method};")
+                            } else {
+                                format!(
+                                    "\n{indent}let {} = {init_method}.{usage_method};",
+                                    snippet(cx, apa.last_bind_ident.span, ".."),
+                                )
+                            };
+                            diag.span_suggestion_verbose(
+                                apa.first_stmt_span,
+                                "merge the temporary construction with its single usage",
+                                stmt,
+                                Applicability::MaybeIncorrect,
+                            );
+                            diag.span_suggestion(
+                                apa.last_stmt_span,
+                                "remove separated single usage",
+                                "",
+                                Applicability::MaybeIncorrect,
+                            );
+                        },
+                        _ => {
+                            diag.span_suggestion(
+                                apa.last_stmt_span.shrink_to_hi(),
+                                "drop the temporary after the end of its last usage",
+                                format!(
+                                    "\n{}drop({});",
+                                    " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)),
+                                    apa.first_bind_ident
+                                ),
+                                Applicability::MaybeIncorrect,
+                            );
+                        },
+                    }
+                    diag.note("this might lead to unnecessary resource contention");
+                    diag.span_label(
+                        apa.first_block_span,
+                        format!(
+                            "temporary `{}` is currently being dropped at the end of its contained scope",
+                            apa.first_bind_ident
+                        ),
+                    );
                 },
             );
         }
     }
 }
 
-/// Auxiliary parameters used on each block check.
-struct SigDropAuxParams {
-    /// The binding or variable that references the initial construction of the type marked with
-    /// `#[has_significant_drop]`.
-    init_bind_ident: Ident,
-    /// Similar to `init_bind_ident` but encompasses the right-hand method call.
-    init_method_span: Span,
-    /// Similar to `init_bind_ident` but encompasses the whole contained statement.
-    init_stmt_span: Span,
-
-    /// The last visited binding or variable span within a block that had any referenced inner type
-    /// marked with `#[has_significant_drop]`.
-    last_use_bind_span: Option<Span>,
-    /// Index of the last visited statement within a block that had any referenced inner type
-    /// marked with `#[has_significant_drop]`.
-    last_use_stmt_idx: usize,
-    /// Similar to `last_use_bind_span` but encompasses the whole contained statement.
-    last_use_stmt_span: Span,
-    /// Similar to `last_use_bind_span` but encompasses the right-hand method call.
-    last_use_method_span: Span,
-
-    /// Total number of statements within a block that have any referenced inner type marked with
-    /// `#[has_significant_drop]`.
-    number_of_stmts: usize,
-}
-
-impl Default for SigDropAuxParams {
-    fn default() -> Self {
-        Self {
-            init_bind_ident: Ident::empty(),
-            init_method_span: DUMMY_SP,
-            init_stmt_span: DUMMY_SP,
-            last_use_bind_span: None,
-            last_use_method_span: DUMMY_SP,
-            last_use_stmt_idx: 0,
-            last_use_stmt_span: DUMMY_SP,
-            number_of_stmts: 0,
-        }
-    }
-}
-
-/// Checks the existence of the `#[has_significant_drop]` attribute
-struct SigDropChecker<'cx, 'sdt, 'tcx> {
+/// Checks the existence of the `#[has_significant_drop]` attribute.
+struct AttrChecker<'cx, 'others, 'tcx> {
     cx: &'cx LateContext<'tcx>,
-    seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
-    type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+    seen_types: &'others mut FxHashSet<Ty<'tcx>>,
+    type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
 }
 
-impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
+impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
     pub(crate) fn new(
         cx: &'cx LateContext<'tcx>,
-        seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
-        type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+        seen_types: &'others mut FxHashSet<Ty<'tcx>>,
+        type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
     ) -> Self {
         seen_types.clear();
         Self {
@@ -314,7 +162,17 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
         }
     }
 
-    pub(crate) fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
+    fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+        // The borrow checker prevents us from using something fancier like or_insert_with.
+        if let Some(ty) = self.type_cache.get(&ty) {
+            return *ty;
+        }
+        let value = self.has_sig_drop_attr_uncached(ty);
+        self.type_cache.insert(ty, value);
+        value
+    }
+
+    fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
         if let Some(adt) = ty.ty_adt_def() {
             let mut iter = get_attr(
                 self.cx.sess(),
@@ -333,7 +191,7 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
                         return true;
                     }
                 }
-                for generic_arg in b.iter() {
+                for generic_arg in *b {
                     if let GenericArgKind::Type(ty) = generic_arg.unpack() {
                         if self.has_sig_drop_attr(ty) {
                             return true;
@@ -350,73 +208,244 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
         }
     }
 
-    pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
-        // The borrow checker prevents us from using something fancier like or_insert_with.
-        if let Some(ty) = self.type_cache.get(&ty) {
-            return *ty;
-        }
-        let value = self.has_sig_drop_attr_uncached(ty);
-        self.type_cache.insert(ty, value);
-        value
-    }
-
     fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
         !self.seen_types.insert(ty)
     }
 }
 
-/// Performs recursive calls to find any inner type marked with `#[has_significant_drop]`.
-struct SigDropFinder<'cx, 'sdt, 'tcx> {
-    cx: &'cx LateContext<'tcx>,
-    has_sig_drop: bool,
-    sig_drop_checker: SigDropChecker<'cx, 'sdt, 'tcx>,
+struct StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
+    ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
+    cx: &'lc LateContext<'tcx>,
+    seen_types: &'others mut FxHashSet<Ty<'tcx>>,
+    type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
 }
 
-impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> {
+impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
     fn new(
-        cx: &'cx LateContext<'tcx>,
-        seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
-        type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+        ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
+        cx: &'lc LateContext<'tcx>,
+        seen_types: &'others mut FxHashSet<Ty<'tcx>>,
+        type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
     ) -> Self {
         Self {
+            ap,
             cx,
-            has_sig_drop: false,
-            sig_drop_checker: SigDropChecker::new(cx, seen_types, type_cache),
+            seen_types,
+            type_cache,
+        }
+    }
+
+    fn manage_has_expensive_expr_after_last_attr(&mut self) {
+        let has_expensive_stmt = match self.ap.curr_stmt.kind {
+            hir::StmtKind::Expr(expr) if !is_expensive_expr(expr) => false,
+            hir::StmtKind::Local(local) if let Some(expr) = local.init
+                && let hir::ExprKind::Path(_) = expr.kind => false,
+            _ => true
+        };
+        if has_expensive_stmt {
+            for apa in self.ap.apas.values_mut() {
+                let last_stmt_is_not_dummy = apa.last_stmt_span != DUMMY_SP;
+                let last_stmt_is_not_curr = self.ap.curr_stmt.span != apa.last_stmt_span;
+                let block_equals_curr = self.ap.curr_block_hir_id == apa.first_block_hir_id;
+                let block_is_ancestor = self
+                    .cx
+                    .tcx
+                    .hir()
+                    .parent_iter(self.ap.curr_block_hir_id)
+                    .any(|(id, _)| id == apa.first_block_hir_id);
+                if last_stmt_is_not_dummy && last_stmt_is_not_curr && (block_equals_curr || block_is_ancestor) {
+                    apa.has_expensive_expr_after_last_attr = true;
+                }
+            }
         }
     }
 }
 
-impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> {
-    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'_>) {
-        if self
-            .sig_drop_checker
-            .has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex))
-        {
-            self.has_sig_drop = true;
-            return;
+impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
+    fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
+        self.ap.curr_block_hir_id = block.hir_id;
+        self.ap.curr_block_span = block.span;
+        for stmt in block.stmts {
+            self.ap.curr_stmt = Cow::Borrowed(stmt);
+            self.visit_stmt(stmt);
+            self.ap.curr_block_hir_id = block.hir_id;
+            self.ap.curr_block_span = block.span;
+            self.manage_has_expensive_expr_after_last_attr();
+        }
+        if let Some(expr) = block.expr {
+            self.ap.curr_stmt = Cow::Owned(dummy_stmt_expr(expr));
+            self.visit_expr(expr);
+            self.ap.curr_block_hir_id = block.hir_id;
+            self.ap.curr_block_span = block.span;
+            self.manage_has_expensive_expr_after_last_attr();
         }
+    }
 
-        match ex.kind {
-            hir::ExprKind::MethodCall(_, expr, ..) => {
-                self.visit_expr(expr);
-            },
-            hir::ExprKind::Array(..)
-            | hir::ExprKind::Assign(..)
-            | hir::ExprKind::AssignOp(..)
-            | hir::ExprKind::Binary(..)
-            | hir::ExprKind::Call(..)
-            | hir::ExprKind::Field(..)
-            | hir::ExprKind::If(..)
-            | hir::ExprKind::Index(..)
-            | hir::ExprKind::Match(..)
-            | hir::ExprKind::Repeat(..)
-            | hir::ExprKind::Ret(..)
-            | hir::ExprKind::Tup(..)
-            | hir::ExprKind::Unary(..)
-            | hir::ExprKind::Yield(..) => {
-                walk_expr(self, ex);
-            },
-            _ => {},
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+        let modify_apa_params = |apa: &mut AuxParamsAttr| {
+            apa.counter = apa.counter.wrapping_add(1);
+            apa.has_expensive_expr_after_last_attr = false;
+        };
+        let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache);
+        if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
+            if let hir::StmtKind::Local(local) = self.ap.curr_stmt.kind
+                && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
+                && !self.ap.apas.contains_key(&hir_id)
+                && {
+                    if let Some(local_hir_id) = path_to_local(expr) {
+                        local_hir_id == hir_id
+                    }
+                    else {
+                        true
+                    }
+                }
+            {
+                let mut apa = AuxParamsAttr {
+                    first_bind_ident: ident,
+                    first_block_hir_id: self.ap.curr_block_hir_id,
+                    first_block_span: self.ap.curr_block_span,
+                    first_method_span: {
+                        let expr_or_init = expr_or_init(self.cx, expr);
+                        if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind {
+                            local_expr.span.to(span)
+                        }
+                        else {
+                            expr_or_init.span
+                        }
+                    },
+                    first_stmt_span: self.ap.curr_stmt.span,
+                    ..Default::default()
+                };
+                modify_apa_params(&mut apa);
+                let _ = self.ap.apas.insert(hir_id, apa);
+            } else {
+                let Some(hir_id) = path_to_local(expr) else { return; };
+                let Some(apa) = self.ap.apas.get_mut(&hir_id) else { return; };
+                match self.ap.curr_stmt.kind {
+                    hir::StmtKind::Local(local) => {
+                        if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
+                            apa.last_bind_ident = ident;
+                        }
+                        if let Some(local_init) = local.init
+                            && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind
+                        {
+                            apa.last_method_span = span;
+                        }
+                    },
+                    hir::StmtKind::Semi(expr) => {
+                        if has_drop(expr, &apa.first_bind_ident) {
+                            apa.has_expensive_expr_after_last_attr = false;
+                            apa.last_stmt_span = DUMMY_SP;
+                            return;
+                        }
+                        if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind {
+                            apa.last_method_span = span;
+                        }
+                    },
+                    _ => {},
+                }
+                apa.last_stmt_span = self.ap.curr_stmt.span;
+                modify_apa_params(apa);
+            }
+        }
+        walk_expr(self, expr);
+    }
+}
+
+/// Auxiliary parameters used on each block check of an item
+struct AuxParams<'others, 'stmt, 'tcx> {
+    //// See [AuxParamsAttr].
+    apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>,
+    /// The current block identifier that is being visited.
+    curr_block_hir_id: hir::HirId,
+    /// The current block span that is being visited.
+    curr_block_span: Span,
+    /// The current statement that is being visited.
+    curr_stmt: Cow<'stmt, hir::Stmt<'tcx>>,
+}
+
+impl<'others, 'stmt, 'tcx> AuxParams<'others, 'stmt, 'tcx> {
+    fn new(apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
+        Self {
+            apas,
+            curr_block_hir_id: hir::HirId::INVALID,
+            curr_block_span: DUMMY_SP,
+            curr_stmt: Cow::Borrowed(curr_stmt),
+        }
+    }
+}
+
+/// Auxiliary parameters used on expression created with `#[has_significant_drop]`.
+#[derive(Debug)]
+struct AuxParamsAttr {
+    /// The number of times `#[has_significant_drop]` was referenced.
+    counter: usize,
+    /// If an expensive expression follows the last use of anything marked with
+    /// `#[has_significant_drop]`.
+    has_expensive_expr_after_last_attr: bool,
+
+    /// The identifier of the block that involves the first `#[has_significant_drop]`.
+    first_block_hir_id: hir::HirId,
+    /// The span of the block that involves the first `#[has_significant_drop]`.
+    first_block_span: Span,
+    /// The binding or variable that references the initial construction of the type marked with
+    /// `#[has_significant_drop]`.
+    first_bind_ident: Ident,
+    /// Similar to `init_bind_ident` but encompasses the right-hand method call.
+    first_method_span: Span,
+    /// Similar to `init_bind_ident` but encompasses the whole contained statement.
+    first_stmt_span: Span,
+
+    /// The last visited binding or variable span within a block that had any referenced inner type
+    /// marked with `#[has_significant_drop]`.
+    last_bind_ident: Ident,
+    /// Similar to `last_bind_span` but encompasses the right-hand method call.
+    last_method_span: Span,
+    /// Similar to `last_bind_span` but encompasses the whole contained statement.
+    last_stmt_span: Span,
+}
+
+impl Default for AuxParamsAttr {
+    fn default() -> Self {
+        Self {
+            counter: 0,
+            has_expensive_expr_after_last_attr: false,
+            first_block_hir_id: hir::HirId::INVALID,
+            first_bind_ident: Ident::empty(),
+            first_block_span: DUMMY_SP,
+            first_method_span: DUMMY_SP,
+            first_stmt_span: DUMMY_SP,
+            last_bind_ident: Ident::empty(),
+            last_method_span: DUMMY_SP,
+            last_stmt_span: DUMMY_SP,
         }
     }
 }
+
+fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
+    hir::Stmt {
+        hir_id: hir::HirId::INVALID,
+        kind: hir::StmtKind::Expr(expr),
+        span: DUMMY_SP,
+    }
+}
+
+fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident) -> bool {
+    if let hir::ExprKind::Call(fun, args) = expr.kind
+        && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
+        && let [fun_ident, ..] = fun_path.segments
+        && fun_ident.ident.name == rustc_span::sym::drop
+        && let [first_arg, ..] = args
+        && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind
+        && let [first_arg_ps, .. ] = arg_path.segments
+    {
+        &first_arg_ps.ident == first_bind_ident
+    }
+    else {
+        false
+    }
+}
+
+fn is_expensive_expr(expr: &hir::Expr<'_>) -> bool {
+    !matches!(expr.kind, hir::ExprKind::Path(_))
+}
diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
new file mode 100644
index 00000000000..42753d2e951
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
@@ -0,0 +1,133 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{is_from_proc_macro, is_in_test_function};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for functions that are only used once. Does not lint tests.
+    ///
+    /// ### Why is this bad?
+    /// It's usually not, splitting a function into multiple parts often improves readability and in
+    /// the case of generics, can prevent the compiler from duplicating the function dozens of
+    /// time; instead, only duplicating a thunk. But this can prevent segmentation across a
+    /// codebase, where many small functions are used only once.
+    ///
+    /// Note: If this lint is used, prepare to allow this a lot.
+    ///
+    /// ### Example
+    /// ```rust
+    /// pub fn a<T>(t: &T)
+    /// where
+    ///     T: AsRef<str>,
+    /// {
+    ///     a_inner(t.as_ref())
+    /// }
+    ///
+    /// fn a_inner(t: &str) {
+    ///     /* snip */
+    /// }
+    ///
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// pub fn a<T>(t: &T)
+    /// where
+    ///     T: AsRef<str>,
+    /// {
+    ///     let t = t.as_ref();
+    ///     /* snip */
+    /// }
+    ///
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub SINGLE_CALL_FN,
+    restriction,
+    "checks for functions that are only used once"
+}
+impl_lint_pass!(SingleCallFn => [SINGLE_CALL_FN]);
+
+#[derive(Clone)]
+pub struct SingleCallFn {
+    pub avoid_breaking_exported_api: bool,
+    pub def_id_to_usage: FxHashMap<LocalDefId, (Span, Vec<Span>)>,
+}
+
+impl<'tcx> LateLintPass<'tcx> for SingleCallFn {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        kind: FnKind<'tcx>,
+        _: &'tcx FnDecl<'_>,
+        body: &'tcx Body<'_>,
+        span: Span,
+        def_id: LocalDefId,
+    ) {
+        if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id)
+            || in_external_macro(cx.sess(), span)
+            || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span))
+            || is_in_test_function(cx.tcx, body.value.hir_id)
+        {
+            return;
+        }
+
+        self.def_id_to_usage.insert(def_id, (span, vec![]));
+    }
+
+    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
+        let mut v = FnUsageVisitor {
+            cx,
+            def_id_to_usage: &mut self.def_id_to_usage,
+        };
+        cx.tcx.hir().visit_all_item_likes_in_crate(&mut v);
+
+        for usage in self.def_id_to_usage.values() {
+            let single_call_fn_span = usage.0;
+            if let [caller_span] = *usage.1 {
+                span_lint_and_help(
+                    cx,
+                    SINGLE_CALL_FN,
+                    single_call_fn_span,
+                    "this function is only used once",
+                    Some(caller_span),
+                    "used here",
+                );
+            }
+        }
+    }
+}
+
+struct FnUsageVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    def_id_to_usage: &'a mut FxHashMap<LocalDefId, (Span, Vec<Span>)>,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for FnUsageVisitor<'a, 'tcx> {
+    type NestedFilter = OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        let Self { cx, .. } = *self;
+
+        if let ExprKind::Path(qpath) = expr.kind
+            && let res = cx.qpath_res(&qpath, expr.hir_id)
+            && let Some(call_def_id) = res.opt_def_id()
+            && let Some(def_id) = call_def_id.as_local()
+            && let Some(usage) = self.def_id_to_usage.get_mut(&def_id)
+        {
+            usage.1.push(expr.span);
+        }
+
+        walk_expr(self, expr);
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
new file mode 100644
index 00000000000..dfe8be7a6a6
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs
@@ -0,0 +1,147 @@
+use clippy_utils::{
+    diagnostics::span_lint_and_then, get_trait_def_id, higher::VecArgs, macros::root_macro_call_first_node,
+    source::snippet_opt, ty::implements_trait,
+};
+use rustc_ast::{LitIntType, LitKind, UintTy};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, LangItem, QPath};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use std::fmt::{self, Display, Formatter};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `Vec` or array initializations that contain only one range.
+    ///
+    /// ### Why is this bad?
+    /// This is almost always incorrect, as it will result in a `Vec` that has only one element.
+    /// Almost always, the programmer intended for it to include all elements in the range or for
+    /// the end of the range to be the length instead.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let x = [0..200];
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// // If it was intended to include every element in the range...
+    /// let x = (0..200).collect::<Vec<i32>>();
+    /// // ...Or if 200 was meant to be the len
+    /// let x = [0; 200];
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub SINGLE_RANGE_IN_VEC_INIT,
+    suspicious,
+    "checks for initialization of `Vec` or arrays which consist of a single range"
+}
+declare_lint_pass!(SingleRangeInVecInit => [SINGLE_RANGE_IN_VEC_INIT]);
+
+enum SuggestedType {
+    Vec,
+    Array,
+}
+
+impl SuggestedType {
+    fn starts_with(&self) -> &'static str {
+        if matches!(self, SuggestedType::Vec) {
+            "vec!"
+        } else {
+            "["
+        }
+    }
+
+    fn ends_with(&self) -> &'static str {
+        if matches!(self, SuggestedType::Vec) { "" } else { "]" }
+    }
+}
+
+impl Display for SuggestedType {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        if matches!(&self, SuggestedType::Vec) {
+            write!(f, "a `Vec`")
+        } else {
+            write!(f, "an array")
+        }
+    }
+}
+
+impl LateLintPass<'_> for SingleRangeInVecInit {
+    fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        // inner_expr: `vec![0..200]` or `[0..200]`
+        //                   ^^^^^^       ^^^^^^^
+        // span: `vec![0..200]` or `[0..200]`
+        //        ^^^^^^^^^^^^      ^^^^^^^^
+        // suggested_type: What to print, "an array" or "a `Vec`"
+        let (inner_expr, span, suggested_type) = if let ExprKind::Array([inner_expr]) = expr.kind
+            && !expr.span.from_expansion()
+        {
+            (inner_expr, expr.span, SuggestedType::Array)
+        } else if let Some(macro_call) = root_macro_call_first_node(cx, expr)
+            && let Some(VecArgs::Vec([expr])) = VecArgs::hir(cx, expr)
+        {
+            (expr, macro_call.span, SuggestedType::Vec)
+        } else {
+            return;
+        };
+
+        let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], None) = inner_expr.kind else {
+            return;
+        };
+
+        if matches!(lang_item, LangItem::Range)
+            && let ty = cx.typeck_results().expr_ty(start.expr)
+            && let Some(snippet) = snippet_opt(cx, span)
+            // `is_from_proc_macro` will skip any `vec![]`. Let's not!
+            && snippet.starts_with(suggested_type.starts_with())
+            && snippet.ends_with(suggested_type.ends_with())
+            && let Some(start_snippet) = snippet_opt(cx, start.span)
+            && let Some(end_snippet) = snippet_opt(cx, end.span)
+        {
+            let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx, &["core", "iter", "Step"])
+                && implements_trait(cx, ty, step_def_id, &[])
+            {
+                true
+            } else {
+                false
+            };
+            let should_emit_of_len = if let Some(copy_def_id) = cx.tcx.lang_items().copy_trait()
+                && implements_trait(cx, ty, copy_def_id, &[])
+                && let ExprKind::Lit(lit_kind) = end.expr.kind
+                && let LitKind::Int(.., suffix_type) = lit_kind.node
+                && let LitIntType::Unsigned(UintTy::Usize) | LitIntType::Unsuffixed = suffix_type
+            {
+                true
+            } else {
+                false
+            };
+
+            if should_emit_every_value || should_emit_of_len {
+                span_lint_and_then(
+                    cx,
+                    SINGLE_RANGE_IN_VEC_INIT,
+                    span,
+                    &format!("{suggested_type} of `Range` that is only one element"),
+                    |diag| {
+                        if should_emit_every_value {
+                            diag.span_suggestion(
+                                span,
+                                "if you wanted a `Vec` that contains the entire range, try",
+                                format!("({start_snippet}..{end_snippet}).collect::<std::vec::Vec<{ty}>>()"),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+
+                        if should_emit_of_len {
+                            diag.span_suggestion(
+                                inner_expr.span,
+                                format!("if you wanted {suggested_type} of len {end_snippet}, try"),
+                                format!("{start_snippet}; {end_snippet}"),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    },
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index 4ccda15068b..6db330dfa61 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
-use clippy_utils::{SpanlessEq, SpanlessHash};
+use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
 use core::hash::{Hash, Hasher};
 use if_chain::if_chain;
 use itertools::Itertools;
@@ -9,7 +10,7 @@ use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{
-    GenericArg, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath,
+    GenericArg, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath,
     TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass};
@@ -86,15 +87,16 @@ declare_clippy_lint! {
     "check if the same trait bounds are specified more than once during a generic declaration"
 }
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct TraitBounds {
     max_trait_bounds: u64,
+    msrv: Msrv,
 }
 
 impl TraitBounds {
     #[must_use]
-    pub fn new(max_trait_bounds: u64) -> Self {
-        Self { max_trait_bounds }
+    pub fn new(max_trait_bounds: u64, msrv: Msrv) -> Self {
+        Self { max_trait_bounds, msrv }
     }
 }
 
@@ -139,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
                     ) = cx.tcx.hir().get_if_local(*def_id);
                 then {
                     if self_bounds_map.is_empty() {
-                        for bound in self_bounds.iter() {
+                        for bound in *self_bounds {
                             let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { continue };
                             self_bounds_map.insert(self_res, self_segments);
                         }
@@ -184,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
 
                 // Iterate the bounds and add them to our seen hash
                 // If we haven't yet seen it, add it to the fixed traits
-                for bound in bounds.iter() {
+                for bound in bounds {
                     let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
 
                     let new_trait = seen_def_ids.insert(def_id);
@@ -222,10 +224,24 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 impl TraitBounds {
-    fn check_type_repetition<'tcx>(self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
+    /// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on
+    /// this MSRV? See <https://github.com/rust-lang/rust-clippy/issues/8772> for details.
+    fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool {
+        if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE)
+            && let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound
+        {
+            cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id()
+        } else {
+            false
+        }
+    }
+
+    fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
         struct SpanlessTy<'cx, 'tcx> {
             ty: &'tcx Ty<'tcx>,
             cx: &'cx LateContext<'tcx>,
@@ -256,11 +272,10 @@ impl TraitBounds {
                 if p.origin != PredicateOrigin::ImplTrait;
                 if p.bounds.len() as u64 <= self.max_trait_bounds;
                 if !p.span.from_expansion();
-                if let Some(ref v) = map.insert(
-                    SpanlessTy { ty: p.bounded_ty, cx },
-                    p.bounds.iter().collect::<Vec<_>>()
-                );
-
+                let bounds = p.bounds.iter().filter(|b| !self.cannot_combine_maybe_bound(cx, b)).collect::<Vec<_>>();
+                if !bounds.is_empty();
+                if let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds);
+                if !is_from_proc_macro(cx, p.bounded_ty);
                 then {
                     let trait_bounds = v
                         .iter()
@@ -342,7 +357,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
                             "this trait bound is already specified in the where clause",
                             None,
                             "consider removing this trait bound",
-                            );
+                        );
                     }
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
new file mode 100644
index 00000000000..bd983306508
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
@@ -0,0 +1,235 @@
+use clippy_utils::{
+    diagnostics::span_lint_and_help,
+    is_from_proc_macro,
+    msrvs::{self, Msrv},
+    path_to_local,
+};
+use rustc_ast::LitKind;
+use rustc_hir::{Expr, ExprKind, HirId, Node, Pat};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::{lint::in_external_macro, ty};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use std::iter::once;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for tuple<=>array conversions that are not done with `.into()`.
+    ///
+    /// ### Why is this bad?
+    /// It's unnecessary complexity. `.into()` works for tuples<=>arrays at or below 12 elements and
+    /// conveys the intent a lot better, while also leaving less room for hard to spot bugs!
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// let t1 = &[(1, 2), (3, 4)];
+    /// let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect();
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// let t1 = &[(1, 2), (3, 4)];
+    /// let v1: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect();
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub TUPLE_ARRAY_CONVERSIONS,
+    complexity,
+    "checks for tuple<=>array conversions that are not done with `.into()`"
+}
+impl_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]);
+
+#[derive(Clone)]
+pub struct TupleArrayConversions {
+    pub msrv: Msrv,
+}
+
+impl LateLintPass<'_> for TupleArrayConversions {
+    fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if !in_external_macro(cx.sess(), expr.span) && self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) {
+            match expr.kind {
+                ExprKind::Array(elements) if (1..=12).contains(&elements.len()) => check_array(cx, expr, elements),
+                ExprKind::Tup(elements) if (1..=12).contains(&elements.len()) => check_tuple(cx, expr, elements),
+                _ => {},
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
+
+#[expect(
+    clippy::blocks_in_if_conditions,
+    reason = "not a FP, but this is much easier to understand"
+)]
+fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) {
+    if should_lint(
+        cx,
+        elements,
+        // This is cursed.
+        Some,
+        |(first_id, local)| {
+            if let Node::Pat(pat) = local
+                && let parent = parent_pat(cx, pat)
+                && parent.hir_id == first_id
+            {
+                return matches!(
+                    cx.typeck_results().pat_ty(parent).peel_refs().kind(),
+                    ty::Tuple(len) if len.len() == elements.len()
+                );
+            }
+
+            false
+        },
+    ) || should_lint(
+        cx,
+        elements,
+        |(i, expr)| {
+            if let ExprKind::Field(path, field) = expr.kind && field.as_str() == i.to_string() {
+                return Some((i, path));
+            };
+
+            None
+        },
+        |(first_id, local)| {
+            if let Node::Pat(pat) = local
+                && let parent = parent_pat(cx, pat)
+                && parent.hir_id == first_id
+            {
+                return matches!(
+                    cx.typeck_results().pat_ty(parent).peel_refs().kind(),
+                    ty::Tuple(len) if len.len() == elements.len()
+                );
+            }
+
+            false
+        },
+    ) {
+        emit_lint(cx, expr, ToType::Array);
+    }
+}
+
+#[expect(
+    clippy::blocks_in_if_conditions,
+    reason = "not a FP, but this is much easier to understand"
+)]
+#[expect(clippy::cast_possible_truncation)]
+fn check_tuple<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) {
+    if should_lint(cx, elements, Some, |(first_id, local)| {
+        if let Node::Pat(pat) = local
+                && let parent = parent_pat(cx, pat)
+                && parent.hir_id == first_id
+            {
+                return matches!(
+                    cx.typeck_results().pat_ty(parent).peel_refs().kind(),
+                    ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len()
+                );
+            }
+
+        false
+    }) || should_lint(
+        cx,
+        elements,
+        |(i, expr)| {
+            if let ExprKind::Index(path, index) = expr.kind
+                && let ExprKind::Lit(lit) = index.kind
+                && let LitKind::Int(val, _) = lit.node
+                && val as usize == i
+            {
+                return Some((i, path));
+            };
+
+            None
+        },
+        |(first_id, local)| {
+            if let Node::Pat(pat) = local
+                && let parent = parent_pat(cx, pat)
+                && parent.hir_id == first_id
+            {
+                return matches!(
+                    cx.typeck_results().pat_ty(parent).peel_refs().kind(),
+                    ty::Array(_, len) if len.eval_target_usize(cx.tcx, cx.param_env) as usize == elements.len()
+                );
+            }
+
+            false
+        },
+    ) {
+        emit_lint(cx, expr, ToType::Tuple);
+    }
+}
+
+/// Walks up the `Pat` until it's reached the final containing `Pat`.
+fn parent_pat<'tcx>(cx: &LateContext<'tcx>, start: &'tcx Pat<'tcx>) -> &'tcx Pat<'tcx> {
+    let mut end = start;
+    for (_, node) in cx.tcx.hir().parent_iter(start.hir_id) {
+        if let Node::Pat(pat) = node {
+            end = pat;
+        } else {
+            break;
+        }
+    }
+    end
+}
+
+#[derive(Clone, Copy)]
+enum ToType {
+    Array,
+    Tuple,
+}
+
+impl ToType {
+    fn msg(self) -> &'static str {
+        match self {
+            ToType::Array => "it looks like you're trying to convert a tuple to an array",
+            ToType::Tuple => "it looks like you're trying to convert an array to a tuple",
+        }
+    }
+
+    fn help(self) -> &'static str {
+        match self {
+            ToType::Array => "use `.into()` instead, or `<[T; N]>::from` if type annotations are needed",
+            ToType::Tuple => "use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed",
+        }
+    }
+}
+
+fn emit_lint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, to_type: ToType) -> bool {
+    if !is_from_proc_macro(cx, expr) {
+        span_lint_and_help(
+            cx,
+            TUPLE_ARRAY_CONVERSIONS,
+            expr.span,
+            to_type.msg(),
+            None,
+            to_type.help(),
+        );
+
+        return true;
+    }
+
+    false
+}
+
+fn should_lint<'tcx>(
+    cx: &LateContext<'tcx>,
+    elements: &'tcx [Expr<'tcx>],
+    map: impl FnMut((usize, &'tcx Expr<'tcx>)) -> Option<(usize, &Expr<'_>)>,
+    predicate: impl FnMut((HirId, &Node<'tcx>)) -> bool,
+) -> bool {
+    if let Some(elements) = elements
+            .iter()
+            .enumerate()
+            .map(map)
+            .collect::<Option<Vec<_>>>()
+        && let Some(locals) = elements
+            .iter()
+            .map(|(_, element)| path_to_local(element).and_then(|local| cx.tcx.hir().find(local)))
+            .collect::<Option<Vec<_>>>()
+        && let [first, rest @ ..] = &*locals
+        && let Node::Pat(first_pat) = first
+        && let parent = parent_pat(cx, first_pat).hir_id
+        && rest.iter().chain(once(first)).map(|i| (parent, i)).all(predicate)
+    {
+        return true;
+    }
+
+    false
+}
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 2920684ade3..a9deee96784 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{BytePos, Pos, Span, SyntaxContext};
 
 declare_clippy_lint! {
@@ -92,7 +92,22 @@ declare_clippy_lint! {
     "annotating safe code with a safety comment"
 }
 
-declare_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]);
+#[derive(Copy, Clone)]
+pub struct UndocumentedUnsafeBlocks {
+    accept_comment_above_statement: bool,
+    accept_comment_above_attributes: bool,
+}
+
+impl UndocumentedUnsafeBlocks {
+    pub fn new(accept_comment_above_statement: bool, accept_comment_above_attributes: bool) -> Self {
+        Self {
+            accept_comment_above_statement,
+            accept_comment_above_attributes,
+        }
+    }
+}
+
+impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]);
 
 impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
@@ -101,7 +116,12 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
             && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id)
             && !is_unsafe_from_proc_macro(cx, block.span)
             && !block_has_safety_comment(cx, block.span)
-            && !block_parents_have_safety_comment(cx, block.hir_id)
+            && !block_parents_have_safety_comment(
+                self.accept_comment_above_statement,
+                self.accept_comment_above_attributes,
+                cx,
+                block.hir_id,
+            )
         {
             let source_map = cx.tcx.sess.source_map();
             let span = if source_map.is_multiline(block.span) {
@@ -313,29 +333,95 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
 
 // Checks if any parent {expression, statement, block, local, const, static}
 // has a safety comment
-fn block_parents_have_safety_comment(cx: &LateContext<'_>, id: hir::HirId) -> bool {
+fn block_parents_have_safety_comment(
+    accept_comment_above_statement: bool,
+    accept_comment_above_attributes: bool,
+    cx: &LateContext<'_>,
+    id: hir::HirId,
+) -> bool {
     if let Some(node) = get_parent_node(cx.tcx, id) {
         return match node {
-            Node::Expr(expr) => !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span),
+            Node::Expr(expr) => {
+                if let Some(
+                    Node::Local(hir::Local { span, .. })
+                    | Node::Item(hir::Item {
+                        kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                        span,
+                        ..
+                    }),
+                ) = get_parent_node(cx.tcx, expr.hir_id)
+                {
+                    let hir_id = match get_parent_node(cx.tcx, expr.hir_id) {
+                        Some(Node::Local(hir::Local { hir_id, .. })) => *hir_id,
+                        Some(Node::Item(hir::Item { owner_id, .. })) => {
+                            cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)
+                        },
+                        _ => unreachable!(),
+                    };
+
+                    // if unsafe block is part of a let/const/static statement,
+                    // and accept_comment_above_statement is set to true
+                    // we accept the safety comment in the line the precedes this statement.
+                    accept_comment_above_statement
+                        && span_with_attrs_in_body_has_safety_comment(
+                            cx,
+                            *span,
+                            hir_id,
+                            accept_comment_above_attributes,
+                        )
+                } else {
+                    !is_branchy(expr)
+                        && span_with_attrs_in_body_has_safety_comment(
+                            cx,
+                            expr.span,
+                            expr.hir_id,
+                            accept_comment_above_attributes,
+                        )
+                }
+            },
             Node::Stmt(hir::Stmt {
                 kind:
-                    hir::StmtKind::Local(hir::Local { span, .. })
-                    | hir::StmtKind::Expr(hir::Expr { span, .. })
-                    | hir::StmtKind::Semi(hir::Expr { span, .. }),
+                    hir::StmtKind::Local(hir::Local { span, hir_id, .. })
+                    | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. })
+                    | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }),
                 ..
             })
-            | Node::Local(hir::Local { span, .. })
-            | Node::Item(hir::Item {
+            | Node::Local(hir::Local { span, hir_id, .. }) => {
+                span_with_attrs_in_body_has_safety_comment(cx, *span, *hir_id, accept_comment_above_attributes)
+            },
+            Node::Item(hir::Item {
                 kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
                 span,
+                owner_id,
                 ..
-            }) => span_in_body_has_safety_comment(cx, *span),
+            }) => span_with_attrs_in_body_has_safety_comment(
+                cx,
+                *span,
+                cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id),
+                accept_comment_above_attributes,
+            ),
             _ => false,
         };
     }
     false
 }
 
+/// Extends `span` to also include its attributes, then checks if that span has a safety comment.
+fn span_with_attrs_in_body_has_safety_comment(
+    cx: &LateContext<'_>,
+    span: Span,
+    hir_id: HirId,
+    accept_comment_above_attributes: bool,
+) -> bool {
+    let span = if accept_comment_above_attributes {
+        include_attrs_in_span(cx, hir_id, span)
+    } else {
+        span
+    };
+
+    span_in_body_has_safety_comment(cx, span)
+}
+
 /// Checks if an expression is "branchy", e.g. loop, match/if/etc.
 fn is_branchy(expr: &hir::Expr<'_>) -> bool {
     matches!(
@@ -360,6 +446,15 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
     ) || span_in_body_has_safety_comment(cx, span)
 }
 
+fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
+    span.to(cx
+        .tcx
+        .hir()
+        .attrs(hir_id)
+        .iter()
+        .fold(span, |acc, attr| acc.to(attr.span)))
+}
+
 enum HasSafetyComment {
     Yes(BytePos),
     No,
@@ -546,7 +641,14 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
     for (_, node) in map.parent_iter(body.hir_id) {
         match node {
             Node::Expr(e) => span = e.span,
-            Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (),
+            Node::Block(_)
+            | Node::Arm(_)
+            | Node::Stmt(_)
+            | Node::Local(_)
+            | Node::Item(hir::Item {
+                kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                ..
+            }) => (),
             _ => break,
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index 117dda09222..5e42cf7e4f3 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_def_id_trait_method;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource};
 use rustc_lint::{LateContext, LateLintPass};
@@ -91,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
         span: Span,
         def_id: LocalDefId,
     ) {
-        if !span.from_expansion() && fn_kind.asyncness().is_async() {
+        if !span.from_expansion() && fn_kind.asyncness().is_async() && !is_def_id_trait_method(cx, def_id) {
             let mut visitor = AsyncFnVisitor {
                 cx,
                 found_await: false,
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 1d2d3eb12e1..4df1e3299ed 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -65,7 +65,7 @@ fn correct_ident(ident: &str) -> String {
 
     let mut ident = fragments.clone().next().unwrap();
     for (ref prev, ref curr) in fragments.tuple_windows() {
-        if [prev, curr]
+        if <[&String; 2]>::from((prev, curr))
             .iter()
             .all(|s| s.len() == 1 && s.chars().next().unwrap().is_ascii_uppercase())
         {
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 28c3fc859e3..b6c11cfb355 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,16 +1,17 @@
-use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::is_ty_alias;
-use clippy_utils::source::{snippet, snippet_with_context};
+use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
+use rustc_hir::def_id::DefId;
 use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::sym;
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -43,6 +44,64 @@ pub struct UselessConversion {
 
 impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]);
 
+enum MethodOrFunction {
+    Method,
+    Function,
+}
+
+impl MethodOrFunction {
+    /// Maps the argument position in `pos` to the parameter position.
+    /// For methods, `self` is skipped.
+    fn param_pos(self, pos: usize) -> usize {
+        match self {
+            MethodOrFunction::Method => pos + 1,
+            MethodOrFunction::Function => pos,
+        }
+    }
+}
+
+/// Returns the span of the `IntoIterator` trait bound in the function pointed to by `fn_did`
+fn into_iter_bound(cx: &LateContext<'_>, fn_did: DefId, into_iter_did: DefId, param_index: u32) -> Option<Span> {
+    cx.tcx
+        .predicates_of(fn_did)
+        .predicates
+        .iter()
+        .find_map(|&(ref pred, span)| {
+            if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder()
+                && tr.def_id() == into_iter_did
+                && tr.self_ty().is_param(param_index)
+            {
+                Some(span)
+            } else {
+                None
+            }
+        })
+}
+
+/// Extracts the receiver of a `.into_iter()` method call.
+fn into_iter_call<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>) -> Option<&'hir Expr<'hir>> {
+    if let ExprKind::MethodCall(name, recv, _, _) = expr.kind
+        && is_trait_method(cx, expr, sym::IntoIterator)
+        && name.ident.name == sym::into_iter
+    {
+        Some(recv)
+    } else {
+        None
+    }
+}
+
+/// Same as [`into_iter_call`], but tries to look for the innermost `.into_iter()` call, e.g.:
+/// `foo.into_iter().into_iter()`
+///  ^^^  we want this expression
+fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> (&'hir Expr<'hir>, usize) {
+    let mut depth = 0;
+    while let Some(recv) = into_iter_call(cx, expr) {
+        expr = recv;
+        depth += 1;
+    }
+    (expr, depth)
+}
+
 #[expect(clippy::too_many_lines)]
 impl<'tcx> LateLintPass<'tcx> for UselessConversion {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
@@ -82,9 +141,59 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         );
                     }
                 }
-                if is_trait_method(cx, e, sym::IntoIterator) && name.ident.name == sym::into_iter {
-                    if get_parent_expr(cx, e).is_some() &&
-                       let Some(id) = path_to_local(recv) &&
+                if let Some(into_iter_recv) = into_iter_call(cx, e)
+                    // Make sure that there is no parent expression, or if there is, make sure it's not a `.into_iter()` call.
+                    // The reason for that is that we only want to lint once (the outermost call)
+                    // in cases like `foo.into_iter().into_iter()`
+                    && get_parent_expr(cx, e)
+                        .and_then(|parent| into_iter_call(cx, parent))
+                        .is_none()
+                {
+                    if let Some(parent) = get_parent_expr(cx, e) {
+                        let parent_fn = match parent.kind {
+                            ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => {
+                                cx.qpath_res(qpath, recv.hir_id).opt_def_id()
+                                    .map(|did| (did, args, MethodOrFunction::Function))
+                            }
+                            ExprKind::MethodCall(.., args, _) => {
+                                cx.typeck_results().type_dependent_def_id(parent.hir_id)
+                                    .map(|did| (did, args, MethodOrFunction::Method))
+                            }
+                            _ => None,
+                        };
+
+                        if let Some((parent_fn_did, args, kind)) = parent_fn
+                            && let Some(into_iter_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
+                            && let sig = cx.tcx.fn_sig(parent_fn_did).skip_binder().skip_binder()
+                            && let Some(arg_pos) = args.iter().position(|x| x.hir_id == e.hir_id)
+                            && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos))
+                            && let ty::Param(param) = into_iter_param.kind()
+                            && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index)
+                        {
+                            // Get the "innermost" `.into_iter()` call, e.g. given this expression:
+                            // `foo.into_iter().into_iter()`
+                            //  ^^^
+                            let (into_iter_recv, depth) = into_iter_deep_call(cx, into_iter_recv);
+
+                            let plural = if depth == 0 { "" } else { "s" };
+                            let mut applicability = Applicability::MachineApplicable;
+                            let sugg = snippet_with_applicability(cx, into_iter_recv.span.source_callsite(), "<expr>", &mut applicability).into_owned();
+                            span_lint_and_then(cx, USELESS_CONVERSION, e.span, "explicit call to `.into_iter()` in function argument accepting `IntoIterator`", |diag| {
+                                diag.span_suggestion(
+                                    e.span,
+                                    format!("consider removing the `.into_iter()`{plural}"),
+                                    sugg,
+                                    applicability,
+                                );
+                                diag.span_note(span, "this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`");
+                            });
+
+                            // Early return to avoid linting again with contradicting suggestions
+                            return;
+                        }
+                    }
+
+                    if let Some(id) = path_to_local(recv) &&
                        let Node::Pat(pat) = cx.tcx.hir().get(id) &&
                        let PatKind::Binding(ann, ..) = pat.kind &&
                        ann != BindingAnnotation::MUT
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 35f40830681..f1d05c7529b 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -21,6 +21,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
     "GitHub", "GitLab",
     "IPv4", "IPv6",
     "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript",
+    "WebAssembly",
     "NaN", "NaNs",
     "OAuth", "GraphQL",
     "OCaml",
@@ -34,6 +35,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
     "CamelCase",
 ];
 const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
+const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
 
 /// Holds information used by `MISSING_ENFORCED_IMPORT_RENAMES` lint.
 #[derive(Clone, Debug, Deserialize)]
@@ -288,11 +290,11 @@ define_Conf! {
     /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
     /// ```
     (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
-    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS.
+    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN.
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD.
     ///
     /// The minimum rust version that the project supports
     (msrv: Option<String> = None),
@@ -305,6 +307,10 @@ define_Conf! {
     ///
     /// The maximum cognitive complexity a function can have
     (cognitive_complexity_threshold: u64 = 25),
+    /// Lint: EXCESSIVE_NESTING.
+    ///
+    /// The maximum amount of nesting a block can reside in
+    (excessive_nesting_threshold: u64 = 0),
     /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
     ///
     /// Use the Cognitive Complexity lint instead.
@@ -382,6 +388,10 @@ define_Conf! {
     ///
     /// The maximum allowed size for arrays on the stack
     (array_size_threshold: u64 = 512_000),
+    /// Lint: LARGE_STACK_FRAMES.
+    ///
+    /// The maximum allowed stack size for functions in bytes
+    (stack_size_threshold: u64 = 512_000),
     /// Lint: VEC_BOX.
     ///
     /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
@@ -514,6 +524,33 @@ define_Conf! {
     ///
     /// The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
     (unnecessary_box_size: u64 = 128),
+    /// Lint: MODULE_INCEPTION.
+    ///
+    /// Whether to allow module inception if it's not public.
+    (allow_private_module_inception: bool = false),
+    /// Lint: MIN_IDENT_CHARS.
+    ///
+    /// Allowed names below the minimum allowed characters. The value `".."` 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.
+    (allowed_idents_below_min_chars: rustc_data_structures::fx::FxHashSet<String> =
+        super::DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()),
+    /// Lint: MIN_IDENT_CHARS.
+    ///
+    /// Minimum chars an ident can have, anything below or equal to this will be linted.
+    (min_ident_chars_threshold: u64 = 1),
+    /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
+    ///
+    /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
+    (accept_comment_above_statement: bool = false),
+    /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
+    ///
+    /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
+    (accept_comment_above_attributes: bool = false),
+    /// Lint: UNNECESSARY_RAW_STRING_HASHES.
+    ///
+    /// Whether to allow `r#""#` when `r""` can be used
+    (allow_one_hash_in_raw_strings: bool = false),
 }
 
 /// Search for the configuration file.
@@ -581,6 +618,12 @@ pub fn read(sess: &Session, path: &Path) -> TryConf {
         Ok(mut conf) => {
             extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
             extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
+            // TODO: THIS SHOULD BE TESTED, this comment will be gone soon
+            if conf.conf.allowed_idents_below_min_chars.contains(&"..".to_owned()) {
+                conf.conf
+                    .allowed_idents_below_min_chars
+                    .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string));
+            }
 
             conf
         },
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 71f6c9909dd..e222a5448c9 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -1,3 +1,4 @@
+pub mod almost_standard_lint_formulation;
 pub mod clippy_lints_internal;
 pub mod collapsible_calls;
 pub mod compiler_lint_functions;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
new file mode 100644
index 00000000000..570a88a0ed2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
@@ -0,0 +1,87 @@
+use crate::utils::internal_lints::lint_without_lint_pass::is_lint_ref_type;
+use clippy_utils::diagnostics::span_lint_and_help;
+use regex::Regex;
+use rustc_ast as ast;
+use rustc_hir::{Item, ItemKind, Mutability};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if lint formulations have a standardized format.
+    ///
+    /// ### Why is this bad?
+    /// It's not neccessarily bad, but we try to enforce a standard in Clippy.
+    ///
+    /// ### Example
+    /// `Checks for use...` can be written as `Checks for usage...` .
+    pub ALMOST_STANDARD_LINT_FORMULATION,
+    internal,
+    "lint formulations must have a standardized format."
+}
+
+impl_lint_pass!(AlmostStandardFormulation => [ALMOST_STANDARD_LINT_FORMULATION]);
+
+pub struct AlmostStandardFormulation {
+    standard_formulations: Vec<StandardFormulations<'static>>,
+}
+
+#[derive(Debug)]
+struct StandardFormulations<'a> {
+    wrong_pattern: Regex,
+    correction: &'a str,
+}
+
+impl AlmostStandardFormulation {
+    pub fn new() -> Self {
+        let standard_formulations = vec![StandardFormulations {
+            wrong_pattern: Regex::new("^(Check for|Detects? uses?)").unwrap(),
+            correction: "Checks for",
+        }];
+        Self { standard_formulations }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        let mut check_next = false;
+        if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
+            let lines = cx
+                .tcx
+                .hir()
+                .attrs(item.hir_id())
+                .iter()
+                .filter_map(|attr| ast::Attribute::doc_str(attr).map(|sym| (sym, attr)));
+            if is_lint_ref_type(cx, ty) {
+                for (line, attr) in lines {
+                    let cur_line = line.as_str().trim();
+                    if check_next && !cur_line.is_empty() {
+                        for formulation in &self.standard_formulations {
+                            let starts_with_correct_formulation = cur_line.starts_with(formulation.correction);
+                            if !starts_with_correct_formulation && formulation.wrong_pattern.is_match(cur_line) {
+                                if let Some(ident) = attr.ident() {
+                                    span_lint_and_help(
+                                        cx,
+                                        ALMOST_STANDARD_LINT_FORMULATION,
+                                        ident.span,
+                                        "non-standard lint formulation",
+                                        None,
+                                        &format!("try using `{}` instead", formulation.correction),
+                                    );
+                                }
+                                return;
+                            }
+                        }
+                        return;
+                    } else if cur_line.contains("What it does") {
+                        check_next = true;
+                    } else if cur_line.contains("Why is this bad") {
+                        // Formulation documentation is done. Can add check to ensure that missing formulation is added
+                        // and add a check if it matches no accepted formulation
+                        return;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index f8978e30a8e..dced9fcf9ab 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
 
         for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
             for def_id in def_path_def_ids(cx, module) {
-                for item in cx.tcx.module_children(def_id).iter() {
+                for item in cx.tcx.module_children(def_id) {
                     if_chain! {
                         if let Res::Def(DefKind::Const, item_def_id) = item.res;
                         let ty = cx.tcx.type_of(item_def_id).subst_identity();
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 7a1cd3effae..107a62806a8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -104,6 +104,8 @@ const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved";
 /// The version that will be displayed if none has been defined
 const VERSION_DEFAULT_STR: &str = "Unknown";
 
+const CHANGELOG_PATH: &str = "../CHANGELOG.md";
+
 declare_clippy_lint! {
     /// ### What it does
     /// Collects metadata about clippy lints for the website.
@@ -195,8 +197,14 @@ This lint has the following configuration variables:
 
     fn get_markdown_docs(&self) -> String {
         format!(
-            "## Lint Configuration Options\n| <div style=\"width:290px\">Option</div> | Default Value |\n|--|--|\n{}\n\n{}\n",
-            self.configs_to_markdown(ClippyConfiguration::to_markdown_table_entry),
+            r#"# Lint Configuration Options
+
+The following list shows each configuration option, along with a description, its default value, an example
+and lints affected.
+
+---
+
+{}"#,
             self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph),
         )
     }
@@ -254,6 +262,22 @@ Please use that command to update the file and do not edit it by hand.
             self.get_markdown_docs(),
         )
         .unwrap();
+
+        // Write configuration links to CHANGELOG.md
+        let mut changelog = std::fs::read_to_string(CHANGELOG_PATH).unwrap();
+        let mut changelog_file = OpenOptions::new().read(true).write(true).open(CHANGELOG_PATH).unwrap();
+
+        if let Some(position) = changelog.find("<!-- begin autogenerated links to configuration documentation -->") {
+            // I know this is kinda wasteful, we just don't have regex on `clippy_lints` so... this is the best
+            // we can do AFAIK.
+            changelog = changelog[..position].to_string();
+        }
+        writeln!(
+            changelog_file,
+            "{changelog}<!-- begin autogenerated links to configuration documentation -->\n{}\n<!-- end autogenerated links to configuration documentation -->",
+            self.configs_to_markdown(ClippyConfiguration::to_markdown_link)
+        )
+        .unwrap();
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index d3ea7cafa80..fb08256931f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -12,6 +12,9 @@ fn to_kebab(config_name: &str) -> String {
     config_name.replace('_', "-")
 }
 
+#[cfg(feature = "internal")]
+const BOOK_CONFIGS_PATH: &str = "https://doc.rust-lang.org/clippy/lint_configuration.html";
+
 // ==================================================================
 // Configuration
 // ==================================================================
@@ -51,7 +54,7 @@ impl ClippyConfiguration {
     #[cfg(feature = "internal")]
     fn to_markdown_paragraph(&self) -> String {
         format!(
-            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
+            "## `{}`\n{}\n\n**Default Value:** `{}` (`{}`)\n\n---\n**Affected lints:**\n{}\n\n",
             self.name,
             self.doc
                 .lines()
@@ -62,14 +65,13 @@ impl ClippyConfiguration {
             self.lints
                 .iter()
                 .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
-                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
+                .map(|name| format!("* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
                 .join("\n"),
         )
     }
-
     #[cfg(feature = "internal")]
-    fn to_markdown_table_entry(&self) -> String {
-        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
+    fn to_markdown_link(&self) -> String {
+        format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name)
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 7329e508106..2a594e750b9 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -1,26 +1,32 @@
+use std::ops::ControlFlow;
+
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_copy;
+use clippy_utils::visitors::for_each_local_use_after_expr;
+use clippy_utils::{get_parent_expr, higher, is_trait_method};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
+use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
+use rustc_span::sym;
 
 #[expect(clippy::module_name_repetitions)]
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct UselessVec {
     pub too_large_for_stack: u64,
+    pub msrv: Msrv,
 }
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for usage of `&vec![..]` when using `&[..]` would
+    /// Checks for usage of `vec![..]` when using `[..]` would
     /// be possible.
     ///
     /// ### Why is this bad?
@@ -46,16 +52,73 @@ declare_clippy_lint! {
 
 impl_lint_pass!(UselessVec => [USELESS_VEC]);
 
+fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+    matches!(cx.typeck_results().expr_ty_adjusted(e).kind(), ty::Ref(_, ty, _) if ty.is_slice())
+}
+
+/// Checks if the given expression is a method call to a `Vec` method
+/// that also exists on slices. If this returns true, it means that
+/// this expression does not actually require a `Vec` and could just work with an array.
+fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+    const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"];
+
+    if let ExprKind::MethodCall(path, ..) = e.kind {
+        ALLOWED_METHOD_NAMES.contains(&path.ident.name.as_str())
+    } else {
+        is_trait_method(cx, e, sym::IntoIterator)
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for UselessVec {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        // search for `&vec![_]` expressions where the adjusted type is `&[_]`
+        // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]`
         if_chain! {
-            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind();
-            if let ty::Slice(..) = ty.kind();
-            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
-            if let Some(vec_args) = higher::VecArgs::hir(cx, addressee);
+            if adjusts_to_slice(cx, expr);
+            if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows());
             then {
-                self.check_vec_macro(cx, &vec_args, mutability, expr.span);
+                let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind {
+                    // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.)
+                    (SuggestedType::SliceRef(mutability), expr.span)
+                } else {
+                    // `expr` is the `vec![_]` expansion, so suggest `[_]`
+                    // and also use the span of the actual `vec![_]` expression
+                    (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site)
+                };
+
+                self.check_vec_macro(cx, &vec_args, span, suggest_slice);
+            }
+        }
+
+        // search for `let foo = vec![_]` expressions where all uses of `foo`
+        // adjust to slices or call a method that exist on slices (e.g. len)
+        if let Some(vec_args) = higher::VecArgs::hir(cx, expr)
+            && let Node::Local(local) = cx.tcx.hir().get_parent(expr.hir_id)
+            // for now ignore locals with type annotations.
+            // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..];
+            && local.ty.is_none()
+            && let PatKind::Binding(_, id, ..) = local.pat.kind
+            && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr)))
+        {
+            let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| {
+                // allow indexing into a vec and some set of allowed method calls that exist on slices, too
+                if let Some(parent) = get_parent_expr(cx, expr)
+                    && (adjusts_to_slice(cx, expr)
+                        || matches!(parent.kind, ExprKind::Index(..))
+                        || is_allowed_vec_method(cx, parent))
+                {
+                    ControlFlow::Continue(())
+                } else {
+                    ControlFlow::Break(())
+                }
+            }).is_continue();
+
+            if only_slice_uses {
+                self.check_vec_macro(
+                    cx,
+                    &vec_args,
+                    expr.span.ctxt().outer_expn_data().call_site,
+                    SuggestedType::Array
+                );
             }
         }
 
@@ -63,25 +126,36 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
         if_chain! {
             if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr);
             if let Some(vec_args) = higher::VecArgs::hir(cx, arg);
-            if is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(arg)));
+            if self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR);
             then {
                 // report the error around the `vec!` not inside `<std macros>:`
                 let span = arg.span.ctxt().outer_expn_data().call_site;
-                self.check_vec_macro(cx, &vec_args, Mutability::Not, span);
+                self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array);
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
+}
+
+#[derive(Copy, Clone)]
+enum SuggestedType {
+    /// Suggest using a slice `&[..]` / `&mut [..]`
+    SliceRef(Mutability),
+    /// Suggest using an array: `[..]`
+    Array,
 }
 
 impl UselessVec {
     fn check_vec_macro<'tcx>(
-        self,
+        &mut self,
         cx: &LateContext<'tcx>,
         vec_args: &higher::VecArgs<'tcx>,
-        mutability: Mutability,
         span: Span,
+        suggest_slice: SuggestedType,
     ) {
         let mut applicability = Applicability::MachineApplicable;
+
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
                 if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
@@ -90,21 +164,13 @@ impl UselessVec {
                         return;
                     }
 
-                    match mutability {
-                        Mutability::Mut => {
-                            format!(
-                                "&mut [{}; {}]",
-                                snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
-                                snippet_with_applicability(cx, len.span, "len", &mut applicability)
-                            )
-                        },
-                        Mutability::Not => {
-                            format!(
-                                "&[{}; {}]",
-                                snippet_with_applicability(cx, elem.span, "elem", &mut applicability),
-                                snippet_with_applicability(cx, len.span, "len", &mut applicability)
-                            )
-                        },
+                    let elem = snippet_with_applicability(cx, elem.span, "elem", &mut applicability);
+                    let len = snippet_with_applicability(cx, len.span, "len", &mut applicability);
+
+                    match suggest_slice {
+                        SuggestedType::SliceRef(Mutability::Mut) => format!("&mut [{elem}; {len}]"),
+                        SuggestedType::SliceRef(Mutability::Not) => format!("&[{elem}; {len}]"),
+                        SuggestedType::Array => format!("[{elem}; {len}]"),
                     }
                 } else {
                     return;
@@ -116,22 +182,24 @@ impl UselessVec {
                         return;
                     }
                     let span = args[0].span.to(last.span);
+                    let args = snippet_with_applicability(cx, span, "..", &mut applicability);
 
-                    match mutability {
-                        Mutability::Mut => {
-                            format!(
-                                "&mut [{}]",
-                                snippet_with_applicability(cx, span, "..", &mut applicability)
-                            )
+                    match suggest_slice {
+                        SuggestedType::SliceRef(Mutability::Mut) => {
+                            format!("&mut [{args}]")
+                        },
+                        SuggestedType::SliceRef(Mutability::Not) => {
+                            format!("&[{args}]")
                         },
-                        Mutability::Not => {
-                            format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
+                        SuggestedType::Array => {
+                            format!("[{args}]")
                         },
                     }
                 } else {
-                    match mutability {
-                        Mutability::Mut => "&mut []".into(),
-                        Mutability::Not => "&[]".into(),
+                    match suggest_slice {
+                        SuggestedType::SliceRef(Mutability::Mut) => "&mut []".to_owned(),
+                        SuggestedType::SliceRef(Mutability::Not) => "&[]".to_owned(),
+                        SuggestedType::Array => "[]".to_owned(),
                     }
                 }
             },
@@ -142,7 +210,13 @@ impl UselessVec {
             USELESS_VEC,
             span,
             "useless use of `vec!`",
-            "you can use a slice directly",
+            &format!(
+                "you can use {} directly",
+                match suggest_slice {
+                    SuggestedType::SliceRef(_) => "a slice",
+                    SuggestedType::Array => "an array",
+                }
+            ),
             snippet,
             applicability,
         );
diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs
new file mode 100644
index 00000000000..43248bccc13
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/visibility.rs
@@ -0,0 +1,131 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt};
+use rustc_ast::ast::{Item, VisibilityKind};
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{symbol::kw, Span};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `pub(self)` and `pub(in self)`.
+    ///
+    /// ### Why is this bad?
+    /// It's unnecessary, omitting the `pub` entirely will give the same results.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// pub(self) type OptBox<T> = Option<Box<T>>;
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// type OptBox<T> = Option<Box<T>>;
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub NEEDLESS_PUB_SELF,
+    style,
+    "checks for usage of `pub(self)` and `pub(in self)`."
+}
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `pub(<loc>)` with `in`.
+    ///
+    /// ### Why is this bad?
+    /// Consistency. Use it or don't, just be consistent about it.
+    ///
+    /// Also see the `pub_without_shorthand` lint for an alternative.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// pub(super) type OptBox<T> = Option<Box<T>>;
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// pub(in super) type OptBox<T> = Option<Box<T>>;
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub PUB_WITH_SHORTHAND,
+    restriction,
+    "disallows usage of `pub(<loc>)`, without `in`"
+}
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `pub(<loc>)` without `in`.
+    ///
+    /// Note: As you cannot write a module's path in `pub(<loc>)`, this will only trigger on
+    /// `pub(super)` and the like.
+    ///
+    /// ### Why is this bad?
+    /// Consistency. Use it or don't, just be consistent about it.
+    ///
+    /// Also see the `pub_with_shorthand` lint for an alternative.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// pub(in super) type OptBox<T> = Option<Box<T>>;
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// pub(super) type OptBox<T> = Option<Box<T>>;
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub PUB_WITHOUT_SHORTHAND,
+    restriction,
+    "disallows usage of `pub(in <loc>)` with `in`"
+}
+declare_lint_pass!(Visibility => [NEEDLESS_PUB_SELF, PUB_WITH_SHORTHAND, PUB_WITHOUT_SHORTHAND]);
+
+impl EarlyLintPass for Visibility {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+        if !in_external_macro(cx.sess(), item.span)
+            && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind
+        {
+            if **path == kw::SelfLower && let Some(false) = is_from_proc_macro(cx, item.vis.span) {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_PUB_SELF,
+                    item.vis.span,
+                    &format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }),
+                    "remove it",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate)
+                && !*shorthand
+                && let [.., last] = &*path.segments
+                && let Some(false) = is_from_proc_macro(cx, item.vis.span)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    PUB_WITHOUT_SHORTHAND,
+                    item.vis.span,
+                    "usage of `pub` with `in`",
+                    "remove it",
+                    format!("pub({})", last.ident),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if *shorthand
+                && let [.., last] = &*path.segments
+                && let Some(false) = is_from_proc_macro(cx, item.vis.span)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    PUB_WITH_SHORTHAND,
+                    item.vis.span,
+                    "usage of `pub` without `in`",
+                    "add it",
+                    format!("pub(in {})", last.ident),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
+
+fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option<bool> {
+    snippet_opt(cx, span).map(|s| !s.starts_with("pub"))
+}
diff --git a/src/tools/clippy/clippy_test_deps/Cargo.toml b/src/tools/clippy/clippy_test_deps/Cargo.toml
new file mode 100644
index 00000000000..362c08e0d77
--- /dev/null
+++ b/src/tools/clippy/clippy_test_deps/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "clippy_test_deps"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clippy_utils = { path = "../clippy_utils" }
+derive-new = "0.5"
+if_chain = "1.0"
+itertools = "0.10.1"
+quote = "1.0"
+serde = { version = "1.0.125", features = ["derive"] }
+syn = { version = "2.0", features = ["full"] }
+futures = "0.3"
+parking_lot = "0.12"
+tokio = { version = "1", features = ["io-util"] }
+regex = "1.5"
+clippy_lints = { path = "../clippy_lints" }
+
+[features]
+internal = ["clippy_lints/internal"]
diff --git a/src/tools/clippy/clippy_test_deps/src/lib.rs b/src/tools/clippy/clippy_test_deps/src/lib.rs
new file mode 100644
index 00000000000..7d12d9af819
--- /dev/null
+++ b/src/tools/clippy/clippy_test_deps/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: usize, right: usize) -> usize {
+    left + right
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn it_works() {
+        let result = add(2, 2);
+        assert_eq!(result, 4);
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 9edaae85373..c6d0b654f57 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -12,25 +12,33 @@
 //! code was written, and check if the span contains that text. Note this will only work correctly
 //! if the span is not from a `macro_rules` based macro.
 
-use rustc_ast::ast::{IntTy, LitIntType, LitKind, StrStyle, UintTy};
+use rustc_ast::{
+    ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, UintTy},
+    token::CommentKind,
+    AttrStyle,
+};
 use rustc_hir::{
     intravisit::FnKind, Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, HirId,
-    Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, Node, QPath, TraitItem,
-    TraitItemKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource,
+    Impl, ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem,
+    TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource,
 };
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::{Span, Symbol};
+use rustc_span::{symbol::Ident, Span, Symbol};
 use rustc_target::spec::abi::Abi;
 
 /// The search pattern to look for. Used by `span_matches_pat`
-#[derive(Clone, Copy)]
+#[derive(Clone)]
 pub enum Pat {
     /// A single string.
     Str(&'static str),
+    /// A single string.
+    OwnedStr(String),
     /// Any of the given strings.
     MultiStr(&'static [&'static str]),
+    /// Any of the given strings.
+    OwnedMultiStr(Vec<String>),
     /// The string representation of the symbol.
     Sym(Symbol),
     /// Any decimal or hexadecimal digit depending on the location.
@@ -51,12 +59,16 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
         let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ',');
         (match start_pat {
             Pat::Str(text) => start_str.starts_with(text),
+            Pat::OwnedStr(text) => start_str.starts_with(&text),
             Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
+            Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
             Pat::Sym(sym) => start_str.starts_with(sym.as_str()),
             Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit),
         } && match end_pat {
             Pat::Str(text) => end_str.ends_with(text),
+            Pat::OwnedStr(text) => end_str.starts_with(&text),
             Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)),
+            Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
             Pat::Sym(sym) => end_str.ends_with(sym.as_str()),
             Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit),
         })
@@ -271,14 +283,79 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI
     (start_pat, end_pat)
 }
 
-pub trait WithSearchPat {
+fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) {
+    match attr.kind {
+        AttrKind::Normal(..) => {
+            let mut pat = if matches!(attr.style, AttrStyle::Outer) {
+                (Pat::Str("#["), Pat::Str("]"))
+            } else {
+                (Pat::Str("#!["), Pat::Str("]"))
+            };
+
+            if let Some(ident) = attr.ident() && let Pat::Str(old_pat) = pat.0 {
+                // TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of
+                // refactoring
+                // NOTE: This will likely have false positives, like `allow = 1`
+                pat.0 = Pat::OwnedMultiStr(vec![ident.to_string(), old_pat.to_owned()]);
+                pat.1 = Pat::Str("");
+            }
+
+            pat
+        },
+        AttrKind::DocComment(_kind @ CommentKind::Line, ..) => {
+            if matches!(attr.style, AttrStyle::Outer) {
+                (Pat::Str("///"), Pat::Str(""))
+            } else {
+                (Pat::Str("//!"), Pat::Str(""))
+            }
+        },
+        AttrKind::DocComment(_kind @ CommentKind::Block, ..) => {
+            if matches!(attr.style, AttrStyle::Outer) {
+                (Pat::Str("/**"), Pat::Str("*/"))
+            } else {
+                (Pat::Str("/*!"), Pat::Str("*/"))
+            }
+        },
+    }
+}
+
+fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
+    match ty.kind {
+        TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")),
+        TyKind::Ptr(MutTy { mutbl, ty }) => (
+            if mutbl.is_mut() {
+                Pat::Str("*const")
+            } else {
+                Pat::Str("*mut")
+            },
+            ty_search_pat(ty).1,
+        ),
+        TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1),
+        TyKind::BareFn(bare_fn) => (
+            Pat::OwnedStr(format!("{}{} fn", bare_fn.unsafety.prefix_str(), bare_fn.abi.name())),
+            ty_search_pat(ty).1,
+        ),
+        TyKind::Never => (Pat::Str("!"), Pat::Str("")),
+        TyKind::Tup(..) => (Pat::Str("("), Pat::Str(")")),
+        TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")),
+        TyKind::Path(qpath) => qpath_search_pat(&qpath),
+        // NOTE: This is missing `TraitObject`. It always return true then.
+        _ => (Pat::Str(""), Pat::Str("")),
+    }
+}
+
+fn ident_search_pat(ident: Ident) -> (Pat, Pat) {
+    (Pat::OwnedStr(ident.name.as_str().to_owned()), Pat::Str(""))
+}
+
+pub trait WithSearchPat<'cx> {
     type Context: LintContext;
     fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat);
     fn span(&self) -> Span;
 }
 macro_rules! impl_with_search_pat {
     ($cx:ident: $ty:ident with $fn:ident $(($tcx:ident))?) => {
-        impl<'cx> WithSearchPat for $ty<'cx> {
+        impl<'cx> WithSearchPat<'cx> for $ty<'cx> {
             type Context = $cx<'cx>;
             #[allow(unused_variables)]
             fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) {
@@ -297,8 +374,9 @@ impl_with_search_pat!(LateContext: TraitItem with trait_item_search_pat);
 impl_with_search_pat!(LateContext: ImplItem with impl_item_search_pat);
 impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat);
 impl_with_search_pat!(LateContext: Variant with variant_search_pat);
+impl_with_search_pat!(LateContext: Ty with ty_search_pat);
 
-impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
+impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
     type Context = LateContext<'cx>;
 
     fn search_pat(&self, cx: &Self::Context) -> (Pat, Pat) {
@@ -310,11 +388,37 @@ impl<'cx> WithSearchPat for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
     }
 }
 
+// `Attribute` does not have the `hir` associated lifetime, so we cannot use the macro
+impl<'cx> WithSearchPat<'cx> for &'cx Attribute {
+    type Context = LateContext<'cx>;
+
+    fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) {
+        attr_search_pat(self)
+    }
+
+    fn span(&self) -> Span {
+        self.span
+    }
+}
+
+// `Ident` does not have the `hir` associated lifetime, so we cannot use the macro
+impl<'cx> WithSearchPat<'cx> for Ident {
+    type Context = LateContext<'cx>;
+
+    fn search_pat(&self, _cx: &Self::Context) -> (Pat, Pat) {
+        ident_search_pat(*self)
+    }
+
+    fn span(&self) -> Span {
+        self.span
+    }
+}
+
 /// Checks if the item likely came from a proc-macro.
 ///
 /// This should be called after `in_external_macro` and the initial pattern matching of the ast as
 /// it is significantly slower than both of those.
-pub fn is_from_proc_macro<T: WithSearchPat>(cx: &T::Context, item: &T) -> bool {
+pub fn is_from_proc_macro<'cx, T: WithSearchPat<'cx>>(cx: &T::Context, item: &T) -> bool {
     let (start_pat, end_pat) = item.search_pat(cx);
     !span_matches_pat(cx.sess(), item.span(), start_pat, end_pat)
 }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index cc3183759ae..dd3cda8ec52 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -6,7 +6,7 @@ use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir;
@@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
 use rustc_middle::ty::{List, SubstsRef};
 use rustc_middle::{bug, span_bug};
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::SyntaxContext;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
@@ -22,7 +22,8 @@ use std::iter;
 
 /// A `LitKind`-like enum to fold constant `Expr`s into.
 #[derive(Debug, Clone)]
-pub enum Constant {
+pub enum Constant<'tcx> {
+    Adt(rustc_middle::mir::ConstantKind<'tcx>),
     /// A `String` (e.g., "abc").
     Str(String),
     /// A binary string (e.g., `b"abc"`).
@@ -38,20 +39,20 @@ pub enum Constant {
     /// `true` or `false`.
     Bool(bool),
     /// An array of constants.
-    Vec(Vec<Constant>),
+    Vec(Vec<Constant<'tcx>>),
     /// Also an array, but with only one constant, repeated N times.
-    Repeat(Box<Constant>, u64),
+    Repeat(Box<Constant<'tcx>>, u64),
     /// A tuple of constants.
-    Tuple(Vec<Constant>),
+    Tuple(Vec<Constant<'tcx>>),
     /// A raw pointer.
     RawPtr(u128),
     /// A reference
-    Ref(Box<Constant>),
+    Ref(Box<Constant<'tcx>>),
     /// A literal with syntax error.
     Err,
 }
 
-impl PartialEq for Constant {
+impl<'tcx> PartialEq for Constant<'tcx> {
     fn eq(&self, other: &Self) -> bool {
         match (self, other) {
             (Self::Str(ls), Self::Str(rs)) => ls == rs,
@@ -80,13 +81,16 @@ impl PartialEq for Constant {
     }
 }
 
-impl Hash for Constant {
+impl<'tcx> Hash for Constant<'tcx> {
     fn hash<H>(&self, state: &mut H)
     where
         H: Hasher,
     {
         std::mem::discriminant(self).hash(state);
         match *self {
+            Self::Adt(ref elem) => {
+                elem.hash(state);
+            },
             Self::Str(ref s) => {
                 s.hash(state);
             },
@@ -126,7 +130,7 @@ impl Hash for Constant {
     }
 }
 
-impl Constant {
+impl<'tcx> Constant<'tcx> {
     pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
         match (left, right) {
             (Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)),
@@ -209,7 +213,7 @@ impl Constant {
 }
 
 /// Parses a `LitKind` to a `Constant`.
-pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
+pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constant<'tcx> {
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
@@ -248,7 +252,7 @@ pub fn constant<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<Constant> {
+) -> Option<Constant<'tcx>> {
     ConstEvalLateContext::new(lcx, typeck_results).expr(e)
 }
 
@@ -257,7 +261,7 @@ pub fn constant_with_source<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<(Constant, ConstantSource)> {
+) -> Option<(Constant<'tcx>, ConstantSource)> {
     let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
     let res = ctxt.expr(e);
     res.map(|x| (x, ctxt.source))
@@ -268,7 +272,7 @@ pub fn constant_simple<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<Constant> {
+) -> Option<Constant<'tcx>> {
     constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
 }
 
@@ -338,8 +342,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 
     /// Simple constant folding: Insert an expression, get a constant or none.
-    pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
+    pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
         match e.kind {
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value),
+            ExprKind::DropTemps(e) => self.expr(e),
             ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
             ExprKind::Block(block, _) => self.block(block),
             ExprKind::Lit(lit) => {
@@ -392,13 +398,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
             },
             ExprKind::Index(arr, index) => self.index(arr, index),
             ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))),
-            // TODO: add other expressions.
+            ExprKind::Field(local_expr, ref field) => {
+                let result = self.expr(local_expr);
+                if let Some(Constant::Adt(constant)) = &self.expr(local_expr)
+                    && let ty::Adt(adt_def, _) = constant.ty().kind()
+                    && adt_def.is_struct()
+                    && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field)
+                {
+                    miri_to_const(self.lcx, desired_field)
+                }
+                else {
+                    result
+                }
+            },
             _ => None,
         }
     }
 
     #[expect(clippy::cast_possible_wrap)]
-    fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
+    fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
         use self::Constant::{Bool, Int};
         match *o {
             Bool(b) => Some(Bool(!b)),
@@ -414,7 +432,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
-    fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
+    fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
         use self::Constant::{Int, F32, F64};
         match *o {
             Int(value) => {
@@ -433,28 +451,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
 
     /// Create `Some(Vec![..])` of all constants, unless there is any
     /// non-constant part.
-    fn multi(&mut self, vec: &[Expr<'_>]) -> Option<Vec<Constant>> {
+    fn multi(&mut self, vec: &[Expr<'_>]) -> Option<Vec<Constant<'tcx>>> {
         vec.iter().map(|elem| self.expr(elem)).collect::<Option<_>>()
     }
 
     /// Lookup a possibly constant expression from an `ExprKind::Path`.
-    fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<Constant> {
+    fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<Constant<'tcx>> {
         let res = self.typeck_results.qpath_res(qpath, id);
         match res {
             Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => {
                 // Check if this constant is based on `cfg!(..)`,
                 // which is NOT constant for our purposes.
-                if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) &&
-                let Node::Item(&Item {
-                    kind: ItemKind::Const(_, body_id),
-                    ..
-                }) = node &&
-                let Node::Expr(&Expr {
-                    kind: ExprKind::Lit(_),
-                    span,
-                    ..
-                }) = self.lcx.tcx.hir().get(body_id.hir_id) &&
-                is_direct_expn_of(span, "cfg").is_some() {
+                if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id)
+                    && let Node::Item(Item { kind: ItemKind::Const(_, body_id), .. }) = node
+                    && let Node::Expr(Expr { kind: ExprKind::Lit(_), span, .. }) = self.lcx
+                        .tcx
+                        .hir()
+                        .get(body_id.hir_id)
+                    && is_direct_expn_of(*span, "cfg").is_some()
+                {
                     return None;
                 }
 
@@ -464,23 +479,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                 } else {
                     EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs)
                 };
-
                 let result = self
                     .lcx
                     .tcx
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
                     .ok()
                     .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx.tcx, result)?;
+                let result = miri_to_const(self.lcx, result)?;
                 self.source = ConstantSource::Constant;
                 Some(result)
             },
-            // FIXME: cover all usable cases.
             _ => None,
         }
     }
 
-    fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant> {
+    fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant<'tcx>> {
         let lhs = self.expr(lhs);
         let index = self.expr(index);
 
@@ -506,7 +519,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 
     /// A block can only yield a constant if it only has one constant expression.
-    fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
+    fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
         if block.stmts.is_empty()
             && let Some(expr) = block.expr
         {
@@ -539,7 +552,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
-    fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant> {
+    fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant<'tcx>> {
         if let Some(Constant::Bool(b)) = self.expr(cond) {
             if b {
                 self.expr(then)
@@ -551,7 +564,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
-    fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant> {
+    fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> {
         let l = self.expr(left)?;
         let r = self.expr(right);
         match (l, r) {
@@ -644,23 +657,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 }
 
-pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant> {
+pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant<'tcx>> {
     use rustc_middle::mir::interpret::ConstValue;
     match result {
-        mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => {
-            match result.ty().kind() {
-                ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
-                ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
-                ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
-                    int.try_into().expect("invalid f32 bit representation"),
-                ))),
-                ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
-                    int.try_into().expect("invalid f64 bit representation"),
-                ))),
-                ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
-                // FIXME: implement other conversions.
-                _ => None,
-            }
+        mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
+            ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
+            ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
+            ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
+                int.try_into().expect("invalid f32 bit representation"),
+            ))),
+            ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
+                int.try_into().expect("invalid f64 bit representation"),
+            ))),
+            ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
+            _ => None,
         },
         mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
             ty::Ref(_, tam, _) => match tam.kind() {
@@ -676,35 +687,53 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
             _ => None,
         },
         mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
             ty::Array(sub_type, len) => match sub_type.kind() {
-                ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) {
+                ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) {
                     Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
                         .to_owned()
                         .array_chunks::<4>()
                         .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
-                        .collect::<Option<Vec<Constant>>>()
+                        .collect::<Option<Vec<Constant<'tcx>>>>()
                         .map(Constant::Vec),
                     _ => None,
                 },
-                ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(tcx) {
+                ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) {
                     Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
                         .to_owned()
                         .array_chunks::<8>()
                         .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
-                        .collect::<Option<Vec<Constant>>>()
+                        .collect::<Option<Vec<Constant<'tcx>>>>()
                         .map(Constant::Vec),
                     _ => None,
                 },
-                // FIXME: implement other array type conversions.
                 _ => None,
             },
             _ => None,
         },
-        // FIXME: implement other conversions.
         _ => None,
     }
 }
+
+fn field_of_struct<'tcx>(
+    adt_def: ty::AdtDef<'tcx>,
+    lcx: &LateContext<'tcx>,
+    result: mir::ConstantKind<'tcx>,
+    field: &Ident,
+) -> Option<mir::ConstantKind<'tcx>> {
+    if let Some(dc) = lcx.tcx.try_destructure_mir_constant(lcx.param_env.and(result))
+        && let Some(dc_variant) = dc.variant
+        && let Some(variant) = adt_def.variants().get(dc_variant)
+        && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
+        && let Some(dc_field) = dc.fields.get(field_idx)
+    {
+        Some(*dc_field)
+    }
+    else {
+        None
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 659c693f87a..4a845ca63b4 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -16,6 +16,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
+use rustc_middle::ty::adjustment::Adjust;
 use rustc_span::{sym, Symbol};
 use std::cmp;
 use std::ops;
@@ -114,6 +115,20 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
             if self.eagerness == ForceNoChange {
                 return;
             }
+
+            // Autoderef through a user-defined `Deref` impl can have side-effects,
+            // so don't suggest changing it.
+            if self
+                .cx
+                .typeck_results()
+                .expr_adjustments(e)
+                .iter()
+                .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_))))
+            {
+                self.eagerness |= NoChange;
+                return;
+            }
+
             match e.kind {
                 ExprKind::Call(
                     &Expr {
@@ -173,11 +188,15 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                         self.eagerness = Lazy;
                     }
                 },
-
+                // Custom `Deref` impl might have side effects
+                ExprKind::Unary(UnOp::Deref, e)
+                    if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() =>
+                {
+                    self.eagerness |= NoChange;
+                },
                 // Dereferences should be cheap, but dereferencing a raw pointer earlier may not be safe.
                 ExprKind::Unary(UnOp::Deref, e) if !self.cx.typeck_results().expr_ty(e).is_unsafe_ptr() => (),
                 ExprKind::Unary(UnOp::Deref, _) => self.eagerness |= NoChange,
-
                 ExprKind::Unary(_, e)
                     if matches!(
                         self.cx.typeck_results().expr_ty(e).kind(),
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 8c883445a79..727b59f1f43 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -20,6 +20,7 @@
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
+extern crate rustc_const_eval;
 extern crate rustc_data_structures;
 // The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate.
 #[allow(unused_extern_crates)]
@@ -326,6 +327,18 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
         .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
 }
 
+/// Checks if the `def_id` belongs to a function that is part of a trait impl.
+pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
+    if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id)
+        && let Node::Item(item) = cx.tcx.hir().get_parent(hir_id)
+        && let ItemKind::Impl(imp) = item.kind
+    {
+        imp.of_trait.is_some()
+    } else {
+        false
+    }
+}
+
 /// Checks if the given expression is a path referring an item on the trait
 /// that is marked with the given diagnostic item.
 ///
@@ -1498,7 +1511,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                 && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
                 && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
                 && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
-                && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind)
+                && let Some(min_const) = miri_to_const(cx, min_const_kind)
                 && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
@@ -1514,7 +1527,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                         && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
                         && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
                         && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
-                        && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind)
+                        && let Some(max_const) = miri_to_const(cx, max_const_kind)
                         && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const
@@ -2396,7 +2409,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol
 
 /// Checks if the function containing the given `HirId` is a `#[test]` function
 ///
-/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function
+/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function
 pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     with_test_item_names(tcx, tcx.parent_module(id), |names| {
         tcx.hir()
@@ -2418,7 +2431,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 
 /// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied
 ///
-/// Note: Add `// compile-flags: --test` to UI tests with a `#[cfg(test)]` function
+/// Note: Add `//@compile-flags: --test` to UI tests with a `#[cfg(test)]` function
 pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     fn is_cfg_test(attr: &Attribute) -> bool {
         if attr.has_name(sym::cfg)
@@ -2440,7 +2453,7 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 /// Checks whether item either has `test` attribute applied, or
 /// is a module with `test` in its name.
 ///
-/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function
+/// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function
 pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
     is_in_test_function(tcx, item.hir_id())
         || matches!(item.kind, ItemKind::Mod(..))
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index e4a4936ff42..00f3abaec8a 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -9,7 +9,7 @@ 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, Symbol};
+use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol};
 use std::cell::RefCell;
 use std::ops::ControlFlow;
 use std::sync::atomic::{AtomicBool, Ordering};
@@ -415,8 +415,18 @@ pub fn find_format_arg_expr<'hir, 'ast>(
     start: &'hir Expr<'hir>,
     target: &'ast FormatArgument,
 ) -> Result<&'hir rustc_hir::Expr<'hir>, &'ast rustc_ast::Expr> {
+    let SpanData {
+        lo,
+        hi,
+        ctxt,
+        parent: _,
+    } = target.expr.span.data();
+
     for_each_expr(start, |expr| {
-        if expr.span == target.expr.span {
+        // When incremental compilation is enabled spans gain a parent during AST to HIR lowering,
+        // since we're comparing an AST span to a HIR one we need to ignore the parent field
+        let data = expr.span.data();
+        if data.lo == lo && data.hi == hi && data.ctxt == ctxt {
             ControlFlow::Break(expr)
         } else {
             ControlFlow::Continue(())
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 6f102308f0b..3637476c408 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -19,6 +19,8 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,71,0 { TUPLE_ARRAY_CONVERSIONS }
+    1,70,0 { OPTION_IS_SOME_AND }
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
@@ -28,7 +30,7 @@ msrv_aliases! {
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
     1,50,0 { BOOL_THEN, CLAMP }
-    1,47,0 { TAU, IS_ASCII_DIGIT_CONST }
+    1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN }
     1,46,0 { CONST_IF_MATCH }
     1,45,0 { STR_STRIP_PREFIX }
     1,43,0 { LOG2_10, LOG10_2 }
@@ -42,11 +44,13 @@ msrv_aliases! {
     1,34,0 { TRY_FROM }
     1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
     1,28,0 { FROM_BOOL }
+    1,27,0 { ITERATOR_TRY_FOLD }
     1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN }
     1,24,0 { IS_ASCII_DIGIT }
     1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
     1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
     1,16,0 { STR_REPEAT }
+    1,15,0 { MAYBE_BOUND_IN_WHERE }
 }
 
 fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index c225398ad2a..bbe4149fe2a 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -161,7 +161,7 @@ impl<'a> NumericLiteral<'a> {
         }
 
         if let Some((separator, exponent)) = self.exponent {
-            if exponent != "0" {
+            if !exponent.is_empty() && exponent != "0" {
                 output.push_str(separator);
                 Self::group_digits(&mut output, exponent, group_size, true, false);
             }
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 b7e83ce6caa..c9938caefb0 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
@@ -4,17 +4,24 @@
 // differ from the time of `rustc` even if the name stays the same.
 
 use crate::msrvs::Msrv;
+use hir::LangItem;
+use rustc_const_eval::transform::check_consts::ConstCx;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::Obligation;
 use rustc_middle::mir::{
     Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind,
     Terminator, TerminatorKind,
 };
+use rustc_middle::traits::{ImplSource, ObligationCause};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
+use rustc_middle::ty::{BoundConstness, TraitRef};
 use rustc_semver::RustcVersion;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext};
 use std::borrow::Cow;
 
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
@@ -32,7 +39,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
         body.local_decls.iter().next().unwrap().source_info.span,
     )?;
 
-    for bb in body.basic_blocks.iter() {
+    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)?;
@@ -60,7 +67,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
                 return Err((span, "function pointers in const fn are unstable".into()));
             },
             ty::Dynamic(preds, _, _) => {
-                for pred in preds.iter() {
+                for pred in *preds {
                     match pred.skip_binder() {
                         ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => {
                             return Err((
@@ -227,7 +234,19 @@ fn check_statement<'tcx>(
 
 fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
     match operand {
-        Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body),
+        Operand::Move(place) => {
+            if !place.projection.as_ref().is_empty()
+                && !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body)
+            {
+                return Err((
+                    span,
+                    "cannot drop locals with a non constant destructor in const fn".into(),
+                ));
+            }
+
+            check_place(tcx, *place, span, body)
+        },
+        Operand::Copy(place) => check_place(tcx, *place, span, body),
         Operand::Constant(c) => match c.check_static_ptr(tcx) {
             Some(_) => Err((span, "cannot access `static` items in const fn".into())),
             None => Ok(()),
@@ -236,12 +255,10 @@ 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 {
-    let mut cursor = place.projection.as_ref();
-    while let [ref proj_base @ .., elem] = *cursor {
-        cursor = proj_base;
+    for (base, elem) in place.as_ref().iter_projections() {
         match elem {
             ProjectionElem::Field(..) => {
-                let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty;
+                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() {
@@ -276,15 +293,19 @@ fn check_terminator<'tcx>(
         | TerminatorKind::Resume
         | TerminatorKind::Terminate
         | TerminatorKind::Unreachable => Ok(()),
-
-        TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
-
+        TerminatorKind::Drop { place, .. } => {
+            if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) {
+                return Err((
+                    span,
+                    "cannot drop locals with a non constant destructor in const fn".into(),
+                ));
+            }
+            Ok(())
+        },
         TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
-
         TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
             Err((span, "const fn generators are unstable".into()))
         },
-
         TerminatorKind::Call {
             func,
             args,
@@ -328,7 +349,6 @@ fn check_terminator<'tcx>(
                 Err((span, "can only call other const fns within const fn".into()))
             }
         },
-
         TerminatorKind::Assert {
             cond,
             expected: _,
@@ -336,7 +356,6 @@ fn check_terminator<'tcx>(
             target: _,
             unwind: _,
         } => check_operand(tcx, cond, span, body),
-
         TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
     }
 }
@@ -350,8 +369,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
                 // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
 
                 // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver`
-                // doesn't accept                  the `-dev` version number so we have to strip it
-                // off.
+                // doesn't accept the `-dev` version number so we have to strip it off.
                 let short_version = since
                     .as_str()
                     .split('-')
@@ -369,3 +387,35 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
             }
         })
 }
+
+#[expect(clippy::similar_names)] // bit too pedantic
+fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool {
+    // Avoid selecting for simple cases, such as builtin types.
+    if ty::util::is_trivially_const_drop(ty) {
+        return true;
+    }
+
+    let obligation = Obligation::new(
+        tcx,
+        ObligationCause::dummy_with_span(body.span),
+        ConstCx::new(tcx, body).param_env.with_const(),
+        TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst),
+    );
+
+    let infcx = tcx.infer_ctxt().build();
+    let mut selcx = SelectionContext::new(&infcx);
+    let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
+        return false;
+    };
+
+    if !matches!(
+        impl_src,
+        ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
+    ) {
+        return false;
+    }
+
+    let ocx = ObligationCtxt::new(&infcx);
+    ocx.register_obligations(impl_src.nested_obligations());
+    ocx.select_all_or_error().is_empty()
+}
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index b38b9553558..cf781e18cd6 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -944,7 +944,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         },
                         // item is used in a call
                         // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
-                        ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => {
+                        ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => {
                             let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
                             let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
 
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 8d3aecd4785..9c39d22c61b 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -17,8 +17,8 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
     self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv,
-    Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr,
+    Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    UintTy, VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::symbol::Ident;
@@ -277,7 +277,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             false
         },
         ty::Dynamic(binder, _, _) => {
-            for predicate in binder.iter() {
+            for predicate in *binder {
                 if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
                     if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) {
                         return true;
@@ -760,9 +760,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
                 }
                 inputs = Some(i);
             },
-            ty::ClauseKind::Projection(p)
-                if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
-            {
+            ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => {
                 if output.is_some() {
                     // Multiple different fn trait impls. Is this even allowed?
                     return None;
@@ -1180,3 +1178,51 @@ pub fn is_interior_mut_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         _ => false,
     }
 }
+
+pub fn make_normalized_projection_with_regions<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
+    container_id: DefId,
+    assoc_ty: Symbol,
+    substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+) -> Option<Ty<'tcx>> {
+    fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
+        #[cfg(debug_assertions)]
+        if let Some((i, subst)) = ty
+            .substs
+            .iter()
+            .enumerate()
+            .find(|(_, subst)| subst.has_late_bound_regions())
+        {
+            debug_assert!(
+                false,
+                "substs contain late-bound region at index `{i}` which can't be normalized.\n\
+                    use `TyCtxt::erase_late_bound_regions`\n\
+                    note: subst is `{subst:#?}`",
+            );
+            return None;
+        }
+        let cause = rustc_middle::traits::ObligationCause::dummy();
+        match tcx
+            .infer_ctxt()
+            .build()
+            .at(&cause, param_env)
+            .query_normalize(tcx.mk_projection(ty.def_id, ty.substs))
+        {
+            Ok(ty) => Some(ty.value),
+            Err(e) => {
+                debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
+                None
+            },
+        }
+    }
+    helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, substs)?)
+}
+
+pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+    let cause = rustc_middle::traits::ObligationCause::dummy();
+    match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) {
+        Ok(ty) => ty.value,
+        Err(_) => ty,
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index ab3976a13bd..9855085216f 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -82,7 +82,7 @@ pub struct ParamBindingIdCollector {
 impl<'tcx> ParamBindingIdCollector {
     fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec<hir::HirId> {
         let mut hir_ids: Vec<hir::HirId> = Vec::new();
-        for param in body.params.iter() {
+        for param in body.params {
             let mut finder = ParamBindingIdCollector {
                 binding_hir_ids: Vec::new(),
             };
diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs
index 5232e4ab7d7..0057256f659 100644
--- a/src/tools/clippy/declare_clippy_lint/src/lib.rs
+++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs
@@ -85,8 +85,8 @@ impl Parse for ClippyLint {
 /// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions.
 /// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or
 ///    `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of.
-/// 4. The `description` that contains a short explanation on what's wrong with code where the
-///    lint is triggered.
+/// 4. The `description` that contains a short explanation on what's wrong with code where the lint
+///    is triggered.
 ///
 /// Currently the categories `style`, `correctness`, `suspicious`, `complexity` and `perf` are
 /// enabled by default. As said in the README.md of this repository, if the lint level mapping
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 03d1877d6c6..de56a6f8275 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -474,7 +474,7 @@ fn read_crates(toml_path: &Path) -> (Vec<CrateSource>, RecursiveOptions) {
             });
         } else if let Some(ref versions) = tk.versions {
             // if we have multiple versions, save each one
-            for ver in versions.iter() {
+            for ver in versions {
                 crate_sources.push(CrateSource::CratesIo {
                     name: tk.name.clone(),
                     version: ver.to_string(),
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 0d2e1eee643..4475d914ced 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-06-02"
+channel = "nightly-2023-06-29"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/rustfmt.toml b/src/tools/clippy/rustfmt.toml
index 10d39762043..18b2a33469d 100644
--- a/src/tools/clippy/rustfmt.toml
+++ b/src/tools/clippy/rustfmt.toml
@@ -5,3 +5,4 @@ wrap_comments = true
 edition = "2021"
 error_on_line_overflow = true
 version = "Two"
+ignore = ["tests/ui/crashes/ice-10912.rs"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index f3cc94aeff0..1eb288b153a 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -16,9 +16,9 @@ extern crate rustc_session;
 extern crate rustc_span;
 
 use rustc_interface::interface;
-use rustc_session::EarlyErrorHandler;
 use rustc_session::config::ErrorOutputType;
 use rustc_session::parse::ParseSess;
+use rustc_session::EarlyErrorHandler;
 use rustc_span::symbol::Symbol;
 
 use std::env;
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index 188ff87abfc..cdc85cb33ca 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -6,7 +6,7 @@ use std::env;
 use std::path::PathBuf;
 use std::process::{self, Command};
 
-const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.
+const CARGO_CLIPPY_HELP: &str = "Checks a package to catch common mistakes and improve your Rust code.
 
 Usage:
     cargo clippy [options] [--] [<opts>...]
@@ -31,7 +31,7 @@ with:
 You can use tool lints to allow or deny lints from your code, e.g.:
 
     #[allow(clippy::needless_lifetimes)]
-"#;
+";
 
 fn show_help() {
     println!("{CARGO_CLIPPY_HELP}");
@@ -57,7 +57,9 @@ pub fn main() {
     if let Some(pos) = env::args().position(|a| a == "--explain") {
         if let Some(mut lint) = env::args().nth(pos + 1) {
             lint.make_ascii_lowercase();
-            clippy_lints::explain(&lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"));
+            process::exit(clippy_lints::explain(
+                &lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"),
+            ));
         } else {
             show_help();
         }
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 35d75cc51c2..0fd37c640ae 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -4,16 +4,14 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use compiletest_rs as compiletest;
-use compiletest_rs::common::Mode as TestMode;
+use compiletest::{status_emitter, CommandBuilder};
+use ui_test as compiletest;
+use ui_test::Mode as TestMode;
 
-use std::collections::HashMap;
 use std::env::{self, remove_var, set_var, var_os};
 use std::ffi::{OsStr, OsString};
 use std::fs;
-use std::io;
 use std::path::{Path, PathBuf};
-use std::sync::LazyLock;
 use test_utils::IS_RUSTC_TEST_SUITE;
 
 mod test_utils;
@@ -21,143 +19,41 @@ mod test_utils;
 // whether to run internal tests or not
 const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal");
 
-/// All crates used in UI tests are listed here
-static TEST_DEPENDENCIES: &[&str] = &[
-    "clippy_lints",
-    "clippy_utils",
-    "derive_new",
-    "futures",
-    "if_chain",
-    "itertools",
-    "quote",
-    "regex",
-    "serde",
-    "serde_derive",
-    "syn",
-    "tokio",
-    "parking_lot",
-    "rustc_semver",
-];
-
-// Test dependencies may need an `extern crate` here to ensure that they show up
-// in the depinfo file (otherwise cargo thinks they are unused)
-#[allow(unused_extern_crates)]
-extern crate clippy_lints;
-#[allow(unused_extern_crates)]
-extern crate clippy_utils;
-#[allow(unused_extern_crates)]
-extern crate derive_new;
-#[allow(unused_extern_crates)]
-extern crate futures;
-#[allow(unused_extern_crates)]
-extern crate if_chain;
-#[allow(unused_extern_crates)]
-extern crate itertools;
-#[allow(unused_extern_crates)]
-extern crate parking_lot;
-#[allow(unused_extern_crates)]
-extern crate quote;
-#[allow(unused_extern_crates)]
-extern crate rustc_semver;
-#[allow(unused_extern_crates)]
-extern crate syn;
-#[allow(unused_extern_crates)]
-extern crate tokio;
-
-/// Produces a string with an `--extern` flag for all UI test crate
-/// dependencies.
-///
-/// The dependency files are located by parsing the depinfo file for this test
-/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test
-/// dependencies must be added to Cargo.toml at the project root. Test
-/// dependencies that are not *directly* used by this test module require an
-/// `extern crate` declaration.
-static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| {
-    let current_exe_depinfo = {
-        let mut path = env::current_exe().unwrap();
-        path.set_extension("d");
-        fs::read_to_string(path).unwrap()
-    };
-    let mut crates: HashMap<&str, &str> = HashMap::with_capacity(TEST_DEPENDENCIES.len());
-    for line in current_exe_depinfo.lines() {
-        // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:`
-        let parse_name_path = || {
-            if line.starts_with(char::is_whitespace) {
-                return None;
-            }
-            let path_str = line.strip_suffix(':')?;
-            let path = Path::new(path_str);
-            if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") {
-                return None;
-            }
-            let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?;
-            // the "lib" prefix is not present for dll files
-            let name = name.strip_prefix("lib").unwrap_or(name);
-            Some((name, path_str))
-        };
-        if let Some((name, path)) = parse_name_path() {
-            if TEST_DEPENDENCIES.contains(&name) {
-                // A dependency may be listed twice if it is available in sysroot,
-                // and the sysroot dependencies are listed first. As of the writing,
-                // this only seems to apply to if_chain.
-                crates.insert(name, path);
-            }
-        }
-    }
-    let not_found: Vec<&str> = TEST_DEPENDENCIES
-        .iter()
-        .copied()
-        .filter(|n| !crates.contains_key(n))
-        .collect();
-    assert!(
-        not_found.is_empty(),
-        "dependencies not found in depinfo: {not_found:?}\n\
-        help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\
-        help: Try adding to dev-dependencies in Cargo.toml\n\
-        help: Be sure to also add `extern crate ...;` to tests/compile-test.rs",
-    );
-    crates
-        .into_iter()
-        .map(|(name, path)| format!(" --extern {name}={path}"))
-        .collect()
-});
-
 fn base_config(test_dir: &str) -> compiletest::Config {
     let mut config = compiletest::Config {
-        edition: Some("2021".into()),
-        mode: TestMode::Ui,
-        strict_headers: true,
-        ..Default::default()
+        mode: TestMode::Yolo,
+        stderr_filters: vec![],
+        stdout_filters: vec![],
+        output_conflict_handling: if var_os("BLESS").is_some() || env::args().any(|arg| arg == "--bless") {
+            compiletest::OutputConflictHandling::Bless
+        } else {
+            compiletest::OutputConflictHandling::Error("cargo test -- -- --bless".into())
+        },
+        dependencies_crate_manifest_path: Some("clippy_test_deps/Cargo.toml".into()),
+        target: None,
+        out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap_or("target".into())).join("ui_test"),
+        ..compiletest::Config::rustc(Path::new("tests").join(test_dir))
     };
 
-    if let Ok(filters) = env::var("TESTNAME") {
-        config.filters = filters.split(',').map(ToString::to_string).collect();
-    }
-
-    if let Some(path) = option_env!("RUSTC_LIB_PATH") {
-        let path = PathBuf::from(path);
-        config.run_lib_path = path.clone();
-        config.compile_lib_path = path;
+    if let Some(_path) = option_env!("RUSTC_LIB_PATH") {
+        //let path = PathBuf::from(path);
+        //config.run_lib_path = path.clone();
+        //config.compile_lib_path = path;
     }
     let current_exe_path = env::current_exe().unwrap();
     let deps_path = current_exe_path.parent().unwrap();
     let profile_path = deps_path.parent().unwrap();
 
-    // Using `-L dependency={}` enforces that external dependencies are added with `--extern`.
-    // This is valuable because a) it allows us to monitor what external dependencies are used
-    // and b) it ensures that conflicting rlibs are resolved properly.
-    let host_libs = option_env!("HOST_LIBS")
-        .map(|p| format!(" -L dependency={}", Path::new(p).join("deps").display()))
-        .unwrap_or_default();
-    config.target_rustcflags = Some(format!(
-        "--emit=metadata -Dwarnings -Zui-testing -L dependency={}{host_libs}{}",
-        deps_path.display(),
-        &*EXTERN_FLAGS,
-    ));
-
-    config.src_base = Path::new("tests").join(test_dir);
-    config.build_base = profile_path.join("test").join(test_dir);
-    config.rustc_path = profile_path.join(if cfg!(windows) {
+    config.program.args.push("--emit=metadata".into());
+    config.program.args.push("-Aunused".into());
+    config.program.args.push("-Zui-testing".into());
+    config.program.args.push("-Dwarnings".into());
+
+    // Normalize away slashes in windows paths.
+    config.stderr_filter(r"\\", "/");
+
+    //config.build_base = profile_path.join("test").join(test_dir);
+    config.program.program = profile_path.join(if cfg!(windows) {
         "clippy-driver.exe"
     } else {
         "clippy-driver"
@@ -165,9 +61,18 @@ fn base_config(test_dir: &str) -> compiletest::Config {
     config
 }
 
+fn test_filter() -> Box<dyn Sync + Fn(&Path) -> bool> {
+    if let Ok(filters) = env::var("TESTNAME") {
+        let filters: Vec<_> = filters.split(',').map(ToString::to_string).collect();
+        Box::new(move |path| filters.iter().any(|f| path.to_string_lossy().contains(f)))
+    } else {
+        Box::new(|_| true)
+    }
+}
+
 fn run_ui() {
-    let mut config = base_config("ui");
-    config.rustfix_coverage = true;
+    let config = base_config("ui");
+    //config.rustfix_coverage = true;
     // use tests/clippy.toml
     let _g = VarGuard::set("CARGO_MANIFEST_DIR", fs::canonicalize("tests").unwrap());
     let _threads = VarGuard::set(
@@ -179,7 +84,19 @@ fn run_ui() {
                 .to_string()
         }),
     );
-    compiletest::run_tests(&config);
+    eprintln!("   Compiler: {}", config.program.display());
+
+    let name = config.root_dir.display().to_string();
+
+    let test_filter = test_filter();
+
+    compiletest::run_tests_generic(
+        config,
+        move |path| compiletest::default_file_filter(path) && test_filter(path),
+        compiletest::default_per_file_config,
+        (status_emitter::Text, status_emitter::Gha::<true> { name }),
+    )
+    .unwrap();
     check_rustfix_coverage();
 }
 
@@ -188,177 +105,118 @@ fn run_internal_tests() {
     if !RUN_INTERNAL_TESTS {
         return;
     }
-    let config = base_config("ui-internal");
-    compiletest::run_tests(&config);
+    let mut config = base_config("ui-internal");
+    config.dependency_builder.args.push("--features".into());
+    config.dependency_builder.args.push("internal".into());
+    compiletest::run_tests(config).unwrap();
 }
 
 fn run_ui_toml() {
-    fn run_tests(config: &compiletest::Config, mut tests: Vec<tester::TestDescAndFn>) -> Result<bool, io::Error> {
-        let mut result = true;
-        let opts = compiletest::test_opts(config);
-        for dir in fs::read_dir(&config.src_base)? {
-            let dir = dir?;
-            if !dir.file_type()?.is_dir() {
-                continue;
-            }
-            let dir_path = dir.path();
-            let _g = VarGuard::set("CARGO_MANIFEST_DIR", &dir_path);
-            for file in fs::read_dir(&dir_path)? {
-                let file = file?;
-                let file_path = file.path();
-                if file.file_type()?.is_dir() {
-                    continue;
-                }
-                if file_path.extension() != Some(OsStr::new("rs")) {
-                    continue;
-                }
-                let paths = compiletest::common::TestPaths {
-                    file: file_path,
-                    base: config.src_base.clone(),
-                    relative_dir: dir_path.file_name().unwrap().into(),
-                };
-                let test_name = compiletest::make_test_name(config, &paths);
-                let index = tests
-                    .iter()
-                    .position(|test| test.desc.name == test_name)
-                    .expect("The test should be in there");
-                result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
-            }
-        }
-        Ok(result)
-    }
-
     let mut config = base_config("ui-toml");
-    config.src_base = config.src_base.canonicalize().unwrap();
 
-    let tests = compiletest::make_tests(&config);
+    config.stderr_filter(
+        &regex::escape(
+            &fs::canonicalize("tests")
+                .unwrap()
+                .parent()
+                .unwrap()
+                .display()
+                .to_string()
+                .replace('\\', "/"),
+        ),
+        "$$DIR",
+    );
+
+    let name = config.root_dir.display().to_string();
+
+    let test_filter = test_filter();
 
-    let res = run_tests(&config, tests);
-    match res {
-        Ok(true) => {},
-        Ok(false) => panic!("Some tests failed"),
-        Err(e) => {
-            panic!("I/O failure during tests: {e:?}");
+    ui_test::run_tests_generic(
+        config,
+        |path| test_filter(path) && path.extension() == Some("rs".as_ref()),
+        |config, path| {
+            let mut config = config.clone();
+            config
+                .program
+                .envs
+                .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into())));
+            Some(config)
         },
-    }
+        (status_emitter::Text, status_emitter::Gha::<true> { name }),
+    )
+    .unwrap();
 }
 
 fn run_ui_cargo() {
-    fn run_tests(
-        config: &compiletest::Config,
-        filters: &[String],
-        mut tests: Vec<tester::TestDescAndFn>,
-    ) -> Result<bool, io::Error> {
-        let mut result = true;
-        let opts = compiletest::test_opts(config);
-
-        for dir in fs::read_dir(&config.src_base)? {
-            let dir = dir?;
-            if !dir.file_type()?.is_dir() {
-                continue;
-            }
-
-            // Use the filter if provided
-            let dir_path = dir.path();
-            for filter in filters {
-                if !dir_path.ends_with(filter) {
-                    continue;
-                }
-            }
-
-            for case in fs::read_dir(&dir_path)? {
-                let case = case?;
-                if !case.file_type()?.is_dir() {
-                    continue;
-                }
-
-                let src_path = case.path().join("src");
-
-                // When switching between branches, if the previous branch had a test
-                // that the current branch does not have, the directory is not removed
-                // because an ignored Cargo.lock file exists.
-                if !src_path.exists() {
-                    continue;
-                }
-
-                env::set_current_dir(&src_path)?;
-
-                let cargo_toml_path = case.path().join("Cargo.toml");
-                let cargo_content = fs::read(cargo_toml_path)?;
-                let cargo_parsed: toml::Value = toml::from_str(
-                    std::str::from_utf8(&cargo_content).expect("`Cargo.toml` is not a valid utf-8 file!"),
-                )
-                .expect("Can't parse `Cargo.toml`");
-
-                let _g = VarGuard::set("CARGO_MANIFEST_DIR", case.path());
-                let _h = VarGuard::set(
-                    "CARGO_PKG_RUST_VERSION",
-                    cargo_parsed
-                        .get("package")
-                        .and_then(|p| p.get("rust-version"))
-                        .and_then(toml::Value::as_str)
-                        .unwrap_or(""),
-                );
-
-                for file in fs::read_dir(&src_path)? {
-                    let file = file?;
-                    if file.file_type()?.is_dir() {
-                        continue;
-                    }
-
-                    // Search for the main file to avoid running a test for each file in the project
-                    let file_path = file.path();
-                    match file_path.file_name().and_then(OsStr::to_str) {
-                        Some("main.rs") => {},
-                        _ => continue,
-                    }
-                    let _g = VarGuard::set("CLIPPY_CONF_DIR", case.path());
-                    let paths = compiletest::common::TestPaths {
-                        file: file_path,
-                        base: config.src_base.clone(),
-                        relative_dir: src_path.strip_prefix(&config.src_base).unwrap().into(),
-                    };
-                    let test_name = compiletest::make_test_name(config, &paths);
-                    let index = tests
-                        .iter()
-                        .position(|test| test.desc.name == test_name)
-                        .expect("The test should be in there");
-                    result &= tester::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
-                }
-            }
-        }
-        Ok(result)
-    }
-
     if IS_RUSTC_TEST_SUITE {
         return;
     }
 
     let mut config = base_config("ui-cargo");
-    config.src_base = config.src_base.canonicalize().unwrap();
+    config.program.input_file_flag = CommandBuilder::cargo().input_file_flag;
+    config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag;
+    config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()];
+    config
+        .program
+        .envs
+        .push(("RUSTFLAGS".into(), Some("-Dwarnings".into())));
+    // We need to do this while we still have a rustc in the `program` field.
+    config.fill_host_and_target().unwrap();
+    config.dependencies_crate_manifest_path = None;
+    config.program.program.set_file_name(if cfg!(windows) {
+        "cargo-clippy.exe"
+    } else {
+        "cargo-clippy"
+    });
+    config.edition = None;
+
+    config.stderr_filter(
+        &regex::escape(
+            &fs::canonicalize("tests")
+                .unwrap()
+                .parent()
+                .unwrap()
+                .display()
+                .to_string()
+                .replace('\\', "/"),
+        ),
+        "$$DIR",
+    );
 
-    let tests = compiletest::make_tests(&config);
+    let name = config.root_dir.display().to_string();
 
-    let current_dir = env::current_dir().unwrap();
-    let res = run_tests(&config, &config.filters, tests);
-    env::set_current_dir(current_dir).unwrap();
+    let test_filter = test_filter();
 
-    match res {
-        Ok(true) => {},
-        Ok(false) => panic!("Some tests failed"),
-        Err(e) => {
-            panic!("I/O failure during tests: {e:?}");
+    ui_test::run_tests_generic(
+        config,
+        |path| test_filter(path) && path.ends_with("Cargo.toml"),
+        |config, path| {
+            let mut config = config.clone();
+            config.out_dir = PathBuf::from("target/ui_test_cargo/").join(path.parent().unwrap());
+            Some(config)
         },
-    }
+        (status_emitter::Text, status_emitter::Gha::<true> { name }),
+    )
+    .unwrap();
 }
 
-#[test]
-fn compile_test() {
+fn main() {
+    // Support being run by cargo nextest - https://nexte.st/book/custom-test-harnesses.html
+    if env::args().any(|arg| arg == "--list") {
+        if !env::args().any(|arg| arg == "--ignored") {
+            println!("compile_test: test");
+        }
+
+        return;
+    }
+
     set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
     run_ui();
     run_ui_toml();
     run_ui_cargo();
     run_internal_tests();
+    rustfix_coverage_known_exceptions_accuracy();
+    ui_cargo_toml_metadata();
 }
 
 const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
@@ -384,7 +242,6 @@ const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
     "needless_for_each_unfixable.rs",
     "nonminimal_bool.rs",
     "print_literal.rs",
-    "print_with_newline.rs",
     "redundant_static_lifetimes_multiple.rs",
     "ref_binding_to_reference.rs",
     "repl_uninit.rs",
@@ -399,7 +256,6 @@ const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
     "unnecessary_lazy_eval_unfixable.rs",
     "write_literal.rs",
     "write_literal_2.rs",
-    "write_with_newline.rs",
 ];
 
 fn check_rustfix_coverage() {
@@ -432,25 +288,15 @@ fn check_rustfix_coverage() {
     }
 }
 
-#[test]
 fn rustfix_coverage_known_exceptions_accuracy() {
     for filename in RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS {
         let rs_path = Path::new("tests/ui").join(filename);
-        assert!(
-            rs_path.exists(),
-            "`{}` does not exist",
-            rs_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
-        );
+        assert!(rs_path.exists(), "`{}` does not exist", rs_path.display());
         let fixed_path = rs_path.with_extension("fixed");
-        assert!(
-            !fixed_path.exists(),
-            "`{}` exists",
-            fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
-        );
+        assert!(!fixed_path.exists(), "`{}` exists", fixed_path.display());
     }
 }
 
-#[test]
 fn ui_cargo_toml_metadata() {
     let ui_cargo_path = Path::new("tests/ui-cargo");
     let cargo_common_metadata_path = ui_cargo_path.join("cargo_common_metadata");
diff --git a/src/tools/clippy/tests/headers.rs b/src/tools/clippy/tests/headers.rs
new file mode 100644
index 00000000000..1d1e566cbf6
--- /dev/null
+++ b/src/tools/clippy/tests/headers.rs
@@ -0,0 +1,29 @@
+use regex::Regex;
+use std::fs;
+use walkdir::WalkDir;
+
+#[test]
+fn old_test_headers() {
+    let old_headers = Regex::new(
+        r"^//( ?\[\w+\])? ?((check|build|run|ignore|aux|only|needs|rustc|unset|no|normalize|run|compile)-|edition|incremental|revisions).*",
+    )
+    .unwrap();
+    let mut failed = false;
+
+    for entry in WalkDir::new("tests") {
+        let entry = entry.unwrap();
+        if !entry.file_type().is_file() {
+            continue;
+        }
+
+        let file = fs::read_to_string(entry.path()).unwrap();
+
+        if let Some(header) = old_headers.find(&file) {
+            println!("Found header `{}` in {}", header.as_str(), entry.path().display());
+
+            failed = true;
+        }
+    }
+
+    assert!(!failed, "use `//@foo` style test headers instead");
+}
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index 8feea800fdb..15e5cdd6992 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -20,16 +20,16 @@ impl Message {
         // also no punctuation (except for "?" ?) at the end of a line
         static REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
             RegexSet::new([
-                r"error: [A-Z]",
-                r"help: [A-Z]",
-                r"warning: [A-Z]",
-                r"note: [A-Z]",
-                r"try this: [A-Z]",
-                r"error: .*[.!]$",
-                r"help: .*[.!]$",
-                r"warning: .*[.!]$",
-                r"note: .*[.!]$",
-                r"try this: .*[.!]$",
+                "error: [A-Z]",
+                "help: [A-Z]",
+                "warning: [A-Z]",
+                "note: [A-Z]",
+                "try this: [A-Z]",
+                "error: .*[.!]$",
+                "help: .*[.!]$",
+                "warning: .*[.!]$",
+                "note: .*[.!]$",
+                "try this: .*[.!]$",
             ])
             .unwrap()
         });
@@ -39,11 +39,11 @@ impl Message {
         static EXCEPTIONS_SET: LazyLock<RegexSet> = LazyLock::new(|| {
             RegexSet::new([
                 r"\.\.\.$",
-                r".*C-like enum variant discriminant is not portable to 32-bit targets",
-                r".*Intel x86 assembly syntax used",
-                r".*AT&T x86 assembly syntax used",
-                r"note: Clippy version: .*",
-                r"the compiler unexpectedly panicked. this is a bug.",
+                ".*C-like enum variant discriminant is not portable to 32-bit targets",
+                ".*Intel x86 assembly syntax used",
+                ".*AT&T x86 assembly syntax used",
+                "note: Clippy version: .*",
+                "the compiler unexpectedly panicked. this is a bug.",
             ])
             .unwrap()
         });
diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs
index caedd5d76cd..0d35a22cd9a 100644
--- a/src/tools/clippy/tests/missing-test-files.rs
+++ b/src/tools/clippy/tests/missing-test-files.rs
@@ -41,8 +41,8 @@ fn explore_directory(dir: &Path) -> Vec<String> {
             x.path().extension().and_then(OsStr::to_str),
             y.path().extension().and_then(OsStr::to_str),
         ) {
-            (Some("rs"), _) => Ordering::Less,
-            (_, Some("rs")) => Ordering::Greater,
+            (Some("rs" | "toml"), _) => Ordering::Less,
+            (_, Some("rs" | "toml")) => Ordering::Greater,
             _ => Ordering::Equal,
         }
     });
@@ -54,7 +54,7 @@ fn explore_directory(dir: &Path) -> Vec<String> {
             let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string();
             if let Some(ext) = path.extension() {
                 match ext.to_str().unwrap() {
-                    "rs" => current_file = file_prefix.clone(),
+                    "rs" | "toml" => current_file = file_prefix.clone(),
                     "stderr" | "stdout" => {
                         if file_prefix != current_file {
                             missing_files.push(path.to_str().unwrap().to_string());
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr
index 86953142bef..e161507b533 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail/Cargo.stderr
@@ -1,6 +1,6 @@
 error: package `cargo_common_metadata_fail` is missing `package.description` metadata
-   |
-   = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
+  |
+  = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
 error: package `cargo_common_metadata_fail` is missing `either package.license or package.license_file` metadata
 
@@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail` is missing `package.keywords` metada
 
 error: package `cargo_common_metadata_fail` is missing `package.categories` metadata
 
-error: aborting due to 6 previous errors
-
+error: could not compile `cargo_common_metadata_fail` (bin "cargo_common_metadata_fail") due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr
index ac1b5e8e903..dbf494cc342 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.stderr
@@ -1,6 +1,6 @@
 error: package `cargo_common_metadata_fail_publish` is missing `package.description` metadata
-   |
-   = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
+  |
+  = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
 error: package `cargo_common_metadata_fail_publish` is missing `either package.license or package.license_file` metadata
 
@@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail_publish` is missing `package.keywords
 
 error: package `cargo_common_metadata_fail_publish` is missing `package.categories` metadata
 
-error: aborting due to 6 previous errors
-
+error: could not compile `cargo_common_metadata_fail_publish` (bin "cargo_common_metadata_fail_publish") due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr
index be32c0dc418..ae5967406f6 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.stderr
@@ -1,6 +1,6 @@
 error: package `cargo_common_metadata_fail_publish_true` is missing `package.description` metadata
-   |
-   = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
+  |
+  = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
 error: package `cargo_common_metadata_fail_publish_true` is missing `either package.license or package.license_file` metadata
 
@@ -12,5 +12,4 @@ error: package `cargo_common_metadata_fail_publish_true` is missing `package.key
 
 error: package `cargo_common_metadata_fail_publish_true` is missing `package.categories` metadata
 
-error: aborting due to 6 previous errors
-
+error: could not compile `cargo_common_metadata_fail_publish_true` (bin "cargo_common_metadata_fail_publish_true") due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr
new file mode 100644
index 00000000000..dfbf19d33a5
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.stderr
@@ -0,0 +1,21 @@
+warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml`
+
+error: unnecessary structure name repetition
+ --> src/main.rs:6:21
+  |
+6 |     pub fn bar() -> Foo {
+  |                     ^^^ help: use the applicable keyword: `Self`
+  |
+note: the lint level is defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(clippy::use_self)]
+  |         ^^^^^^^^^^^^^^^^
+
+error: unnecessary structure name repetition
+ --> src/main.rs:7:9
+  |
+7 |         Foo
+  |         ^^^ help: use the applicable keyword: `Self`
+
+error: could not compile `fail-both-diff` (bin "fail-both-diff") due to 2 previous errors; 1 warning emitted
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
deleted file mode 100644
index 163f8bb35e7..00000000000
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_diff/src/main.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.59.0` from `clippy.toml`
-
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:6:21
-   |
-LL |     pub fn bar() -> Foo {
-   |                     ^^^ help: use the applicable keyword: `Self`
-   |
-note: the lint level is defined here
-  --> $DIR/main.rs:1:9
-   |
-LL | #![deny(clippy::use_self)]
-   |         ^^^^^^^^^^^^^^^^
-
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:7:9
-   |
-LL |         Foo
-   |         ^^^ help: use the applicable keyword: `Self`
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr
new file mode 100644
index 00000000000..407a9055de8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.stderr
@@ -0,0 +1,19 @@
+error: unnecessary structure name repetition
+ --> src/main.rs:6:21
+  |
+6 |     pub fn bar() -> Foo {
+  |                     ^^^ help: use the applicable keyword: `Self`
+  |
+note: the lint level is defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(clippy::use_self)]
+  |         ^^^^^^^^^^^^^^^^
+
+error: unnecessary structure name repetition
+ --> src/main.rs:7:9
+  |
+7 |         Foo
+  |         ^^^ help: use the applicable keyword: `Self`
+
+error: could not compile `fail-both-same` (bin "fail-both-same") due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
deleted file mode 100644
index 259d39b1252..00000000000
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_both_same/src/main.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:6:21
-   |
-LL |     pub fn bar() -> Foo {
-   |                     ^^^ help: use the applicable keyword: `Self`
-   |
-note: the lint level is defined here
-  --> $DIR/main.rs:1:9
-   |
-LL | #![deny(clippy::use_self)]
-   |         ^^^^^^^^^^^^^^^^
-
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:7:9
-   |
-LL |         Foo
-   |         ^^^ help: use the applicable keyword: `Self`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr
new file mode 100644
index 00000000000..566f5a68689
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.stderr
@@ -0,0 +1,19 @@
+error: unnecessary structure name repetition
+ --> src/main.rs:6:21
+  |
+6 |     pub fn bar() -> Foo {
+  |                     ^^^ help: use the applicable keyword: `Self`
+  |
+note: the lint level is defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(clippy::use_self)]
+  |         ^^^^^^^^^^^^^^^^
+
+error: unnecessary structure name repetition
+ --> src/main.rs:7:9
+  |
+7 |         Foo
+  |         ^^^ help: use the applicable keyword: `Self`
+
+error: could not compile `fail-cargo` (bin "fail-cargo") due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
deleted file mode 100644
index 259d39b1252..00000000000
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:6:21
-   |
-LL |     pub fn bar() -> Foo {
-   |                     ^^^ help: use the applicable keyword: `Self`
-   |
-note: the lint level is defined here
-  --> $DIR/main.rs:1:9
-   |
-LL | #![deny(clippy::use_self)]
-   |         ^^^^^^^^^^^^^^^^
-
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:7:9
-   |
-LL |         Foo
-   |         ^^^ help: use the applicable keyword: `Self`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr
new file mode 100644
index 00000000000..83d4be3bae4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.stderr
@@ -0,0 +1,19 @@
+error: unnecessary structure name repetition
+ --> src/main.rs:6:21
+  |
+6 |     pub fn bar() -> Foo {
+  |                     ^^^ help: use the applicable keyword: `Self`
+  |
+note: the lint level is defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(clippy::use_self)]
+  |         ^^^^^^^^^^^^^^^^
+
+error: unnecessary structure name repetition
+ --> src/main.rs:7:9
+  |
+7 |         Foo
+  |         ^^^ help: use the applicable keyword: `Self`
+
+error: could not compile `fail-clippy` (bin "fail-clippy") due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr
index 259d39b1252..14a6b5047b1 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_clippy/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr
@@ -1,20 +1,19 @@
 error: unnecessary structure name repetition
-  --> $DIR/main.rs:6:21
+  --> src/main.rs:11:21
    |
-LL |     pub fn bar() -> Foo {
+11 |     pub fn bar() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
    |
 note: the lint level is defined here
-  --> $DIR/main.rs:1:9
+  --> src/main.rs:6:9
    |
-LL | #![deny(clippy::use_self)]
+6  | #![deny(clippy::use_self)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unnecessary structure name repetition
-  --> $DIR/main.rs:7:9
+  --> src/main.rs:12:9
    |
-LL |         Foo
+12 |         Foo
    |         ^^^ help: use the applicable keyword: `Self`
 
-error: aborting due to 2 previous errors
-
+error: could not compile `fail-file-attr` (bin "fail-file-attr") due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
deleted file mode 100644
index 97e6c3d5a55..00000000000
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/fail_file_attr/src/main.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:11:21
-   |
-LL |     pub fn bar() -> Foo {
-   |                     ^^^ help: use the applicable keyword: `Self`
-   |
-note: the lint level is defined here
-  --> $DIR/main.rs:6:9
-   |
-LL | #![deny(clippy::use_self)]
-   |         ^^^^^^^^^^^^^^^^
-
-error: unnecessary structure name repetition
-  --> $DIR/main.rs:12:9
-   |
-LL |         Foo
-   |         ^^^ help: use the applicable keyword: `Self`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr
index eeae5b7b275..e89388b501b 100644
--- a/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.stderr
@@ -1,4 +1,2 @@
 warning: the MSRV in `clippy.toml` and `Cargo.toml` differ; using `1.13.0` from `clippy.toml`
 
-warning: 1 warning emitted
-
diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
new file mode 100644
index 00000000000..fde3a1e6599
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr
@@ -0,0 +1,52 @@
+error: file is loaded as a module multiple times: `src/b.rs`
+ --> src/main.rs:5:1
+  |
+5 |   mod b;
+  |   ^^^^^^ first loaded here
+6 | / #[path = "b.rs"]
+7 | | mod b2;
+  | |_______^ loaded again here
+  |
+  = help: replace all but one `mod` item with `use` items
+  = note: `-D clippy::duplicate-mod` implied by `-D warnings`
+
+error: file is loaded as a module multiple times: `src/c.rs`
+  --> src/main.rs:9:1
+   |
+9  |   mod c;
+   |   ^^^^^^ first loaded here
+10 | / #[path = "c.rs"]
+11 | | mod c2;
+   | |_______^ loaded again here
+12 | / #[path = "c.rs"]
+13 | | mod c3;
+   | |_______^ loaded again here
+   |
+   = help: replace all but one `mod` item with `use` items
+
+error: file is loaded as a module multiple times: `src/d.rs`
+  --> src/main.rs:18:1
+   |
+18 |   mod d;
+   |   ^^^^^^ first loaded here
+19 | / #[path = "d.rs"]
+20 | | mod d2;
+   | |_______^ loaded again here
+   |
+   = help: replace all but one `mod` item with `use` items
+
+error: file is loaded as a module multiple times: `src/from_other_module.rs`
+  --> src/main.rs:15:1
+   |
+15 |   mod from_other_module;
+   |   ^^^^^^^^^^^^^^^^^^^^^^ first loaded here
+   |
+  ::: src/other_module/mod.rs:1:1
+   |
+1  | / #[path = "../from_other_module.rs"]
+2  | | mod m;
+   | |______^ loaded again here
+   |
+   = help: replace all but one `mod` item with `use` items
+
+error: could not compile `duplicate_mod` (bin "duplicate_mod") due to 4 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr
deleted file mode 100644
index 3b80d89a686..00000000000
--- a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr
+++ /dev/null
@@ -1,53 +0,0 @@
-error: file is loaded as a module multiple times: `$DIR/b.rs`
-  --> $DIR/main.rs:5:1
-   |
-LL |   mod b;
-   |   ^^^^^^ first loaded here
-LL | / #[path = "b.rs"]
-LL | | mod b2;
-   | |_______^ loaded again here
-   |
-   = help: replace all but one `mod` item with `use` items
-   = note: `-D clippy::duplicate-mod` implied by `-D warnings`
-
-error: file is loaded as a module multiple times: `$DIR/c.rs`
-  --> $DIR/main.rs:9:1
-   |
-LL |   mod c;
-   |   ^^^^^^ first loaded here
-LL | / #[path = "c.rs"]
-LL | | mod c2;
-   | |_______^ loaded again here
-LL | / #[path = "c.rs"]
-LL | | mod c3;
-   | |_______^ loaded again here
-   |
-   = help: replace all but one `mod` item with `use` items
-
-error: file is loaded as a module multiple times: `$DIR/d.rs`
-  --> $DIR/main.rs:18:1
-   |
-LL |   mod d;
-   |   ^^^^^^ first loaded here
-LL | / #[path = "d.rs"]
-LL | | mod d2;
-   | |_______^ loaded again here
-   |
-   = help: replace all but one `mod` item with `use` items
-
-error: file is loaded as a module multiple times: `$DIR/from_other_module.rs`
-  --> $DIR/main.rs:15:1
-   |
-LL |   mod from_other_module;
-   |   ^^^^^^^^^^^^^^^^^^^^^^ first loaded here
-   |
-  ::: $DIR/other_module/mod.rs:1:1
-   |
-LL | / #[path = "../from_other_module.rs"]
-LL | | mod m;
-   | |______^ loaded again here
-   |
-   = help: replace all but one `mod` item with `use` items
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.stderr
new file mode 100644
index 00000000000..da2db45d3b8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.stderr
@@ -0,0 +1,43 @@
+error: the "no-" prefix in the feature name "no-qaq" is negative
+  |
+  = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
+  = note: `-D clippy::negative-feature-names` implied by `-D warnings`
+
+error: the "no_" prefix in the feature name "no_qaq" is negative
+  |
+  = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
+
+error: the "not-" prefix in the feature name "not-orz" is negative
+  |
+  = help: consider renaming the feature to "orz", but make sure the feature adds functionality
+
+error: the "not_" prefix in the feature name "not_orz" is negative
+  |
+  = help: consider renaming the feature to "orz", but make sure the feature adds functionality
+
+error: the "-support" suffix in the feature name "qvq-support" is redundant
+  |
+  = help: consider renaming the feature to "qvq"
+  = note: `-D clippy::redundant-feature-names` implied by `-D warnings`
+
+error: the "_support" suffix in the feature name "qvq_support" is redundant
+  |
+  = help: consider renaming the feature to "qvq"
+
+error: the "use-" prefix in the feature name "use-qwq" is redundant
+  |
+  = help: consider renaming the feature to "qwq"
+
+error: the "use_" prefix in the feature name "use_qwq" is redundant
+  |
+  = help: consider renaming the feature to "qwq"
+
+error: the "with-" prefix in the feature name "with-owo" is redundant
+  |
+  = help: consider renaming the feature to "owo"
+
+error: the "with_" prefix in the feature name "with_owo" is redundant
+  |
+  = help: consider renaming the feature to "owo"
+
+error: could not compile `feature_name` (bin "feature_name") due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
deleted file mode 100644
index c6a11fa93eb..00000000000
--- a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-error: the "no-" prefix in the feature name "no-qaq" is negative
-   |
-   = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
-   = note: `-D clippy::negative-feature-names` implied by `-D warnings`
-
-error: the "no_" prefix in the feature name "no_qaq" is negative
-   |
-   = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
-
-error: the "not-" prefix in the feature name "not-orz" is negative
-   |
-   = help: consider renaming the feature to "orz", but make sure the feature adds functionality
-
-error: the "not_" prefix in the feature name "not_orz" is negative
-   |
-   = help: consider renaming the feature to "orz", but make sure the feature adds functionality
-
-error: the "-support" suffix in the feature name "qvq-support" is redundant
-   |
-   = help: consider renaming the feature to "qvq"
-   = note: `-D clippy::redundant-feature-names` implied by `-D warnings`
-
-error: the "_support" suffix in the feature name "qvq_support" is redundant
-   |
-   = help: consider renaming the feature to "qvq"
-
-error: the "use-" prefix in the feature name "use-qwq" is redundant
-   |
-   = help: consider renaming the feature to "qwq"
-
-error: the "use_" prefix in the feature name "use_qwq" is redundant
-   |
-   = help: consider renaming the feature to "qwq"
-
-error: the "with-" prefix in the feature name "with-owo" is redundant
-   |
-   = help: consider renaming the feature to "owo"
-
-error: the "with_" prefix in the feature name "with_owo" is redundant
-   |
-   = help: consider renaming the feature to "owo"
-
-error: aborting due to 10 previous errors
-
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.stderr
new file mode 100644
index 00000000000..c2907f319e6
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.stderr
@@ -0,0 +1,18 @@
+error: `mod.rs` files are required, found `src/bad/inner.rs`
+ --> src/bad/inner.rs:1:1
+  |
+1 | pub mod stuff;
+  | ^
+  |
+  = help: move `src/bad/inner.rs` to `src/bad/inner/mod.rs`
+  = note: `-D clippy::self-named-module-files` implied by `-D warnings`
+
+error: `mod.rs` files are required, found `src/bad/inner/stuff.rs`
+ --> src/bad/inner/stuff.rs:1:1
+  |
+1 | pub mod most;
+  | ^
+  |
+  = help: move `src/bad/inner/stuff.rs` to `src/bad/inner/stuff/mod.rs`
+
+error: could not compile `fail-mod` (bin "fail-mod") due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
deleted file mode 100644
index 697c8b57c4a..00000000000
--- a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error: `mod.rs` files are required, found `bad/inner.rs`
-  --> $DIR/bad/inner.rs:1:1
-   |
-LL | pub mod stuff;
-   | ^
-   |
-   = help: move `bad/inner.rs` to `bad/inner/mod.rs`
-   = note: `-D clippy::self-named-module-files` implied by `-D warnings`
-
-error: `mod.rs` files are required, found `bad/inner/stuff.rs`
-  --> $DIR/bad/inner/stuff.rs:1:1
-   |
-LL | pub mod most;
-   | ^
-   |
-   = help: move `bad/inner/stuff.rs` to `bad/inner/stuff/mod.rs`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr
new file mode 100644
index 00000000000..fcf1a3c5e66
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.stderr
@@ -0,0 +1,10 @@
+error: `mod.rs` files are required, found `src/bad.rs`
+ --> src/bad.rs:1:1
+  |
+1 | pub mod inner;
+  | ^
+  |
+  = help: move `src/bad.rs` to `src/bad/mod.rs`
+  = note: `-D clippy::self-named-module-files` implied by `-D warnings`
+
+error: could not compile `fail-mod-remap` (bin "fail-mod-remap") due to previous error
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr
deleted file mode 100644
index ea6ea98064a..00000000000
--- a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `mod.rs` files are required, found `bad.rs`
-  --> /remapped/module_style/fail_mod_remap/src/bad.rs:1:1
-   |
-LL | pub mod inner;
-   | ^
-   |
-   = help: move `bad.rs` to `bad/mod.rs`
-   = note: `-D clippy::self-named-module-files` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr
new file mode 100644
index 00000000000..f61642ca2ef
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.stderr
@@ -0,0 +1,10 @@
+error: `mod.rs` files are not allowed, found `src/bad/mod.rs`
+ --> src/bad/mod.rs:1:1
+  |
+1 | pub struct Thing;
+  | ^
+  |
+  = help: move `src/bad/mod.rs` to `src/bad.rs`
+  = note: `-D clippy::mod-module-files` implied by `-D warnings`
+
+error: could not compile `fail-no-mod` (bin "fail-no-mod") due to previous error
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
deleted file mode 100644
index f40ceea234b..00000000000
--- a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `mod.rs` files are not allowed, found `bad/mod.rs`
-  --> $DIR/bad/mod.rs:1:1
-   |
-LL | pub struct Thing;
-   | ^
-   |
-   = help: move `bad/mod.rs` to `bad.rs`
-   = note: `-D clippy::mod-module-files` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr
new file mode 100644
index 00000000000..d82b9e73f78
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/Cargo.stderr
@@ -0,0 +1,2 @@
+warning: using config file `$DIR/$DIR/.clippy.toml`, `$DIR/$DIR/clippy.toml` will be ignored
+
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr
deleted file mode 100644
index aa1b3c638a0..00000000000
--- a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr
+++ /dev/null
@@ -1,4 +0,0 @@
-warning: using config file `$SRC_DIR/.clippy.toml`, `$SRC_DIR/clippy.toml` will be ignored
-
-warning: 1 warning emitted
-
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr
new file mode 100644
index 00000000000..5bcce920455
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/Cargo.stderr
@@ -0,0 +1,5 @@
+error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9
+  |
+  = note: `-D clippy::multiple-crate-versions` implied by `-D warnings`
+
+error: could not compile `multiple_crate_versions` (bin "multiple_crate_versions") due to previous error
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr
deleted file mode 100644
index f3113e09365..00000000000
--- a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/fail/src/main.stderr
+++ /dev/null
@@ -1,6 +0,0 @@
-error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9
-   |
-   = note: `-D clippy::multiple-crate-versions` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui-cargo/update-all-references.sh b/src/tools/clippy/tests/ui-cargo/update-all-references.sh
index 4391499a1e1..d4204307026 100755
--- a/src/tools/clippy/tests/ui-cargo/update-all-references.sh
+++ b/src/tools/clippy/tests/ui-cargo/update-all-references.sh
@@ -1,3 +1,3 @@
 #!/bin/bash
 
-echo "Please use 'cargo dev bless' instead."
+echo "Please use 'cargo bless' instead."
diff --git a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr
new file mode 100644
index 00000000000..b1578c9f324
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/Cargo.stderr
@@ -0,0 +1,5 @@
+error: wildcard dependency for `regex`
+  |
+  = note: `-D clippy::wildcard-dependencies` implied by `-D warnings`
+
+error: could not compile `wildcard_dependencies` (bin "wildcard_dependencies") due to previous error
diff --git a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr
deleted file mode 100644
index 9e65d2f9942..00000000000
--- a/src/tools/clippy/tests/ui-cargo/wildcard_dependencies/fail/src/main.stderr
+++ /dev/null
@@ -1,6 +0,0 @@
-error: wildcard dependency for `regex`
-   |
-   = note: `-D clippy::wildcard-dependencies` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.rs b/src/tools/clippy/tests/ui-internal/check_formulation.rs
new file mode 100644
index 00000000000..43fc996033e
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/check_formulation.rs
@@ -0,0 +1,54 @@
+#![warn(clippy::almost_standard_lint_formulation)]
+#![feature(rustc_private)]
+
+#[macro_use]
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_session;
+extern crate rustc_lint;
+
+declare_tool_lint! {
+    /// # What it does
+    ///
+    /// Checks for usage of correct lint formulations
+    #[clippy::version = "pre 1.29.0"]
+    pub clippy::VALID,
+    Warn,
+    "One",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    /// # What it does
+    /// Check for lint formulations that are correct
+    #[clippy::version = "pre 1.29.0"]
+    pub clippy::INVALID1,
+    Warn,
+    "One",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    /// # What it does
+    /// Detects uses of incorrect formulations
+    #[clippy::version = "pre 1.29.0"]
+    pub clippy::INVALID2,
+    Warn,
+    "One",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    /// # What it does
+    /// Detects uses of incorrect formulations (allowed with attribute)
+    #[allow(clippy::almost_standard_lint_formulation)]
+    #[clippy::version = "pre 1.29.0"]
+    pub clippy::ALLOWED_INVALID,
+    Warn,
+    "One",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(Pass => [VALID, INVALID1, INVALID2]);
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.stderr b/src/tools/clippy/tests/ui-internal/check_formulation.stderr
new file mode 100644
index 00000000000..10eabca4b9d
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/check_formulation.stderr
@@ -0,0 +1,19 @@
+error: non-standard lint formulation
+  --> $DIR/check_formulation.rs:23:5
+   |
+LL |     /// Check for lint formulations that are correct
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try using `Checks for` instead
+   = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings`
+
+error: non-standard lint formulation
+  --> $DIR/check_formulation.rs:33:5
+   |
+LL |     /// Detects uses of incorrect formulations
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try using `Checks for` instead
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index b9ea5a64de7..b88aeae2a9b 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -7,7 +7,7 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy
 
 note: rustc <version> running on <target>
 
-note: compiler flags: -C prefer-dynamic -Z ui-testing
+note: compiler flags: -Z ui-testing
+
+note: Clippy version: foo
 
-query stack during panic:
-thread panicked while processing panic. aborting.
diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.rs b/src/tools/clippy/tests/ui-internal/if_chain_style.rs
index b0d89e038aa..b462b20e04c 100644
--- a/src/tools/clippy/tests/ui-internal/if_chain_style.rs
+++ b/src/tools/clippy/tests/ui-internal/if_chain_style.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::if_chain_style)]
-#![allow(clippy::no_effect, clippy::nonminimal_bool, clippy::missing_clippy_version_attribute)]
+#![allow(
+    clippy::needless_if,
+    clippy::no_effect,
+    clippy::nonminimal_bool,
+    clippy::missing_clippy_version_attribute
+)]
 
 extern crate if_chain;
 
diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr
index d8f1ffb21ba..b12df278652 100644
--- a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr
+++ b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr
@@ -1,5 +1,5 @@
 error: this `if` can be part of the inner `if_chain!`
-  --> $DIR/if_chain_style.rs:9:5
+  --> $DIR/if_chain_style.rs:14:5
    |
 LL | /     if true {
 LL | |         let x = "";
@@ -11,14 +11,14 @@ LL | |     }
    | |_____^
    |
 help: this `let` statement can also be in the `if_chain!`
-  --> $DIR/if_chain_style.rs:10:9
+  --> $DIR/if_chain_style.rs:15:9
    |
 LL |         let x = "";
    |         ^^^^^^^^^^^
    = note: `-D clippy::if-chain-style` implied by `-D warnings`
 
 error: `if a && b;` should be `if a; if b;`
-  --> $DIR/if_chain_style.rs:19:12
+  --> $DIR/if_chain_style.rs:24:12
    |
 LL |           if true
    |  ____________^
@@ -27,25 +27,25 @@ LL | |             && false;
    | |____________________^
 
 error: `let` expression should be inside `then { .. }`
-  --> $DIR/if_chain_style.rs:24:9
+  --> $DIR/if_chain_style.rs:29:9
    |
 LL |         let x = "";
    |         ^^^^^^^^^^^
 
 error: this `if` can be part of the outer `if_chain!`
-  --> $DIR/if_chain_style.rs:35:13
+  --> $DIR/if_chain_style.rs:40:13
    |
 LL |             if true {}
    |             ^^^^^^^^^^
    |
 help: this `let` statement can also be in the `if_chain!`
-  --> $DIR/if_chain_style.rs:33:13
+  --> $DIR/if_chain_style.rs:38:13
    |
 LL |             let x = "";
    |             ^^^^^^^^^^^
 
 error: `if_chain!` only has one `if`
-  --> $DIR/if_chain_style.rs:29:5
+  --> $DIR/if_chain_style.rs:34:5
    |
 LL | /     if_chain! {
 LL | |         // single `if` condition
@@ -59,13 +59,13 @@ LL | |     }
    = note: this error originates in the macro `__if_chain` which comes from the expansion of the macro `if_chain` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `let` expression should be above the `if_chain!`
-  --> $DIR/if_chain_style.rs:40:9
+  --> $DIR/if_chain_style.rs:45:9
    |
 LL |         let x = "";
    |         ^^^^^^^^^^^
 
 error: this `if_chain!` can be merged with the outer `if_chain!`
-  --> $DIR/if_chain_style.rs:46:13
+  --> $DIR/if_chain_style.rs:51:13
    |
 LL | /             if_chain! {
 LL | |                 if true;
@@ -75,7 +75,7 @@ LL | |             }
    | |_____________^
    |
 help: these `let` statements can also be in the `if_chain!`
-  --> $DIR/if_chain_style.rs:43:13
+  --> $DIR/if_chain_style.rs:48:13
    |
 LL | /             let x = "";
 LL | |             let x = "";
diff --git a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed
index 23e7bc16d23..c9085684528 100644
--- a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::uninlined_format_args)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
     let local_i32 = 1;
diff --git a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs
index d66b2b8ff6a..661350c5c6d 100644
--- a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::uninlined_format_args)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
     let local_i32 = 1;
diff --git a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr
index 1be0cda12fc..6ec79a618de 100644
--- a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr
+++ b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr
@@ -1,5 +1,5 @@
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:9:5
+  --> $DIR/uninlined_format_args.rs:10:5
    |
 LL |     println!("val='{}'", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL +     println!("val='{local_i32}'");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:10:5
+  --> $DIR/uninlined_format_args.rs:11:5
    |
 LL |     println!("Hello {} is {:.*}", "x", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL +     println!("Hello {} is {local_f64:.local_i32$}", "x");
    |
 
 error: literal with an empty format string
-  --> $DIR/uninlined_format_args.rs:10:35
+  --> $DIR/uninlined_format_args.rs:11:35
    |
 LL |     println!("Hello {} is {:.*}", "x", local_i32, local_f64);
    |                                   ^^^
@@ -37,7 +37,7 @@ LL +     println!("Hello x is {:.*}", local_i32, local_f64);
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:11:5
+  --> $DIR/uninlined_format_args.rs:12:5
    |
 LL |     println!("Hello {} is {:.*}", local_i32, 5, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL +     println!("Hello {local_i32} is {local_f64:.*}", 5);
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:12:5
+  --> $DIR/uninlined_format_args.rs:13:5
    |
 LL |     println!("Hello {} is {2:.*}", local_i32, 5, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL +     println!("Hello {local_i32} is {local_f64:.*}", 5);
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:13:5
+  --> $DIR/uninlined_format_args.rs:14:5
    |
 LL |     println!("{}, {}", local_i32, local_opt.unwrap());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
index fb5b1b193f8..33f7c8ba804 100644
--- a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
+++ b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::arithmetic_side_effects)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 use core::ops::{Add, Neg};
 
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr
index ad89534aa1b..4f98ca19231 100644
--- a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr
+++ b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr
@@ -1,5 +1,5 @@
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:68:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:69:13
    |
 LL |     let _ = Baz + Baz;
    |             ^^^^^^^^^
@@ -7,49 +7,49 @@ LL |     let _ = Baz + Baz;
    = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:79:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:80:13
    |
 LL |     let _ = 1i32 + Baz;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:82:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:83:13
    |
 LL |     let _ = 1i64 + Foo;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:86:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:87:13
    |
 LL |     let _ = 1i64 + Baz;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:97:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:98:13
    |
 LL |     let _ = Baz + 1i32;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:100:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:101:13
    |
 LL |     let _ = Foo + 1i64;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:104:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:105:13
    |
 LL |     let _ = Baz + 1i64;
    |             ^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:113:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:114:13
    |
 LL |     let _ = -Bar;
    |             ^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects_allowed.rs:115:13
+  --> $DIR/arithmetic_side_effects_allowed.rs:116:13
    |
 LL |     let _ = -Baz;
    |             ^^^^
diff --git a/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.rs b/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.rs
index f328e4d9d04..c69fcd30033 100644
--- a/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.rs
+++ b/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.rs
@@ -1 +1,3 @@
+//@error-in-other-file: error reading Clippy's configuration file: expected `.`, `=`
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr b/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr
index 5b7e8c0db74..f7d53763a43 100644
--- a/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr
+++ b/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr
@@ -1,5 +1,5 @@
 error: error reading Clippy's configuration file: expected `.`, `=`
-  --> $DIR/clippy.toml:1:4
+  --> $DIR/$DIR/clippy.toml:1:4
    |
 LL | fn this_is_obviously(not: a, toml: file) {
    |    ^
diff --git a/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.rs b/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.rs
index f328e4d9d04..688c92d8717 100644
--- a/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.rs
+++ b/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.rs
@@ -1 +1,3 @@
+//@error-in-other-file: invalid type: integer `42`, expected a sequence
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr
index 386e1135df9..fb0a1408152 100644
--- a/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr
+++ b/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr
@@ -1,5 +1,5 @@
 error: error reading Clippy's configuration file: invalid type: integer `42`, expected a sequence
-  --> $DIR/clippy.toml:1:20
+  --> $DIR/$DIR/clippy.toml:1:20
    |
 LL | disallowed-names = 42
    |                    ^^
diff --git a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
index 123ad94dd09..89d84eb2455 100644
--- a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
@@ -1,11 +1,11 @@
 warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead
-  --> $DIR/clippy.toml:2:1
+  --> $DIR/$DIR/clippy.toml:2:1
    |
 LL | cyclomatic-complexity-threshold = 2
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: error reading Clippy's configuration file: deprecated field `blacklisted-names`. Please use `disallowed-names` instead
-  --> $DIR/clippy.toml:3:1
+  --> $DIR/$DIR/clippy.toml:3:1
    |
 LL | blacklisted-names = [ "..", "wibble" ]
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.rs b/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.rs
index f328e4d9d04..187775545ed 100644
--- a/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.rs
+++ b/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.rs
@@ -1 +1,3 @@
+//@error-in-other-file: duplicate key `cognitive-complexity-threshold`
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr b/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr
index 54997735274..7c56dfdb948 100644
--- a/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr
+++ b/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr
@@ -1,5 +1,5 @@
 error: error reading Clippy's configuration file: duplicate key `cognitive-complexity-threshold` in document root
-  --> $DIR/clippy.toml:2:1
+  --> $DIR/$DIR/clippy.toml:2:1
    |
 LL | cognitive-complexity-threshold = 4
    | ^
diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr
index 2ae7848f183..0af8c0add6c 100644
--- a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr
+++ b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr
@@ -1,11 +1,11 @@
 error: error reading Clippy's configuration file: duplicate field `cognitive_complexity_threshold` (provided as `cyclomatic_complexity_threshold`)
-  --> $DIR/clippy.toml:3:1
+  --> $DIR/$DIR/clippy.toml:3:1
    |
 LL | cyclomatic-complexity-threshold = 3
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead
-  --> $DIR/clippy.toml:3:1
+  --> $DIR/$DIR/clippy.toml:3:1
    |
 LL | cyclomatic-complexity-threshold = 3
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr
index 53ad4271246..a4b1e9c335c 100644
--- a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr
+++ b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr
@@ -1,11 +1,11 @@
 error: error reading Clippy's configuration file: duplicate field `cognitive-complexity-threshold`
-  --> $DIR/clippy.toml:4:1
+  --> $DIR/$DIR/clippy.toml:4:1
    |
 LL | cognitive-complexity-threshold = 4
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: error reading Clippy's configuration file: deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead
-  --> $DIR/clippy.toml:2:1
+  --> $DIR/$DIR/clippy.toml:2:1
    |
 LL | cyclomatic-complexity-threshold = 3
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs
new file mode 100644
index 00000000000..ebadd4e440a
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/auxiliary/proc_macros.rs
@@ -0,0 +1,472 @@
+// NOTE: Copied from `ui/auxiliary/proc_macros.rs`, couldn't get `../` to work for some reason
+
+#![feature(let_chains)]
+#![feature(proc_macro_span)]
+#![allow(clippy::excessive_nesting, dead_code)]
+
+extern crate proc_macro;
+
+use core::mem;
+use proc_macro::{
+    token_stream::IntoIter,
+    Delimiter::{self, Brace, Parenthesis},
+    Group, Ident, Literal, Punct,
+    Spacing::{self, Alone, Joint},
+    Span, TokenStream, TokenTree as TT,
+};
+
+type Result<T> = core::result::Result<T, TokenStream>;
+
+/// Make a `compile_error!` pointing to the given span.
+fn make_error(msg: &str, span: Span) -> TokenStream {
+    TokenStream::from_iter([
+        TT::Ident(Ident::new("compile_error", span)),
+        TT::Punct(punct_with_span('!', Alone, span)),
+        TT::Group({
+            let mut msg = Literal::string(msg);
+            msg.set_span(span);
+            group_with_span(Parenthesis, TokenStream::from_iter([TT::Literal(msg)]), span)
+        }),
+    ])
+}
+
+fn expect_tt<T>(tt: Option<TT>, f: impl FnOnce(TT) -> Option<T>, expected: &str, span: Span) -> Result<T> {
+    match tt {
+        None => Err(make_error(
+            &format!("unexpected end of input, expected {expected}"),
+            span,
+        )),
+        Some(tt) => {
+            let span = tt.span();
+            match f(tt) {
+                Some(x) => Ok(x),
+                None => Err(make_error(&format!("unexpected token, expected {expected}"), span)),
+            }
+        },
+    }
+}
+
+fn punct_with_span(c: char, spacing: Spacing, span: Span) -> Punct {
+    let mut p = Punct::new(c, spacing);
+    p.set_span(span);
+    p
+}
+
+fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Group {
+    let mut g = Group::new(delimiter, stream);
+    g.set_span(span);
+    g
+}
+
+/// Token used to escape the following token from the macro's span rules.
+const ESCAPE_CHAR: char = '$';
+
+/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
+/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
+#[proc_macro]
+pub fn with_span(input: TokenStream) -> TokenStream {
+    let mut iter = input.into_iter();
+    let span = iter.next().unwrap().span();
+    let mut res = TokenStream::new();
+    if let Err(e) = write_with_span(span, iter, &mut res) {
+        e
+    } else {
+        res
+    }
+}
+
+/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be
+/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`.
+#[proc_macro]
+pub fn external(input: TokenStream) -> TokenStream {
+    let mut res = TokenStream::new();
+    if let Err(e) = write_with_span(Span::mixed_site(), input.into_iter(), &mut res) {
+        e
+    } else {
+        res
+    }
+}
+
+/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped
+/// either by `#ident` or `#(tokens)`.
+fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> {
+    while let Some(tt) = input.next() {
+        match tt {
+            TT::Punct(p) if p.as_char() == ESCAPE_CHAR => {
+                expect_tt(
+                    input.next(),
+                    |tt| match tt {
+                        tt @ (TT::Ident(_) | TT::Literal(_)) => {
+                            out.extend([tt]);
+                            Some(())
+                        },
+                        TT::Punct(mut p) if p.as_char() == ESCAPE_CHAR => {
+                            p.set_span(s);
+                            out.extend([TT::Punct(p)]);
+                            Some(())
+                        },
+                        TT::Group(g) if g.delimiter() == Parenthesis => {
+                            out.extend([TT::Group(group_with_span(Delimiter::None, g.stream(), g.span()))]);
+                            Some(())
+                        },
+                        _ => None,
+                    },
+                    "an ident, a literal, or parenthesized tokens",
+                    p.span(),
+                )?;
+            },
+            TT::Group(g) => {
+                let mut stream = TokenStream::new();
+                write_with_span(s, g.stream().into_iter(), &mut stream)?;
+                out.extend([TT::Group(group_with_span(g.delimiter(), stream, s))]);
+            },
+            mut tt => {
+                tt.set_span(s);
+                out.extend([tt]);
+            },
+        }
+    }
+    Ok(())
+}
+
+/// Within the item this attribute is attached to, an `inline!` macro is available which expands the
+/// contained tokens as though they came from a macro expansion.
+///
+/// Within the `inline!` macro, any token preceded by `$` is passed as though it were an argument
+/// with an automatically chosen fragment specifier. `$ident` will be passed as `ident`, `$1` or
+/// `$"literal"` will be passed as `literal`, `$'lt` will be passed as `lifetime`, and `$(...)` will
+/// pass the contained tokens as a `tt` sequence (the wrapping parenthesis are removed). If another
+/// specifier is required it can be specified within parenthesis like `$(@expr ...)`. This will
+/// expand the remaining tokens as a single argument.
+///
+/// Multiple `inline!` macros may be nested within each other. This will expand as nested macro
+/// calls. However, any arguments will be passed as though they came from the outermost context.
+#[proc_macro_attribute]
+pub fn inline_macros(args: TokenStream, input: TokenStream) -> TokenStream {
+    let mut args = args.into_iter();
+    let mac_name = match args.next() {
+        Some(TT::Ident(name)) => Some(name),
+        Some(tt) => {
+            return make_error(
+                "unexpected argument, expected either an ident or no arguments",
+                tt.span(),
+            );
+        },
+        None => None,
+    };
+    if let Some(tt) = args.next() {
+        return make_error(
+            "unexpected argument, expected either an ident or no arguments",
+            tt.span(),
+        );
+    };
+
+    let mac_name = if let Some(mac_name) = mac_name {
+        Ident::new(&format!("__inline_mac_{mac_name}"), Span::call_site())
+    } else {
+        let mut input = match LookaheadIter::new(input.clone().into_iter()) {
+            Some(x) => x,
+            None => return input,
+        };
+        loop {
+            match input.next() {
+                None => break Ident::new("__inline_mac", Span::call_site()),
+                Some(TT::Ident(kind)) => match &*kind.to_string() {
+                    "impl" => break Ident::new("__inline_mac_impl", Span::call_site()),
+                    kind @ ("struct" | "enum" | "union" | "fn" | "mod" | "trait" | "type" | "const" | "static") => {
+                        if let TT::Ident(name) = &input.tt {
+                            break Ident::new(&format!("__inline_mac_{kind}_{name}"), Span::call_site());
+                        } else {
+                            break Ident::new(&format!("__inline_mac_{kind}"), Span::call_site());
+                        }
+                    },
+                    _ => {},
+                },
+                _ => {},
+            }
+        }
+    };
+
+    let mut expander = Expander::default();
+    let mut mac = MacWriter::new(mac_name);
+    if let Err(e) = expander.expand(input.into_iter(), &mut mac) {
+        return e;
+    }
+    let mut out = TokenStream::new();
+    mac.finish(&mut out);
+    out.extend(expander.expn);
+    out
+}
+
+/// Wraps a `TokenStream` iterator with a single token lookahead.
+struct LookaheadIter {
+    tt: TT,
+    iter: IntoIter,
+}
+impl LookaheadIter {
+    fn new(mut iter: IntoIter) -> Option<Self> {
+        iter.next().map(|tt| Self { tt, iter })
+    }
+
+    /// Get's the lookahead token, replacing it with the next token in the stream.
+    /// Note: If there isn't a next token, this will not return the lookahead token.
+    fn next(&mut self) -> Option<TT> {
+        self.iter.next().map(|tt| mem::replace(&mut self.tt, tt))
+    }
+}
+
+/// Builds the macro used to implement all the `inline!` macro calls.
+struct MacWriter {
+    name: Ident,
+    macros: TokenStream,
+    next_idx: usize,
+}
+impl MacWriter {
+    fn new(name: Ident) -> Self {
+        Self {
+            name,
+            macros: TokenStream::new(),
+            next_idx: 0,
+        }
+    }
+
+    /// Inserts a new `inline!` call.
+    fn insert(&mut self, name_span: Span, bang_span: Span, body: Group, expander: &mut Expander) -> Result<()> {
+        let idx = self.next_idx;
+        self.next_idx += 1;
+
+        let mut inner = Expander::for_arm(idx);
+        inner.expand(body.stream().into_iter(), self)?;
+        let new_arm = inner.arm.unwrap();
+
+        self.macros.extend([
+            TT::Group(Group::new(Parenthesis, new_arm.args_def)),
+            TT::Punct(Punct::new('=', Joint)),
+            TT::Punct(Punct::new('>', Alone)),
+            TT::Group(Group::new(Parenthesis, inner.expn)),
+            TT::Punct(Punct::new(';', Alone)),
+        ]);
+
+        expander.expn.extend([
+            TT::Ident({
+                let mut name = self.name.clone();
+                name.set_span(name_span);
+                name
+            }),
+            TT::Punct(punct_with_span('!', Alone, bang_span)),
+        ]);
+        let mut call_body = TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]);
+        if let Some(arm) = expander.arm.as_mut() {
+            if !new_arm.args.is_empty() {
+                arm.add_sub_args(new_arm.args, &mut call_body);
+            }
+        } else {
+            call_body.extend(new_arm.args);
+        }
+        let mut g = Group::new(body.delimiter(), call_body);
+        g.set_span(body.span());
+        expander.expn.extend([TT::Group(g)]);
+        Ok(())
+    }
+
+    /// Creates the macro definition.
+    fn finish(self, out: &mut TokenStream) {
+        if self.next_idx != 0 {
+            out.extend([
+                TT::Ident(Ident::new("macro_rules", Span::call_site())),
+                TT::Punct(Punct::new('!', Alone)),
+                TT::Ident(self.name),
+                TT::Group(Group::new(Brace, self.macros)),
+            ])
+        }
+    }
+}
+
+struct MacroArm {
+    args_def: TokenStream,
+    args: Vec<TT>,
+}
+impl MacroArm {
+    fn add_single_arg_def(&mut self, kind: &str, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
+        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
+        self.args_def.extend([
+            TT::Punct(Punct::new('$', Alone)),
+            TT::Ident(name.clone()),
+            TT::Punct(Punct::new(':', Alone)),
+            TT::Ident(Ident::new(kind, Span::call_site())),
+        ]);
+        name.set_span(arg_span);
+        out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
+    }
+
+    fn add_parenthesized_arg_def(&mut self, kind: Ident, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
+        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
+        self.args_def.extend([TT::Group(Group::new(
+            Parenthesis,
+            TokenStream::from_iter([
+                TT::Punct(Punct::new('$', Alone)),
+                TT::Ident(name.clone()),
+                TT::Punct(Punct::new(':', Alone)),
+                TT::Ident(kind),
+            ]),
+        ))]);
+        name.set_span(arg_span);
+        out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
+    }
+
+    fn add_multi_arg_def(&mut self, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
+        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
+        self.args_def.extend([TT::Group(Group::new(
+            Parenthesis,
+            TokenStream::from_iter([
+                TT::Punct(Punct::new('$', Alone)),
+                TT::Group(Group::new(
+                    Parenthesis,
+                    TokenStream::from_iter([
+                        TT::Punct(Punct::new('$', Alone)),
+                        TT::Ident(name.clone()),
+                        TT::Punct(Punct::new(':', Alone)),
+                        TT::Ident(Ident::new("tt", Span::call_site())),
+                    ]),
+                )),
+                TT::Punct(Punct::new('*', Alone)),
+            ]),
+        ))]);
+        name.set_span(arg_span);
+        out.extend([
+            TT::Punct(punct_with_span('$', Alone, dollar_span)),
+            TT::Group(group_with_span(
+                Parenthesis,
+                TokenStream::from_iter([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]),
+                dollar_span,
+            )),
+            TT::Punct(punct_with_span('*', Alone, dollar_span)),
+        ]);
+    }
+
+    fn add_arg(&mut self, dollar_span: Span, tt: TT, input: &mut IntoIter, out: &mut TokenStream) -> Result<()> {
+        match tt {
+            TT::Punct(p) if p.as_char() == ESCAPE_CHAR => out.extend([TT::Punct(p)]),
+            TT::Punct(p) if p.as_char() == '\'' && p.spacing() == Joint => {
+                let lt_name = expect_tt(
+                    input.next(),
+                    |tt| match tt {
+                        TT::Ident(x) => Some(x),
+                        _ => None,
+                    },
+                    "lifetime name",
+                    p.span(),
+                )?;
+                let arg_span = p.span().join(lt_name.span()).unwrap_or(p.span());
+                self.add_single_arg_def("lifetime", dollar_span, arg_span, out);
+                self.args.extend([TT::Punct(p), TT::Ident(lt_name)]);
+            },
+            TT::Ident(x) => {
+                self.add_single_arg_def("ident", dollar_span, x.span(), out);
+                self.args.push(TT::Ident(x));
+            },
+            TT::Literal(x) => {
+                self.add_single_arg_def("literal", dollar_span, x.span(), out);
+                self.args.push(TT::Literal(x));
+            },
+            TT::Group(g) if g.delimiter() == Parenthesis => {
+                let mut inner = g.stream().into_iter();
+                if let Some(TT::Punct(p)) = inner.next()
+                    && p.as_char() == '@'
+                {
+                    let kind = expect_tt(
+                        inner.next(),
+                        |tt| match tt {
+                            TT::Ident(kind) => Some(kind),
+                            _ => None,
+                        },
+                        "a macro fragment specifier",
+                        p.span(),
+                    )?;
+                    self.add_parenthesized_arg_def(kind, dollar_span, g.span(), out);
+                    self.args.push(TT::Group(group_with_span(Parenthesis, inner.collect(), g.span())))
+                } else {
+                    self.add_multi_arg_def(dollar_span, g.span(), out);
+                    self.args.push(TT::Group(g));
+                }
+            },
+            tt => return Err(make_error("unsupported escape", tt.span())),
+        };
+        Ok(())
+    }
+
+    fn add_sub_args(&mut self, args: Vec<TT>, out: &mut TokenStream) {
+        self.add_multi_arg_def(Span::call_site(), Span::call_site(), out);
+        self.args
+            .extend([TT::Group(Group::new(Parenthesis, TokenStream::from_iter(args)))]);
+    }
+}
+
+#[derive(Default)]
+struct Expander {
+    arm: Option<MacroArm>,
+    expn: TokenStream,
+}
+impl Expander {
+    fn for_arm(idx: usize) -> Self {
+        Self {
+            arm: Some(MacroArm {
+                args_def: TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]),
+                args: Vec::new(),
+            }),
+            expn: TokenStream::new(),
+        }
+    }
+
+    fn write_tt(&mut self, tt: TT, mac: &mut MacWriter) -> Result<()> {
+        match tt {
+            TT::Group(g) => {
+                let outer = mem::take(&mut self.expn);
+                self.expand(g.stream().into_iter(), mac)?;
+                let inner = mem::replace(&mut self.expn, outer);
+                self.expn
+                    .extend([TT::Group(group_with_span(g.delimiter(), inner, g.span()))]);
+            },
+            tt => self.expn.extend([tt]),
+        }
+        Ok(())
+    }
+
+    fn expand(&mut self, input: IntoIter, mac: &mut MacWriter) -> Result<()> {
+        let Some(mut input) = LookaheadIter::new(input) else {
+            return Ok(());
+        };
+        while let Some(tt) = input.next() {
+            if let TT::Punct(p) = &tt
+                && p.as_char() == ESCAPE_CHAR
+                && let Some(arm) = self.arm.as_mut()
+            {
+                arm.add_arg(p.span(), mem::replace(&mut input.tt, tt), &mut input.iter, &mut self.expn)?;
+                if input.next().is_none() {
+                    return Ok(());
+                }
+            } else if let TT::Punct(p) = &input.tt
+                && p.as_char() == '!'
+                && let TT::Ident(name) = &tt
+                && name.to_string() == "inline"
+            {
+                let g = expect_tt(
+                    input.iter.next(),
+                    |tt| match tt {
+                        TT::Group(g) => Some(g),
+                        _ => None,
+                    },
+                    "macro arguments",
+                    p.span(),
+                )?;
+                mac.insert(name.span(), p.span(), g, self)?;
+                if input.next().is_none() {
+                    return Ok(());
+                }
+            } else {
+                self.write_tt(tt, mac)?;
+            }
+        }
+        self.write_tt(input.tt, mac)
+    }
+}
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/clippy.toml b/src/tools/clippy/tests/ui-toml/excessive_nesting/clippy.toml
new file mode 100644
index 00000000000..e60ac978cac
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/clippy.toml
@@ -0,0 +1 @@
+excessive-nesting-threshold = 4
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs
new file mode 100644
index 00000000000..c28220b973e
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs
@@ -0,0 +1,197 @@
+//@aux-build:proc_macros.rs:proc-macro
+#![rustfmt::skip]
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
+#![allow(clippy::let_and_return)]
+#![allow(clippy::redundant_closure_call)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::never_loop)]
+#![allow(clippy::needless_if)]
+#![warn(clippy::excessive_nesting)]
+#![allow(clippy::collapsible_if)]
+
+#[macro_use]
+extern crate proc_macros;
+
+static X: u32 = {
+    let x = {
+        let y = {
+            let z = {
+                let w = { 3 };
+                w
+            };
+            z
+        };
+        y
+    };
+    x
+};
+
+macro_rules! xx {
+    () => {{
+        {
+            {
+                {
+                    {
+                        {
+                            {
+                                {
+                                    {
+                                        {
+                                            {
+                                                println!("ehe"); // should not lint
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }};
+}
+
+struct A;
+
+impl A {
+    pub fn a(&self, v: u32) {
+        struct B;
+
+        impl B {
+            pub fn b() {
+                struct C;
+
+                impl C {
+                    pub fn c() {}
+                }
+            }
+        }
+    }
+}
+
+struct D { d: u32 }
+
+trait Lol {
+    fn lmao() {
+        fn bb() {
+            fn cc() {
+                let x = { 1 }; // not a warning, but cc is
+            }
+
+            let x = { 1 }; // warning
+        }
+    }
+}
+
+#[allow(clippy::excessive_nesting)]
+fn l() {{{{{{{{{}}}}}}}}}
+
+use a::{b::{c::{d::{e::{f::{}}}}}}; // should not lint
+
+pub mod a {
+    pub mod b {
+        pub mod c {
+            pub mod d {
+                pub mod e {
+                    pub mod f {}
+                } // not here
+            } // only warning should be here
+        }
+    }
+}
+
+fn a_but_not(v: u32) {}
+
+fn main() {
+    let a = A;
+
+    a_but_not({{{{{{{{0}}}}}}}});
+    a.a({{{{{{{{{0}}}}}}}}});
+    (0, {{{{{{{1}}}}}}});
+
+    if true {
+        if true {
+            if true {
+                if true {
+                    if true {
+
+                    }
+                }
+            }
+        }
+    }
+
+    let y = (|| {
+        let x = (|| {
+            let y = (|| {
+                let z = (|| {
+                    let w = { 3 };
+                    w
+                })();
+                z
+            })();
+            y
+        })();
+        x
+    })();
+
+    external! { {{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}} }; // ensure this isn't linted in external macros
+    with_span! { span {{{{{{{{{{{{}}}}}}}}}}}} }; // don't lint for proc macros
+    xx!(); // ensure this is never linted
+    let boo = true;
+    !{boo as u32 + !{boo as u32 + !{boo as u32}}};
+
+    // this is a mess, but that's intentional
+    let mut y = 1;
+    y += {{{{{5}}}}};
+    let z = y + {{{{{{{{{5}}}}}}}}};
+    [0, {{{{{{{{{{0}}}}}}}}}}];
+    let mut xx = [0; {{{{{{{{100}}}}}}}}];
+    xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}];
+    &mut {{{{{{{{{{y}}}}}}}}}};
+
+    for i in {{{{xx}}}} {{{{{{{{}}}}}}}}
+
+    while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}}
+    
+    while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}}
+
+    let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} };
+
+    {{{{1;}}}}..{{{{{{3}}}}}};
+    {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}};
+    ..{{{{{{{5}}}}}}};
+    ..={{{{{3}}}}};
+    {{{{{1;}}}}}..;
+
+    loop { break {{{{1}}}} };
+    loop {{{{{{}}}}}}
+
+    match {{{{{{true}}}}}} {
+        true => {{{{}}}},
+        false => {{{{}}}},
+    }
+
+    {
+        {
+            {
+                {
+                    println!("warning! :)");
+                }
+            }
+        }
+    }
+}
+
+async fn b() -> u32 {
+    async fn c() -> u32 {{{{{{{0}}}}}}}
+
+    c().await
+}
+
+async fn a() {
+    {{{{b().await}}}};
+}
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
new file mode 100644
index 00000000000..1a7311b33e8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
@@ -0,0 +1,314 @@
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:21:25
+   |
+LL |                 let w = { 3 };
+   |                         ^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+   = note: `-D clippy::excessive-nesting` implied by `-D warnings`
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:67:17
+   |
+LL | /                 impl C {
+LL | |                     pub fn c() {}
+LL | |                 }
+   | |_________________^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:81:25
+   |
+LL |                 let x = { 1 }; // not a warning, but cc is
+   |                         ^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:98:17
+   |
+LL | /                 pub mod e {
+LL | |                     pub mod f {}
+LL | |                 } // not here
+   | |_________________^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:111:18
+   |
+LL |     a_but_not({{{{{{{{0}}}}}}}});
+   |                  ^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:112:12
+   |
+LL |     a.a({{{{{{{{{0}}}}}}}}});
+   |            ^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:113:12
+   |
+LL |     (0, {{{{{{{1}}}}}}});
+   |            ^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:118:25
+   |
+LL |                   if true {
+   |  _________________________^
+LL | |                     if true {
+LL | |
+LL | |                     }
+LL | |                 }
+   | |_________________^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:130:29
+   |
+LL |                   let z = (|| {
+   |  _____________________________^
+LL | |                     let w = { 3 };
+LL | |                     w
+LL | |                 })();
+   | |_________________^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:149:13
+   |
+LL |     y += {{{{{5}}}}};
+   |             ^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:150:20
+   |
+LL |     let z = y + {{{{{{{{{5}}}}}}}}};
+   |                    ^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:151:12
+   |
+LL |     [0, {{{{{{{{{{0}}}}}}}}}}];
+   |            ^^^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:152:25
+   |
+LL |     let mut xx = [0; {{{{{{{{100}}}}}}}}];
+   |                         ^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:153:11
+   |
+LL |     xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}];
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:154:13
+   |
+LL |     &mut {{{{{{{{{{y}}}}}}}}}};
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:156:17
+   |
+LL |     for i in {{{{xx}}}} {{{{{{{{}}}}}}}}
+   |                 ^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:156:28
+   |
+LL |     for i in {{{{xx}}}} {{{{{{{{}}}}}}}}
+   |                            ^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:158:28
+   |
+LL |     while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}}
+   |                            ^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:158:48
+   |
+LL |     while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}}
+   |                                                ^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:160:14
+   |
+LL |     while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}}
+   |              ^^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:160:35
+   |
+LL |     while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}}
+   |                                   ^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:162:23
+   |
+LL |     let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} };
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:164:8
+   |
+LL |     {{{{1;}}}}..{{{{{{3}}}}}};
+   |        ^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:164:20
+   |
+LL |     {{{{1;}}}}..{{{{{{3}}}}}};
+   |                    ^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:165:8
+   |
+LL |     {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}};
+   |        ^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:165:21
+   |
+LL |     {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}};
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:166:10
+   |
+LL |     ..{{{{{{{5}}}}}}};
+   |          ^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:167:11
+   |
+LL |     ..={{{{{3}}}}};
+   |           ^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:168:8
+   |
+LL |     {{{{{1;}}}}}..;
+   |        ^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:170:20
+   |
+LL |     loop { break {{{{1}}}} };
+   |                    ^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:171:13
+   |
+LL |     loop {{{{{{}}}}}}
+   |             ^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:173:14
+   |
+LL |     match {{{{{{true}}}}}} {
+   |              ^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:174:20
+   |
+LL |         true => {{{{}}}},
+   |                    ^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:175:21
+   |
+LL |         false => {{{{}}}},
+   |                     ^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:181:17
+   |
+LL | /                 {
+LL | |                     println!("warning! :)");
+LL | |                 }
+   | |_________________^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:190:28
+   |
+LL |     async fn c() -> u32 {{{{{{{0}}}}}}}
+   |                            ^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: this block is too nested
+  --> $DIR/excessive_nesting.rs:196:8
+   |
+LL |     {{{{b().await}}}};
+   |        ^^^^^^^^^^^
+   |
+   = help: try refactoring your code to minimize nesting
+
+error: aborting due to 37 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
index 9e267c89300..206788e19f0 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
@@ -1,5 +1,6 @@
 //@compile-flags: --test
 #![warn(clippy::expect_used)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn expect_option() {
     let opt = Some(0);
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
index 1e9bb48c333..9eef0e1bfaa 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
@@ -1,5 +1,5 @@
 error: used `expect()` on an `Option` value
-  --> $DIR/expect_used.rs:6:13
+  --> $DIR/expect_used.rs:7:13
    |
 LL |     let _ = opt.expect("");
    |             ^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let _ = opt.expect("");
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `expect()` on a `Result` value
-  --> $DIR/expect_used.rs:11:13
+  --> $DIR/expect_used.rs:12:13
    |
 LL |     let _ = res.expect("");
    |             ^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
index 2ebf28645e5..03fa719975b 100644
--- a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
+++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
@@ -1,3 +1,5 @@
+//@error-in-other-file: `invalid.version` is not a valid Rust version
+
 #![allow(clippy::redundant_clone)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
index 2498672d77f..bd5110138c8 100644
--- a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
+++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
@@ -1,5 +1,5 @@
 #![allow(clippy::excessive_precision)]
-#[deny(clippy::unreadable_literal)]
+#![warn(clippy::unreadable_literal)]
 
 fn allow_inconsistent_digit_grouping() {
     #![allow(clippy::inconsistent_digit_grouping)]
diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
index be505bda479..ac9d89d0cbe 100644
--- a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
@@ -6,5 +6,13 @@ LL |     let _fail1 = 100_200_300.123456789;
    |
    = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
 
-error: aborting due to previous error
+error: long literal lacking separators
+  --> $DIR/test.rs:22:18
+   |
+LL |     let _fail2 = 100200300.300200100;
+   |                  ^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.300_200_100`
+   |
+   = note: `-D clippy::unreadable-literal` implied by `-D warnings`
+
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
index 21849a14fa9..da76bb20fd9 100644
--- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
+++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.rs
@@ -3,6 +3,7 @@
 fn below_limit() {
     let slice: Option<&[u32]> = Some(&[1, 2, 3]);
     if let Some(slice) = slice {
+        //~^ ERROR: binding can be a slice pattern
         // This would usually not be linted but is included now due to the
         // index limit in the config file
         println!("{}", slice[7]);
diff --git a/src/tools/clippy/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs b/src/tools/clippy/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs
new file mode 100644
index 00000000000..06a144f2218
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/min_ident_chars/auxiliary/extern_types.rs
@@ -0,0 +1,3 @@
+#![allow(nonstandard_style, unused)]
+
+pub struct Aaa;
diff --git a/src/tools/clippy/tests/ui-toml/min_ident_chars/clippy.toml b/src/tools/clippy/tests/ui-toml/min_ident_chars/clippy.toml
new file mode 100644
index 00000000000..0114ca75014
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/min_ident_chars/clippy.toml
@@ -0,0 +1,2 @@
+allowed-idents-below-min-chars = ["Owo", "Uwu", "wha", "t_e", "lse", "_do", "_i_", "put", "her", "_e"]
+min-ident-chars-threshold = 3
diff --git a/src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.rs b/src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.rs
new file mode 100644
index 00000000000..4326c7159c8
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.rs
@@ -0,0 +1,19 @@
+//@aux-build:extern_types.rs
+#![allow(nonstandard_style, unused)]
+#![warn(clippy::min_ident_chars)]
+
+extern crate extern_types;
+use extern_types::Aaa;
+
+struct Owo {
+    Uwu: u128,
+    aaa: Aaa,
+}
+
+fn main() {
+    let wha = 1;
+    let vvv = 1;
+    let uuu = 1;
+    let (mut a, mut b) = (1, 2);
+    for i in 0..1000 {}
+}
diff --git a/src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.stderr b/src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.stderr
new file mode 100644
index 00000000000..d9a27628ddb
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/min_ident_chars/min_ident_chars.stderr
@@ -0,0 +1,46 @@
+error: this ident is too short (3 <= 3)
+  --> $DIR/min_ident_chars.rs:6:19
+   |
+LL | use extern_types::Aaa;
+   |                   ^^^
+   |
+   = note: `-D clippy::min-ident-chars` implied by `-D warnings`
+
+error: this ident is too short (3 <= 3)
+  --> $DIR/min_ident_chars.rs:10:5
+   |
+LL |     aaa: Aaa,
+   |     ^^^
+
+error: this ident is too short (3 <= 3)
+  --> $DIR/min_ident_chars.rs:15:9
+   |
+LL |     let vvv = 1;
+   |         ^^^
+
+error: this ident is too short (3 <= 3)
+  --> $DIR/min_ident_chars.rs:16:9
+   |
+LL |     let uuu = 1;
+   |         ^^^
+
+error: this ident is too short (1 <= 3)
+  --> $DIR/min_ident_chars.rs:17:14
+   |
+LL |     let (mut a, mut b) = (1, 2);
+   |              ^
+
+error: this ident is too short (1 <= 3)
+  --> $DIR/min_ident_chars.rs:17:21
+   |
+LL |     let (mut a, mut b) = (1, 2);
+   |                     ^
+
+error: this ident is too short (1 <= 3)
+  --> $DIR/min_ident_chars.rs:18:9
+   |
+LL |     for i in 0..1000 {}
+   |         ^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs
index 1e3ec123a3c..e1dc3f4389c 100644
--- a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs
+++ b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs
@@ -41,7 +41,7 @@ fn match_like_matches() {
 fn match_same_arms() {
     match (1, 2, 3) {
         (1, .., 3) => 42,
-        (.., 3) => 42, //~ ERROR match arms have same body
+        (.., 3) => 42,
         _ => 0,
     };
 }
@@ -49,7 +49,7 @@ fn match_same_arms() {
 fn match_same_arms2() {
     let _ = match Some(42) {
         Some(_) => 24,
-        None => 24, //~ ERROR match arms have same body
+        None => 24,
     };
 }
 
diff --git a/src/tools/clippy/tests/ui-toml/module_inception/clippy.toml b/src/tools/clippy/tests/ui-toml/module_inception/clippy.toml
new file mode 100644
index 00000000000..787620d865c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/module_inception/clippy.toml
@@ -0,0 +1 @@
+allow-private-module-inception = true
diff --git a/src/tools/clippy/tests/ui-toml/module_inception/module_inception.rs b/src/tools/clippy/tests/ui-toml/module_inception/module_inception.rs
new file mode 100644
index 00000000000..cd495c884a4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/module_inception/module_inception.rs
@@ -0,0 +1,34 @@
+#![warn(clippy::module_inception)]
+
+// Lint
+pub mod foo2 {
+    pub mod bar2 {
+        pub mod bar2 {
+            pub mod foo2 {}
+        }
+        pub mod foo2 {}
+    }
+    pub mod foo2 {
+        pub mod bar2 {}
+    }
+}
+
+// Don't lint
+mod foo {
+    pub mod bar {
+        pub mod foo {
+            pub mod bar {}
+        }
+    }
+    pub mod foo {
+        pub mod bar {}
+    }
+}
+
+// No warning. See <https://github.com/rust-lang/rust-clippy/issues/1220>.
+pub mod bar {
+    #[allow(clippy::module_inception)]
+    pub mod bar {}
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/module_inception/module_inception.stderr b/src/tools/clippy/tests/ui-toml/module_inception/module_inception.stderr
new file mode 100644
index 00000000000..a5a09c322e1
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/module_inception/module_inception.stderr
@@ -0,0 +1,20 @@
+error: module has the same name as its containing module
+  --> $DIR/module_inception.rs:6:9
+   |
+LL | /         pub mod bar2 {
+LL | |             pub mod foo2 {}
+LL | |         }
+   | |_________^
+   |
+   = note: `-D clippy::module-inception` implied by `-D warnings`
+
+error: module has the same name as its containing module
+  --> $DIR/module_inception.rs:11:5
+   |
+LL | /     pub mod foo2 {
+LL | |         pub mod bar2 {}
+LL | |     }
+   | |_____^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
index f5761c6afeb..e7ac05dd3c6 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs
@@ -1,8 +1,3 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
 extern crate proc_macro;
 
 use proc_macro::TokenStream;
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
index e4747bedddb..054db5d9330 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 //@run-rustfix
 
 #![warn(clippy::nonstandard_macro_braces)]
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
index 54edded99f4..95d1a2297e5 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 //@run-rustfix
 
 #![warn(clippy::nonstandard_macro_braces)]
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
index 5a2df9f6c5d..17c1b03d88c 100644
--- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
@@ -3,11 +3,17 @@
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
 #![warn(clippy::out_of_bounds_indexing)]
-#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(
+    unconditional_panic,
+    clippy::no_effect,
+    clippy::unnecessary_operation,
+    clippy::useless_vec
+)]
 
 const ARR: [i32; 2] = [1, 2];
 const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
 const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+//~^ ERROR: failed
 
 const fn idx() -> usize {
     1
@@ -29,6 +35,8 @@ fn main() {
     x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
     const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
     const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+    //
+    //~^^ ERROR: failed
 
     let y = &x;
     y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
index bc178b7e131..14e13194427 100644
--- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
@@ -1,17 +1,17 @@
 error[E0080]: evaluation of `main::{constant#3}` failed
-  --> $DIR/test.rs:31:14
+  --> $DIR/test.rs:37:14
    |
 LL |     const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
    |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
 note: erroneous constant used
-  --> $DIR/test.rs:31:5
+  --> $DIR/test.rs:37:5
    |
 LL |     const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: indexing may panic
-  --> $DIR/test.rs:22:5
+  --> $DIR/test.rs:28:5
    |
 LL |     x[index];
    |     ^^^^^^^^
@@ -20,7 +20,7 @@ LL |     x[index];
    = note: `-D clippy::indexing-slicing` implied by `-D warnings`
 
 error: indexing may panic
-  --> $DIR/test.rs:38:5
+  --> $DIR/test.rs:46:5
    |
 LL |     v[0];
    |     ^^^^
@@ -28,7 +28,7 @@ LL |     v[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/test.rs:39:5
+  --> $DIR/test.rs:47:5
    |
 LL |     v[10];
    |     ^^^^^
@@ -36,7 +36,7 @@ LL |     v[10];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/test.rs:40:5
+  --> $DIR/test.rs:48:5
    |
 LL |     v[1 << 3];
    |     ^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     v[1 << 3];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/test.rs:46:5
+  --> $DIR/test.rs:54:5
    |
 LL |     v[N];
    |     ^^^^
@@ -52,7 +52,7 @@ LL |     v[N];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/test.rs:47:5
+  --> $DIR/test.rs:55:5
    |
 LL |     v[M];
    |     ^^^^
@@ -60,7 +60,7 @@ LL |     v[M];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/test.rs:10:24
+  --> $DIR/test.rs:15:24
    |
 LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
    |                        ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
index 8e1a1710a6c..63fdea710cb 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
@@ -1,6 +1,8 @@
 //@compile-flags: --crate-name conf_disallowed_methods
 
+#![allow(clippy::needless_raw_strings)]
 #![warn(clippy::disallowed_methods)]
+#![allow(clippy::useless_vec)]
 
 extern crate futures;
 extern crate regex;
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
index 148d1cae51f..fc137c225d8 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
@@ -1,5 +1,5 @@
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:33:14
+  --> $DIR/conf_disallowed_methods.rs:35:14
    |
 LL |     let re = Regex::new(r"ab.*c").unwrap();
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     let re = Regex::new(r"ab.*c").unwrap();
    = note: `-D clippy::disallowed-methods` implied by `-D warnings`
 
 error: use of a disallowed method `regex::Regex::is_match`
-  --> $DIR/conf_disallowed_methods.rs:34:5
+  --> $DIR/conf_disallowed_methods.rs:36:5
    |
 LL |     re.is_match("abc");
    |     ^^^^^^^^^^^^^^^^^^
@@ -15,73 +15,73 @@ LL |     re.is_match("abc");
    = note: no matching allowed (from clippy.toml)
 
 error: use of a disallowed method `std::iter::Iterator::sum`
-  --> $DIR/conf_disallowed_methods.rs:37:5
+  --> $DIR/conf_disallowed_methods.rs:39:5
    |
 LL |     a.iter().sum::<i32>();
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `slice::sort_unstable`
-  --> $DIR/conf_disallowed_methods.rs:39:5
+  --> $DIR/conf_disallowed_methods.rs:41:5
    |
 LL |     a.sort_unstable();
    |     ^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `f32::clamp`
-  --> $DIR/conf_disallowed_methods.rs:41:13
+  --> $DIR/conf_disallowed_methods.rs:43:13
    |
 LL |     let _ = 2.0f32.clamp(3.0f32, 4.0f32);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:44:61
+  --> $DIR/conf_disallowed_methods.rs:46:61
    |
 LL |     let indirect: fn(&str) -> Result<Regex, regex::Error> = Regex::new;
    |                                                             ^^^^^^^^^^
 
 error: use of a disallowed method `f32::clamp`
-  --> $DIR/conf_disallowed_methods.rs:47:28
+  --> $DIR/conf_disallowed_methods.rs:49:28
    |
 LL |     let in_call = Box::new(f32::clamp);
    |                            ^^^^^^^^^^
 
 error: use of a disallowed method `regex::Regex::new`
-  --> $DIR/conf_disallowed_methods.rs:48:53
+  --> $DIR/conf_disallowed_methods.rs:50:53
    |
 LL |     let in_method_call = ["^", "$"].into_iter().map(Regex::new);
    |                                                     ^^^^^^^^^^
 
 error: use of a disallowed method `futures::stream::select_all`
-  --> $DIR/conf_disallowed_methods.rs:51:31
+  --> $DIR/conf_disallowed_methods.rs:53:31
    |
 LL |     let same_name_as_module = select_all(vec![empty::<()>()]);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `conf_disallowed_methods::local_fn`
-  --> $DIR/conf_disallowed_methods.rs:53:5
+  --> $DIR/conf_disallowed_methods.rs:55:5
    |
 LL |     local_fn();
    |     ^^^^^^^^^^
 
 error: use of a disallowed method `conf_disallowed_methods::local_mod::f`
-  --> $DIR/conf_disallowed_methods.rs:54:5
+  --> $DIR/conf_disallowed_methods.rs:56:5
    |
 LL |     local_mod::f();
    |     ^^^^^^^^^^^^^^
 
 error: use of a disallowed method `conf_disallowed_methods::Struct::method`
-  --> $DIR/conf_disallowed_methods.rs:56:5
+  --> $DIR/conf_disallowed_methods.rs:58:5
    |
 LL |     s.method();
    |     ^^^^^^^^^^
 
 error: use of a disallowed method `conf_disallowed_methods::Trait::provided_method`
-  --> $DIR/conf_disallowed_methods.rs:57:5
+  --> $DIR/conf_disallowed_methods.rs:59:5
    |
 LL |     s.provided_method();
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: use of a disallowed method `conf_disallowed_methods::Trait::implemented_method`
-  --> $DIR/conf_disallowed_methods.rs:58:5
+  --> $DIR/conf_disallowed_methods.rs:60:5
    |
 LL |     s.implemented_method();
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs b/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs
index 179b1266169..f267a67f40e 100644
--- a/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.rs
@@ -1,7 +1,7 @@
 //@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
 //@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
 
-#![deny(clippy::trivially_copy_pass_by_ref)]
+#![warn(clippy::trivially_copy_pass_by_ref)]
 
 #[derive(Copy, Clone)]
 struct Foo(u8);
diff --git a/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.stderr b/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.stderr
index b3ef5928e8e..d2b55eff16d 100644
--- a/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_trivially_copy/test.stderr
@@ -4,11 +4,7 @@ error: this argument (N byte) is passed by reference, but would be more efficien
 LL | fn bad(x: &u16, y: &Foo) {}
    |           ^^^^ help: consider passing by value instead: `u16`
    |
-note: the lint level is defined here
-  --> $DIR/test.rs:4:9
-   |
-LL | #![deny(clippy::trivially_copy_pass_by_ref)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
   --> $DIR/test.rs:14:20
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
index 569fd2c3553..38009627757 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
@@ -1,3 +1,3 @@
-//@error-pattern: unknown field `foobar`, expected one of
+//@error-in-other-file: unknown field `foobar`, expected one of
 
 fn main() {}
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 b6038f031f3..6ba26e97730 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
@@ -1,9 +1,14 @@
 error: error reading Clippy's configuration file: unknown field `foobar`, expected one of
+           accept-comment-above-attributes
+           accept-comment-above-statement
            allow-dbg-in-tests
            allow-expect-in-tests
            allow-mixed-uninlined-format-args
+           allow-one-hash-in-raw-strings
            allow-print-in-tests
+           allow-private-module-inception
            allow-unwrap-in-tests
+           allowed-idents-below-min-chars
            allowed-scripts
            arithmetic-side-effects-allowed
            arithmetic-side-effects-allowed-binary
@@ -24,6 +29,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
+           excessive-nesting-threshold
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
@@ -34,12 +40,14 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            max-struct-bools
            max-suggested-slice-pattern-length
            max-trait-bounds
+           min-ident-chars-threshold
            missing-docs-in-crate-items
            msrv
            pass-by-value-size-limit
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
+           stack-size-threshold
            standard-macro-braces
            suppress-restriction-lint-in-const
            third-party
@@ -54,17 +62,22 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            vec-box-size-threshold
            verbose-bit-mask-threshold
            warn-on-all-wildcard-imports
-  --> $DIR/clippy.toml:2:1
+  --> $DIR/$DIR/clippy.toml:2:1
    |
 LL | foobar = 42
    | ^^^^^^
 
 error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of
+           accept-comment-above-attributes
+           accept-comment-above-statement
            allow-dbg-in-tests
            allow-expect-in-tests
            allow-mixed-uninlined-format-args
+           allow-one-hash-in-raw-strings
            allow-print-in-tests
+           allow-private-module-inception
            allow-unwrap-in-tests
+           allowed-idents-below-min-chars
            allowed-scripts
            arithmetic-side-effects-allowed
            arithmetic-side-effects-allowed-binary
@@ -85,6 +98,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
+           excessive-nesting-threshold
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
@@ -95,12 +109,14 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            max-struct-bools
            max-suggested-slice-pattern-length
            max-trait-bounds
+           min-ident-chars-threshold
            missing-docs-in-crate-items
            msrv
            pass-by-value-size-limit
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
+           stack-size-threshold
            standard-macro-braces
            suppress-restriction-lint-in-const
            third-party
@@ -115,7 +131,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
-  --> $DIR/clippy.toml:4:1
+  --> $DIR/$DIR/clippy.toml:4:1
    |
 LL | barfoo = 53
    | ^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
new file mode 100644
index 00000000000..1c591fc76f3
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
@@ -0,0 +1,13 @@
+extern crate proc_macro;
+
+use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree};
+
+#[proc_macro]
+pub fn unsafe_block(input: TokenStream) -> TokenStream {
+    let span = input.into_iter().next().unwrap().span();
+    TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), {
+        let mut group = Group::new(Delimiter::Brace, TokenStream::new());
+        group.set_span(span);
+        TokenTree::Group(group)
+    }])
+}
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml
new file mode 100644
index 00000000000..e6dbb3d3784
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml
@@ -0,0 +1,2 @@
+accept-comment-above-statement = true
+accept-comment-above-attributes = true
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
new file mode 100644
index 00000000000..33d63670958
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
@@ -0,0 +1,567 @@
+//@aux-build:proc_macro_unsafe.rs:proc-macro
+
+#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
+#![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)]
+#![feature(lint_reasons)]
+
+extern crate proc_macro_unsafe;
+
+// Valid comments
+
+fn nested_local() {
+    let _ = {
+        let _ = {
+            // SAFETY:
+            let _ = unsafe {};
+        };
+    };
+}
+
+fn deep_nest() {
+    let _ = {
+        let _ = {
+            // SAFETY:
+            let _ = unsafe {};
+
+            // Safety:
+            unsafe {};
+
+            let _ = {
+                let _ = {
+                    let _ = {
+                        let _ = {
+                            let _ = {
+                                // Safety:
+                                let _ = unsafe {};
+
+                                // SAFETY:
+                                unsafe {};
+                            };
+                        };
+                    };
+
+                    // Safety:
+                    unsafe {};
+                };
+            };
+        };
+
+        // Safety:
+        unsafe {};
+    };
+
+    // SAFETY:
+    unsafe {};
+}
+
+fn local_tuple_expression() {
+    // Safety:
+    let _ = (42, unsafe {});
+}
+
+fn line_comment() {
+    // Safety:
+    unsafe {}
+}
+
+fn line_comment_newlines() {
+    // SAFETY:
+
+    unsafe {}
+}
+
+fn line_comment_empty() {
+    // Safety:
+    //
+    //
+    //
+    unsafe {}
+}
+
+fn line_comment_with_extras() {
+    // This is a description
+    // Safety:
+    unsafe {}
+}
+
+fn block_comment() {
+    /* Safety: */
+    unsafe {}
+}
+
+fn block_comment_newlines() {
+    /* SAFETY: */
+
+    unsafe {}
+}
+
+fn block_comment_with_extras() {
+    /* This is a description
+     * SAFETY:
+     */
+    unsafe {}
+}
+
+fn block_comment_terminator_same_line() {
+    /* This is a description
+     * Safety: */
+    unsafe {}
+}
+
+fn buried_safety() {
+    // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+    // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
+    // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
+    // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
+    // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
+    // laborum. Safety:
+    // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi
+    // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio
+    // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl
+    // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus.
+    unsafe {}
+}
+
+fn safety_with_prepended_text() {
+    // This is a test. safety:
+    unsafe {}
+}
+
+fn local_line_comment() {
+    // Safety:
+    let _ = unsafe {};
+}
+
+fn local_block_comment() {
+    /* SAFETY: */
+    let _ = unsafe {};
+}
+
+fn comment_array() {
+    // Safety:
+    let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+}
+
+fn comment_tuple() {
+    // sAFETY:
+    let _ = (42, unsafe {}, "test", unsafe {});
+}
+
+fn comment_unary() {
+    // SAFETY:
+    let _ = *unsafe { &42 };
+}
+
+#[allow(clippy::match_single_binding)]
+fn comment_match() {
+    // SAFETY:
+    let _ = match unsafe {} {
+        _ => {},
+    };
+}
+
+fn comment_addr_of() {
+    // Safety:
+    let _ = &unsafe {};
+}
+
+fn comment_repeat() {
+    // Safety:
+    let _ = [unsafe {}; 5];
+}
+
+fn comment_macro_call() {
+    macro_rules! t {
+        ($b:expr) => {
+            $b
+        };
+    }
+
+    t!(
+        // SAFETY:
+        unsafe {}
+    );
+}
+
+fn comment_macro_def() {
+    macro_rules! t {
+        () => {
+            // Safety:
+            unsafe {}
+        };
+    }
+
+    t!();
+}
+
+fn non_ascii_comment() {
+    // ॐ᧻໒ SaFeTy: ௵∰
+    unsafe {};
+}
+
+fn local_commented_block() {
+    let _ =
+        // safety:
+        unsafe {};
+}
+
+fn local_nest() {
+    // safety:
+    let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})];
+}
+
+fn in_fn_call(x: *const u32) {
+    fn f(x: u32) {}
+
+    // Safety: reason
+    f(unsafe { *x });
+}
+
+fn multi_in_fn_call(x: *const u32) {
+    fn f(x: u32, y: u32) {}
+
+    // Safety: reason
+    f(unsafe { *x }, unsafe { *x });
+}
+
+fn in_multiline_fn_call(x: *const u32) {
+    fn f(x: u32, y: u32) {}
+
+    f(
+        // Safety: reason
+        unsafe { *x },
+        0,
+    );
+}
+
+fn in_macro_call(x: *const u32) {
+    // Safety: reason
+    println!("{}", unsafe { *x });
+}
+
+fn in_multiline_macro_call(x: *const u32) {
+    println!(
+        "{}",
+        // Safety: reason
+        unsafe { *x },
+    );
+}
+
+fn from_proc_macro() {
+    proc_macro_unsafe::unsafe_block!(token);
+}
+
+fn in_closure(x: *const u32) {
+    // Safety: reason
+    let _ = || unsafe { *x };
+}
+
+// Invalid comments
+
+#[rustfmt::skip]
+fn inline_block_comment() {
+    /* Safety: */ unsafe {}
+}
+
+fn no_comment() {
+    unsafe {}
+}
+
+fn no_comment_array() {
+    let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+}
+
+fn no_comment_tuple() {
+    let _ = (42, unsafe {}, "test", unsafe {});
+}
+
+fn no_comment_unary() {
+    let _ = *unsafe { &42 };
+}
+
+#[allow(clippy::match_single_binding)]
+fn no_comment_match() {
+    let _ = match unsafe {} {
+        _ => {},
+    };
+}
+
+fn no_comment_addr_of() {
+    let _ = &unsafe {};
+}
+
+fn no_comment_repeat() {
+    let _ = [unsafe {}; 5];
+}
+
+fn local_no_comment() {
+    let _ = unsafe {};
+}
+
+fn no_comment_macro_call() {
+    macro_rules! t {
+        ($b:expr) => {
+            $b
+        };
+    }
+
+    t!(unsafe {});
+}
+
+fn no_comment_macro_def() {
+    macro_rules! t {
+        () => {
+            unsafe {}
+        };
+    }
+
+    t!();
+}
+
+fn trailing_comment() {
+    unsafe {} // SAFETY:
+}
+
+fn internal_comment() {
+    unsafe {
+        // SAFETY:
+    }
+}
+
+fn interference() {
+    // SAFETY
+
+    let _ = 42;
+
+    unsafe {};
+}
+
+pub fn print_binary_tree() {
+    println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
+}
+
+mod unsafe_impl_smoke_test {
+    unsafe trait A {}
+
+    // error: no safety comment
+    unsafe impl A for () {}
+
+    // Safety: ok
+    unsafe impl A for (i32) {}
+
+    mod sub_mod {
+        // error:
+        unsafe impl B for (u32) {}
+        unsafe trait B {}
+    }
+
+    #[rustfmt::skip]
+    mod sub_mod2 {
+        //
+        // SAFETY: ok
+        //
+
+        unsafe impl B for (u32) {}
+        unsafe trait B {}
+    }
+}
+
+mod unsafe_impl_from_macro {
+    unsafe trait T {}
+
+    // error
+    macro_rules! no_safety_comment {
+        ($t:ty) => {
+            unsafe impl T for $t {}
+        };
+    }
+
+    // ok
+    no_safety_comment!(());
+
+    // ok
+    macro_rules! with_safety_comment {
+        ($t:ty) => {
+            // SAFETY:
+            unsafe impl T for $t {}
+        };
+    }
+
+    // ok
+    with_safety_comment!((i32));
+}
+
+mod unsafe_impl_macro_and_not_macro {
+    unsafe trait T {}
+
+    // error
+    macro_rules! no_safety_comment {
+        ($t:ty) => {
+            unsafe impl T for $t {}
+        };
+    }
+
+    // ok
+    no_safety_comment!(());
+
+    // error
+    unsafe impl T for (i32) {}
+
+    // ok
+    no_safety_comment!(u32);
+
+    // error
+    unsafe impl T for (bool) {}
+}
+
+#[rustfmt::skip]
+mod unsafe_impl_valid_comment {
+    unsafe trait SaFety {}
+    // SaFety:
+    unsafe impl SaFety for () {}
+
+    unsafe trait MultiLineComment {}
+    // The following impl is safe
+    // ...
+    // Safety: reason
+    unsafe impl MultiLineComment for () {}
+
+    unsafe trait NoAscii {}
+    // 安全 SAFETY: 以下のコードは安全です
+    unsafe impl NoAscii for () {}
+
+    unsafe trait InlineAndPrecedingComment {}
+    // SAFETY:
+    /* comment */ unsafe impl InlineAndPrecedingComment for () {}
+
+    unsafe trait BuriedSafety {}
+    // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+    // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
+    // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
+    // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
+    // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
+    // laborum. Safety:
+    // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi
+    // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio
+    // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl
+    // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus.
+    unsafe impl BuriedSafety for () {}
+
+    unsafe trait MultiLineBlockComment {}
+    /* This is a description
+     * Safety: */
+    unsafe impl MultiLineBlockComment for () {}
+}
+
+#[rustfmt::skip]
+mod unsafe_impl_invalid_comment {
+    unsafe trait NoComment {}
+
+    unsafe impl NoComment for () {}
+
+    unsafe trait InlineComment {}
+
+    /* SAFETY: */ unsafe impl InlineComment for () {}
+
+    unsafe trait TrailingComment {}
+
+    unsafe impl TrailingComment for () {} // SAFETY:
+
+    unsafe trait Interference {}
+    // SAFETY:
+    const BIG_NUMBER: i32 = 1000000;
+    unsafe impl Interference for () {}
+}
+
+unsafe trait ImplInFn {}
+
+fn impl_in_fn() {
+    // error
+    unsafe impl ImplInFn for () {}
+
+    // SAFETY: ok
+    unsafe impl ImplInFn for (i32) {}
+}
+
+unsafe trait CrateRoot {}
+
+// error
+unsafe impl CrateRoot for () {}
+
+// SAFETY: ok
+unsafe impl CrateRoot for (i32) {}
+
+fn issue_9142() {
+    // SAFETY: ok
+    let _ =
+        // we need this comment to avoid rustfmt putting
+        // it all on one line
+        unsafe {};
+
+    // SAFETY: this is more than one level away, so it should warn
+    let _ = {
+        if unsafe { true } {
+            todo!();
+        } else {
+            let bar = unsafe {};
+            todo!();
+            bar
+        }
+    };
+}
+
+pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    1
+}
+
+pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    2
+}
+
+fn issue_10832() {
+    // Safety: A safety comment
+    let _some_variable_with_a_very_long_name_to_break_the_line =
+        unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Another safety comment
+    const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Yet another safety comment
+    static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+}
+
+fn issue_8679<T: Copy>() {
+    // SAFETY:
+    #[allow(unsafe_code)]
+    unsafe {}
+
+    // SAFETY:
+    #[expect(unsafe_code, reason = "totally safe")]
+    unsafe {
+        *std::ptr::null::<T>()
+    };
+
+    // Safety: A safety comment
+    #[allow(unsafe_code)]
+    let _some_variable_with_a_very_long_name_to_break_the_line =
+        unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Another safety comment
+    #[allow(unsafe_code)]
+    const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Yet another safety comment
+    #[allow(unsafe_code)]
+    static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // SAFETY:
+    #[allow(unsafe_code)]
+    // This also works I guess
+    unsafe {}
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr
new file mode 100644
index 00000000000..9a0fd059389
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr
@@ -0,0 +1,314 @@
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:263:19
+   |
+LL |     /* Safety: */ unsafe {}
+   |                   ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:267:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:271:14
+   |
+LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+   |              ^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:271:29
+   |
+LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+   |                             ^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:271:48
+   |
+LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+   |                                                ^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:275:18
+   |
+LL |     let _ = (42, unsafe {}, "test", unsafe {});
+   |                  ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:275:37
+   |
+LL |     let _ = (42, unsafe {}, "test", unsafe {});
+   |                                     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:279:14
+   |
+LL |     let _ = *unsafe { &42 };
+   |              ^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:284:19
+   |
+LL |     let _ = match unsafe {} {
+   |                   ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:290:14
+   |
+LL |     let _ = &unsafe {};
+   |              ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:294:14
+   |
+LL |     let _ = [unsafe {}; 5];
+   |              ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:298:13
+   |
+LL |     let _ = unsafe {};
+   |             ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:308:8
+   |
+LL |     t!(unsafe {});
+   |        ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:314:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^^^^
+...
+LL |     t!();
+   |     ---- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:322:5
+   |
+LL |     unsafe {} // SAFETY:
+   |     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:326:5
+   |
+LL |     unsafe {
+   |     ^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:336:5
+   |
+LL |     unsafe {};
+   |     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:340:20
+   |
+LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:347:5
+   |
+LL |     unsafe impl A for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:354:9
+   |
+LL |         unsafe impl B for (u32) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:375:13
+   |
+LL |             unsafe impl T for $t {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     no_safety_comment!(());
+   |     ---------------------- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:400:13
+   |
+LL |             unsafe impl T for $t {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     no_safety_comment!(());
+   |     ---------------------- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:408:5
+   |
+LL |     unsafe impl T for (i32) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:400:13
+   |
+LL |             unsafe impl T for $t {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     no_safety_comment!(u32);
+   |     ----------------------- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:414:5
+   |
+LL |     unsafe impl T for (bool) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:460:5
+   |
+LL |     unsafe impl NoComment for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:464:19
+   |
+LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:468:5
+   |
+LL |     unsafe impl TrailingComment for () {} // SAFETY:
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: constant item has unnecessary safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:472:5
+   |
+LL |     const BIG_NUMBER: i32 = 1000000;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider removing the safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:471:5
+   |
+LL |     // SAFETY:
+   |     ^^^^^^^^^^
+   = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings`
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:473:5
+   |
+LL |     unsafe impl Interference for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:480:5
+   |
+LL |     unsafe impl ImplInFn for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:489:1
+   |
+LL | unsafe impl CrateRoot for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: statement has unnecessary safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:502:5
+   |
+LL | /     let _ = {
+LL | |         if unsafe { true } {
+LL | |             todo!();
+LL | |         } else {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider removing the safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:501:5
+   |
+LL |     // SAFETY: this is more than one level away, so it should warn
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:503:12
+   |
+LL |         if unsafe { true } {
+   |            ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:506:23
+   |
+LL |             let bar = unsafe {};
+   |                       ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: aborting due to 35 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
index 5d3e800cadd..dde1c6d7c37 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
@@ -1,8 +1,13 @@
 //@compile-flags: --test
 
-#![allow(unused_mut, clippy::get_first, clippy::from_iter_instead_of_collect)]
+#![allow(
+    unused_mut,
+    clippy::get_first,
+    clippy::from_iter_instead_of_collect,
+    clippy::useless_vec
+)]
 #![warn(clippy::unwrap_used)]
-#![deny(clippy::get_unwrap)]
+#![warn(clippy::get_unwrap)]
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 8a32750e3c9..eb66a5cf50b 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -1,17 +1,13 @@
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:35:17
+  --> $DIR/unwrap_used.rs:40:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
    |
-note: the lint level is defined here
-  --> $DIR/unwrap_used.rs:5:9
-   |
-LL | #![deny(clippy::get_unwrap)]
-   |         ^^^^^^^^^^^^^^^^^^
+   = note: `-D clippy::get-unwrap` implied by `-D warnings`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:35:17
+  --> $DIR/unwrap_used.rs:40:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,13 +16,13 @@ LL |         let _ = boxed_slice.get(1).unwrap();
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:36:17
+  --> $DIR/unwrap_used.rs:41:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:36:17
+  --> $DIR/unwrap_used.rs:41:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,13 +30,13 @@ LL |         let _ = some_slice.get(0).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:37:17
+  --> $DIR/unwrap_used.rs:42:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:37:17
+  --> $DIR/unwrap_used.rs:42:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -48,13 +44,13 @@ LL |         let _ = some_vec.get(0).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:38:17
+  --> $DIR/unwrap_used.rs:43:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:38:17
+  --> $DIR/unwrap_used.rs:43:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,13 +58,13 @@ LL |         let _ = some_vecdeque.get(0).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:39:17
+  --> $DIR/unwrap_used.rs:44:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:39:17
+  --> $DIR/unwrap_used.rs:44:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,13 +72,13 @@ LL |         let _ = some_hashmap.get(&1).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:40:17
+  --> $DIR/unwrap_used.rs:45:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:40:17
+  --> $DIR/unwrap_used.rs:45:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,13 +86,13 @@ LL |         let _ = some_btreemap.get(&1).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:44:21
+  --> $DIR/unwrap_used.rs:49:21
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:44:22
+  --> $DIR/unwrap_used.rs:49:22
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,13 +100,13 @@ LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:49:9
+  --> $DIR/unwrap_used.rs:54:9
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:49:10
+  --> $DIR/unwrap_used.rs:54:10
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,13 +114,13 @@ LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:50:9
+  --> $DIR/unwrap_used.rs:55:9
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:50:10
+  --> $DIR/unwrap_used.rs:55:10
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -132,13 +128,13 @@ LL |         *some_slice.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:51:9
+  --> $DIR/unwrap_used.rs:56:9
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:51:10
+  --> $DIR/unwrap_used.rs:56:10
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -146,13 +142,13 @@ LL |         *some_vec.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:52:9
+  --> $DIR/unwrap_used.rs:57:9
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:52:10
+  --> $DIR/unwrap_used.rs:57:10
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -160,13 +156,13 @@ LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:64:17
+  --> $DIR/unwrap_used.rs:69:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:64:17
+  --> $DIR/unwrap_used.rs:69:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -174,13 +170,13 @@ LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:65:17
+  --> $DIR/unwrap_used.rs:70:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_used.rs:65:17
+  --> $DIR/unwrap_used.rs:70:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -188,13 +184,13 @@ LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:72:13
+  --> $DIR/unwrap_used.rs:77:13
    |
 LL |     let _ = boxed_slice.get(1).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:90:17
+  --> $DIR/unwrap_used.rs:95:17
    |
 LL |         let _ = Box::new([0]).get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]`
diff --git a/src/tools/clippy/tests/ui-toml/update-all-references.sh b/src/tools/clippy/tests/ui-toml/update-all-references.sh
index 4391499a1e1..d4204307026 100755
--- a/src/tools/clippy/tests/ui-toml/update-all-references.sh
+++ b/src/tools/clippy/tests/ui-toml/update-all-references.sh
@@ -1,3 +1,3 @@
 #!/bin/bash
 
-echo "Please use 'cargo dev bless' instead."
+echo "Please use 'cargo bless' instead."
diff --git a/src/tools/clippy/tests/ui/allow_attributes.fixed b/src/tools/clippy/tests/ui/allow_attributes.fixed
index f0936b2608e..cc95a06817d 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.fixed
+++ b/src/tools/clippy/tests/ui/allow_attributes.fixed
@@ -1,9 +1,12 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 #![allow(unused)]
 #![warn(clippy::allow_attributes)]
 #![feature(lint_reasons)]
+#![no_main]
 
-fn main() {}
+extern crate proc_macros;
+use proc_macros::{external, with_span};
 
 // Using clippy::needless_borrow just as a placeholder, it isn't relevant.
 
@@ -20,6 +23,21 @@ struct T4;
 #[cfg_attr(panic = "unwind", expect(dead_code))]
 struct CfgT;
 
+fn ignore_external() {
+    external! {
+        #[allow(clippy::needless_borrow)] // Should not lint
+        fn a() {}
+    }
+}
+
+fn ignore_proc_macro() {
+    with_span! {
+        span
+        #[allow(clippy::needless_borrow)] // Should not lint
+        fn a() {}
+    }
+}
+
 fn ignore_inner_attr() {
     #![allow(unused)] // Should not lint
 }
diff --git a/src/tools/clippy/tests/ui/allow_attributes.rs b/src/tools/clippy/tests/ui/allow_attributes.rs
index 2fb9e86126e..2eb6ad304ea 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes.rs
@@ -1,9 +1,12 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 #![allow(unused)]
 #![warn(clippy::allow_attributes)]
 #![feature(lint_reasons)]
+#![no_main]
 
-fn main() {}
+extern crate proc_macros;
+use proc_macros::{external, with_span};
 
 // Using clippy::needless_borrow just as a placeholder, it isn't relevant.
 
@@ -20,6 +23,21 @@ struct T4;
 #[cfg_attr(panic = "unwind", allow(dead_code))]
 struct CfgT;
 
+fn ignore_external() {
+    external! {
+        #[allow(clippy::needless_borrow)] // Should not lint
+        fn a() {}
+    }
+}
+
+fn ignore_proc_macro() {
+    with_span! {
+        span
+        #[allow(clippy::needless_borrow)] // Should not lint
+        fn a() {}
+    }
+}
+
 fn ignore_inner_attr() {
     #![allow(unused)] // Should not lint
 }
diff --git a/src/tools/clippy/tests/ui/allow_attributes.stderr b/src/tools/clippy/tests/ui/allow_attributes.stderr
index 681837e9ed7..d17fd86cb86 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes.stderr
@@ -1,5 +1,5 @@
 error: #[allow] attribute found
-  --> $DIR/allow_attributes.rs:11:3
+  --> $DIR/allow_attributes.rs:14:3
    |
 LL | #[allow(dead_code)]
    |   ^^^^^ help: replace it with: `expect`
@@ -7,7 +7,7 @@ LL | #[allow(dead_code)]
    = note: `-D clippy::allow-attributes` implied by `-D warnings`
 
 error: #[allow] attribute found
-  --> $DIR/allow_attributes.rs:20:30
+  --> $DIR/allow_attributes.rs:23:30
    |
 LL | #[cfg_attr(panic = "unwind", allow(dead_code))]
    |                              ^^^^^ help: replace it with: `expect`
diff --git a/src/tools/clippy/tests/ui/allow_attributes_false_positive.rs b/src/tools/clippy/tests/ui/allow_attributes_false_positive.rs
deleted file mode 100644
index 5c3407628be..00000000000
--- a/src/tools/clippy/tests/ui/allow_attributes_false_positive.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![warn(clippy::allow_attributes)]
-#![feature(lint_reasons)]
-#![crate_type = "proc-macro"]
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
index 1a0d4e88657..d223d564221 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
@@ -1,9 +1,15 @@
+//@aux-build:proc_macros.rs:proc-macro
 #![feature(lint_reasons)]
 #![deny(clippy::allow_attributes_without_reason)]
+#![allow(unfulfilled_lint_expectations)]
+
+extern crate proc_macros;
+use proc_macros::{external, with_span};
 
 // These should trigger the lint
 #[allow(dead_code)]
 #[allow(dead_code, deprecated)]
+#[expect(dead_code)]
 // These should be fine
 #[allow(dead_code, reason = "This should be allowed")]
 #[warn(dyn_drop, reason = "Warnings can also have reasons")]
@@ -11,4 +17,28 @@
 #[deny(deref_nullptr)]
 #[forbid(deref_nullptr)]
 
-fn main() {}
+fn main() {
+    external! {
+        #[allow(dead_code)]
+        fn a() {}
+    }
+    with_span! {
+        span
+        #[allow(dead_code)]
+        fn b() {}
+    }
+}
+
+// Make sure this is not triggered on `?` desugaring
+
+pub fn trigger_fp_option() -> Option<()> {
+    Some(())?;
+    None?;
+    Some(())
+}
+
+pub fn trigger_fp_result() -> Result<(), &'static str> {
+    Ok(())?;
+    Err("asdf")?;
+    Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
index 23f17e9a7af..96f747d0026 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
@@ -1,23 +1,39 @@
 error: `allow` attribute without specifying a reason
-  --> $DIR/allow_attributes_without_reason.rs:5:1
+  --> $DIR/allow_attributes_without_reason.rs:4:1
    |
-LL | #[allow(dead_code)]
-   | ^^^^^^^^^^^^^^^^^^^
+LL | #![allow(unfulfilled_lint_expectations)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a reason at the end with `, reason = ".."`
 note: the lint level is defined here
-  --> $DIR/allow_attributes_without_reason.rs:2:9
+  --> $DIR/allow_attributes_without_reason.rs:3:9
    |
 LL | #![deny(clippy::allow_attributes_without_reason)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `allow` attribute without specifying a reason
-  --> $DIR/allow_attributes_without_reason.rs:6:1
+  --> $DIR/allow_attributes_without_reason.rs:10:1
+   |
+LL | #[allow(dead_code)]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a reason at the end with `, reason = ".."`
+
+error: `allow` attribute without specifying a reason
+  --> $DIR/allow_attributes_without_reason.rs:11:1
    |
 LL | #[allow(dead_code, deprecated)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a reason at the end with `, reason = ".."`
 
-error: aborting due to 2 previous errors
+error: `expect` attribute without specifying a reason
+  --> $DIR/allow_attributes_without_reason.rs:12:1
+   |
+LL | #[expect(dead_code)]
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a reason at the end with `, reason = ".."`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.fixed b/src/tools/clippy/tests/ui/almost_complete_range.fixed
index 5cd0dcce6f7..50a13f16b44 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.fixed
+++ b/src/tools/clippy/tests/ui/almost_complete_range.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 //@edition:2018
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![feature(exclusive_range_pattern)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.rs b/src/tools/clippy/tests/ui/almost_complete_range.rs
index db0bfc8afc3..fd8223a2309 100644
--- a/src/tools/clippy/tests/ui/almost_complete_range.rs
+++ b/src/tools/clippy/tests/ui/almost_complete_range.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 //@edition:2018
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![feature(exclusive_range_pattern)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs b/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs
new file mode 100644
index 00000000000..ac786f68c12
--- /dev/null
+++ b/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs
@@ -0,0 +1,17 @@
+#![warn(clippy::arc_with_non_send_sync)]
+#![allow(unused_variables)]
+use std::cell::RefCell;
+use std::sync::{Arc, Mutex};
+
+fn foo<T>(x: T) {
+    // Should not lint - purposefully ignoring generic args.
+    let a = Arc::new(x);
+}
+
+fn main() {
+    // This is safe, as `i32` implements `Send` and `Sync`.
+    let a = Arc::new(42);
+
+    // This is not safe, as `RefCell` does not implement `Sync`.
+    let b = Arc::new(RefCell::new(42));
+}
diff --git a/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr b/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr
new file mode 100644
index 00000000000..fc2fc5f93b1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr
@@ -0,0 +1,11 @@
+error: usage of `Arc<T>` where `T` is not `Send` or `Sync`
+  --> $DIR/arc_with_non_send_sync.rs:16:13
+   |
+LL |     let b = Arc::new(RefCell::new(42));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using `Rc<T>` instead or wrapping `T` in a std::sync type like `Mutex<T>`
+   = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index f95af1017bc..4f38e50c81d 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![allow(
     clippy::assign_op_pattern,
@@ -466,4 +466,19 @@ pub fn issue_10767() {
     &3.5_f32 + &1.3_f32;
 }
 
+pub fn issue_10792() {
+    struct One {
+        a: u32,
+    }
+    struct Two {
+        b: u32,
+        c: u64,
+    }
+    const ONE: One = One { a: 1 };
+    const TWO: Two = Two { b: 2, c: 3 };
+    let _ = 10 / ONE.a;
+    let _ = 10 / TWO.b;
+    let _ = 10 / TWO.c;
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/as_conversions.rs b/src/tools/clippy/tests/ui/as_conversions.rs
index 890bf0b0a7e..427842a51d9 100644
--- a/src/tools/clippy/tests/ui/as_conversions.rs
+++ b/src/tools/clippy/tests/ui/as_conversions.rs
@@ -1,10 +1,11 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::as_conversions)]
-#![allow(clippy::borrow_as_ptr)]
+#![allow(clippy::borrow_as_ptr, unused)]
 
 extern crate proc_macros;
 use proc_macros::external;
+use proc_macros::with_span;
 
 fn main() {
     let i = 0u32 as u64;
@@ -13,3 +14,11 @@ fn main() {
 
     external!(0u32 as u64);
 }
+
+with_span!(
+    span
+
+    fn coverting() {
+        let x = 0u32 as u64;
+    }
+);
diff --git a/src/tools/clippy/tests/ui/as_conversions.stderr b/src/tools/clippy/tests/ui/as_conversions.stderr
index 54037a64997..ca41d1378aa 100644
--- a/src/tools/clippy/tests/ui/as_conversions.stderr
+++ b/src/tools/clippy/tests/ui/as_conversions.stderr
@@ -1,5 +1,5 @@
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:10:13
+  --> $DIR/as_conversions.rs:11:13
    |
 LL |     let i = 0u32 as u64;
    |             ^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let i = 0u32 as u64;
    = note: `-D clippy::as-conversions` implied by `-D warnings`
 
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:12:13
+  --> $DIR/as_conversions.rs:13:13
    |
 LL |     let j = &i as *const u64 as *mut u64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     let j = &i as *const u64 as *mut u64;
    = help: consider using a safe wrapper for this conversion
 
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:12:13
+  --> $DIR/as_conversions.rs:13:13
    |
 LL |     let j = &i as *const u64 as *mut u64;
    |             ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs b/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs
index 0d1d9258433..7d71947e428 100644
--- a/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs
+++ b/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs
@@ -1,6 +1,6 @@
 #![allow(unused)]
 #![warn(clippy::as_ptr_cast_mut)]
-#![allow(clippy::wrong_self_convention)]
+#![allow(clippy::wrong_self_convention, clippy::unnecessary_cast)]
 
 struct MutPtrWrapper(Vec<u8>);
 impl MutPtrWrapper {
diff --git a/src/tools/clippy/tests/ui/asm_syntax.rs b/src/tools/clippy/tests/ui/asm_syntax.rs
index c93995f939a..af02e202b17 100644
--- a/src/tools/clippy/tests/ui/asm_syntax.rs
+++ b/src/tools/clippy/tests/ui/asm_syntax.rs
@@ -1,5 +1,5 @@
-//@only-x86_64
-//@ignore-aarch64
+//@only-target-x86_64
+//@ignore-target-aarch64
 
 #[warn(clippy::inline_asm_x86_intel_syntax)]
 mod warn_intel {
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.fixed b/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
index ea8b895664c..3152bd3cae1 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::assertions_on_result_states)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 use std::result::Result;
 
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.rs b/src/tools/clippy/tests/ui/assertions_on_result_states.rs
index 6fc20f85988..42755e935aa 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.rs
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::assertions_on_result_states)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 use std::result::Result;
 
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.stderr b/src/tools/clippy/tests/ui/assertions_on_result_states.stderr
index 298d63c9c34..be581030cb6 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.stderr
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.stderr
@@ -1,5 +1,5 @@
 error: called `assert!` with `Result::is_ok`
-  --> $DIR/assertions_on_result_states.rs:24:5
+  --> $DIR/assertions_on_result_states.rs:25:5
    |
 LL |     assert!(r.is_ok());
    |     ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
@@ -7,37 +7,37 @@ LL |     assert!(r.is_ok());
    = note: `-D clippy::assertions-on-result-states` implied by `-D warnings`
 
 error: called `assert!` with `Result::is_ok`
-  --> $DIR/assertions_on_result_states.rs:42:5
+  --> $DIR/assertions_on_result_states.rs:43:5
    |
 LL |     assert!(get_ok().is_ok());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()`
 
 error: called `assert!` with `Result::is_ok`
-  --> $DIR/assertions_on_result_states.rs:45:5
+  --> $DIR/assertions_on_result_states.rs:46:5
    |
 LL |     assert!(get_ok_macro!().is_ok());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()`
 
 error: called `assert!` with `Result::is_ok`
-  --> $DIR/assertions_on_result_states.rs:58:5
+  --> $DIR/assertions_on_result_states.rs:59:5
    |
 LL |     assert!(r.is_ok());
    |     ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
 
 error: called `assert!` with `Result::is_ok`
-  --> $DIR/assertions_on_result_states.rs:64:9
+  --> $DIR/assertions_on_result_states.rs:65:9
    |
 LL |         assert!(r.is_ok());
    |         ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
 
 error: called `assert!` with `Result::is_err`
-  --> $DIR/assertions_on_result_states.rs:72:5
+  --> $DIR/assertions_on_result_states.rs:73:5
    |
 LL |     assert!(r.is_err());
    |     ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
 
 error: called `assert!` with `Result::is_err`
-  --> $DIR/assertions_on_result_states.rs:82:5
+  --> $DIR/assertions_on_result_states.rs:83:5
    |
 LL |     assert!(res.is_err())
    |     ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();`
diff --git a/src/tools/clippy/tests/ui/assign_ops.fixed b/src/tools/clippy/tests/ui/assign_ops.fixed
index b50682ea00c..ef45e97d1de 100644
--- a/src/tools/clippy/tests/ui/assign_ops.fixed
+++ b/src/tools/clippy/tests/ui/assign_ops.fixed
@@ -2,7 +2,7 @@
 
 use core::num::Wrapping;
 
-#[allow(dead_code, unused_assignments)]
+#[allow(dead_code, unused_assignments, clippy::useless_vec)]
 #[warn(clippy::assign_op_pattern)]
 fn main() {
     let mut a = 5;
diff --git a/src/tools/clippy/tests/ui/assign_ops.rs b/src/tools/clippy/tests/ui/assign_ops.rs
index 780d2d040f1..ae87afc485e 100644
--- a/src/tools/clippy/tests/ui/assign_ops.rs
+++ b/src/tools/clippy/tests/ui/assign_ops.rs
@@ -2,7 +2,7 @@
 
 use core::num::Wrapping;
 
-#[allow(dead_code, unused_assignments)]
+#[allow(dead_code, unused_assignments, clippy::useless_vec)]
 #[warn(clippy::assign_op_pattern)]
 fn main() {
     let mut a = 5;
diff --git a/src/tools/clippy/tests/ui/auxiliary/extern_fake_libc.rs b/src/tools/clippy/tests/ui/auxiliary/extern_fake_libc.rs
new file mode 100644
index 00000000000..eb5a5d2b836
--- /dev/null
+++ b/src/tools/clippy/tests/ui/auxiliary/extern_fake_libc.rs
@@ -0,0 +1,10 @@
+#![allow(nonstandard_style)]
+#![allow(clippy::missing_safety_doc, unused)]
+
+type pid_t = i32;
+pub unsafe fn getpid() -> pid_t {
+    pid_t::from(0)
+}
+pub fn getpid_SAFE_TRUTH() -> pid_t {
+    unsafe { getpid() }
+}
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index e5bb906663c..6b164967a28 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -1,7 +1,6 @@
 #![allow(dead_code)]
 
 //! Used to test that certain lints don't trigger in imported external macros
-
 #[macro_export]
 macro_rules! try_err {
     () => {
@@ -44,3 +43,10 @@ macro_rules! issue_10421 {
         b = a;
     };
 }
+
+#[macro_export]
+macro_rules! macro_with_panic {
+    () => {
+        panic!()
+    };
+}
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs b/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs
index 7ed8a28dbd9..cab216b51ac 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_use_helper.rs
@@ -1,3 +1,5 @@
+//@aux-build:macro_rules.rs
+
 extern crate macro_rules;
 
 // STMT
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index d164dd0e545..fdfe5fc4181 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -1,7 +1,3 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
 #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
 #![allow(incomplete_features)]
 #![allow(clippy::useless_conversion, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index 5a924ca1830..37f0ec2b37d 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -1,7 +1,3 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
 #![feature(repr128, proc_macro_quote)]
 #![allow(incomplete_features)]
 #![allow(clippy::field_reassign_with_default)]
@@ -90,70 +86,58 @@ pub fn extra_lifetime(_input: TokenStream) -> TokenStream {
 #[allow(unused)]
 #[proc_macro_derive(ArithmeticDerive)]
 pub fn arithmetic_derive(_: TokenStream) -> TokenStream {
-    <TokenStream as FromIterator<TokenTree>>::from_iter(
-        [
-            Ident::new("fn", Span::call_site()).into(),
-            Ident::new("_foo", Span::call_site()).into(),
-            Group::new(Delimiter::Parenthesis, TokenStream::new()).into(),
-            Group::new(
-                Delimiter::Brace,
-                <TokenStream as FromIterator<TokenTree>>::from_iter(
-                    [
-                        Ident::new("let", Span::call_site()).into(),
-                        Ident::new("mut", Span::call_site()).into(),
-                        Ident::new("_n", Span::call_site()).into(),
-                        Punct::new('=', Spacing::Alone).into(),
-                        Literal::i32_unsuffixed(9).into(),
-                        Punct::new(';', Spacing::Alone).into(),
-                        Ident::new("_n", Span::call_site()).into(),
-                        Punct::new('=', Spacing::Alone).into(),
-                        Literal::i32_unsuffixed(9).into(),
-                        Punct::new('/', Spacing::Alone).into(),
-                        Literal::i32_unsuffixed(2).into(),
-                        Punct::new(';', Spacing::Alone).into(),
-                        Ident::new("_n", Span::call_site()).into(),
-                        Punct::new('=', Spacing::Alone).into(),
-                        Punct::new('-', Spacing::Alone).into(),
-                        Ident::new("_n", Span::call_site()).into(),
-                        Punct::new(';', Spacing::Alone).into(),
-                    ]
-                    .into_iter(),
-                ),
-            )
-            .into(),
-        ]
-        .into_iter(),
-    )
+    <TokenStream as FromIterator<TokenTree>>::from_iter([
+        Ident::new("fn", Span::call_site()).into(),
+        Ident::new("_foo", Span::call_site()).into(),
+        Group::new(Delimiter::Parenthesis, TokenStream::new()).into(),
+        Group::new(
+            Delimiter::Brace,
+            <TokenStream as FromIterator<TokenTree>>::from_iter([
+                Ident::new("let", Span::call_site()).into(),
+                Ident::new("mut", Span::call_site()).into(),
+                Ident::new("_n", Span::call_site()).into(),
+                Punct::new('=', Spacing::Alone).into(),
+                Literal::i32_unsuffixed(9).into(),
+                Punct::new(';', Spacing::Alone).into(),
+                Ident::new("_n", Span::call_site()).into(),
+                Punct::new('=', Spacing::Alone).into(),
+                Literal::i32_unsuffixed(9).into(),
+                Punct::new('/', Spacing::Alone).into(),
+                Literal::i32_unsuffixed(2).into(),
+                Punct::new(';', Spacing::Alone).into(),
+                Ident::new("_n", Span::call_site()).into(),
+                Punct::new('=', Spacing::Alone).into(),
+                Punct::new('-', Spacing::Alone).into(),
+                Ident::new("_n", Span::call_site()).into(),
+                Punct::new(';', Spacing::Alone).into(),
+            ]),
+        )
+        .into(),
+    ])
 }
 
 #[allow(unused)]
 #[proc_macro_derive(ShadowDerive)]
 pub fn shadow_derive(_: TokenStream) -> TokenStream {
-    <TokenStream as FromIterator<TokenTree>>::from_iter(
-        [
-            Ident::new("fn", Span::call_site()).into(),
-            Ident::new("_foo", Span::call_site()).into(),
-            Group::new(Delimiter::Parenthesis, TokenStream::new()).into(),
-            Group::new(
-                Delimiter::Brace,
-                <TokenStream as FromIterator<TokenTree>>::from_iter(
-                    [
-                        Ident::new("let", Span::call_site()).into(),
-                        Ident::new("_x", Span::call_site()).into(),
-                        Punct::new('=', Spacing::Alone).into(),
-                        Literal::i32_unsuffixed(2).into(),
-                        Punct::new(';', Spacing::Alone).into(),
-                        Ident::new("let", Span::call_site()).into(),
-                        Ident::new("_x", Span::call_site()).into(),
-                        Punct::new('=', Spacing::Alone).into(),
-                        Ident::new("_x", Span::call_site()).into(),
-                        Punct::new(';', Spacing::Alone).into(),
-                    ]
-                    .into_iter(),
-                ),
-            )
-            .into(),
-        ]
-        .into_iter(),
-    )
+    <TokenStream as FromIterator<TokenTree>>::from_iter([
+        Ident::new("fn", Span::call_site()).into(),
+        Ident::new("_foo", Span::call_site()).into(),
+        Group::new(Delimiter::Parenthesis, TokenStream::new()).into(),
+        Group::new(
+            Delimiter::Brace,
+            <TokenStream as FromIterator<TokenTree>>::from_iter([
+                Ident::new("let", Span::call_site()).into(),
+                Ident::new("_x", Span::call_site()).into(),
+                Punct::new('=', Spacing::Alone).into(),
+                Literal::i32_unsuffixed(2).into(),
+                Punct::new(';', Spacing::Alone).into(),
+                Ident::new("let", Span::call_site()).into(),
+                Ident::new("_x", Span::call_site()).into(),
+                Punct::new('=', Spacing::Alone).into(),
+                Ident::new("_x", Span::call_site()).into(),
+                Punct::new(';', Spacing::Alone).into(),
+            ]),
+        )
+        .into(),
+    ])
 }
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
index f13b76e44b0..79e8eff3aa1 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
@@ -1,8 +1,3 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
 extern crate proc_macro;
 use proc_macro::{token_stream, Delimiter, Group, Ident, Span, TokenStream, TokenTree};
 
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs
index c2326678d0d..1c591fc76f3 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_unsafe.rs
@@ -1,8 +1,3 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
 extern crate proc_macro;
 
 use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree};
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
index 94f075ed09c..4d008c8cb59 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
@@ -1,10 +1,6 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
 #![feature(let_chains)]
 #![feature(proc_macro_span)]
-#![allow(dead_code)]
+#![allow(clippy::needless_if, dead_code)]
 
 extern crate proc_macro;
 
diff --git a/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed
index a9f18782e58..2a3867ac8fc 100644
--- a/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_if_conditions.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::blocks_in_if_conditions)]
-#![allow(unused, clippy::let_and_return)]
+#![allow(unused, clippy::let_and_return, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
 macro_rules! blocky {
diff --git a/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs
index 0a70317c4d4..704d09fbad3 100644
--- a/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_if_conditions.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::blocks_in_if_conditions)]
-#![allow(unused, clippy::let_and_return)]
+#![allow(unused, clippy::let_and_return, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
 macro_rules! blocky {
diff --git a/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.rs b/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.rs
index 169589f6d4e..d6d085d7fd1 100644
--- a/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::blocks_in_if_conditions)]
-#![allow(unused, clippy::let_and_return)]
+#![allow(
+    unused,
+    clippy::let_and_return,
+    clippy::needless_if,
+    clippy::unnecessary_literal_unwrap
+)]
 
 fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val: T) -> bool {
     pfn(val)
diff --git a/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.stderr b/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.stderr
index 941d604dd5f..5ac02e7504e 100644
--- a/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.stderr
+++ b/src/tools/clippy/tests/ui/blocks_in_if_conditions_closure.stderr
@@ -1,5 +1,5 @@
 error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> $DIR/blocks_in_if_conditions_closure.rs:18:17
+  --> $DIR/blocks_in_if_conditions_closure.rs:23:17
    |
 LL |               |x| {
    |  _________________^
@@ -11,7 +11,7 @@ LL | |             },
    = note: `-D clippy::blocks-in-if-conditions` implied by `-D warnings`
 
 error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> $DIR/blocks_in_if_conditions_closure.rs:27:13
+  --> $DIR/blocks_in_if_conditions_closure.rs:32:13
    |
 LL |           |x| {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/bool_comparison.fixed b/src/tools/clippy/tests/ui/bool_comparison.fixed
index 670eef6a21d..d6774c03598 100644
--- a/src/tools/clippy/tests/ui/bool_comparison.fixed
+++ b/src/tools/clippy/tests/ui/bool_comparison.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 
+#![allow(clippy::needless_if)]
 #![warn(clippy::bool_comparison)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/bool_comparison.rs b/src/tools/clippy/tests/ui/bool_comparison.rs
index 72851be635d..c0483fd7374 100644
--- a/src/tools/clippy/tests/ui/bool_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_comparison.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 
+#![allow(clippy::needless_if)]
 #![warn(clippy::bool_comparison)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/bool_comparison.stderr b/src/tools/clippy/tests/ui/bool_comparison.stderr
index 31522d4a525..f4dded365fb 100644
--- a/src/tools/clippy/tests/ui/bool_comparison.stderr
+++ b/src/tools/clippy/tests/ui/bool_comparison.stderr
@@ -1,5 +1,5 @@
 error: equality checks against true are unnecessary
-  --> $DIR/bool_comparison.rs:7:8
+  --> $DIR/bool_comparison.rs:8:8
    |
 LL |     if x == true {
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -7,127 +7,127 @@ LL |     if x == true {
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/bool_comparison.rs:12:8
+  --> $DIR/bool_comparison.rs:13:8
    |
 LL |     if x == false {
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/bool_comparison.rs:17:8
+  --> $DIR/bool_comparison.rs:18:8
    |
 LL |     if true == x {
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/bool_comparison.rs:22:8
+  --> $DIR/bool_comparison.rs:23:8
    |
 LL |     if false == x {
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: inequality checks against true can be replaced by a negation
-  --> $DIR/bool_comparison.rs:27:8
+  --> $DIR/bool_comparison.rs:28:8
    |
 LL |     if x != true {
    |        ^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: inequality checks against false are unnecessary
-  --> $DIR/bool_comparison.rs:32:8
+  --> $DIR/bool_comparison.rs:33:8
    |
 LL |     if x != false {
    |        ^^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: inequality checks against true can be replaced by a negation
-  --> $DIR/bool_comparison.rs:37:8
+  --> $DIR/bool_comparison.rs:38:8
    |
 LL |     if true != x {
    |        ^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: inequality checks against false are unnecessary
-  --> $DIR/bool_comparison.rs:42:8
+  --> $DIR/bool_comparison.rs:43:8
    |
 LL |     if false != x {
    |        ^^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: less than comparison against true can be replaced by a negation
-  --> $DIR/bool_comparison.rs:47:8
+  --> $DIR/bool_comparison.rs:48:8
    |
 LL |     if x < true {
    |        ^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: greater than checks against false are unnecessary
-  --> $DIR/bool_comparison.rs:52:8
+  --> $DIR/bool_comparison.rs:53:8
    |
 LL |     if false < x {
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: greater than checks against false are unnecessary
-  --> $DIR/bool_comparison.rs:57:8
+  --> $DIR/bool_comparison.rs:58:8
    |
 LL |     if x > false {
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: less than comparison against true can be replaced by a negation
-  --> $DIR/bool_comparison.rs:62:8
+  --> $DIR/bool_comparison.rs:63:8
    |
 LL |     if true > x {
    |        ^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: order comparisons between booleans can be simplified
-  --> $DIR/bool_comparison.rs:68:8
+  --> $DIR/bool_comparison.rs:69:8
    |
 LL |     if x < y {
    |        ^^^^^ help: try simplifying it as shown: `!x & y`
 
 error: order comparisons between booleans can be simplified
-  --> $DIR/bool_comparison.rs:73:8
+  --> $DIR/bool_comparison.rs:74:8
    |
 LL |     if x > y {
    |        ^^^^^ help: try simplifying it as shown: `x & !y`
 
 error: this comparison might be written more concisely
-  --> $DIR/bool_comparison.rs:121:8
+  --> $DIR/bool_comparison.rs:122:8
    |
 LL |     if a == !b {};
    |        ^^^^^^^ help: try simplifying it as shown: `a != b`
 
 error: this comparison might be written more concisely
-  --> $DIR/bool_comparison.rs:122:8
+  --> $DIR/bool_comparison.rs:123:8
    |
 LL |     if !a == b {};
    |        ^^^^^^^ help: try simplifying it as shown: `a != b`
 
 error: this comparison might be written more concisely
-  --> $DIR/bool_comparison.rs:126:8
+  --> $DIR/bool_comparison.rs:127:8
    |
 LL |     if b == !a {};
    |        ^^^^^^^ help: try simplifying it as shown: `b != a`
 
 error: this comparison might be written more concisely
-  --> $DIR/bool_comparison.rs:127:8
+  --> $DIR/bool_comparison.rs:128:8
    |
 LL |     if !b == a {};
    |        ^^^^^^^ help: try simplifying it as shown: `b != a`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/bool_comparison.rs:151:8
+  --> $DIR/bool_comparison.rs:152:8
    |
 LL |     if false == m!(func) {}
    |        ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/bool_comparison.rs:152:8
+  --> $DIR/bool_comparison.rs:153:8
    |
 LL |     if m!(func) == false {}
    |        ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/bool_comparison.rs:153:8
+  --> $DIR/bool_comparison.rs:154:8
    |
 LL |     if true == m!(func) {}
    |        ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/bool_comparison.rs:154:8
+  --> $DIR/bool_comparison.rs:155:8
    |
 LL |     if m!(func) == true {}
    |        ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)`
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
index 3f440ce0045..996cc3650ff 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed
@@ -1,9 +1,18 @@
 //@run-rustfix
 #![warn(clippy::borrow_as_ptr)]
+#![allow(clippy::useless_vec)]
+
+fn a() -> i32 {
+    0
+}
 
 fn main() {
     let val = 1;
     let _p = std::ptr::addr_of!(val);
+    let _p = &0 as *const i32;
+    let _p = &a() as *const i32;
+    let vec = vec![1];
+    let _p = &vec.len() as *const usize;
 
     let mut val_mut = 1;
     let _p_mut = std::ptr::addr_of_mut!(val_mut);
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.rs b/src/tools/clippy/tests/ui/borrow_as_ptr.rs
index c1ca9180eef..5eafaeb2fc3 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.rs
@@ -1,9 +1,18 @@
 //@run-rustfix
 #![warn(clippy::borrow_as_ptr)]
+#![allow(clippy::useless_vec)]
+
+fn a() -> i32 {
+    0
+}
 
 fn main() {
     let val = 1;
     let _p = &val as *const i32;
+    let _p = &0 as *const i32;
+    let _p = &a() as *const i32;
+    let vec = vec![1];
+    let _p = &vec.len() as *const usize;
 
     let mut val_mut = 1;
     let _p_mut = &mut val_mut as *mut i32;
diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.stderr b/src/tools/clippy/tests/ui/borrow_as_ptr.stderr
index be1ed733056..c9990bb6f22 100644
--- a/src/tools/clippy/tests/ui/borrow_as_ptr.stderr
+++ b/src/tools/clippy/tests/ui/borrow_as_ptr.stderr
@@ -1,5 +1,5 @@
 error: borrow as raw pointer
-  --> $DIR/borrow_as_ptr.rs:6:14
+  --> $DIR/borrow_as_ptr.rs:11:14
    |
 LL |     let _p = &val as *const i32;
    |              ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)`
@@ -7,7 +7,7 @@ LL |     let _p = &val as *const i32;
    = note: `-D clippy::borrow-as-ptr` implied by `-D warnings`
 
 error: borrow as raw pointer
-  --> $DIR/borrow_as_ptr.rs:9:18
+  --> $DIR/borrow_as_ptr.rs:18:18
    |
 LL |     let _p_mut = &mut val_mut as *mut i32;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)`
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
index 75526461792..b951ba04c37 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
index e319d365f7e..52980e55fbe 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
index 29b08ab3643..da940a4cfb5 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.rs
@@ -1,6 +1,6 @@
 //@aux-build:helper.rs
 
-#![warn(clippy::borrow_interior_mutable_const)]
+#![deny(clippy::borrow_interior_mutable_const)]
 #![allow(clippy::declare_interior_mutable_const)]
 
 // this file (mostly) replicates its `declare` counterpart. Please see it for more discussions.
@@ -19,7 +19,7 @@ const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
 const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
 
 fn borrow_optional_cell() {
-    let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
+    let _ = &UNFROZEN_VARIANT; //~ ERROR: interior mutability
     let _ = &FROZEN_VARIANT;
 }
 
@@ -34,11 +34,11 @@ trait AssocConsts {
         // This is the "suboptimal behavior" mentioned in `is_value_unfrozen`
         // caused by a similar reason to unfrozen types without any default values
         // get linted even if it has frozen variants'.
-        let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR: interior mutability
 
         // The lint ignores default values because an impl of this trait can set
         // an unfrozen variant to `DEFAULTED_ON_FROZEN_VARIANT` and use the default impl for `function`.
-        let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR: interior mutability
     }
 }
 
@@ -47,9 +47,9 @@ impl AssocConsts for u64 {
     const TO_BE_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
 
     fn function() {
-        let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability
         let _ = &<Self as AssocConsts>::TO_BE_FROZEN_VARIANT;
-        let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR: interior mutability
         let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT;
     }
 }
@@ -67,11 +67,11 @@ trait AssocTypes {
 impl AssocTypes for u64 {
     type ToBeUnfrozen = AtomicUsize;
 
-    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
+    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4));
     const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
 
     fn function() {
-        let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+        let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR: interior mutability
         let _ = &<Self as AssocTypes>::TO_BE_FROZEN_VARIANT;
     }
 }
@@ -83,19 +83,19 @@ enum BothOfCellAndGeneric<T> {
 }
 
 impl<T> BothOfCellAndGeneric<T> {
-    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
-    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
+    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null());
     const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);
 
     fn function() {
-        let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
-        let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
+        let _ = &Self::UNFROZEN_VARIANT; //~ ERROR: interior mutability
+        let _ = &Self::GENERIC_VARIANT; //~ ERROR: interior mutability
         let _ = &Self::FROZEN_VARIANT;
     }
 }
 
 fn main() {
     // constants defined in foreign crates
-    let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability
+    let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR: interior mutability
     let _ = &helper::WRAPPED_PRIVATE_FROZEN_VARIANT;
 }
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
index b0cab977a03..b753ec92608 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
@@ -1,16 +1,20 @@
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:22:14
    |
-LL |     let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
+LL |     let _ = &UNFROZEN_VARIANT;
    |              ^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
-   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+note: the lint level is defined here
+  --> $DIR/enums.rs:3:9
+   |
+LL | #![deny(clippy::borrow_interior_mutable_const)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:37:18
    |
-LL |         let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable
+LL |         let _ = &Self::TO_BE_FROZEN_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -18,7 +22,7 @@ LL |         let _ = &Self::TO_BE_FROZEN_VARIANT; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:41:18
    |
-LL |         let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior mutable
+LL |         let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -26,7 +30,7 @@ LL |         let _ = &Self::DEFAULTED_ON_FROZEN_VARIANT; //~ ERROR interior muta
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:50:18
    |
-LL |         let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+LL |         let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -34,7 +38,7 @@ LL |         let _ = &<Self as AssocConsts>::TO_BE_UNFROZEN_VARIANT; //~ ERROR i
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:52:18
    |
-LL |         let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mutable
+LL |         let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -42,7 +46,7 @@ LL |         let _ = &Self::DEFAULTED_ON_UNFROZEN_VARIANT; //~ ERROR interior mu
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:74:18
    |
-LL |         let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR interior mutable
+LL |         let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -50,7 +54,7 @@ LL |         let _ = &<Self as AssocTypes>::TO_BE_UNFROZEN_VARIANT; //~ ERROR in
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:91:18
    |
-LL |         let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
+LL |         let _ = &Self::UNFROZEN_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -58,7 +62,7 @@ LL |         let _ = &Self::UNFROZEN_VARIANT; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:92:18
    |
-LL |         let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
+LL |         let _ = &Self::GENERIC_VARIANT;
    |                  ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -66,7 +70,7 @@ LL |         let _ = &Self::GENERIC_VARIANT; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/enums.rs:99:14
    |
-LL |     let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT; //~ ERROR interior mutability
+LL |     let _ = &helper::WRAPPED_PRIVATE_UNFROZEN_VARIANT;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
index 7c57864245a..0ea93dd8462 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::borrow_interior_mutable_const)]
+#![deny(clippy::borrow_interior_mutable_const)]
 #![allow(clippy::declare_interior_mutable_const, clippy::needless_borrow)]
 #![allow(const_item_mutation)]
 
@@ -51,14 +51,14 @@ impl<T> std::ops::Deref for StaticRef<T> {
 const CELL_REF: StaticRef<(UnsafeCell<u32>,)> = unsafe { StaticRef::new(std::ptr::null()) };
 
 fn main() {
-    ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
-    assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
+    ATOMIC.store(1, Ordering::SeqCst); //~ ERROR: interior mutability
+    assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR: interior mutability
 
     let _once = ONCE_INIT;
-    let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
-    let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
-    let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
-    let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
+    let _once_ref = &ONCE_INIT; //~ ERROR: interior mutability
+    let _once_ref_2 = &&ONCE_INIT; //~ ERROR: interior mutability
+    let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR: interior mutability
+    let _once_mut = &mut ONCE_INIT; //~ ERROR: interior mutability
     let _atomic_into_inner = ATOMIC.into_inner();
     // these should be all fine.
     let _twice = (ONCE_INIT, ONCE_INIT);
@@ -69,23 +69,23 @@ fn main() {
     let _ref_array_once = &[ONCE_INIT, ONCE_INIT][0];
 
     // referencing projection is still bad.
-    let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
-    let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
-    let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
-    let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
-    let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
+    let _ = &ATOMIC_TUPLE; //~ ERROR: interior mutability
+    let _ = &ATOMIC_TUPLE.0; //~ ERROR: interior mutability
+    let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR: interior mutability
+    let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability
+    let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR: interior mutability
     let _ = &*ATOMIC_TUPLE.1;
     let _ = &ATOMIC_TUPLE.2;
     let _ = (&&&&ATOMIC_TUPLE).0;
     let _ = (&&&&ATOMIC_TUPLE).2;
     let _ = ATOMIC_TUPLE.0;
-    let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+    let _ = ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability
     let _ = ATOMIC_TUPLE.1.into_iter();
     let _ = ATOMIC_TUPLE.2;
     let _ = &{ ATOMIC_TUPLE };
 
-    CELL.set(2); //~ ERROR interior mutability
-    assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
+    CELL.set(2); //~ ERROR: interior mutability
+    assert_eq!(CELL.get(), 6); //~ ERROR: interior mutability
 
     assert_eq!(INTEGER, 8);
     assert!(STRING.is_empty());
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
index c87ad206c2a..200e04b8f6b 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
@@ -1,16 +1,20 @@
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:54:5
    |
-LL |     ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
+LL |     ATOMIC.store(1, Ordering::SeqCst);
    |     ^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
-   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+note: the lint level is defined here
+  --> $DIR/others.rs:1:9
+   |
+LL | #![deny(clippy::borrow_interior_mutable_const)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:55:16
    |
-LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutability
+LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5);
    |                ^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -18,7 +22,7 @@ LL |     assert_eq!(ATOMIC.load(Ordering::SeqCst), 5); //~ ERROR interior mutabi
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:58:22
    |
-LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
+LL |     let _once_ref = &ONCE_INIT;
    |                      ^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -26,7 +30,7 @@ LL |     let _once_ref = &ONCE_INIT; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:59:25
    |
-LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
+LL |     let _once_ref_2 = &&ONCE_INIT;
    |                         ^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -34,7 +38,7 @@ LL |     let _once_ref_2 = &&ONCE_INIT; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:60:27
    |
-LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
+LL |     let _once_ref_4 = &&&&ONCE_INIT;
    |                           ^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -42,7 +46,7 @@ LL |     let _once_ref_4 = &&&&ONCE_INIT; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:61:26
    |
-LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
+LL |     let _once_mut = &mut ONCE_INIT;
    |                          ^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -50,7 +54,7 @@ LL |     let _once_mut = &mut ONCE_INIT; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:72:14
    |
-LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
+LL |     let _ = &ATOMIC_TUPLE;
    |              ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -58,7 +62,7 @@ LL |     let _ = &ATOMIC_TUPLE; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:73:14
    |
-LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
+LL |     let _ = &ATOMIC_TUPLE.0;
    |              ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -66,7 +70,7 @@ LL |     let _ = &ATOMIC_TUPLE.0; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:74:19
    |
-LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
+LL |     let _ = &(&&&&ATOMIC_TUPLE).0;
    |                   ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -74,7 +78,7 @@ LL |     let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:75:14
    |
-LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+LL |     let _ = &ATOMIC_TUPLE.0[0];
    |              ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -82,7 +86,7 @@ LL |     let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:76:13
    |
-LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mutability
+LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst);
    |             ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -90,7 +94,7 @@ LL |     let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR interior mu
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:82:13
    |
-LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
+LL |     let _ = ATOMIC_TUPLE.0[0];
    |             ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -98,7 +102,7 @@ LL |     let _ = ATOMIC_TUPLE.0[0]; //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:87:5
    |
-LL |     CELL.set(2); //~ ERROR interior mutability
+LL |     CELL.set(2);
    |     ^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -106,7 +110,7 @@ LL |     CELL.set(2); //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/others.rs:88:16
    |
-LL |     assert_eq!(CELL.get(), 6); //~ ERROR interior mutability
+LL |     assert_eq!(CELL.get(), 6);
    |                ^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
index 06b5d62e8f9..4da3833cbf5 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::borrow_interior_mutable_const)]
+#![deny(clippy::borrow_interior_mutable_const)]
 #![allow(clippy::declare_interior_mutable_const)]
 
 // this file replicates its `declare` counterpart. Please see it for more discussions.
@@ -12,7 +12,7 @@ trait ConcreteTypes {
     const STRING: String;
 
     fn function() {
-        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::ATOMIC; //~ ERROR: interior mutability
         let _ = &Self::STRING;
     }
 }
@@ -23,7 +23,7 @@ impl ConcreteTypes for u64 {
 
     fn function() {
         // Lint this again since implementers can choose not to borrow it.
-        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::ATOMIC; //~ ERROR: interior mutability
         let _ = &Self::STRING;
     }
 }
@@ -48,7 +48,7 @@ impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for Vec<T> {
 
     fn function() {
         let _ = &Self::TO_REMAIN_GENERIC;
-        let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
+        let _ = &Self::TO_BE_CONCRETE; //~ ERROR: interior mutability
     }
 }
 
@@ -83,8 +83,8 @@ impl<T: ConstDefault> AssocTypes for Vec<T> {
 
     fn function() {
         let _ = &Self::TO_BE_FROZEN;
-        let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
-        let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
+        let _ = &Self::TO_BE_UNFROZEN; //~ ERROR: interior mutability
+        let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR: interior mutability
         let _ = &Self::WRAPPED_TO_BE_GENERIC_PARAM;
     }
 }
@@ -106,7 +106,7 @@ where
 
     fn function() {
         let _ = &Self::NOT_BOUNDED;
-        let _ = &Self::BOUNDED; //~ ERROR interior mutable
+        let _ = &Self::BOUNDED; //~ ERROR: interior mutability
     }
 }
 
@@ -119,7 +119,7 @@ where
 
     fn function() {
         let _ = &Self::NOT_BOUNDED;
-        let _ = &Self::BOUNDED; //~ ERROR interior mutable
+        let _ = &Self::BOUNDED; //~ ERROR: interior mutability
     }
 }
 
@@ -148,8 +148,8 @@ impl SelfType for AtomicUsize {
     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
 
     fn function() {
-        let _ = &Self::SELF; //~ ERROR interior mutable
-        let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
+        let _ = &Self::SELF; //~ ERROR: interior mutability
+        let _ = &Self::WRAPPED_SELF; //~ ERROR: interior mutability
     }
 }
 
@@ -159,7 +159,7 @@ trait BothOfCellAndGeneric<T> {
 
     fn function() {
         let _ = &Self::DIRECT;
-        let _ = &Self::INDIRECT; //~ ERROR interior mutable
+        let _ = &Self::INDIRECT; //~ ERROR: interior mutability
     }
 }
 
@@ -169,7 +169,7 @@ impl<T: ConstDefault> BothOfCellAndGeneric<T> for Vec<T> {
 
     fn function() {
         let _ = &Self::DIRECT;
-        let _ = &Self::INDIRECT; //~ ERROR interior mutable
+        let _ = &Self::INDIRECT; //~ ERROR: interior mutability
     }
 }
 
@@ -188,15 +188,15 @@ where
     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
 
     fn function() {
-        let _ = &Self::ATOMIC; //~ ERROR interior mutable
+        let _ = &Self::ATOMIC; //~ ERROR: interior mutability
         let _ = &Self::COW;
         let _ = &Self::GENERIC_TYPE;
         let _ = &Self::ASSOC_TYPE;
-        let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
+        let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR: interior mutability
     }
 }
 
 fn main() {
-    u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
-    assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
+    u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR: interior mutability
+    assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR: interior mutability
 }
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
index f34ae8814c3..add223acd68 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
@@ -1,16 +1,20 @@
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:15:18
    |
-LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
+LL |         let _ = &Self::ATOMIC;
    |                  ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
-   = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
+note: the lint level is defined here
+  --> $DIR/traits.rs:1:9
+   |
+LL | #![deny(clippy::borrow_interior_mutable_const)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:26:18
    |
-LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
+LL |         let _ = &Self::ATOMIC;
    |                  ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -18,7 +22,7 @@ LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:51:18
    |
-LL |         let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
+LL |         let _ = &Self::TO_BE_CONCRETE;
    |                  ^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -26,7 +30,7 @@ LL |         let _ = &Self::TO_BE_CONCRETE; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:86:18
    |
-LL |         let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
+LL |         let _ = &Self::TO_BE_UNFROZEN;
    |                  ^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -34,7 +38,7 @@ LL |         let _ = &Self::TO_BE_UNFROZEN; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:87:18
    |
-LL |         let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
+LL |         let _ = &Self::WRAPPED_TO_BE_UNFROZEN;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -42,7 +46,7 @@ LL |         let _ = &Self::WRAPPED_TO_BE_UNFROZEN; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:109:18
    |
-LL |         let _ = &Self::BOUNDED; //~ ERROR interior mutable
+LL |         let _ = &Self::BOUNDED;
    |                  ^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -50,7 +54,7 @@ LL |         let _ = &Self::BOUNDED; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:122:18
    |
-LL |         let _ = &Self::BOUNDED; //~ ERROR interior mutable
+LL |         let _ = &Self::BOUNDED;
    |                  ^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -58,7 +62,7 @@ LL |         let _ = &Self::BOUNDED; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:151:18
    |
-LL |         let _ = &Self::SELF; //~ ERROR interior mutable
+LL |         let _ = &Self::SELF;
    |                  ^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -66,7 +70,7 @@ LL |         let _ = &Self::SELF; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:152:18
    |
-LL |         let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
+LL |         let _ = &Self::WRAPPED_SELF;
    |                  ^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -74,7 +78,7 @@ LL |         let _ = &Self::WRAPPED_SELF; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:162:18
    |
-LL |         let _ = &Self::INDIRECT; //~ ERROR interior mutable
+LL |         let _ = &Self::INDIRECT;
    |                  ^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -82,7 +86,7 @@ LL |         let _ = &Self::INDIRECT; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:172:18
    |
-LL |         let _ = &Self::INDIRECT; //~ ERROR interior mutable
+LL |         let _ = &Self::INDIRECT;
    |                  ^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -90,7 +94,7 @@ LL |         let _ = &Self::INDIRECT; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:191:18
    |
-LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
+LL |         let _ = &Self::ATOMIC;
    |                  ^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -98,7 +102,7 @@ LL |         let _ = &Self::ATOMIC; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:195:18
    |
-LL |         let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
+LL |         let _ = &Self::BOUNDED_ASSOC_TYPE;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -106,7 +110,7 @@ LL |         let _ = &Self::BOUNDED_ASSOC_TYPE; //~ ERROR interior mutable
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:200:5
    |
-LL |     u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
+LL |     u64::ATOMIC.store(5, Ordering::SeqCst);
    |     ^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
@@ -114,7 +118,7 @@ LL |     u64::ATOMIC.store(5, Ordering::SeqCst); //~ ERROR interior mutability
 error: a `const` item with interior mutability should not be borrowed
   --> $DIR/traits.rs:201:16
    |
-LL |     assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9); //~ ERROR interior mutability
+LL |     assert_eq!(u64::ATOMIC.load(Ordering::SeqCst), 9);
    |                ^^^^^^^^^^^
    |
    = help: assign this const to a local or static variable, and use the variable here
diff --git a/src/tools/clippy/tests/ui/builtin_type_shadow.rs b/src/tools/clippy/tests/ui/builtin_type_shadow.rs
index 69b8b6a0e68..c5addd53434 100644
--- a/src/tools/clippy/tests/ui/builtin_type_shadow.rs
+++ b/src/tools/clippy/tests/ui/builtin_type_shadow.rs
@@ -3,7 +3,7 @@
 
 fn foo<u32>(a: u32) -> u32 {
     42
-    // ^ rustc's type error
+    //~^ ERROR: mismatched types
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/bytecount.rs b/src/tools/clippy/tests/ui/bytecount.rs
index d3ad26921bf..4d168bfeab9 100644
--- a/src/tools/clippy/tests/ui/bytecount.rs
+++ b/src/tools/clippy/tests/ui/bytecount.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::needless_borrow)]
+#![allow(clippy::needless_borrow, clippy::useless_vec)]
 
 #[deny(clippy::naive_bytecount)]
 fn main() {
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index a86b85706a3..60a0eabf55b 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -41,6 +41,14 @@ fn main() {
     1u32 as i32;
     1u64 as i64;
     1usize as isize;
+    1usize as i8; // should not wrap, usize is never 8 bits
+    1usize as i16; // wraps on 16 bit ptr size
+    1usize as i32; // wraps on 32 bit ptr size
+    1usize as i64; // wraps on 64 bit ptr size
+    1u8 as isize; // should not wrap, isize is never 8 bits
+    1u16 as isize; // wraps on 16 bit ptr size
+    1u32 as isize; // wraps on 32 bit ptr size
+    1u64 as isize; // wraps on 64 bit ptr size
     // Test clippy::cast_sign_loss
     1i32 as u32;
     -1i32 as u32;
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 65ecf1aa37a..de29af78ef3 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -215,20 +215,110 @@ error: casting `usize` to `isize` may wrap around the value
 LL |     1usize as isize;
    |     ^^^^^^^^^^^^^^^
 
-error: casting `i32` to `u32` may lose the sign of the value
+error: casting `usize` to `i8` may truncate the value
+  --> $DIR/cast.rs:44:5
+   |
+LL |     1usize as i8; // should not wrap, usize is never 8 bits
+   |     ^^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |     i8::try_from(1usize); // should not wrap, usize is never 8 bits
+   |     ~~~~~~~~~~~~~~~~~~~~
+
+error: casting `usize` to `i16` may truncate the value
+  --> $DIR/cast.rs:45:5
+   |
+LL |     1usize as i16; // wraps on 16 bit ptr size
+   |     ^^^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |     i16::try_from(1usize); // wraps on 16 bit ptr size
+   |     ~~~~~~~~~~~~~~~~~~~~~
+
+error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers
+  --> $DIR/cast.rs:45:5
+   |
+LL |     1usize as i16; // wraps on 16 bit ptr size
+   |     ^^^^^^^^^^^^^
+   |
+   = note: `usize` and `isize` may be as small as 16 bits on some platforms
+   = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
+
+error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
   --> $DIR/cast.rs:46:5
    |
+LL |     1usize as i32; // wraps on 32 bit ptr size
+   |     ^^^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |     i32::try_from(1usize); // wraps on 32 bit ptr size
+   |     ~~~~~~~~~~~~~~~~~~~~~
+
+error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
+  --> $DIR/cast.rs:46:5
+   |
+LL |     1usize as i32; // wraps on 32 bit ptr size
+   |     ^^^^^^^^^^^^^
+
+error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers
+  --> $DIR/cast.rs:47:5
+   |
+LL |     1usize as i64; // wraps on 64 bit ptr size
+   |     ^^^^^^^^^^^^^
+
+error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers
+  --> $DIR/cast.rs:49:5
+   |
+LL |     1u16 as isize; // wraps on 16 bit ptr size
+   |     ^^^^^^^^^^^^^
+   |
+   = note: `usize` and `isize` may be as small as 16 bits on some platforms
+   = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
+
+error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
+  --> $DIR/cast.rs:50:5
+   |
+LL |     1u32 as isize; // wraps on 32 bit ptr size
+   |     ^^^^^^^^^^^^^
+
+error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
+  --> $DIR/cast.rs:51:5
+   |
+LL |     1u64 as isize; // wraps on 64 bit ptr size
+   |     ^^^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |     isize::try_from(1u64); // wraps on 64 bit ptr size
+   |     ~~~~~~~~~~~~~~~~~~~~~
+
+error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
+  --> $DIR/cast.rs:51:5
+   |
+LL |     1u64 as isize; // wraps on 64 bit ptr size
+   |     ^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:54:5
+   |
 LL |     -1i32 as u32;
    |     ^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> $DIR/cast.rs:48:5
+  --> $DIR/cast.rs:56:5
    |
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `i8` may truncate the value
-  --> $DIR/cast.rs:115:5
+  --> $DIR/cast.rs:123:5
    |
 LL |     (-99999999999i64).min(1) as i8; // should be linted because signed
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,7 +330,7 @@ LL |     i8::try_from((-99999999999i64).min(1)); // should be linted because sig
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `u8` may truncate the value
-  --> $DIR/cast.rs:127:5
+  --> $DIR/cast.rs:135:5
    |
 LL |     999999u64.clamp(0, 256) as u8; // should still be linted
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -252,7 +342,7 @@ LL |     u8::try_from(999999u64.clamp(0, 256)); // should still be linted
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2` to `u8` may truncate the value
-  --> $DIR/cast.rs:148:21
+  --> $DIR/cast.rs:156:21
    |
 LL |             let _ = self as u8;
    |                     ^^^^^^^^^^
@@ -264,7 +354,7 @@ LL |             let _ = u8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2::B` to `u8` will truncate the value
-  --> $DIR/cast.rs:149:21
+  --> $DIR/cast.rs:157:21
    |
 LL |             let _ = Self::B as u8;
    |                     ^^^^^^^^^^^^^
@@ -272,7 +362,7 @@ LL |             let _ = Self::B as u8;
    = note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
 
 error: casting `main::E5` to `i8` may truncate the value
-  --> $DIR/cast.rs:185:21
+  --> $DIR/cast.rs:193:21
    |
 LL |             let _ = self as i8;
    |                     ^^^^^^^^^^
@@ -284,13 +374,13 @@ LL |             let _ = i8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E5::A` to `i8` will truncate the value
-  --> $DIR/cast.rs:186:21
+  --> $DIR/cast.rs:194:21
    |
 LL |             let _ = Self::A as i8;
    |                     ^^^^^^^^^^^^^
 
 error: casting `main::E6` to `i16` may truncate the value
-  --> $DIR/cast.rs:200:21
+  --> $DIR/cast.rs:208:21
    |
 LL |             let _ = self as i16;
    |                     ^^^^^^^^^^^
@@ -302,7 +392,7 @@ LL |             let _ = i16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast.rs:215:21
+  --> $DIR/cast.rs:223:21
    |
 LL |             let _ = self as usize;
    |                     ^^^^^^^^^^^^^
@@ -314,7 +404,7 @@ LL |             let _ = usize::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E10` to `u16` may truncate the value
-  --> $DIR/cast.rs:256:21
+  --> $DIR/cast.rs:264:21
    |
 LL |             let _ = self as u16;
    |                     ^^^^^^^^^^^
@@ -326,7 +416,7 @@ LL |             let _ = u16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> $DIR/cast.rs:264:13
+  --> $DIR/cast.rs:272:13
    |
 LL |     let c = (q >> 16) as u8;
    |             ^^^^^^^^^^^^^^^
@@ -338,7 +428,7 @@ LL |     let c = u8::try_from(q >> 16);
    |             ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> $DIR/cast.rs:267:13
+  --> $DIR/cast.rs:275:13
    |
 LL |     let c = (q / 1000) as u8;
    |             ^^^^^^^^^^^^^^^^
@@ -349,5 +439,5 @@ help: ... or use `try_from` and handle the error accordingly
 LL |     let c = u8::try_from(q / 1000);
    |             ~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 41 previous errors
+error: aborting due to 51 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs b/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs
index b77f01883bf..27e03ebb719 100644
--- a/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/tests/ui/cast_slice_different_sizes.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::let_unit_value)]
+#![allow(clippy::let_unit_value, clippy::unnecessary_cast)]
 
 fn main() {
     let x: [i32; 3] = [1_i32, 2, 3];
diff --git a/src/tools/clippy/tests/ui/cfg_features.rs b/src/tools/clippy/tests/ui/cfg_features.rs
new file mode 100644
index 00000000000..bc4109c2c89
--- /dev/null
+++ b/src/tools/clippy/tests/ui/cfg_features.rs
@@ -0,0 +1,12 @@
+#![warn(clippy::maybe_misused_cfg)]
+
+fn main() {
+    #[cfg(features = "not-really-a-feature")]
+    let _ = 1 + 2;
+
+    #[cfg(all(feature = "right", features = "wrong"))]
+    let _ = 1 + 2;
+
+    #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))]
+    let _ = 1 + 2;
+}
diff --git a/src/tools/clippy/tests/ui/cfg_features.stderr b/src/tools/clippy/tests/ui/cfg_features.stderr
new file mode 100644
index 00000000000..00405985d48
--- /dev/null
+++ b/src/tools/clippy/tests/ui/cfg_features.stderr
@@ -0,0 +1,28 @@
+error: feature may misspelled as features
+  --> $DIR/cfg_features.rs:4:11
+   |
+LL |     #[cfg(features = "not-really-a-feature")]
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `feature = "not-really-a-feature"`
+   |
+   = note: `-D clippy::maybe-misused-cfg` implied by `-D warnings`
+
+error: feature may misspelled as features
+  --> $DIR/cfg_features.rs:7:34
+   |
+LL |     #[cfg(all(feature = "right", features = "wrong"))]
+   |                                  ^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong"`
+
+error: feature may misspelled as features
+  --> $DIR/cfg_features.rs:10:15
+   |
+LL |     #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))]
+   |               ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong1"`
+
+error: feature may misspelled as features
+  --> $DIR/cfg_features.rs:10:59
+   |
+LL |     #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))]
+   |                                                           ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong2"`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs
index ec082c73b44..16e54a7d969 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.rs
@@ -1,5 +1,9 @@
 #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
-#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::branches_sharing_code,
+    clippy::unnecessary_literal_unwrap
+)]
 
 fn test_complex_conditions() {
     let x: Result<(), ()> = Ok(());
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
index d44d5072e48..c395c5ba06f 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
@@ -1,5 +1,5 @@
 error: called `unwrap` on `x` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:8:9
+  --> $DIR/complex_conditionals.rs:12:9
    |
 LL |     if x.is_ok() && y.is_err() {
    |        --------- the check is happening here
@@ -14,7 +14,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/complex_conditionals.rs:9:9
+  --> $DIR/complex_conditionals.rs:13:9
    |
 LL |     if x.is_ok() && y.is_err() {
    |        --------- because of this check
@@ -29,7 +29,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals.rs:10:9
+  --> $DIR/complex_conditionals.rs:14:9
    |
 LL |     if x.is_ok() && y.is_err() {
    |                     ---------- because of this check
@@ -38,7 +38,7 @@ LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `y` after checking its variant with `is_err`
-  --> $DIR/complex_conditionals.rs:11:9
+  --> $DIR/complex_conditionals.rs:15:9
    |
 LL |     if x.is_ok() && y.is_err() {
    |                     ---------- the check is happening here
@@ -49,7 +49,7 @@ LL |         y.unwrap_err(); // unnecessary
    = help: try using `if let` or `match`
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals.rs:25:9
+  --> $DIR/complex_conditionals.rs:29:9
    |
 LL |     if x.is_ok() || y.is_ok() {
    |        --------- because of this check
@@ -58,7 +58,7 @@ LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `x` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:26:9
+  --> $DIR/complex_conditionals.rs:30:9
    |
 LL |     if x.is_ok() || y.is_ok() {
    |        --------- the check is happening here
@@ -69,7 +69,7 @@ LL |         x.unwrap_err(); // unnecessary
    = help: try using `if let` or `match`
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals.rs:27:9
+  --> $DIR/complex_conditionals.rs:31:9
    |
 LL |     if x.is_ok() || y.is_ok() {
    |                     --------- because of this check
@@ -78,7 +78,7 @@ LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `y` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:28:9
+  --> $DIR/complex_conditionals.rs:32:9
    |
 LL |     if x.is_ok() || y.is_ok() {
    |                     --------- the check is happening here
@@ -89,7 +89,7 @@ LL |         y.unwrap_err(); // unnecessary
    = help: try using `if let` or `match`
 
 error: called `unwrap` on `x` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:32:9
+  --> $DIR/complex_conditionals.rs:36:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |        --------- the check is happening here
@@ -99,7 +99,7 @@ LL |         x.unwrap(); // unnecessary
    = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/complex_conditionals.rs:33:9
+  --> $DIR/complex_conditionals.rs:37:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |        --------- because of this check
@@ -108,7 +108,7 @@ LL |         x.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals.rs:34:9
+  --> $DIR/complex_conditionals.rs:38:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |                       --------- because of this check
@@ -117,7 +117,7 @@ LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `y` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:35:9
+  --> $DIR/complex_conditionals.rs:39:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |                       --------- the check is happening here
@@ -128,7 +128,7 @@ LL |         y.unwrap_err(); // unnecessary
    = help: try using `if let` or `match`
 
 error: called `unwrap` on `z` after checking its variant with `is_err`
-  --> $DIR/complex_conditionals.rs:36:9
+  --> $DIR/complex_conditionals.rs:40:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |                                    ---------- the check is happening here
@@ -139,7 +139,7 @@ LL |         z.unwrap(); // unnecessary
    = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/complex_conditionals.rs:37:9
+  --> $DIR/complex_conditionals.rs:41:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |                                    ---------- because of this check
@@ -148,7 +148,7 @@ LL |         z.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals.rs:45:9
+  --> $DIR/complex_conditionals.rs:49:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
    |        --------- because of this check
@@ -157,7 +157,7 @@ LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `x` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:46:9
+  --> $DIR/complex_conditionals.rs:50:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
    |        --------- the check is happening here
@@ -168,7 +168,7 @@ LL |         x.unwrap_err(); // unnecessary
    = help: try using `if let` or `match`
 
 error: called `unwrap` on `y` after checking its variant with `is_ok`
-  --> $DIR/complex_conditionals.rs:47:9
+  --> $DIR/complex_conditionals.rs:51:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
    |                       --------- the check is happening here
@@ -179,7 +179,7 @@ LL |         y.unwrap(); // unnecessary
    = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/complex_conditionals.rs:48:9
+  --> $DIR/complex_conditionals.rs:52:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
    |                       --------- because of this check
@@ -188,7 +188,7 @@ LL |         y.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals.rs:49:9
+  --> $DIR/complex_conditionals.rs:53:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
    |                                    ---------- because of this check
@@ -197,7 +197,7 @@ LL |         z.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `z` after checking its variant with `is_err`
-  --> $DIR/complex_conditionals.rs:50:9
+  --> $DIR/complex_conditionals.rs:54:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
    |                                    ---------- the check is happening here
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs
index 043ea4148dc..e417cf833cb 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.rs
@@ -1,5 +1,9 @@
 #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
-#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::branches_sharing_code,
+    clippy::unnecessary_literal_unwrap
+)]
 
 fn test_nested() {
     fn nested() {
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
index 542ab53300c..049a69d93bf 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
@@ -1,5 +1,5 @@
 error: called `unwrap` on `x` after checking its variant with `is_some`
-  --> $DIR/complex_conditionals_nested.rs:8:13
+  --> $DIR/complex_conditionals_nested.rs:12:13
    |
 LL |         if x.is_some() {
    |         -------------- help: try: `if let Some(..) = x`
@@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/complex_conditionals_nested.rs:10:13
+  --> $DIR/complex_conditionals_nested.rs:14:13
    |
 LL |         if x.is_some() {
    |            ----------- because of this check
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
index 82dce81979f..61042bb90d2 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
@@ -1,6 +1,10 @@
 #![feature(lint_reasons)]
 #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
-#![allow(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::branches_sharing_code,
+    clippy::unnecessary_literal_unwrap
+)]
 
 macro_rules! m {
     ($a:expr) => {
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
index ef688274222..93809f6551a 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -1,5 +1,5 @@
 error: called `unwrap` on `x` after checking its variant with `is_some`
-  --> $DIR/simple_conditionals.rs:40:9
+  --> $DIR/simple_conditionals.rs:44:9
    |
 LL |     if x.is_some() {
    |     -------------- help: try: `if let Some(..) = x`
@@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: called `expect` on `x` after checking its variant with `is_some`
-  --> $DIR/simple_conditionals.rs:41:9
+  --> $DIR/simple_conditionals.rs:45:9
    |
 LL |     if x.is_some() {
    |     -------------- help: try: `if let Some(..) = x`
@@ -22,7 +22,7 @@ LL |         x.expect("an error message"); // unnecessary
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:43:9
+  --> $DIR/simple_conditionals.rs:47:9
    |
 LL |     if x.is_some() {
    |        ----------- because of this check
@@ -37,7 +37,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `expect()` will always panic
-  --> $DIR/simple_conditionals.rs:44:9
+  --> $DIR/simple_conditionals.rs:48:9
    |
 LL |     if x.is_some() {
    |        ----------- because of this check
@@ -46,7 +46,7 @@ LL |         x.expect("an error message"); // will panic
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:47:9
+  --> $DIR/simple_conditionals.rs:51:9
    |
 LL |     if x.is_none() {
    |        ----------- because of this check
@@ -54,7 +54,7 @@ LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap` on `x` after checking its variant with `is_none`
-  --> $DIR/simple_conditionals.rs:49:9
+  --> $DIR/simple_conditionals.rs:53:9
    |
 LL |     if x.is_none() {
    |     -------------- help: try: `if let Some(..) = x`
@@ -63,7 +63,7 @@ LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
 error: called `unwrap` on `x` after checking its variant with `is_some`
-  --> $DIR/simple_conditionals.rs:8:13
+  --> $DIR/simple_conditionals.rs:12:13
    |
 LL |         if $a.is_some() {
    |         --------------- help: try: `if let Some(..) = x`
@@ -76,7 +76,7 @@ LL |     m!(x);
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: called `unwrap` on `x` after checking its variant with `is_ok`
-  --> $DIR/simple_conditionals.rs:57:9
+  --> $DIR/simple_conditionals.rs:61:9
    |
 LL |     if x.is_ok() {
    |     ------------ help: try: `if let Ok(..) = x`
@@ -84,7 +84,7 @@ LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
 error: called `expect` on `x` after checking its variant with `is_ok`
-  --> $DIR/simple_conditionals.rs:58:9
+  --> $DIR/simple_conditionals.rs:62:9
    |
 LL |     if x.is_ok() {
    |     ------------ help: try: `if let Ok(..) = x`
@@ -93,7 +93,7 @@ LL |         x.expect("an error message"); // unnecessary
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/simple_conditionals.rs:59:9
+  --> $DIR/simple_conditionals.rs:63:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
@@ -102,7 +102,7 @@ LL |         x.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:61:9
+  --> $DIR/simple_conditionals.rs:65:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
@@ -111,7 +111,7 @@ LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: this call to `expect()` will always panic
-  --> $DIR/simple_conditionals.rs:62:9
+  --> $DIR/simple_conditionals.rs:66:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
@@ -120,7 +120,7 @@ LL |         x.expect("an error message"); // will panic
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: called `unwrap_err` on `x` after checking its variant with `is_ok`
-  --> $DIR/simple_conditionals.rs:63:9
+  --> $DIR/simple_conditionals.rs:67:9
    |
 LL |     if x.is_ok() {
    |     ------------ help: try: `if let Err(..) = x`
@@ -129,7 +129,7 @@ LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:66:9
+  --> $DIR/simple_conditionals.rs:70:9
    |
 LL |     if x.is_err() {
    |        ---------- because of this check
@@ -137,7 +137,7 @@ LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
 error: called `unwrap_err` on `x` after checking its variant with `is_err`
-  --> $DIR/simple_conditionals.rs:67:9
+  --> $DIR/simple_conditionals.rs:71:9
    |
 LL |     if x.is_err() {
    |     ------------- help: try: `if let Err(..) = x`
@@ -146,7 +146,7 @@ LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
 
 error: called `unwrap` on `x` after checking its variant with `is_err`
-  --> $DIR/simple_conditionals.rs:69:9
+  --> $DIR/simple_conditionals.rs:73:9
    |
 LL |     if x.is_err() {
    |     ------------- help: try: `if let Ok(..) = x`
@@ -155,7 +155,7 @@ LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/simple_conditionals.rs:70:9
+  --> $DIR/simple_conditionals.rs:74:9
    |
 LL |     if x.is_err() {
    |        ---------- because of this check
diff --git a/src/tools/clippy/tests/ui/clone_on_copy_impl.rs b/src/tools/clippy/tests/ui/clone_on_copy_impl.rs
index 8f9f2a0db8c..b7c186bef77 100644
--- a/src/tools/clippy/tests/ui/clone_on_copy_impl.rs
+++ b/src/tools/clippy/tests/ui/clone_on_copy_impl.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::incorrect_clone_impl_on_copy_type)]
+
 use std::fmt;
 use std::marker::PhantomData;
 
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
index b6e09ab3190..34bd2233440 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
@@ -2,6 +2,7 @@
 
 #![warn(clippy::cloned_instead_of_copied)]
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // yay
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
index fa9e1a99613..fa8444937b6 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::cloned_instead_of_copied)]
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // yay
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr b/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr
index e0361acd956..3ce482006e9 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr
@@ -1,5 +1,5 @@
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:8:24
+  --> $DIR/cloned_instead_of_copied.rs:9:24
    |
 LL |     let _ = [1].iter().cloned();
    |                        ^^^^^^ help: try: `copied`
@@ -7,43 +7,43 @@ LL |     let _ = [1].iter().cloned();
    = note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:9:31
+  --> $DIR/cloned_instead_of_copied.rs:10:31
    |
 LL |     let _ = vec!["hi"].iter().cloned();
    |                               ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:10:22
+  --> $DIR/cloned_instead_of_copied.rs:11:22
    |
 LL |     let _ = Some(&1).cloned();
    |                      ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:11:34
+  --> $DIR/cloned_instead_of_copied.rs:12:34
    |
 LL |     let _ = Box::new([1].iter()).cloned();
    |                                  ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:12:32
+  --> $DIR/cloned_instead_of_copied.rs:13:32
    |
 LL |     let _ = Box::new(Some(&1)).cloned();
    |                                ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:28:22
+  --> $DIR/cloned_instead_of_copied.rs:29:22
    |
 LL |     let _ = Some(&1).cloned(); // Option::copied needs 1.35
    |                      ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:33:24
+  --> $DIR/cloned_instead_of_copied.rs:34:24
    |
 LL |     let _ = [1].iter().cloned(); // Iterator::copied needs 1.36
    |                        ^^^^^^ help: try: `copied`
 
 error: used `cloned` where `copied` could be used instead
-  --> $DIR/cloned_instead_of_copied.rs:34:22
+  --> $DIR/cloned_instead_of_copied.rs:35:22
    |
 LL |     let _ = Some(&1).cloned();
    |                      ^^^^^^ help: try: `copied`
diff --git a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed
index 3bf3deb9b91..11834634856 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed
+++ b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.fixed
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700
+#![allow(
+    unused,
+    clippy::needless_if,
+    clippy::redundant_clone,
+    clippy::derive_partial_eq_without_eq
+)] // See #5700
 
 // Define the types in each module to avoid trait impls leaking between modules.
 macro_rules! impl_types {
diff --git a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs
index 10107dc8f86..3a25d53a5d0 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs
+++ b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.rs
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700
+#![allow(
+    unused,
+    clippy::needless_if,
+    clippy::redundant_clone,
+    clippy::derive_partial_eq_without_eq
+)] // See #5700
 
 // Define the types in each module to avoid trait impls leaking between modules.
 macro_rules! impl_types {
diff --git a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.stderr b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.stderr
index 43bf8851fc6..4714a0daaa6 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.stderr
+++ b/src/tools/clippy/tests/ui/cmp_owned/asymmetric_partial_eq.stderr
@@ -1,5 +1,5 @@
 error: this creates an owned instance just for comparison
-  --> $DIR/asymmetric_partial_eq.rs:42:12
+  --> $DIR/asymmetric_partial_eq.rs:47:12
    |
 LL |         if borrowed.to_owned() == owned {}
    |            ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed`
@@ -7,7 +7,7 @@ LL |         if borrowed.to_owned() == owned {}
    = note: `-D clippy::cmp-owned` implied by `-D warnings`
 
 error: this creates an owned instance just for comparison
-  --> $DIR/asymmetric_partial_eq.rs:43:21
+  --> $DIR/asymmetric_partial_eq.rs:48:21
    |
 LL |         if owned == borrowed.to_owned() {}
    |            ---------^^^^^^^^^^^^^^^^^^^
@@ -15,13 +15,13 @@ LL |         if owned == borrowed.to_owned() {}
    |            help: try: `borrowed == owned`
 
 error: this creates an owned instance just for comparison
-  --> $DIR/asymmetric_partial_eq.rs:61:21
+  --> $DIR/asymmetric_partial_eq.rs:66:21
    |
 LL |         if owned == borrowed.to_owned() {}
    |                     ^^^^^^^^^^^^^^^^^^^ help: try: `borrowed`
 
 error: this creates an owned instance just for comparison
-  --> $DIR/asymmetric_partial_eq.rs:62:12
+  --> $DIR/asymmetric_partial_eq.rs:67:12
    |
 LL |         if borrowed.to_owned() == owned {}
    |            ^^^^^^^^^^^^^^^^^^^---------
@@ -29,7 +29,7 @@ LL |         if borrowed.to_owned() == owned {}
    |            help: try: `owned == borrowed`
 
 error: this creates an owned instance just for comparison
-  --> $DIR/asymmetric_partial_eq.rs:88:20
+  --> $DIR/asymmetric_partial_eq.rs:93:20
    |
 LL |         if "Hi" == borrowed.to_string() {}
    |            --------^^^^^^^^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL |         if "Hi" == borrowed.to_string() {}
    |            help: try: `borrowed == "Hi"`
 
 error: this creates an owned instance just for comparison
-  --> $DIR/asymmetric_partial_eq.rs:89:12
+  --> $DIR/asymmetric_partial_eq.rs:94:12
    |
 LL |         if borrowed.to_string() == "Hi" {}
    |            ^^^^^^^^^^^^^^^^^^^^ help: try: `borrowed`
diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
index 76f90ab2a9d..bf1a58588a8 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
+++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.fixed
@@ -31,7 +31,7 @@ struct Foo;
 impl PartialEq for Foo {
     // Allow this here, because it emits the lint
     // without a suggestion. This is tested in
-    // `tests/ui/cmp_owned/without_suggestion.rs`
+    // `$DIR/without_suggestion.rs`
     #[allow(clippy::cmp_owned)]
     fn eq(&self, other: &Self) -> bool {
         self.to_owned() == *other
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.stderr b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
index 5824631fa83..d867246301a 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity.stderr
+++ b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
@@ -40,6 +40,14 @@ LL | fn bar() {
    = help: you could split it up into multiple smaller functions
 
 error: the function has a cognitive complexity of (2/1)
+  --> $DIR/cognitive_complexity.rs:178:4
+   |
+LL | fn dont_warn_on_tests() {
+   |    ^^^^^^^^^^^^^^^^^^
+   |
+   = help: you could split it up into multiple smaller functions
+
+error: the function has a cognitive complexity of (2/1)
   --> $DIR/cognitive_complexity.rs:186:4
    |
 LL | fn barr() {
@@ -151,5 +159,5 @@ LL |         pub async fn async_method() {
    |
    = help: you could split it up into multiple smaller functions
 
-error: aborting due to 19 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.fixed b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
index 8302cec45e7..c4116cd8520 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.rs b/src/tools/clippy/tests/ui/collapsible_else_if.rs
index 5913dcf41ca..8f51d0ee508 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index c6514a55934..e305e1d7a87 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -2,6 +2,7 @@
 #![allow(
     clippy::assertions_on_constants,
     clippy::equatable_if_let,
+    clippy::needless_if,
     clippy::nonminimal_bool,
     clippy::eq_op
 )]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index 2c85b68df63..7c52959d3b5 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -2,6 +2,7 @@
 #![allow(
     clippy::assertions_on_constants,
     clippy::equatable_if_let,
+    clippy::needless_if,
     clippy::nonminimal_bool,
     clippy::eq_op
 )]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index c687bae1acc..4a1a9e8a60a 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -1,5 +1,5 @@
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:14:5
+  --> $DIR/collapsible_if.rs:15:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" {
@@ -17,7 +17,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:20:5
+  --> $DIR/collapsible_if.rs:21:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -34,7 +34,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:26:5
+  --> $DIR/collapsible_if.rs:27:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -51,7 +51,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:32:5
+  --> $DIR/collapsible_if.rs:33:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -68,7 +68,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:38:5
+  --> $DIR/collapsible_if.rs:39:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -85,7 +85,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:44:5
+  --> $DIR/collapsible_if.rs:45:5
    |
 LL | /     if 42 == 1337 {
 LL | |         if 'a' != 'A' {
@@ -102,7 +102,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:100:5
+  --> $DIR/collapsible_if.rs:101:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" { // Collapsible
@@ -119,7 +119,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:159:5
+  --> $DIR/collapsible_if.rs:160:5
    |
 LL | /     if matches!(true, true) {
 LL | |         if matches!(true, true) {}
@@ -127,7 +127,7 @@ LL | |     }
    | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:164:5
+  --> $DIR/collapsible_if.rs:165:5
    |
 LL | /     if matches!(true, true) && truth() {
 LL | |         if matches!(true, true) {}
diff --git a/src/tools/clippy/tests/ui/collection_is_never_read.rs b/src/tools/clippy/tests/ui/collection_is_never_read.rs
index 2c1a42a72c1..e02c1c57230 100644
--- a/src/tools/clippy/tests/ui/collection_is_never_read.rs
+++ b/src/tools/clippy/tests/ui/collection_is_never_read.rs
@@ -1,4 +1,4 @@
-#![allow(unused)]
+#![allow(unused, clippy::useless_vec)]
 #![warn(clippy::collection_is_never_read)]
 
 use std::collections::{HashMap, HashSet};
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.fixed b/src/tools/clippy/tests/ui/comparison_to_empty.fixed
index dd2615ab25c..c92dd509ebb 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.fixed
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.fixed
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::comparison_to_empty)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // Disallow comparisons to empty
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.rs b/src/tools/clippy/tests/ui/comparison_to_empty.rs
index 5462784c6ac..b3489714380 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.rs
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.rs
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::comparison_to_empty)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // Disallow comparisons to empty
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.stderr b/src/tools/clippy/tests/ui/comparison_to_empty.stderr
index f69d6bd5255..cc09b17eb89 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.stderr
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.stderr
@@ -1,5 +1,5 @@
 error: comparison to empty slice
-  --> $DIR/comparison_to_empty.rs:8:13
+  --> $DIR/comparison_to_empty.rs:9:13
    |
 LL |     let _ = s == "";
    |             ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
@@ -7,19 +7,19 @@ LL |     let _ = s == "";
    = note: `-D clippy::comparison-to-empty` implied by `-D warnings`
 
 error: comparison to empty slice
-  --> $DIR/comparison_to_empty.rs:9:13
+  --> $DIR/comparison_to_empty.rs:10:13
    |
 LL |     let _ = s != "";
    |             ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`
 
 error: comparison to empty slice
-  --> $DIR/comparison_to_empty.rs:12:13
+  --> $DIR/comparison_to_empty.rs:13:13
    |
 LL |     let _ = v == [];
    |             ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`
 
 error: comparison to empty slice
-  --> $DIR/comparison_to_empty.rs:13:13
+  --> $DIR/comparison_to_empty.rs:14:13
    |
 LL |     let _ = v != [];
    |             ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
index 66419656a32..5dffddc119a 100644
--- a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
+++ b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
@@ -1,13 +1,5 @@
-//@compile-flags: --emit=link
-//@no-prefer-dynamic
-// ^ compiletest by default builds all aux files as dylibs, but we don't want that for proc-macro
-// crates. If we don't set this, compiletest will override the `crate_type` attribute below and
-// compile this as dylib. Removing this then causes the test to fail because a `dylib` crate can't
-// contain a proc-macro.
-
 #![feature(repr128)]
 #![allow(incomplete_features)]
-#![crate_type = "proc-macro"]
 
 extern crate proc_macro;
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10148.rs b/src/tools/clippy/tests/ui/crashes/ice-10148.rs
index c7f0224820e..0df22f41374 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10148.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-10148.rs
@@ -1,4 +1,4 @@
-//@aux-build:../../auxiliary/proc_macros.rs
+//@aux-build:../auxiliary/proc_macros.rs:proc-macro
 
 extern crate proc_macros;
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.rs b/src/tools/clippy/tests/ui/crashes/ice-10645.rs
index 4d8698d383b..6e126aff751 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10645.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-10645.rs
@@ -1,4 +1,4 @@
-// compile-flags: --cap-lints=warn
+//@compile-flags: --cap-lints=warn
 // https://github.com/rust-lang/rust-clippy/issues/10645
 
 #![warn(clippy::future_not_send)]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
index fc084e30d7f..0055fe061e2 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
@@ -1,4 +1,4 @@
-error: future cannot be sent between threads safely
+warning: future cannot be sent between threads safely
   --> $DIR/ice-10645.rs:5:35
    |
 LL | pub async fn bar<'a, T: 'a>(_: T) {}
@@ -12,5 +12,5 @@ LL | pub async fn bar<'a, T: 'a>(_: T) {}
    = note: `T` doesn't implement `std::marker::Send`
    = note: `-D clippy::future-not-send` implied by `-D warnings`
 
-error: aborting due to previous error
+warning: 1 warning emitted
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10912.rs b/src/tools/clippy/tests/ui/crashes/ice-10912.rs
new file mode 100644
index 00000000000..69d7f2f395f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-10912.rs
@@ -0,0 +1,4 @@
+#![warn(clippy::unreadable_literal)]
+fn f2() -> impl Sized { && 3.14159265358979323846E }
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10912.stderr b/src/tools/clippy/tests/ui/crashes/ice-10912.stderr
new file mode 100644
index 00000000000..a74ce731577
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-10912.stderr
@@ -0,0 +1,16 @@
+error: expected at least one digit in exponent
+  --> $DIR/ice-10912.rs:2:28
+   |
+LL | fn f2() -> impl Sized { && 3.14159265358979323846E }
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: long literal lacking separators
+  --> $DIR/ice-10912.rs:2:28
+   |
+LL | fn f2() -> impl Sized { && 3.14159265358979323846E }
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: consider: `3.141_592_653_589_793_238_46`
+   |
+   = note: `-D clippy::unreadable-literal` implied by `-D warnings`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
index 81af88962a6..19ab03418ee 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs
@@ -1,4 +1,5 @@
 #![allow(dead_code, unused_variables)]
+#![allow(clippy::unnecessary_cast)]
 
 /// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
 ///
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
index c5ea0b16d1b..a166ccb3ee8 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
@@ -1,8 +1,8 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/ice-2774.rs:15:1
+  --> $DIR/ice-2774.rs:15:28
    |
 LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^                  ^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 help: elide the lifetimes
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3462.rs b/src/tools/clippy/tests/ui/crashes/ice-3462.rs
index b402052882a..21cd9d337cd 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3462.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3462.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::all)]
-#![allow(clippy::disallowed_names, clippy::equatable_if_let)]
+#![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)]
 #![allow(unused)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/3462
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3741.rs b/src/tools/clippy/tests/ui/crashes/ice-3741.rs
index 3106a2e7216..268c5ba0ad0 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3741.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3741.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_crash.rs
+//@aux-build:proc_macro_crash.rs:proc-macro
 
 #![warn(clippy::suspicious_else_formatting)]
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-4968.rs b/src/tools/clippy/tests/ui/crashes/ice-4968.rs
index ac724ac93e3..50473868005 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-4968.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-4968.rs
@@ -1,5 +1,3 @@
-//@check-pass
-
 // Test for https://github.com/rust-lang/rust-clippy/issues/4968
 
 #![warn(clippy::unsound_collection_transmute)]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5497.rs b/src/tools/clippy/tests/ui/crashes/ice-5497.rs
index 0769bce5fc8..f77f691c192 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5497.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5497.rs
@@ -7,5 +7,5 @@ pub trait Foo {
 
 impl<T: Foo> Foo for Vec<T> {
     const OOB: i32 = [1][1] + T::OOB;
-    //~^ ERROR operation will panic
+    //~^ ERROR: operation will panic
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-5579.rs b/src/tools/clippy/tests/ui/crashes/ice-5579.rs
index e1842c73f0e..8ab36bbf93c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-5579.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-5579.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::unnecessary_literal_unwrap)]
+
 trait IsErr {
     fn is_err(&self, err: &str) -> bool;
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr
index db34e6bfa7b..97390af3e89 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr
@@ -1,9 +1,3 @@
-error[E0601]: `main` function not found in crate `ice_6250`
-  --> $DIR/ice-6250.rs:16:2
-   |
-LL | }
-   |  ^ consider adding a `main` function to `$DIR/ice-6250.rs`
-
 error[E0308]: mismatched types
   --> $DIR/ice-6250.rs:12:14
    |
@@ -24,7 +18,6 @@ help: consider adding `let`
 LL |         let Some(reference) = cache.data.get(key) {
    |         +++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0601.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr
index 8da2965c635..68a5766c90c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6251.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6251.stderr
@@ -1,9 +1,3 @@
-error[E0601]: `main` function not found in crate `ice_6251`
-  --> $DIR/ice-6251.rs:6:2
-   |
-LL | }
-   |  ^ consider adding a `main` function to `$DIR/ice-6251.rs`
-
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/ice-6251.rs:4:45
    |
@@ -35,7 +29,7 @@ LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
    = note: expected type `usize`
            found closure `[closure@$DIR/ice-6251.rs:4:44: 4:53]`
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0277, E0308, E0601.
+Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6255.rs b/src/tools/clippy/tests/ui/crashes/ice-6255.rs
index ccde6aa2b0f..b6555ac5c40 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6255.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6255.rs
@@ -4,7 +4,6 @@
 macro_rules! define_other_core {
     ( ) => {
         extern crate std as core;
-        //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
     };
 }
 
@@ -13,3 +12,4 @@ fn main() {
 }
 
 define_other_core!();
+//~^ ERROR: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.rs b/src/tools/clippy/tests/ui/crashes/ice-6256.rs
index f9ee3e058c1..1d336b3cdc0 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6256.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6256.rs
@@ -10,6 +10,6 @@ impl dyn TT {
 
 #[rustfmt::skip]
 fn main() {
-    let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
-                                   //[nll]~^ ERROR: borrowed data escapes outside of closure
+    let f = |x: &dyn TT| x.func();
+    //~^ ERROR: borrowed data escapes outside of closure
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr
index 9cfcccf1e3c..671933157c8 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr
@@ -1,7 +1,7 @@
 error[E0521]: borrowed data escapes outside of closure
   --> $DIR/ice-6256.rs:13:26
    |
-LL |     let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
+LL |     let f = |x: &dyn TT| x.func();
    |              -  -        ^^^^^^^^
    |              |  |        |
    |              |  |        `x` escapes the closure body here
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7169.rs b/src/tools/clippy/tests/ui/crashes/ice-7169.rs
index 82095febc19..b203252f0a1 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7169.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7169.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::needless_if)]
+
 #[derive(Default)]
 struct A<T> {
     a: Vec<A<T>>,
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7169.stderr b/src/tools/clippy/tests/ui/crashes/ice-7169.stderr
index 5a9cd32380a..84e0af3f0d0 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7169.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-7169.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/ice-7169.rs:8:12
+  --> $DIR/ice-7169.rs:10:12
    |
 LL |     if let Ok(_) = Ok::<_, ()>(A::<String>::default()) {}
    |     -------^^^^^-------------------------------------- help: try this: `if Ok::<_, ()>(A::<String>::default()).is_ok()`
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7410.rs b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
index a5373cdcae1..a2683b3ce34 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7410.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
@@ -1,6 +1,6 @@
 //@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-macos
-//@ignore-windows
+//@ignore-target-apple
+//@ignore-target-windows
 
 #![feature(lang_items, start, libc)]
 #![no_std]
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9445.stderr b/src/tools/clippy/tests/ui/crashes/ice-9445.stderr
new file mode 100644
index 00000000000..a59d098e5ac
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9445.stderr
@@ -0,0 +1,12 @@
+error: a `const` item should never be interior mutable
+  --> $DIR/ice-9445.rs:1:1
+   |
+LL | const UNINIT: core::mem::MaybeUninit<core::cell::Cell<&'static ()>> = core::mem::MaybeUninit::uninit();
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | make this a static item (maybe with lazy_static)
+   |
+   = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-96721.rs b/src/tools/clippy/tests/ui/crashes/ice-96721.rs
index 4b3fb764010..ca68ba3d03a 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-96721.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-96721.rs
@@ -4,7 +4,7 @@ macro_rules! foo {
     };
 }
 
-#[path = foo!()] //~ ERROR malformed `path` attribute
+#[path = foo!()] //~ ERROR: malformed `path` attribute
 mod abc {}
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-96721.stderr b/src/tools/clippy/tests/ui/crashes/ice-96721.stderr
index 78c567b8e77..712bd14c685 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-96721.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-96721.stderr
@@ -1,7 +1,7 @@
 error: malformed `path` attribute input
   --> $DIR/ice-96721.rs:7:1
    |
-LL | #[path = foo!()] //~ ERROR malformed `path` attribute
+LL | #[path = foo!()]
    | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]`
 
 error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
index 0b0e0ad2684..37484f5ebd7 100644
--- a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
@@ -1,8 +1,8 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes_impl_trait.rs:15:5
+  --> $DIR/needless_lifetimes_impl_trait.rs:15:12
    |
 LL |     fn baz<'a>(&'a self) -> impl Foo + 'a {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^   ^^                     ^^
    |
 note: the lint level is defined here
   --> $DIR/needless_lifetimes_impl_trait.rs:1:9
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
index d6cd594d7c9..aa76688d801 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
@@ -1,4 +1,4 @@
-//@ignore-macos
+//@ignore-target-apple
 
 #![feature(rustc_attrs)]
 
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr
deleted file mode 100644
index 3d79a115cb3..00000000000
--- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: recursing into entrypoint `a`
-  --> $DIR/entrypoint_recursion.rs:10:5
-   |
-LL |     a();
-   |     ^
-   |
-   = help: consider using another function for this recursion
-   = note: `-D clippy::main-recursion` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
index a382135bb69..32eba969592 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-macos
+//@ignore-target-apple
 
 #![feature(lang_items, start, libc)]
 #![no_std]
diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro.rs
index 10788d40481..6c63c098916 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro.rs
@@ -1,4 +1,3 @@
-//@compile-flags: --test
 #![warn(clippy::dbg_macro)]
 
 fn foo(n: u32) -> u32 {
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index 530e7663317..3d292625959 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -1,5 +1,5 @@
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:5:22
+  --> $DIR/dbg_macro.rs:4:22
    |
 LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
    |                      ^^^^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:10:8
+  --> $DIR/dbg_macro.rs:9:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     if n <= 1 {
    |        ~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:11:9
+  --> $DIR/dbg_macro.rs:10:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -33,7 +33,7 @@ LL |         1
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:13:9
+  --> $DIR/dbg_macro.rs:12:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |         n * factorial(n - 1)
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:18:5
+  --> $DIR/dbg_macro.rs:17:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -55,7 +55,7 @@ LL |     42;
    |     ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:19:5
+  --> $DIR/dbg_macro.rs:18:5
    |
 LL |     dbg!(dbg!(dbg!(42)));
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     dbg!(dbg!(42));
    |     ~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:20:14
+  --> $DIR/dbg_macro.rs:19:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     foo(3) + factorial(4);
    |              ~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:21:5
+  --> $DIR/dbg_macro.rs:20:5
    |
 LL |     dbg!(1, 2, dbg!(3, 4));
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     (1, 2, dbg!(3, 4));
    |     ~~~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:22:5
+  --> $DIR/dbg_macro.rs:21:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -99,7 +99,7 @@ LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:42:5
+  --> $DIR/dbg_macro.rs:41:5
    |
 LL |     dbg!();
    |     ^^^^^^^
@@ -111,7 +111,7 @@ LL +
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:44:13
+  --> $DIR/dbg_macro.rs:43:13
    |
 LL |     let _ = dbg!();
    |             ^^^^^^
@@ -122,7 +122,7 @@ LL |     let _ = ();
    |             ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:45:9
+  --> $DIR/dbg_macro.rs:44:9
    |
 LL |     bar(dbg!());
    |         ^^^^^^
@@ -133,7 +133,7 @@ LL |     bar(());
    |         ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:46:10
+  --> $DIR/dbg_macro.rs:45:10
    |
 LL |     foo!(dbg!());
    |          ^^^^^^
@@ -144,7 +144,7 @@ LL |     foo!(());
    |          ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:47:16
+  --> $DIR/dbg_macro.rs:46:16
    |
 LL |     foo2!(foo!(dbg!()));
    |                ^^^^^^
@@ -155,7 +155,7 @@ LL |     foo2!(foo!(()));
    |                ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:68:9
+  --> $DIR/dbg_macro.rs:67:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
@@ -166,7 +166,7 @@ LL |         2;
    |         ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:74:5
+  --> $DIR/dbg_macro.rs:73:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -177,7 +177,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:79:5
+  --> $DIR/dbg_macro.rs:78:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -188,7 +188,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:85:9
+  --> $DIR/dbg_macro.rs:84:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs
index f44518694b8..a88bf7b21b8 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.rs
@@ -9,7 +9,7 @@ enum OptionalCell {
 }
 
 // a constant with enums should be linted only when the used variant is unfrozen (#3962).
-const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable
+const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR: interior mutable
 const FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
 
 const fn unfrozen_variant() -> OptionalCell {
@@ -20,7 +20,7 @@ const fn frozen_variant() -> OptionalCell {
     OptionalCell::Frozen
 }
 
-const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable
+const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR: interior mutable
 const FROZEN_VARIANT_FROM_FN: OptionalCell = frozen_variant();
 
 enum NestedInnermost {
@@ -43,10 +43,11 @@ struct NestedOutermost {
 
 // a constant with enums should be linted according to its value, no matter how structs involve.
 const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
+    //~^ ERROR: interior mutable
     outer: NestedOuter::NestedInner(NestedInner {
         inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
     }),
-}; //~ ERROR interior mutable
+};
 const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost {
     outer: NestedOuter::NestedInner(NestedInner {
         inner: NestedInnermost::Frozen,
@@ -56,11 +57,11 @@ const NESTED_FROZEN_VARIANT: NestedOutermost = NestedOutermost {
 trait AssocConsts {
     // When there's no default value, lint it only according to its type.
     // Further details are on the corresponding code (`NonCopyConst::check_trait_item`).
-    const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
-    const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+    const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable
+    const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR: interior mutable
 
     // Lint default values accordingly.
-    const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable
+    const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR: interior mutable
     const DEFAULTED_ON_FROZEN_VARIANT: OptionalCell = OptionalCell::Frozen;
 }
 
@@ -86,7 +87,7 @@ trait AssocTypes {
 impl AssocTypes for u64 {
     type ToBeUnfrozen = AtomicUsize;
 
-    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
+    const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR: interior mutable
     const TO_BE_FROZEN_VARIANT: Option<Self::ToBeUnfrozen> = None;
 }
 
@@ -98,25 +99,25 @@ enum BothOfCellAndGeneric<T> {
 }
 
 impl<T> BothOfCellAndGeneric<T> {
-    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
+    const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR: interior mutable
 
     // This is a false positive. The argument about this is on `is_value_unfrozen_raw`
-    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+    const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable
 
     const FROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Frozen(5);
 
     // This is what is likely to be a false negative when one tries to fix
     // the `GENERIC_VARIANT` false positive.
-    const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable
+    const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR: interior mutable
 }
 
 // associated types here is basically the same as the one above.
 trait BothOfCellAndGenericWithAssocType {
     type AssocType;
 
-    const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
-        BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
-    const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+    const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> = //~ ERROR: interior mutable
+        BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
+    const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR: interior mutable
     const FROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Frozen(5);
 }
 
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
index 84198d54615..6070df749ca 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
@@ -1,7 +1,7 @@
 error: a `const` item should never be interior mutable
   --> $DIR/enums.rs:12:1
    |
-LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true)); //~ ERROR interior mutable
+LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
    | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | |
    | make this a static item (maybe with lazy_static)
@@ -11,7 +11,7 @@ LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(tru
 error: a `const` item should never be interior mutable
   --> $DIR/enums.rs:23:1
    |
-LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant(); //~ ERROR interior mutable
+LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant();
    | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | |
    | make this a static item (maybe with lazy_static)
@@ -24,65 +24,66 @@ LL |   const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
    |   |
    |  _make this a static item (maybe with lazy_static)
    | |
+LL | |
 LL | |     outer: NestedOuter::NestedInner(NestedInner {
 LL | |         inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
 LL | |     }),
-LL | | }; //~ ERROR interior mutable
+LL | | };
    | |__^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:59:5
+  --> $DIR/enums.rs:60:5
    |
-LL |     const TO_BE_UNFROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+LL |     const TO_BE_UNFROZEN_VARIANT: OptionalCell;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:60:5
+  --> $DIR/enums.rs:61:5
    |
-LL |     const TO_BE_FROZEN_VARIANT: OptionalCell; //~ ERROR interior mutable
+LL |     const TO_BE_FROZEN_VARIANT: OptionalCell;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:63:5
+  --> $DIR/enums.rs:64:5
    |
-LL |     const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false)); //~ ERROR interior mutable
+LL |     const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:89:5
+  --> $DIR/enums.rs:90:5
    |
-LL |     const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4)); //~ ERROR interior mutable
+LL |     const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:101:5
+  --> $DIR/enums.rs:102:5
    |
-LL |     const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mut...
+LL |     const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:104:5
+  --> $DIR/enums.rs:105:5
    |
-LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mutable
+LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:110:5
+  --> $DIR/enums.rs:111:5
    |
-LL |     const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null()); //~ ERROR interior mutable
+LL |     const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:117:5
+  --> $DIR/enums.rs:118:5
    |
 LL | /     const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
-LL | |         BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null())); //~ ERROR interior mutable
+LL | |         BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
    | |____________________________________________________________________^
 
 error: a `const` item should never be interior mutable
-  --> $DIR/enums.rs:119:5
+  --> $DIR/enums.rs:120:5
    |
-LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null()); //~ ERROR interior mu...
+LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
index 896596b5679..1cec2980652 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
@@ -6,17 +6,17 @@ use std::fmt::Display;
 use std::sync::atomic::AtomicUsize;
 use std::sync::Once;
 
-const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
-const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
+const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR: interior mutable
+const CELL: Cell<usize> = Cell::new(6); //~ ERROR: interior mutable
 const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
-//~^ ERROR interior mutable
+//~^ ERROR: interior mutable
 
 macro_rules! declare_const {
     ($name:ident: $ty:ty = $e:expr) => {
         const $name: $ty = $e;
     };
 }
-declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
+declare_const!(_ONCE: Once = Once::new()); //~ ERROR: interior mutable
 
 // const ATOMIC_REF: &AtomicUsize = &AtomicUsize::new(7); // This will simply trigger E0492.
 
@@ -24,12 +24,12 @@ const INTEGER: u8 = 8;
 const STRING: String = String::new();
 const STR: &str = "012345";
 const COW: Cow<str> = Cow::Borrowed("abcdef");
-//^ note: a const item of Cow is used in the `postgres` package.
+// note: a const item of Cow is used in the `postgres` package.
 
 const NO_ANN: &dyn Display = &70;
 
 static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
-//^ there should be no lints on this line
+// there should be no lints on the line above line
 
 mod issue_8493 {
     use std::cell::Cell;
@@ -40,7 +40,7 @@ mod issue_8493 {
 
     macro_rules! issue_8493 {
         () => {
-            const _BAZ: Cell<usize> = Cell::new(0); //~ ERROR interior mutable
+            const _BAZ: Cell<usize> = Cell::new(0);
             static _FOOBAR: () = {
                 thread_local! {
                     static _VAR: Cell<i32> = const { Cell::new(0) };
@@ -49,7 +49,7 @@ mod issue_8493 {
         };
     }
 
-    issue_8493!();
+    issue_8493!(); //~ ERROR: interior mutable
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
index 1fd6d7322a7..0259f6a4a28 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
@@ -1,7 +1,7 @@
 error: a `const` item should never be interior mutable
   --> $DIR/others.rs:9:1
    |
-LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
+LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5);
    | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | |
    | make this a static item (maybe with lazy_static)
@@ -11,7 +11,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable
 error: a `const` item should never be interior mutable
   --> $DIR/others.rs:10:1
    |
-LL | const CELL: Cell<usize> = Cell::new(6); //~ ERROR interior mutable
+LL | const CELL: Cell<usize> = Cell::new(6);
    | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | |
    | make this a static item (maybe with lazy_static)
@@ -30,7 +30,7 @@ error: a `const` item should never be interior mutable
 LL |         const $name: $ty = $e;
    |         ^^^^^^^^^^^^^^^^^^^^^^
 ...
-LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
+LL | declare_const!(_ONCE: Once = Once::new());
    | ----------------------------------------- in this macro invocation
    |
    = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -38,7 +38,7 @@ LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
 error: a `const` item should never be interior mutable
   --> $DIR/others.rs:43:13
    |
-LL |             const _BAZ: Cell<usize> = Cell::new(0); //~ ERROR interior mutable
+LL |             const _BAZ: Cell<usize> = Cell::new(0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     issue_8493!();
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
index 256a336db82..a6ccdd27079 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
@@ -12,10 +12,10 @@ macro_rules! declare_const {
 
 // a constant whose type is a concrete type should be linted at the definition site.
 trait ConcreteTypes {
-    const ATOMIC: AtomicUsize; //~ ERROR interior mutable
+    const ATOMIC: AtomicUsize; //~ ERROR: interior mutable
     const INTEGER: u64;
     const STRING: String;
-    declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
+    declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR: interior mutable
 }
 
 impl ConcreteTypes for u64 {
@@ -40,7 +40,7 @@ trait GenericTypes<T, U> {
 
 impl<T: ConstDefault> GenericTypes<T, AtomicUsize> for u64 {
     const TO_REMAIN_GENERIC: T = T::DEFAULT;
-    const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
+    const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR: interior mutable
 }
 
 // a helper type used below
@@ -65,8 +65,8 @@ impl<T: ConstDefault> AssocTypes for Vec<T> {
     type ToBeGenericParam = T;
 
     const TO_BE_FROZEN: Self::ToBeFrozen = 12;
-    const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
-    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
+    const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR: interior mutable
+    const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR: interior mutable
     const WRAPPED_TO_BE_GENERIC_PARAM: Wrapper<Self::ToBeGenericParam> = Wrapper(T::DEFAULT);
 }
 
@@ -85,7 +85,7 @@ where
     T: AssocTypesHelper<ToBeBounded = AtomicUsize>,
 {
     const NOT_BOUNDED: T::NotToBeBounded;
-    const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
+    const BOUNDED: T::ToBeBounded; //~ ERROR: interior mutable
 }
 
 impl<T> AssocTypesFromGenericParam<T> for u64
@@ -113,8 +113,8 @@ impl SelfType for u64 {
 impl SelfType for AtomicUsize {
     // this (interior mutable `Self` const) exists in `parking_lot`.
     // `const_trait_impl` will replace it in the future, hopefully.
-    const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
-    const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
+    const SELF: Self = AtomicUsize::new(17); //~ ERROR: interior mutable
+    const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR: interior mutable
 }
 
 // Even though a constant contains a generic type, if it also have an interior mutable type,
@@ -122,7 +122,7 @@ impl SelfType for AtomicUsize {
 trait BothOfCellAndGeneric<T> {
     // this is a false negative in the current implementation.
     const DIRECT: Cell<T>;
-    const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
+    const INDIRECT: Cell<*const T>; //~ ERROR: interior mutable
 }
 
 impl<T: ConstDefault> BothOfCellAndGeneric<T> for u64 {
@@ -138,13 +138,13 @@ impl<T> Local<T>
 where
     T: ConstDefault + AssocTypesHelper<ToBeBounded = AtomicUsize>,
 {
-    const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
+    const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR: interior mutable
     const COW: Cow<'static, str> = Cow::Borrowed("tuvwxy");
 
     const GENERIC_TYPE: T = T::DEFAULT;
 
     const ASSOC_TYPE: T::NotToBeBounded = T::NOT_TO_BE_BOUNDED;
-    const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
+    const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR: interior mutable
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
index 7debe059ff4..ef62919dfea 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
@@ -1,7 +1,7 @@
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:15:5
    |
-LL |     const ATOMIC: AtomicUsize; //~ ERROR interior mutable
+LL |     const ATOMIC: AtomicUsize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
@@ -12,7 +12,7 @@ error: a `const` item should never be interior mutable
 LL |         const $name: $ty = $e;
    |         ^^^^^^^^^^^^^^^^^^^^^^
 ...
-LL |     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR interior mutable
+LL |     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC);
    |     ---------------------------------------------------------- in this macro invocation
    |
    = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -20,55 +20,55 @@ LL |     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC); //~ ERROR i
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:43:5
    |
-LL |     const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11); //~ ERROR interior mutable
+LL |     const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:68:5
    |
-LL |     const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13); //~ ERROR interior mutable
+LL |     const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:69:5
    |
-LL |     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14)); //~ ERROR interior mutable
+LL |     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:88:5
    |
-LL |     const BOUNDED: T::ToBeBounded; //~ ERROR interior mutable
+LL |     const BOUNDED: T::ToBeBounded;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:116:5
    |
-LL |     const SELF: Self = AtomicUsize::new(17); //~ ERROR interior mutable
+LL |     const SELF: Self = AtomicUsize::new(17);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:117:5
    |
-LL |     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
+LL |     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:125:5
    |
-LL |     const INDIRECT: Cell<*const T>; //~ ERROR interior mutable
+LL |     const INDIRECT: Cell<*const T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:141:5
    |
-LL |     const ATOMIC: AtomicUsize = AtomicUsize::new(18); //~ ERROR interior mutable
+LL |     const ATOMIC: AtomicUsize = AtomicUsize::new(18);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a `const` item should never be interior mutable
   --> $DIR/traits.rs:147:5
    |
-LL |     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19); //~ ERROR interior mutable
+LL |     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 11 previous errors
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index f7819068ac5..da0816830b8 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -1,4 +1,4 @@
-//@ignore-macos
+//@ignore-target-apple
 
 #![feature(no_core, lang_items, start)]
 #![no_core]
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
index 9520efe6329..02eb7806013 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::default_numeric_fallback)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
index cacbdb4a95b..79a9669833f 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::default_numeric_fallback)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
index fbabb8bcf8e..23272d07eec 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![feature(lint_reasons)]
 #![warn(clippy::default_numeric_fallback)]
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
index 7bfc390e4bf..fb149141609 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![feature(lint_reasons)]
 #![warn(clippy::default_numeric_fallback)]
diff --git a/src/tools/clippy/tests/ui/default_trait_access.fixed b/src/tools/clippy/tests/ui/default_trait_access.fixed
index bf5dca97641..14eb6d572cf 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.fixed
+++ b/src/tools/clippy/tests/ui/default_trait_access.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![deny(clippy::default_trait_access)]
 #![allow(dead_code, unused_imports)]
 #![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/default_trait_access.rs b/src/tools/clippy/tests/ui/default_trait_access.rs
index 5e8e9ce85b1..aa2ced0a7f0 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.rs
+++ b/src/tools/clippy/tests/ui/default_trait_access.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![deny(clippy::default_trait_access)]
 #![allow(dead_code, unused_imports)]
 #![allow(clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/deref_addrof.fixed b/src/tools/clippy/tests/ui/deref_addrof.fixed
index b27d3bc1002..0ecca1b8ffa 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.fixed
+++ b/src/tools/clippy/tests/ui/deref_addrof.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
-#![allow(clippy::return_self_not_must_use)]
+#![allow(clippy::return_self_not_must_use, clippy::useless_vec)]
 #![warn(clippy::deref_addrof)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/deref_addrof.rs b/src/tools/clippy/tests/ui/deref_addrof.rs
index 825090c7c12..9f91310e61f 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.rs
+++ b/src/tools/clippy/tests/ui/deref_addrof.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
-#![allow(clippy::return_self_not_must_use)]
+#![allow(clippy::return_self_not_must_use, clippy::useless_vec)]
 #![warn(clippy::deref_addrof)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/deref_addrof_macro.rs b/src/tools/clippy/tests/ui/deref_addrof_macro.rs
index c7e60f36506..ce4b94a73bd 100644
--- a/src/tools/clippy/tests/ui/deref_addrof_macro.rs
+++ b/src/tools/clippy/tests/ui/deref_addrof_macro.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::deref_addrof)]
 
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
index aa0efb85c29..a10f3d01070 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.fixed
+++ b/src/tools/clippy/tests/ui/derivable_impls.fixed
@@ -268,4 +268,25 @@ impl Default for OtherGenericType {
     }
 }
 
+mod issue10158 {
+    pub trait T {}
+
+    #[derive(Default)]
+    pub struct S {}
+    impl T for S {}
+
+    pub struct Outer {
+        pub inner: Box<dyn T>,
+    }
+
+    impl Default for Outer {
+        fn default() -> Self {
+            Outer {
+                // Box::<S>::default() adjusts to Box<dyn T>
+                inner: Box::<S>::default(),
+            }
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index 8dc999ad586..18cef1c5be8 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -304,4 +304,25 @@ impl Default for OtherGenericType {
     }
 }
 
+mod issue10158 {
+    pub trait T {}
+
+    #[derive(Default)]
+    pub struct S {}
+    impl T for S {}
+
+    pub struct Outer {
+        pub inner: Box<dyn T>,
+    }
+
+    impl Default for Outer {
+        fn default() -> Self {
+            Outer {
+                // Box::<S>::default() adjusts to Box<dyn T>
+                inner: Box::<S>::default(),
+            }
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive.rs b/src/tools/clippy/tests/ui/derive.rs
index 6e0ce55f57d..e01079bc977 100644
--- a/src/tools/clippy/tests/ui/derive.rs
+++ b/src/tools/clippy/tests/ui/derive.rs
@@ -1,4 +1,4 @@
-#![allow(dead_code)]
+#![allow(clippy::incorrect_clone_impl_on_copy_type, dead_code)]
 #![warn(clippy::expl_impl_clone_on_copy)]
 
 
diff --git a/src/tools/clippy/tests/ui/disallowed_names.rs b/src/tools/clippy/tests/ui/disallowed_names.rs
index e937c49f389..5889f04439f 100644
--- a/src/tools/clippy/tests/ui/disallowed_names.rs
+++ b/src/tools/clippy/tests/ui/disallowed_names.rs
@@ -1,5 +1,6 @@
 #![allow(
     dead_code,
+    clippy::needless_if,
     clippy::similar_names,
     clippy::single_match,
     clippy::toplevel_ref_arg,
diff --git a/src/tools/clippy/tests/ui/disallowed_names.stderr b/src/tools/clippy/tests/ui/disallowed_names.stderr
index 78cb55096ff..9ab68b641f1 100644
--- a/src/tools/clippy/tests/ui/disallowed_names.stderr
+++ b/src/tools/clippy/tests/ui/disallowed_names.stderr
@@ -1,5 +1,5 @@
 error: use of a disallowed/placeholder name `foo`
-  --> $DIR/disallowed_names.rs:11:9
+  --> $DIR/disallowed_names.rs:12:9
    |
 LL | fn test(foo: ()) {}
    |         ^^^
@@ -7,79 +7,79 @@ LL | fn test(foo: ()) {}
    = note: `-D clippy::disallowed-names` implied by `-D warnings`
 
 error: use of a disallowed/placeholder name `foo`
-  --> $DIR/disallowed_names.rs:14:9
+  --> $DIR/disallowed_names.rs:15:9
    |
 LL |     let foo = 42;
    |         ^^^
 
 error: use of a disallowed/placeholder name `baz`
-  --> $DIR/disallowed_names.rs:15:9
+  --> $DIR/disallowed_names.rs:16:9
    |
 LL |     let baz = 42;
    |         ^^^
 
 error: use of a disallowed/placeholder name `quux`
-  --> $DIR/disallowed_names.rs:16:9
+  --> $DIR/disallowed_names.rs:17:9
    |
 LL |     let quux = 42;
    |         ^^^^
 
 error: use of a disallowed/placeholder name `foo`
-  --> $DIR/disallowed_names.rs:27:10
+  --> $DIR/disallowed_names.rs:28:10
    |
 LL |         (foo, Some(baz), quux @ Some(_)) => (),
    |          ^^^
 
 error: use of a disallowed/placeholder name `baz`
-  --> $DIR/disallowed_names.rs:27:20
+  --> $DIR/disallowed_names.rs:28:20
    |
 LL |         (foo, Some(baz), quux @ Some(_)) => (),
    |                    ^^^
 
 error: use of a disallowed/placeholder name `quux`
-  --> $DIR/disallowed_names.rs:27:26
+  --> $DIR/disallowed_names.rs:28:26
    |
 LL |         (foo, Some(baz), quux @ Some(_)) => (),
    |                          ^^^^
 
 error: use of a disallowed/placeholder name `foo`
-  --> $DIR/disallowed_names.rs:32:19
+  --> $DIR/disallowed_names.rs:33:19
    |
 LL | fn issue_1647(mut foo: u8) {
    |                   ^^^
 
 error: use of a disallowed/placeholder name `baz`
-  --> $DIR/disallowed_names.rs:33:13
+  --> $DIR/disallowed_names.rs:34:13
    |
 LL |     let mut baz = 0;
    |             ^^^
 
 error: use of a disallowed/placeholder name `quux`
-  --> $DIR/disallowed_names.rs:34:21
+  --> $DIR/disallowed_names.rs:35:21
    |
 LL |     if let Some(mut quux) = Some(42) {}
    |                     ^^^^
 
 error: use of a disallowed/placeholder name `baz`
-  --> $DIR/disallowed_names.rs:38:13
+  --> $DIR/disallowed_names.rs:39:13
    |
 LL |     let ref baz = 0;
    |             ^^^
 
 error: use of a disallowed/placeholder name `quux`
-  --> $DIR/disallowed_names.rs:39:21
+  --> $DIR/disallowed_names.rs:40:21
    |
 LL |     if let Some(ref quux) = Some(42) {}
    |                     ^^^^
 
 error: use of a disallowed/placeholder name `baz`
-  --> $DIR/disallowed_names.rs:43:17
+  --> $DIR/disallowed_names.rs:44:17
    |
 LL |     let ref mut baz = 0;
    |                 ^^^
 
 error: use of a disallowed/placeholder name `quux`
-  --> $DIR/disallowed_names.rs:44:25
+  --> $DIR/disallowed_names.rs:45:25
    |
 LL |     if let Some(ref mut quux) = Some(42) {}
    |                         ^^^^
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.rs b/src/tools/clippy/tests/ui/diverging_sub_expression.rs
index e8f992e6dde..9b1619baf0e 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.rs
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.rs
@@ -1,5 +1,6 @@
 #![warn(clippy::diverging_sub_expression)]
 #![allow(clippy::match_same_arms, clippy::overly_complex_bool_expr)]
+#![allow(clippy::nonminimal_bool)]
 #[allow(clippy::empty_loop)]
 fn diverge() -> ! {
     loop {}
@@ -21,6 +22,7 @@ fn main() {
 }
 
 #[allow(dead_code, unused_variables)]
+#[rustfmt::skip]
 fn foobar() {
     loop {
         let x = match 5 {
@@ -35,6 +37,20 @@ fn foobar() {
                 99 => return,
                 _ => true || panic!("boo"),
             },
+            // lint blocks as well
+            15 => true || { return; },
+            16 => false || { return; },
+            // ... and when it's a single expression
+            17 => true || { return },
+            18 => false || { return },
+            // ... but not when there's both an expression and a statement
+            19 => true || { _ = 1; return },
+            20 => false || { _ = 1; return },
+            // ... or multiple statements
+            21 => true || { _ = 1; return; },
+            22 => false || { _ = 1; return; },
+            23 => true || { return; true },
+            24 => true || { return; true },
             _ => true || break,
         };
     }
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
index 51a3b0d972e..243a5cf5369 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
@@ -1,5 +1,5 @@
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:19:10
+  --> $DIR/diverging_sub_expression.rs:20:10
    |
 LL |     b || diverge();
    |          ^^^^^^^^^
@@ -7,34 +7,66 @@ LL |     b || diverge();
    = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:20:10
+  --> $DIR/diverging_sub_expression.rs:21:10
    |
 LL |     b || A.foo();
    |          ^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:29:26
+  --> $DIR/diverging_sub_expression.rs:31:26
    |
 LL |             6 => true || return,
    |                          ^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:30:26
+  --> $DIR/diverging_sub_expression.rs:32:26
    |
 LL |             7 => true || continue,
    |                          ^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:33:26
+  --> $DIR/diverging_sub_expression.rs:35:26
    |
 LL |             3 => true || diverge(),
    |                          ^^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:38:26
+  --> $DIR/diverging_sub_expression.rs:38:30
+   |
+LL |                 _ => true || panic!("boo"),
+   |                              ^^^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:41:29
+   |
+LL |             15 => true || { return; },
+   |                             ^^^^^^
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:42:30
+   |
+LL |             16 => false || { return; },
+   |                              ^^^^^^
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:44:29
+   |
+LL |             17 => true || { return },
+   |                             ^^^^^^
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:45:30
+   |
+LL |             18 => false || { return },
+   |                              ^^^^^^
+
+error: sub-expression diverges
+  --> $DIR/diverging_sub_expression.rs:54:26
    |
 LL |             _ => true || break,
    |                          ^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index d3aa2816cb6..14444df4c10 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -60,6 +60,7 @@ fn test_units() {
 /// GitHub GitLab
 /// IPv4 IPv6
 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// WebAssembly
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index d1e7d8017d7..542d33b13a4 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -60,6 +60,7 @@ fn test_units() {
 /// GitHub GitLab
 /// IPv4 IPv6
 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// WebAssembly
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
index 6c67c903c75..94ef43afc08 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -132,7 +132,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:74:5
+  --> $DIR/doc-fixable.rs:75:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -143,7 +143,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:91:5
+  --> $DIR/doc-fixable.rs:92:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:99:8
+  --> $DIR/doc-fixable.rs:100:8
    |
 LL | /// ## CamelCaseThing
    |        ^^^^^^^^^^^^^^
@@ -165,7 +165,7 @@ LL | /// ## `CamelCaseThing`
    |        ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:102:7
+  --> $DIR/doc-fixable.rs:103:7
    |
 LL | /// # CamelCaseThing
    |       ^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL | /// # `CamelCaseThing`
    |       ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:104:22
+  --> $DIR/doc-fixable.rs:105:22
    |
 LL | /// Not a title #897 CamelCaseThing
    |                      ^^^^^^^^^^^^^^
@@ -187,7 +187,7 @@ LL | /// Not a title #897 `CamelCaseThing`
    |                      ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:105:5
+  --> $DIR/doc-fixable.rs:106:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -198,7 +198,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:112:5
+  --> $DIR/doc-fixable.rs:113:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:125:5
+  --> $DIR/doc-fixable.rs:126:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +220,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:136:43
+  --> $DIR/doc-fixable.rs:137:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -231,7 +231,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
    |                                           ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:141:5
+  --> $DIR/doc-fixable.rs:142:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -242,7 +242,7 @@ LL | And `BarQuz` too.
    |     ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:142:1
+  --> $DIR/doc-fixable.rs:143:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -253,7 +253,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:147:43
+  --> $DIR/doc-fixable.rs:148:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -264,7 +264,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
    |                                           ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:152:5
+  --> $DIR/doc-fixable.rs:153:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -275,7 +275,7 @@ LL | And `BarQuz` too.
    |     ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:153:1
+  --> $DIR/doc-fixable.rs:154:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -286,7 +286,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:164:5
+  --> $DIR/doc-fixable.rs:165:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -297,7 +297,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:183:22
+  --> $DIR/doc-fixable.rs:184:22
    |
 LL | /// An iterator over mycrate::Collection's values.
    |                      ^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/doc/needless_doctest_main.rs b/src/tools/clippy/tests/ui/doc/needless_doctest_main.rs
new file mode 100644
index 00000000000..f1a2c0575ee
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/needless_doctest_main.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::needless_doctest_main)]
+//! issue 10491:
+//! ```rust,no_test
+//! use std::collections::HashMap;
+//!
+//! fn main() {
+//!     let mut m = HashMap::new();
+//!     m.insert(1u32, 2u32);
+//! }
+//! ```
+
+/// some description here
+/// ```rust,no_test
+/// fn main() {
+///     foo()
+/// }
+/// ```
+fn foo() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/doc_unsafe.rs b/src/tools/clippy/tests/ui/doc_unsafe.rs
index 0c8eac5ccff..d21b046f167 100644
--- a/src/tools/clippy/tests/ui/doc_unsafe.rs
+++ b/src/tools/clippy/tests/ui/doc_unsafe.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![allow(clippy::let_unit_value)]
 
diff --git a/src/tools/clippy/tests/ui/double_comparison.fixed b/src/tools/clippy/tests/ui/double_comparison.fixed
index c80ff671a5d..f8ca92ef0b3 100644
--- a/src/tools/clippy/tests/ui/double_comparison.fixed
+++ b/src/tools/clippy/tests/ui/double_comparison.fixed
@@ -1,4 +1,5 @@
 //@run-rustfix
+#![allow(clippy::needless_if)]
 
 fn main() {
     let x = 1;
diff --git a/src/tools/clippy/tests/ui/double_comparison.rs b/src/tools/clippy/tests/ui/double_comparison.rs
index bc78694aa68..47ff87bea0a 100644
--- a/src/tools/clippy/tests/ui/double_comparison.rs
+++ b/src/tools/clippy/tests/ui/double_comparison.rs
@@ -1,4 +1,5 @@
 //@run-rustfix
+#![allow(clippy::needless_if)]
 
 fn main() {
     let x = 1;
diff --git a/src/tools/clippy/tests/ui/double_comparison.stderr b/src/tools/clippy/tests/ui/double_comparison.stderr
index 05ef4e25f7f..4df1c28ac48 100644
--- a/src/tools/clippy/tests/ui/double_comparison.stderr
+++ b/src/tools/clippy/tests/ui/double_comparison.stderr
@@ -1,5 +1,5 @@
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:6:8
+  --> $DIR/double_comparison.rs:7:8
    |
 LL |     if x == y || x < y {
    |        ^^^^^^^^^^^^^^^ help: try: `x <= y`
@@ -7,43 +7,43 @@ LL |     if x == y || x < y {
    = note: `-D clippy::double-comparisons` implied by `-D warnings`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:9:8
+  --> $DIR/double_comparison.rs:10:8
    |
 LL |     if x < y || x == y {
    |        ^^^^^^^^^^^^^^^ help: try: `x <= y`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:12:8
+  --> $DIR/double_comparison.rs:13:8
    |
 LL |     if x == y || x > y {
    |        ^^^^^^^^^^^^^^^ help: try: `x >= y`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:15:8
+  --> $DIR/double_comparison.rs:16:8
    |
 LL |     if x > y || x == y {
    |        ^^^^^^^^^^^^^^^ help: try: `x >= y`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:18:8
+  --> $DIR/double_comparison.rs:19:8
    |
 LL |     if x < y || x > y {
    |        ^^^^^^^^^^^^^^ help: try: `x != y`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:21:8
+  --> $DIR/double_comparison.rs:22:8
    |
 LL |     if x > y || x < y {
    |        ^^^^^^^^^^^^^^ help: try: `x != y`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:24:8
+  --> $DIR/double_comparison.rs:25:8
    |
 LL |     if x <= y && x >= y {
    |        ^^^^^^^^^^^^^^^^ help: try: `x == y`
 
 error: this binary expression can be simplified
-  --> $DIR/double_comparison.rs:27:8
+  --> $DIR/double_comparison.rs:28:8
    |
 LL |     if x >= y && x <= y {
    |        ^^^^^^^^^^^^^^^^ help: try: `x == y`
diff --git a/src/tools/clippy/tests/ui/drain_collect.fixed b/src/tools/clippy/tests/ui/drain_collect.fixed
new file mode 100644
index 00000000000..11001bd319f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/drain_collect.fixed
@@ -0,0 +1,77 @@
+//@run-rustfix
+
+#![deny(clippy::drain_collect)]
+#![allow(dead_code)]
+
+use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
+
+fn binaryheap(b: &mut BinaryHeap<i32>) -> BinaryHeap<i32> {
+    std::mem::take(b)
+}
+
+fn binaryheap_dont_lint(b: &mut BinaryHeap<i32>) -> HashSet<i32> {
+    b.drain().collect()
+}
+
+fn hashmap(b: &mut HashMap<i32, i32>) -> HashMap<i32, i32> {
+    std::mem::take(b)
+}
+
+fn hashmap_dont_lint(b: &mut HashMap<i32, i32>) -> Vec<(i32, i32)> {
+    b.drain().collect()
+}
+
+fn hashset(b: &mut HashSet<i32>) -> HashSet<i32> {
+    std::mem::take(b)
+}
+
+fn hashset_dont_lint(b: &mut HashSet<i32>) -> Vec<i32> {
+    b.drain().collect()
+}
+
+fn vecdeque(b: &mut VecDeque<i32>) -> VecDeque<i32> {
+    std::mem::take(b)
+}
+
+fn vecdeque_dont_lint(b: &mut VecDeque<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn vec(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec2(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec3(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec4(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec_no_reborrow() -> Vec<i32> {
+    let mut b = vec![1, 2, 3];
+    std::mem::take(&mut b)
+}
+
+fn vec_dont_lint(b: &mut Vec<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn string(b: &mut String) -> String {
+    std::mem::take(b)
+}
+
+fn string_dont_lint(b: &mut String) -> HashSet<char> {
+    b.drain(..).collect()
+}
+
+fn not_whole_length(v: &mut Vec<i32>) -> Vec<i32> {
+    v.drain(1..).collect()
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/drain_collect.rs b/src/tools/clippy/tests/ui/drain_collect.rs
new file mode 100644
index 00000000000..373a3ca3506
--- /dev/null
+++ b/src/tools/clippy/tests/ui/drain_collect.rs
@@ -0,0 +1,77 @@
+//@run-rustfix
+
+#![deny(clippy::drain_collect)]
+#![allow(dead_code)]
+
+use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
+
+fn binaryheap(b: &mut BinaryHeap<i32>) -> BinaryHeap<i32> {
+    b.drain().collect()
+}
+
+fn binaryheap_dont_lint(b: &mut BinaryHeap<i32>) -> HashSet<i32> {
+    b.drain().collect()
+}
+
+fn hashmap(b: &mut HashMap<i32, i32>) -> HashMap<i32, i32> {
+    b.drain().collect()
+}
+
+fn hashmap_dont_lint(b: &mut HashMap<i32, i32>) -> Vec<(i32, i32)> {
+    b.drain().collect()
+}
+
+fn hashset(b: &mut HashSet<i32>) -> HashSet<i32> {
+    b.drain().collect()
+}
+
+fn hashset_dont_lint(b: &mut HashSet<i32>) -> Vec<i32> {
+    b.drain().collect()
+}
+
+fn vecdeque(b: &mut VecDeque<i32>) -> VecDeque<i32> {
+    b.drain(..).collect()
+}
+
+fn vecdeque_dont_lint(b: &mut VecDeque<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn vec(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(..).collect()
+}
+
+fn vec2(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(0..).collect()
+}
+
+fn vec3(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(..b.len()).collect()
+}
+
+fn vec4(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(0..b.len()).collect()
+}
+
+fn vec_no_reborrow() -> Vec<i32> {
+    let mut b = vec![1, 2, 3];
+    b.drain(..).collect()
+}
+
+fn vec_dont_lint(b: &mut Vec<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn string(b: &mut String) -> String {
+    b.drain(..).collect()
+}
+
+fn string_dont_lint(b: &mut String) -> HashSet<char> {
+    b.drain(..).collect()
+}
+
+fn not_whole_length(v: &mut Vec<i32>) -> Vec<i32> {
+    v.drain(1..).collect()
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/drain_collect.stderr b/src/tools/clippy/tests/ui/drain_collect.stderr
new file mode 100644
index 00000000000..0792f0254cb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/drain_collect.stderr
@@ -0,0 +1,68 @@
+error: you seem to be trying to move all elements into a new `BinaryHeap`
+  --> $DIR/drain_collect.rs:9:5
+   |
+LL |     b.drain().collect()
+   |     ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+   |
+note: the lint level is defined here
+  --> $DIR/drain_collect.rs:3:9
+   |
+LL | #![deny(clippy::drain_collect)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: you seem to be trying to move all elements into a new `HashMap`
+  --> $DIR/drain_collect.rs:17:5
+   |
+LL |     b.drain().collect()
+   |     ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `HashSet`
+  --> $DIR/drain_collect.rs:25:5
+   |
+LL |     b.drain().collect()
+   |     ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:33:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:41:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:45:5
+   |
+LL |     b.drain(0..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:49:5
+   |
+LL |     b.drain(..b.len()).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:53:5
+   |
+LL |     b.drain(0..b.len()).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:58:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)`
+
+error: you seem to be trying to move all elements into a new `String`
+  --> $DIR/drain_collect.rs:66:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.rs b/src/tools/clippy/tests/ui/else_if_without_else.rs
index 879b3ac398e..eb5e2266540 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.rs
+++ b/src/tools/clippy/tests/ui/else_if_without_else.rs
@@ -43,7 +43,7 @@ fn main() {
     if bla1() {
         println!("if");
     } else if bla2() {
-        //~ ERROR else if without else
+        //~^ ERROR: `if` expression with an `else if`, but without a final `else`
         println!("else if");
     }
 
@@ -52,7 +52,7 @@ fn main() {
     } else if bla2() {
         println!("else if 1");
     } else if bla3() {
-        //~ ERROR else if without else
+        //~^ ERROR: `if` expression with an `else if`, but without a final `else`
         println!("else if 2");
     }
 }
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.stderr b/src/tools/clippy/tests/ui/else_if_without_else.stderr
index 90ccfb4fad6..11baf75441a 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.stderr
+++ b/src/tools/clippy/tests/ui/else_if_without_else.stderr
@@ -3,7 +3,7 @@ error: `if` expression with an `else if`, but without a final `else`
    |
 LL |       } else if bla2() {
    |  ____________^
-LL | |         //~ ERROR else if without else
+LL | |
 LL | |         println!("else if");
 LL | |     }
    | |_____^
@@ -16,7 +16,7 @@ error: `if` expression with an `else if`, but without a final `else`
    |
 LL |       } else if bla3() {
    |  ____________^
-LL | |         //~ ERROR else if without else
+LL | |
 LL | |         println!("else if 2");
 LL | |     }
    | |_____^
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
index e843770f578..83db2a07d33 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_attr.rs
+//@aux-build:proc_macro_attr.rs:proc-macro
 #![warn(clippy::empty_line_after_doc_comments)]
 #![allow(clippy::assertions_on_constants)]
 #![feature(custom_inner_attributes)]
diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
index 269e66ea0a8..b2d7ddae427 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_attr.rs
+//@aux-build:proc_macro_attr.rs:proc-macro
 #![warn(clippy::empty_line_after_outer_attr)]
 #![allow(clippy::assertions_on_constants)]
 #![feature(custom_inner_attributes)]
diff --git a/src/tools/clippy/tests/ui/empty_loop.rs b/src/tools/clippy/tests/ui/empty_loop.rs
index 54e8fb4907c..f1a55415c8d 100644
--- a/src/tools/clippy/tests/ui/empty_loop.rs
+++ b/src/tools/clippy/tests/ui/empty_loop.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::empty_loop)]
 
diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.rs b/src/tools/clippy/tests/ui/empty_loop_no_std.rs
index d564b2d24f5..f9ab443dfd9 100644
--- a/src/tools/clippy/tests/ui/empty_loop_no_std.rs
+++ b/src/tools/clippy/tests/ui/empty_loop_no_std.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-macos
+//@ignore-target-apple
 
 #![warn(clippy::empty_loop)]
 #![feature(lang_items, start, libc)]
diff --git a/src/tools/clippy/tests/ui/endian_bytes.rs b/src/tools/clippy/tests/ui/endian_bytes.rs
new file mode 100644
index 00000000000..6bf014fc809
--- /dev/null
+++ b/src/tools/clippy/tests/ui/endian_bytes.rs
@@ -0,0 +1,127 @@
+#![allow(unused)]
+#![allow(clippy::diverging_sub_expression)]
+#![no_main]
+
+macro_rules! fn_body {
+    () => {
+        2u8.to_ne_bytes();
+        2i8.to_ne_bytes();
+        2u16.to_ne_bytes();
+        2i16.to_ne_bytes();
+        2u32.to_ne_bytes();
+        2i32.to_ne_bytes();
+        2u64.to_ne_bytes();
+        2i64.to_ne_bytes();
+        2u128.to_ne_bytes();
+        2i128.to_ne_bytes();
+        2.0f32.to_ne_bytes();
+        2.0f64.to_ne_bytes();
+        2usize.to_ne_bytes();
+        2isize.to_ne_bytes();
+        u8::from_ne_bytes(todo!());
+        i8::from_ne_bytes(todo!());
+        u16::from_ne_bytes(todo!());
+        i16::from_ne_bytes(todo!());
+        u32::from_ne_bytes(todo!());
+        i32::from_ne_bytes(todo!());
+        u64::from_ne_bytes(todo!());
+        i64::from_ne_bytes(todo!());
+        u128::from_ne_bytes(todo!());
+        i128::from_ne_bytes(todo!());
+        usize::from_ne_bytes(todo!());
+        isize::from_ne_bytes(todo!());
+        f32::from_ne_bytes(todo!());
+        f64::from_ne_bytes(todo!());
+
+        2u8.to_le_bytes();
+        2i8.to_le_bytes();
+        2u16.to_le_bytes();
+        2i16.to_le_bytes();
+        2u32.to_le_bytes();
+        2i32.to_le_bytes();
+        2u64.to_le_bytes();
+        2i64.to_le_bytes();
+        2u128.to_le_bytes();
+        2i128.to_le_bytes();
+        2.0f32.to_le_bytes();
+        2.0f64.to_le_bytes();
+        2usize.to_le_bytes();
+        2isize.to_le_bytes();
+        u8::from_le_bytes(todo!());
+        i8::from_le_bytes(todo!());
+        u16::from_le_bytes(todo!());
+        i16::from_le_bytes(todo!());
+        u32::from_le_bytes(todo!());
+        i32::from_le_bytes(todo!());
+        u64::from_le_bytes(todo!());
+        i64::from_le_bytes(todo!());
+        u128::from_le_bytes(todo!());
+        i128::from_le_bytes(todo!());
+        usize::from_le_bytes(todo!());
+        isize::from_le_bytes(todo!());
+        f32::from_le_bytes(todo!());
+        f64::from_le_bytes(todo!());
+    };
+}
+
+// bless breaks if I use fn_body too much (oops)
+macro_rules! fn_body_smol {
+    () => {
+        2u8.to_ne_bytes();
+        u8::from_ne_bytes(todo!());
+
+        2u8.to_le_bytes();
+        u8::from_le_bytes(todo!());
+
+        2u8.to_be_bytes();
+        u8::from_be_bytes(todo!());
+    };
+}
+
+#[rustfmt::skip]
+#[warn(clippy::host_endian_bytes)]
+fn host() { fn_body!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::little_endian_bytes)]
+fn little() { fn_body!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::big_endian_bytes)]
+fn big() { fn_body!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::host_endian_bytes)]
+#[warn(clippy::big_endian_bytes)]
+fn host_encourage_little() { fn_body_smol!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::host_endian_bytes)]
+#[warn(clippy::little_endian_bytes)]
+fn host_encourage_big() { fn_body_smol!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::host_endian_bytes)]
+#[warn(clippy::little_endian_bytes)]
+#[warn(clippy::big_endian_bytes)]
+fn no_help() { fn_body_smol!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::little_endian_bytes)]
+#[warn(clippy::big_endian_bytes)]
+fn little_encourage_host() { fn_body_smol!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::host_endian_bytes)]
+#[warn(clippy::little_endian_bytes)]
+fn little_encourage_big() { fn_body_smol!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::big_endian_bytes)]
+#[warn(clippy::little_endian_bytes)]
+fn big_encourage_host() { fn_body_smol!(); }
+
+#[rustfmt::skip]
+#[warn(clippy::host_endian_bytes)]
+#[warn(clippy::big_endian_bytes)]
+fn big_encourage_little() { fn_body_smol!(); }
diff --git a/src/tools/clippy/tests/ui/endian_bytes.stderr b/src/tools/clippy/tests/ui/endian_bytes.stderr
new file mode 100644
index 00000000000..5e64ea5b5ab
--- /dev/null
+++ b/src/tools/clippy/tests/ui/endian_bytes.stderr
@@ -0,0 +1,1031 @@
+error: usage of the `u8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:7:9
+   |
+LL |         2u8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: `-D clippy::host-endian-bytes` implied by `-D warnings`
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:8:9
+   |
+LL |         2i8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u16::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:9:9
+   |
+LL |         2u16.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i16::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:10:9
+   |
+LL |         2i16.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u32::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:11:9
+   |
+LL |         2u32.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i32::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:12:9
+   |
+LL |         2i32.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u64::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:13:9
+   |
+LL |         2u64.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i64::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:14:9
+   |
+LL |         2i64.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u128::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:15:9
+   |
+LL |         2u128.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i128::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:16:9
+   |
+LL |         2i128.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `f32::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:17:9
+   |
+LL |         2.0f32.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `f64::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:18:9
+   |
+LL |         2.0f64.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `usize::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:19:9
+   |
+LL |         2usize.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `isize::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:20:9
+   |
+LL |         2isize.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:21:9
+   |
+LL |         u8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:22:9
+   |
+LL |         i8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u16::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:23:9
+   |
+LL |         u16::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i16::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:24:9
+   |
+LL |         i16::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u32::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:25:9
+   |
+LL |         u32::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i32::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:26:9
+   |
+LL |         i32::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u64::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:27:9
+   |
+LL |         u64::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i64::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:28:9
+   |
+LL |         i64::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u128::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:29:9
+   |
+LL |         u128::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i128::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:30:9
+   |
+LL |         i128::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `usize::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:31:9
+   |
+LL |         usize::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `isize::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:32:9
+   |
+LL |         isize::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `f32::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:33:9
+   |
+LL |         f32::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `f64::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:34:9
+   |
+LL |         f64::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host() { fn_body!(); }
+   |             ---------- in this macro invocation
+   |
+   = help: specify the desired endianness explicitly
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:36:9
+   |
+LL |         2u8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: `-D clippy::little-endian-bytes` implied by `-D warnings`
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:37:9
+   |
+LL |         2i8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u16::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:38:9
+   |
+LL |         2u16.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i16::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:39:9
+   |
+LL |         2i16.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u32::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:40:9
+   |
+LL |         2u32.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i32::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:41:9
+   |
+LL |         2i32.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u64::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:42:9
+   |
+LL |         2u64.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i64::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:43:9
+   |
+LL |         2i64.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u128::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:44:9
+   |
+LL |         2u128.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `i128::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:45:9
+   |
+LL |         2i128.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `f32::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:46:9
+   |
+LL |         2.0f32.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `f64::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:47:9
+   |
+LL |         2.0f64.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `usize::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:48:9
+   |
+LL |         2usize.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `isize::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:49:9
+   |
+LL |         2isize.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:50:9
+   |
+LL |         u8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:51:9
+   |
+LL |         i8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u16::from_le_bytes`
+  --> $DIR/endian_bytes.rs:52:9
+   |
+LL |         u16::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i16::from_le_bytes`
+  --> $DIR/endian_bytes.rs:53:9
+   |
+LL |         i16::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u32::from_le_bytes`
+  --> $DIR/endian_bytes.rs:54:9
+   |
+LL |         u32::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i32::from_le_bytes`
+  --> $DIR/endian_bytes.rs:55:9
+   |
+LL |         i32::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u64::from_le_bytes`
+  --> $DIR/endian_bytes.rs:56:9
+   |
+LL |         u64::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i64::from_le_bytes`
+  --> $DIR/endian_bytes.rs:57:9
+   |
+LL |         i64::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u128::from_le_bytes`
+  --> $DIR/endian_bytes.rs:58:9
+   |
+LL |         u128::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `i128::from_le_bytes`
+  --> $DIR/endian_bytes.rs:59:9
+   |
+LL |         i128::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `usize::from_le_bytes`
+  --> $DIR/endian_bytes.rs:60:9
+   |
+LL |         usize::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `isize::from_le_bytes`
+  --> $DIR/endian_bytes.rs:61:9
+   |
+LL |         isize::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `f32::from_le_bytes`
+  --> $DIR/endian_bytes.rs:62:9
+   |
+LL |         f32::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `f64::from_le_bytes`
+  --> $DIR/endian_bytes.rs:63:9
+   |
+LL |         f64::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little() { fn_body!(); }
+   |               ---------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:70:9
+   |
+LL |         2u8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_little() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use `u8::to_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:71:9
+   |
+LL |         u8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_little() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use `u8::from_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_be_bytes` method
+  --> $DIR/endian_bytes.rs:76:9
+   |
+LL |         2u8.to_be_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_little() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use `u8::to_le_bytes` instead
+   = note: `-D clippy::big-endian-bytes` implied by `-D warnings`
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_be_bytes`
+  --> $DIR/endian_bytes.rs:77:9
+   |
+LL |         u8::from_be_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_little() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use `u8::from_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:70:9
+   |
+LL |         2u8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_big() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use `u8::to_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:71:9
+   |
+LL |         u8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_big() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use `u8::from_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:73:9
+   |
+LL |         2u8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_big() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use `u8::to_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:74:9
+   |
+LL |         u8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn host_encourage_big() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use `u8::from_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:70:9
+   |
+LL |         2u8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn no_help() { fn_body_smol!(); }
+   |                --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:71:9
+   |
+LL |         u8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn no_help() { fn_body_smol!(); }
+   |                --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:73:9
+   |
+LL |         2u8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn no_help() { fn_body_smol!(); }
+   |                --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:74:9
+   |
+LL |         u8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn no_help() { fn_body_smol!(); }
+   |                --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_be_bytes` method
+  --> $DIR/endian_bytes.rs:76:9
+   |
+LL |         2u8.to_be_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn no_help() { fn_body_smol!(); }
+   |                --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_be_bytes`
+  --> $DIR/endian_bytes.rs:77:9
+   |
+LL |         u8::from_be_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn no_help() { fn_body_smol!(); }
+   |                --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:73:9
+   |
+LL |         2u8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_host() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:74:9
+   |
+LL |         u8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_host() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_be_bytes` method
+  --> $DIR/endian_bytes.rs:76:9
+   |
+LL |         2u8.to_be_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_host() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_be_bytes`
+  --> $DIR/endian_bytes.rs:77:9
+   |
+LL |         u8::from_be_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_host() { fn_body_smol!(); }
+   |                              --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:70:9
+   |
+LL |         2u8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_big() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::to_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:71:9
+   |
+LL |         u8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_big() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::from_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:73:9
+   |
+LL |         2u8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_big() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::to_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:74:9
+   |
+LL |         u8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn little_encourage_big() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::from_be_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_le_bytes` method
+  --> $DIR/endian_bytes.rs:73:9
+   |
+LL |         2u8.to_le_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_host() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_le_bytes`
+  --> $DIR/endian_bytes.rs:74:9
+   |
+LL |         u8::from_le_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_host() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_be_bytes` method
+  --> $DIR/endian_bytes.rs:76:9
+   |
+LL |         2u8.to_be_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_host() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_be_bytes`
+  --> $DIR/endian_bytes.rs:77:9
+   |
+LL |         u8::from_be_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_host() { fn_body_smol!(); }
+   |                           --------------- in this macro invocation
+   |
+   = help: use the native endianness instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_ne_bytes` method
+  --> $DIR/endian_bytes.rs:70:9
+   |
+LL |         2u8.to_ne_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_little() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::to_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_ne_bytes`
+  --> $DIR/endian_bytes.rs:71:9
+   |
+LL |         u8::from_ne_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_little() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::from_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the `u8::to_be_bytes` method
+  --> $DIR/endian_bytes.rs:76:9
+   |
+LL |         2u8.to_be_bytes();
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_little() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::to_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: usage of the function `u8::from_be_bytes`
+  --> $DIR/endian_bytes.rs:77:9
+   |
+LL |         u8::from_be_bytes(todo!());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn big_encourage_little() { fn_body_smol!(); }
+   |                             --------------- in this macro invocation
+   |
+   = help: use `u8::from_le_bytes` instead
+   = note: this error originates in the macro `fn_body_smol` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 86 previous errors
+
diff --git a/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs b/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
index f17556ea907..abe42a2305f 100644
--- a/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
+++ b/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
@@ -1,4 +1,4 @@
-//@ignore-x86
+//@ignore-target-x86
 
 #![warn(clippy::enum_clike_unportable_variant)]
 #![allow(unused, non_upper_case_globals)]
diff --git a/src/tools/clippy/tests/ui/eprint_with_newline.rs b/src/tools/clippy/tests/ui/eprint_with_newline.rs
index de5e121be87..8389806c838 100644
--- a/src/tools/clippy/tests/ui/eprint_with_newline.rs
+++ b/src/tools/clippy/tests/ui/eprint_with_newline.rs
@@ -44,7 +44,7 @@ fn main() {
     // Don't warn on CRLF (#4208)
     eprint!("\r\n");
     eprint!("foo\r\n");
-    eprint!("\\r\n"); //~ ERROR
+    eprint!("\\r\n");
     eprint!("foo\rbar\n");
 
     // Ignore expanded format strings
diff --git a/src/tools/clippy/tests/ui/eprint_with_newline.stderr b/src/tools/clippy/tests/ui/eprint_with_newline.stderr
index 0eefb9f0ca9..0a6bdf15df8 100644
--- a/src/tools/clippy/tests/ui/eprint_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/eprint_with_newline.stderr
@@ -62,13 +62,13 @@ LL +     eprintln!();
 error: using `eprint!()` with a format string that ends in a single newline
   --> $DIR/eprint_with_newline.rs:28:5
    |
-LL |     eprint!("//n"); // should fail
+LL |     eprint!("///n"); // should fail
    |     ^^^^^^^^^^^^^^^
    |
 help: use `eprintln!` instead
    |
-LL -     eprint!("//n"); // should fail
-LL +     eprintln!("/"); // should fail
+LL -     eprint!("///n"); // should fail
+LL +     eprintln!("//"); // should fail
    |
 
 error: using `eprint!()` with a format string that ends in a single newline
@@ -104,13 +104,13 @@ LL ~
 error: using `eprint!()` with a format string that ends in a single newline
   --> $DIR/eprint_with_newline.rs:47:5
    |
-LL |     eprint!("/r/n"); //~ ERROR
+LL |     eprint!("//r/n");
    |     ^^^^^^^^^^^^^^^^
    |
 help: use `eprintln!` instead
    |
-LL -     eprint!("/r/n"); //~ ERROR
-LL +     eprintln!("/r"); //~ ERROR
+LL -     eprint!("//r/n");
+LL +     eprintln!("//r");
    |
 
 error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/eq_op.rs b/src/tools/clippy/tests/ui/eq_op.rs
index cdd33ebe582..e973e5ba2fb 100644
--- a/src/tools/clippy/tests/ui/eq_op.rs
+++ b/src/tools/clippy/tests/ui/eq_op.rs
@@ -1,5 +1,3 @@
-//@compile-flags: --test
-
 #![warn(clippy::eq_op)]
 #![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)]
 #![allow(clippy::suspicious_xor_used_as_pow)]
@@ -12,6 +10,8 @@ fn main() {
     let _ = false != false;
     let _ = 1.5 < 1.5;
     let _ = 1u64 >= 1u64;
+    let x = f32::NAN;
+    let _ = x != x;
 
     // casts, methods, parentheses
     let _ = (1u32 as u64) & (1u32 as u64);
diff --git a/src/tools/clippy/tests/ui/eq_op.stderr b/src/tools/clippy/tests/ui/eq_op.stderr
index d365ab27edc..c7fa253bdca 100644
--- a/src/tools/clippy/tests/ui/eq_op.stderr
+++ b/src/tools/clippy/tests/ui/eq_op.stderr
@@ -1,5 +1,5 @@
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:9:13
+  --> $DIR/eq_op.rs:7:13
    |
 LL |     let _ = 1 == 1;
    |             ^^^^^^
@@ -7,29 +7,37 @@ LL |     let _ = 1 == 1;
    = note: `-D clippy::eq-op` implied by `-D warnings`
 
 error: equal expressions as operands to `==`
-  --> $DIR/eq_op.rs:10:13
+  --> $DIR/eq_op.rs:8:13
    |
 LL |     let _ = "no" == "no";
    |             ^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> $DIR/eq_op.rs:12:13
+  --> $DIR/eq_op.rs:10:13
    |
 LL |     let _ = false != false;
    |             ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `<`
-  --> $DIR/eq_op.rs:13:13
+  --> $DIR/eq_op.rs:11:13
    |
 LL |     let _ = 1.5 < 1.5;
    |             ^^^^^^^^^
 
 error: equal expressions as operands to `>=`
-  --> $DIR/eq_op.rs:14:13
+  --> $DIR/eq_op.rs:12:13
    |
 LL |     let _ = 1u64 >= 1u64;
    |             ^^^^^^^^^^^^
 
+error: equal expressions as operands to `!=`
+  --> $DIR/eq_op.rs:14:13
+   |
+LL |     let _ = x != x;
+   |             ^^^^^^
+   |
+   = note: if you intended to check if the operand is NaN, use `.is_nan()` instead
+
 error: equal expressions as operands to `&`
   --> $DIR/eq_op.rs:17:13
    |
@@ -168,5 +176,5 @@ error: equal expressions as operands to `==`
 LL |     (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 28 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/src/tools/clippy/tests/ui/eq_op_macros.rs b/src/tools/clippy/tests/ui/eq_op_macros.rs
index 6b5b31a1a2e..48240677228 100644
--- a/src/tools/clippy/tests/ui/eq_op_macros.rs
+++ b/src/tools/clippy/tests/ui/eq_op_macros.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::eq_op)]
+#![allow(clippy::useless_vec)]
 
 // lint also in macro definition
 macro_rules! assert_in_macro_def {
diff --git a/src/tools/clippy/tests/ui/eq_op_macros.stderr b/src/tools/clippy/tests/ui/eq_op_macros.stderr
index cd9f1826e59..cb9b0c01862 100644
--- a/src/tools/clippy/tests/ui/eq_op_macros.stderr
+++ b/src/tools/clippy/tests/ui/eq_op_macros.stderr
@@ -1,5 +1,5 @@
 error: identical args used in this `assert_eq!` macro call
-  --> $DIR/eq_op_macros.rs:7:20
+  --> $DIR/eq_op_macros.rs:8:20
    |
 LL |         assert_eq!(a, a);
    |                    ^^^^
@@ -11,7 +11,7 @@ LL |     assert_in_macro_def!();
    = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: identical args used in this `assert_ne!` macro call
-  --> $DIR/eq_op_macros.rs:8:20
+  --> $DIR/eq_op_macros.rs:9:20
    |
 LL |         assert_ne!(a, a);
    |                    ^^^^
@@ -22,7 +22,7 @@ LL |     assert_in_macro_def!();
    = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: identical args used in this `debug_assert_eq!` macro call
-  --> $DIR/eq_op_macros.rs:9:26
+  --> $DIR/eq_op_macros.rs:10:26
    |
 LL |         debug_assert_eq!(a, a);
    |                          ^^^^
@@ -33,7 +33,7 @@ LL |     assert_in_macro_def!();
    = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: identical args used in this `debug_assert_ne!` macro call
-  --> $DIR/eq_op_macros.rs:10:26
+  --> $DIR/eq_op_macros.rs:11:26
    |
 LL |         debug_assert_ne!(a, a);
    |                          ^^^^
@@ -44,49 +44,49 @@ LL |     assert_in_macro_def!();
    = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: identical args used in this `assert_eq!` macro call
-  --> $DIR/eq_op_macros.rs:22:16
+  --> $DIR/eq_op_macros.rs:23:16
    |
 LL |     assert_eq!(a, a);
    |                ^^^^
 
 error: identical args used in this `assert_eq!` macro call
-  --> $DIR/eq_op_macros.rs:23:16
+  --> $DIR/eq_op_macros.rs:24:16
    |
 LL |     assert_eq!(a + 1, a + 1);
    |                ^^^^^^^^^^^^
 
 error: identical args used in this `assert_ne!` macro call
-  --> $DIR/eq_op_macros.rs:30:16
+  --> $DIR/eq_op_macros.rs:31:16
    |
 LL |     assert_ne!(a, a);
    |                ^^^^
 
 error: identical args used in this `assert_ne!` macro call
-  --> $DIR/eq_op_macros.rs:31:16
+  --> $DIR/eq_op_macros.rs:32:16
    |
 LL |     assert_ne!(a + 1, a + 1);
    |                ^^^^^^^^^^^^
 
 error: identical args used in this `debug_assert_eq!` macro call
-  --> $DIR/eq_op_macros.rs:38:22
+  --> $DIR/eq_op_macros.rs:39:22
    |
 LL |     debug_assert_eq!(a, a);
    |                      ^^^^
 
 error: identical args used in this `debug_assert_eq!` macro call
-  --> $DIR/eq_op_macros.rs:39:22
+  --> $DIR/eq_op_macros.rs:40:22
    |
 LL |     debug_assert_eq!(a + 1, a + 1);
    |                      ^^^^^^^^^^^^
 
 error: identical args used in this `debug_assert_ne!` macro call
-  --> $DIR/eq_op_macros.rs:46:22
+  --> $DIR/eq_op_macros.rs:47:22
    |
 LL |     debug_assert_ne!(a, a);
    |                      ^^^^
 
 error: identical args used in this `debug_assert_ne!` macro call
-  --> $DIR/eq_op_macros.rs:47:22
+  --> $DIR/eq_op_macros.rs:48:22
    |
 LL |     debug_assert_ne!(a + 1, a + 1);
    |                      ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.fixed b/src/tools/clippy/tests/ui/equatable_if_let.fixed
index 53e62760bef..6cc070fb552 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.fixed
+++ b/src/tools/clippy/tests/ui/equatable_if_let.fixed
@@ -1,7 +1,12 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
-
-#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
+//@aux-build:proc_macros.rs:proc-macro
+
+#![allow(
+    unused_variables,
+    dead_code,
+    clippy::derive_partial_eq_without_eq,
+    clippy::needless_if
+)]
 #![warn(clippy::equatable_if_let)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.rs b/src/tools/clippy/tests/ui/equatable_if_let.rs
index 55918a5bb11..f00a129bef1 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.rs
+++ b/src/tools/clippy/tests/ui/equatable_if_let.rs
@@ -1,7 +1,12 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
-
-#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
+//@aux-build:proc_macros.rs:proc-macro
+
+#![allow(
+    unused_variables,
+    dead_code,
+    clippy::derive_partial_eq_without_eq,
+    clippy::needless_if
+)]
 #![warn(clippy::equatable_if_let)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.stderr b/src/tools/clippy/tests/ui/equatable_if_let.stderr
index a72d87bb7ba..649495dded7 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.stderr
+++ b/src/tools/clippy/tests/ui/equatable_if_let.stderr
@@ -1,5 +1,5 @@
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:60:8
+  --> $DIR/equatable_if_let.rs:65:8
    |
 LL |     if let 2 = a {}
    |        ^^^^^^^^^ help: try: `a == 2`
@@ -7,79 +7,79 @@ LL |     if let 2 = a {}
    = note: `-D clippy::equatable-if-let` implied by `-D warnings`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:61:8
+  --> $DIR/equatable_if_let.rs:66:8
    |
 LL |     if let Ordering::Greater = a.cmp(&b) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:62:8
+  --> $DIR/equatable_if_let.rs:67:8
    |
 LL |     if let Some(2) = c {}
    |        ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:63:8
+  --> $DIR/equatable_if_let.rs:68:8
    |
 LL |     if let Struct { a: 2, b: false } = d {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:64:8
+  --> $DIR/equatable_if_let.rs:69:8
    |
 LL |     if let Enum::TupleVariant(32, 64) = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:65:8
+  --> $DIR/equatable_if_let.rs:70:8
    |
 LL |     if let Enum::RecordVariant { a: 64, b: 32 } = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:66:8
+  --> $DIR/equatable_if_let.rs:71:8
    |
 LL |     if let Enum::UnitVariant = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:67:8
+  --> $DIR/equatable_if_let.rs:72:8
    |
 LL |     if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using `matches!`
-  --> $DIR/equatable_if_let.rs:76:8
+  --> $DIR/equatable_if_let.rs:81:8
    |
 LL |     if let NotPartialEq::A = f {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:77:8
+  --> $DIR/equatable_if_let.rs:82:8
    |
 LL |     if let NotStructuralEq::A = g {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
 
 error: this pattern matching can be expressed using `matches!`
-  --> $DIR/equatable_if_let.rs:78:8
+  --> $DIR/equatable_if_let.rs:83:8
    |
 LL |     if let Some(NotPartialEq::A) = Some(f) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:79:8
+  --> $DIR/equatable_if_let.rs:84:8
    |
 LL |     if let Some(NotStructuralEq::A) = Some(g) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
 
 error: this pattern matching can be expressed using `matches!`
-  --> $DIR/equatable_if_let.rs:80:8
+  --> $DIR/equatable_if_let.rs:85:8
    |
 LL |     if let NoPartialEqStruct { a: 2, b: false } = h {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:82:8
+  --> $DIR/equatable_if_let.rs:87:8
    |
 LL |     if let inline!("abc") = "abc" {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
diff --git a/src/tools/clippy/tests/ui/err_expect.fixed b/src/tools/clippy/tests/ui/err_expect.fixed
index 6ade6f54689..46e2816da52 100644
--- a/src/tools/clippy/tests/ui/err_expect.fixed
+++ b/src/tools/clippy/tests/ui/err_expect.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused)]
+#![allow(unused, clippy::unnecessary_literal_unwrap)]
 
 struct MyTypeNonDebug;
 
diff --git a/src/tools/clippy/tests/ui/err_expect.rs b/src/tools/clippy/tests/ui/err_expect.rs
index a93fb59493f..b9446034d50 100644
--- a/src/tools/clippy/tests/ui/err_expect.rs
+++ b/src/tools/clippy/tests/ui/err_expect.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused)]
+#![allow(unused, clippy::unnecessary_literal_unwrap)]
 
 struct MyTypeNonDebug;
 
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index b1baf462c0f..bf44bcb564e 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -7,7 +7,8 @@
     clippy::no_effect,
     clippy::option_map_unit_fn,
     clippy::redundant_closure_call,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 use std::path::{Path, PathBuf};
@@ -46,6 +47,12 @@ fn main() {
 
     // issue #7224
     let _: Option<Vec<u32>> = Some(0).map(|_| vec![]);
+
+    // issue #10684
+    fn test<T>(x: impl Fn(usize, usize) -> T) -> T {
+        x(1, 2)
+    }
+    test(|start, end| start..=end);
 }
 
 trait TestTrait {
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index e113c3d6cd6..b2af4bf0953 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -7,7 +7,8 @@
     clippy::no_effect,
     clippy::option_map_unit_fn,
     clippy::redundant_closure_call,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 use std::path::{Path, PathBuf};
@@ -46,6 +47,12 @@ fn main() {
 
     // issue #7224
     let _: Option<Vec<u32>> = Some(0).map(|_| vec![]);
+
+    // issue #10684
+    fn test<T>(x: impl Fn(usize, usize) -> T) -> T {
+        x(1, 2)
+    }
+    test(|start, end| start..=end);
 }
 
 trait TestTrait {
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index a521fb86860..0ac0b901df4 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -1,5 +1,5 @@
 error: redundant closure
-  --> $DIR/eta.rs:28:27
+  --> $DIR/eta.rs:29:27
    |
 LL |     let a = Some(1u8).map(|a| foo(a));
    |                           ^^^^^^^^^^ help: replace the closure with the function itself: `foo`
@@ -7,31 +7,31 @@ LL |     let a = Some(1u8).map(|a| foo(a));
    = note: `-D clippy::redundant-closure` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:32:40
+  --> $DIR/eta.rs:33:40
    |
 LL |     let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec!
    |                                        ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new`
 
 error: redundant closure
-  --> $DIR/eta.rs:33:35
+  --> $DIR/eta.rs:34:35
    |
 LL |     let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted?
    |                                   ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2`
 
 error: redundant closure
-  --> $DIR/eta.rs:34:26
+  --> $DIR/eta.rs:35:26
    |
 LL |     all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
    |                          ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below`
 
 error: redundant closure
-  --> $DIR/eta.rs:41:27
+  --> $DIR/eta.rs:42:27
    |
 LL |     let e = Some(1u8).map(|a| generic(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
 
 error: redundant closure
-  --> $DIR/eta.rs:87:51
+  --> $DIR/eta.rs:94:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    |                                                   ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@@ -39,121 +39,121 @@ LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:88:51
+  --> $DIR/eta.rs:95:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
    |                                                   ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo`
 
 error: redundant closure
-  --> $DIR/eta.rs:90:42
+  --> $DIR/eta.rs:97:42
    |
 LL |     let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
    |                                          ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear`
 
 error: redundant closure
-  --> $DIR/eta.rs:94:29
+  --> $DIR/eta.rs:101:29
    |
 LL |     let e = Some("str").map(|s| s.to_string());
    |                             ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string`
 
 error: redundant closure
-  --> $DIR/eta.rs:95:27
+  --> $DIR/eta.rs:102:27
    |
 LL |     let e = Some('a').map(|s| s.to_uppercase());
    |                           ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase`
 
 error: redundant closure
-  --> $DIR/eta.rs:97:65
+  --> $DIR/eta.rs:104:65
    |
 LL |     let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect();
    |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
 
 error: redundant closure
-  --> $DIR/eta.rs:160:22
+  --> $DIR/eta.rs:167:22
    |
 LL |     requires_fn_once(|| x());
    |                      ^^^^^^ help: replace the closure with the function itself: `x`
 
 error: redundant closure
-  --> $DIR/eta.rs:167:27
+  --> $DIR/eta.rs:174:27
    |
 LL |     let a = Some(1u8).map(|a| foo_ptr(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
 
 error: redundant closure
-  --> $DIR/eta.rs:172:27
+  --> $DIR/eta.rs:179:27
    |
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
 
 error: redundant closure
-  --> $DIR/eta.rs:204:28
+  --> $DIR/eta.rs:211:28
    |
 LL |     x.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> $DIR/eta.rs:205:28
+  --> $DIR/eta.rs:212:28
    |
 LL |     y.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> $DIR/eta.rs:206:28
+  --> $DIR/eta.rs:213:28
    |
 LL |     z.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
 
 error: redundant closure
-  --> $DIR/eta.rs:213:21
+  --> $DIR/eta.rs:220:21
    |
 LL |         Some(1).map(|n| closure(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
 
 error: redundant closure
-  --> $DIR/eta.rs:217:21
+  --> $DIR/eta.rs:224:21
    |
 LL |         Some(1).map(|n| in_loop(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
 
 error: redundant closure
-  --> $DIR/eta.rs:310:18
+  --> $DIR/eta.rs:317:18
    |
 LL |     takes_fn_mut(|| f());
    |                  ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> $DIR/eta.rs:313:19
+  --> $DIR/eta.rs:320:19
    |
 LL |     takes_fn_once(|| f());
    |                   ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> $DIR/eta.rs:317:26
+  --> $DIR/eta.rs:324:26
    |
 LL |     move || takes_fn_mut(|| f_used_once())
    |                          ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
 
 error: redundant closure
-  --> $DIR/eta.rs:329:19
+  --> $DIR/eta.rs:336:19
    |
 LL |     array_opt.map(|a| a.as_slice());
    |                   ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice`
 
 error: redundant closure
-  --> $DIR/eta.rs:332:19
+  --> $DIR/eta.rs:339:19
    |
 LL |     slice_opt.map(|s| s.len());
    |                   ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len`
 
 error: redundant closure
-  --> $DIR/eta.rs:335:17
+  --> $DIR/eta.rs:342:17
    |
 LL |     ptr_opt.map(|p| p.is_null());
    |                 ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null`
 
 error: redundant closure
-  --> $DIR/eta.rs:339:17
+  --> $DIR/eta.rs:346:17
    |
 LL |     dyn_opt.map(|d| d.method_on_dyn());
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
diff --git a/src/tools/clippy/tests/ui/excessive_precision.fixed b/src/tools/clippy/tests/ui/excessive_precision.fixed
index 0a07957386c..7bb4da453c1 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.fixed
+++ b/src/tools/clippy/tests/ui/excessive_precision.fixed
@@ -1,6 +1,12 @@
 //@run-rustfix
 #![warn(clippy::excessive_precision)]
-#![allow(dead_code, unused_variables, clippy::print_literal)]
+#![allow(
+    dead_code,
+    overflowing_literals,
+    unused_variables,
+    clippy::print_literal,
+    clippy::useless_vec
+)]
 
 fn main() {
     // Consts
@@ -66,4 +72,11 @@ fn main() {
 
     // issue #7745
     let _ = 0_f64;
+
+    // issue #9910
+    const INF1: f32 = 1.0e+33f32;
+    const INF2: f64 = 1.0e+3300f64;
+    const NEG_INF1: f32 = -1.0e+33f32;
+    const NEG_INF2: f64 = -1.0e+3300f64;
+    const NEG_INF3: f32 = -3.40282357e+38_f32;
 }
diff --git a/src/tools/clippy/tests/ui/excessive_precision.rs b/src/tools/clippy/tests/ui/excessive_precision.rs
index 62a832caa67..e8d6ab6870a 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.rs
+++ b/src/tools/clippy/tests/ui/excessive_precision.rs
@@ -1,6 +1,12 @@
 //@run-rustfix
 #![warn(clippy::excessive_precision)]
-#![allow(dead_code, unused_variables, clippy::print_literal)]
+#![allow(
+    dead_code,
+    overflowing_literals,
+    unused_variables,
+    clippy::print_literal,
+    clippy::useless_vec
+)]
 
 fn main() {
     // Consts
@@ -66,4 +72,11 @@ fn main() {
 
     // issue #7745
     let _ = 1.000_000_000_000_001e-324_f64;
+
+    // issue #9910
+    const INF1: f32 = 1.0e+33f32;
+    const INF2: f64 = 1.0e+3300f64;
+    const NEG_INF1: f32 = -1.0e+33f32;
+    const NEG_INF2: f64 = -1.0e+3300f64;
+    const NEG_INF3: f32 = -3.40282357e+38_f32;
 }
diff --git a/src/tools/clippy/tests/ui/excessive_precision.stderr b/src/tools/clippy/tests/ui/excessive_precision.stderr
index 42d9d4de193..348ad183d7d 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.stderr
+++ b/src/tools/clippy/tests/ui/excessive_precision.stderr
@@ -1,5 +1,5 @@
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:15:26
+  --> $DIR/excessive_precision.rs:21:26
    |
 LL |     const BAD32_1: f32 = 0.123_456_789_f32;
    |                          ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32`
@@ -7,85 +7,85 @@ LL |     const BAD32_1: f32 = 0.123_456_789_f32;
    = note: `-D clippy::excessive-precision` implied by `-D warnings`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:16:26
+  --> $DIR/excessive_precision.rs:22:26
    |
 LL |     const BAD32_2: f32 = 0.123_456_789;
    |                          ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:17:26
+  --> $DIR/excessive_precision.rs:23:26
    |
 LL |     const BAD32_3: f32 = 0.100_000_000_000_1;
    |                          ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:18:29
+  --> $DIR/excessive_precision.rs:24:29
    |
 LL |     const BAD32_EDGE: f32 = 1.000_000_9;
    |                             ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:22:26
+  --> $DIR/excessive_precision.rs:28:26
    |
 LL |     const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:25:22
+  --> $DIR/excessive_precision.rs:31:22
    |
 LL |     println!("{:?}", 8.888_888_888_888_888_888_888);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:36:22
+  --> $DIR/excessive_precision.rs:42:22
    |
 LL |     let bad32: f32 = 1.123_456_789;
    |                      ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:37:26
+  --> $DIR/excessive_precision.rs:43:26
    |
 LL |     let bad32_suf: f32 = 1.123_456_789_f32;
    |                          ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:38:21
+  --> $DIR/excessive_precision.rs:44:21
    |
 LL |     let bad32_inf = 1.123_456_789_f32;
    |                     ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:48:36
+  --> $DIR/excessive_precision.rs:54:36
    |
 LL |     let bad_vec32: Vec<f32> = vec![0.123_456_789];
    |                                    ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:49:36
+  --> $DIR/excessive_precision.rs:55:36
    |
 LL |     let bad_vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:53:24
+  --> $DIR/excessive_precision.rs:59:24
    |
 LL |     let bad_e32: f32 = 1.123_456_788_888e-10;
    |                        ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:56:27
+  --> $DIR/excessive_precision.rs:62:27
    |
 LL |     let bad_bige32: f32 = 1.123_456_788_888E-10;
    |                           ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:65:13
+  --> $DIR/excessive_precision.rs:71:13
    |
 LL |     let _ = 2.225_073_858_507_201_1e-308_f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:68:13
+  --> $DIR/excessive_precision.rs:74:13
    |
 LL |     let _ = 1.000_000_000_000_001e-324_f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64`
diff --git a/src/tools/clippy/tests/ui/expect.rs b/src/tools/clippy/tests/ui/expect.rs
index d742595e14d..1588579bb0f 100644
--- a/src/tools/clippy/tests/ui/expect.rs
+++ b/src/tools/clippy/tests/ui/expect.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::expect_used)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn expect_option() {
     let opt = Some(0);
diff --git a/src/tools/clippy/tests/ui/expect.stderr b/src/tools/clippy/tests/ui/expect.stderr
index c08e0dbbf74..be340340d47 100644
--- a/src/tools/clippy/tests/ui/expect.stderr
+++ b/src/tools/clippy/tests/ui/expect.stderr
@@ -1,5 +1,5 @@
 error: used `expect()` on an `Option` value
-  --> $DIR/expect.rs:5:13
+  --> $DIR/expect.rs:6:13
    |
 LL |     let _ = opt.expect("");
    |             ^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let _ = opt.expect("");
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `expect()` on a `Result` value
-  --> $DIR/expect.rs:10:13
+  --> $DIR/expect.rs:11:13
    |
 LL |     let _ = res.expect("");
    |             ^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     let _ = res.expect("");
    = help: if this value is an `Err`, it will panic
 
 error: used `expect_err()` on a `Result` value
-  --> $DIR/expect.rs:11:13
+  --> $DIR/expect.rs:12:13
    |
 LL |     let _ = res.expect_err("");
    |             ^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.fixed b/src/tools/clippy/tests/ui/expect_fun_call.fixed
index 8e97054fb6b..73c6c97de84 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/expect_fun_call.fixed
@@ -1,6 +1,10 @@
 //@run-rustfix
 #![warn(clippy::expect_fun_call)]
-#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)]
+#![allow(
+    clippy::to_string_in_format_args,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap
+)]
 
 /// Checks implementation of the `EXPECT_FUN_CALL` lint
 
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.rs b/src/tools/clippy/tests/ui/expect_fun_call.rs
index 31e6bcc7ff6..a786138631c 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.rs
+++ b/src/tools/clippy/tests/ui/expect_fun_call.rs
@@ -1,6 +1,10 @@
 //@run-rustfix
 #![warn(clippy::expect_fun_call)]
-#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)]
+#![allow(
+    clippy::to_string_in_format_args,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap
+)]
 
 /// Checks implementation of the `EXPECT_FUN_CALL` lint
 
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.stderr b/src/tools/clippy/tests/ui/expect_fun_call.stderr
index cb55e32aee0..36fb0e5de15 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/expect_fun_call.stderr
@@ -1,5 +1,5 @@
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:34:26
+  --> $DIR/expect_fun_call.rs:38:26
    |
 LL |     with_none_and_format.expect(&format!("Error {}: fake error", error_code));
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
@@ -7,85 +7,85 @@ LL |     with_none_and_format.expect(&format!("Error {}: fake error", error_code
    = note: `-D clippy::expect-fun-call` implied by `-D warnings`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:37:26
+  --> $DIR/expect_fun_call.rs:41:26
    |
 LL |     with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:40:37
+  --> $DIR/expect_fun_call.rs:44:37
    |
 LL |     with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str());
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:50:25
+  --> $DIR/expect_fun_call.rs:54:25
    |
 LL |     with_err_and_format.expect(&format!("Error {}: fake error", error_code));
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:53:25
+  --> $DIR/expect_fun_call.rs:57:25
    |
 LL |     with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:65:17
+  --> $DIR/expect_fun_call.rs:69:17
    |
 LL |     Some("foo").expect(format!("{} {}", 1, 2).as_ref());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:86:21
+  --> $DIR/expect_fun_call.rs:90:21
    |
 LL |         Some("foo").expect(&get_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:87:21
+  --> $DIR/expect_fun_call.rs:91:21
    |
 LL |         Some("foo").expect(get_string().as_ref());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:88:21
+  --> $DIR/expect_fun_call.rs:92:21
    |
 LL |         Some("foo").expect(get_string().as_str());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:90:21
+  --> $DIR/expect_fun_call.rs:94:21
    |
 LL |         Some("foo").expect(get_static_str());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:91:21
+  --> $DIR/expect_fun_call.rs:95:21
    |
 LL |         Some("foo").expect(get_non_static_str(&0));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:95:16
+  --> $DIR/expect_fun_call.rs:99:16
    |
 LL |     Some(true).expect(&format!("key {}, {}", 1, 2));
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:101:17
+  --> $DIR/expect_fun_call.rs:105:17
    |
 LL |         opt_ref.expect(&format!("{:?}", opt_ref));
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:105:20
+  --> $DIR/expect_fun_call.rs:109:20
    |
 LL |     format_capture.expect(&format!("{error_code}"));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}"))`
 
 error: use of `expect` followed by a function call
-  --> $DIR/expect_fun_call.rs:108:30
+  --> $DIR/expect_fun_call.rs:112:30
    |
 LL |     format_capture_and_value.expect(&format!("{error_code}, {}", 1));
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}, {}", 1))`
diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs
index 0415e33b3fa..2460f33434d 100644
--- a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs
+++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs
@@ -1,4 +1,3 @@
-// check-pass
 #![feature(lint_reasons)]
 //! This file tests the `#[expect]` attribute implementation for tool lints. The same
 //! file is used to test clippy and rustdoc. Any changes to this file should be synced
@@ -12,6 +11,7 @@
 //! This test can't cover every lint from Clippy, rustdoc and potentially other
 //! tools that will be developed. This therefore only tests a small subset of lints
 #![expect(rustdoc::missing_crate_level_docs)]
+#![allow(clippy::needless_if)]
 
 mod rustc_ok {
     //! See <https://doc.rust-lang.org/rustc/lints/index.html>
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.rs b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
index 46565a97f00..e02b8f62b3d 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.rs
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::explicit_counter_loop)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::useless_vec)]
 
 fn main() {
     let mut vec = vec![1, 2, 3, 4];
@@ -23,6 +23,54 @@ fn main() {
     for _v in vec {
         _index += 1;
     }
+
+    let vec = [1, 2, 3, 4];
+    // Potential false positives
+    let mut _index = 0;
+    _index = 1;
+    for _v in &vec {
+        _index += 1
+    }
+
+    let mut _index = 0;
+    _index += 1;
+    for _v in &vec {
+        _index += 1
+    }
+
+    let mut _index = 0;
+    for _v in &vec {
+        _index = 1;
+        _index += 1
+    }
+
+    let mut _index = 0;
+    for _v in &vec {
+        let mut _index = 0;
+        _index += 1
+    }
+
+    let mut _index = 0;
+    for _v in &vec {
+        _index += 1;
+        _index = 0;
+    }
+
+    let mut _index = 0;
+    if true {
+        _index = 1
+    };
+    for _v in &vec {
+        _index += 1
+    }
+
+    let mut _index = 1;
+    if false {
+        _index = 0
+    };
+    for _v in &vec {
+        _index += 1
+    }
 }
 
 mod issue_1219 {
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.stderr b/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
index d3f3c626bbd..0677e4d78c8 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
@@ -25,31 +25,31 @@ LL |     for _v in vec {
    |     ^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.into_iter().enumerate()`
 
 error: the variable `count` is used as a loop counter
-  --> $DIR/explicit_counter_loop.rs:62:9
+  --> $DIR/explicit_counter_loop.rs:110:9
    |
 LL |         for ch in text.chars() {
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()`
 
 error: the variable `count` is used as a loop counter
-  --> $DIR/explicit_counter_loop.rs:73:9
+  --> $DIR/explicit_counter_loop.rs:121:9
    |
 LL |         for ch in text.chars() {
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()`
 
 error: the variable `count` is used as a loop counter
-  --> $DIR/explicit_counter_loop.rs:131:9
+  --> $DIR/explicit_counter_loop.rs:179:9
    |
 LL |         for _i in 3..10 {
    |         ^^^^^^^^^^^^^^^ help: consider using: `for (count, _i) in (3..10).enumerate()`
 
 error: the variable `idx_usize` is used as a loop counter
-  --> $DIR/explicit_counter_loop.rs:171:9
+  --> $DIR/explicit_counter_loop.rs:219:9
    |
 LL |         for _item in slice {
    |         ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_usize, _item) in slice.iter().enumerate()`
 
 error: the variable `idx_u32` is used as a loop counter
-  --> $DIR/explicit_counter_loop.rs:183:9
+  --> $DIR/explicit_counter_loop.rs:231:9
    |
 LL |         for _item in slice {
    |         ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_u32, _item) in (0_u32..).zip(slice.iter())`
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
index 60482c66da7..4d72b58cdf8 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
@@ -1,12 +1,14 @@
 //@run-rustfix
 #![warn(clippy::explicit_deref_methods)]
-#![allow(unused_variables)]
+#![allow(unused_variables, unused_must_use)]
 #![allow(
     clippy::borrow_deref_ref,
     suspicious_double_ref_op,
     clippy::explicit_auto_deref,
     clippy::needless_borrow,
-    clippy::uninlined_format_args
+    clippy::no_effect,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap
 )]
 
 use std::ops::{Deref, DerefMut};
@@ -28,6 +30,22 @@ impl Deref for CustomVec {
     }
 }
 
+struct Aaa;
+
+impl Deref for Aaa {
+    type Target = ();
+
+    fn deref(&self) -> &Self::Target {
+        todo!();
+    }
+}
+
+impl DerefMut for Aaa {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        todo!();
+    }
+}
+
 fn main() {
     let a: &mut String = &mut String::from("foo");
 
@@ -58,6 +76,17 @@ fn main() {
     let opt_a = Some(a.clone());
     let b = &*opt_a.unwrap();
 
+    // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified
+    // syntax
+
+    Aaa::deref(&Aaa);
+    Aaa::deref_mut(&mut Aaa);
+    <Aaa as Deref>::deref(&Aaa);
+    <Aaa as DerefMut>::deref_mut(&mut Aaa);
+    let mut aaa = Aaa;
+    Aaa::deref(&aaa);
+    Aaa::deref_mut(&mut aaa);
+
     // following should not require linting
 
     let cv = CustomVec(vec![0, 42]);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
index e3613e216bb..fcd945de338 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
@@ -1,12 +1,14 @@
 //@run-rustfix
 #![warn(clippy::explicit_deref_methods)]
-#![allow(unused_variables)]
+#![allow(unused_variables, unused_must_use)]
 #![allow(
     clippy::borrow_deref_ref,
     suspicious_double_ref_op,
     clippy::explicit_auto_deref,
     clippy::needless_borrow,
-    clippy::uninlined_format_args
+    clippy::no_effect,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap
 )]
 
 use std::ops::{Deref, DerefMut};
@@ -28,6 +30,22 @@ impl Deref for CustomVec {
     }
 }
 
+struct Aaa;
+
+impl Deref for Aaa {
+    type Target = ();
+
+    fn deref(&self) -> &Self::Target {
+        todo!();
+    }
+}
+
+impl DerefMut for Aaa {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        todo!();
+    }
+}
+
 fn main() {
     let a: &mut String = &mut String::from("foo");
 
@@ -58,6 +76,17 @@ fn main() {
     let opt_a = Some(a.clone());
     let b = opt_a.unwrap().deref();
 
+    // make sure `Aaa::deref` instead of `aaa.deref()` is not linted, as well as fully qualified
+    // syntax
+
+    Aaa::deref(&Aaa);
+    Aaa::deref_mut(&mut Aaa);
+    <Aaa as Deref>::deref(&Aaa);
+    <Aaa as DerefMut>::deref_mut(&mut Aaa);
+    let mut aaa = Aaa;
+    Aaa::deref(&aaa);
+    Aaa::deref_mut(&mut aaa);
+
     // following should not require linting
 
     let cv = CustomVec(vec![0, 42]);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
index 4b10ed1377b..d025035b789 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
@@ -1,5 +1,5 @@
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:36:19
+  --> $DIR/explicit_deref_methods.rs:54:19
    |
 LL |     let b: &str = a.deref();
    |                   ^^^^^^^^^ help: try this: `&*a`
@@ -7,67 +7,67 @@ LL |     let b: &str = a.deref();
    = note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
 
 error: explicit `deref_mut` method call
-  --> $DIR/explicit_deref_methods.rs:38:23
+  --> $DIR/explicit_deref_methods.rs:56:23
    |
 LL |     let b: &mut str = a.deref_mut();
    |                       ^^^^^^^^^^^^^ help: try this: `&mut **a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:41:39
+  --> $DIR/explicit_deref_methods.rs:59:39
    |
 LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
    |                                       ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:41:50
+  --> $DIR/explicit_deref_methods.rs:59:50
    |
 LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
    |                                                  ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:43:20
+  --> $DIR/explicit_deref_methods.rs:61:20
    |
 LL |     println!("{}", a.deref());
    |                    ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:46:11
+  --> $DIR/explicit_deref_methods.rs:64:11
    |
 LL |     match a.deref() {
    |           ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:50:28
+  --> $DIR/explicit_deref_methods.rs:68:28
    |
 LL |     let b: String = concat(a.deref());
    |                            ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:52:13
+  --> $DIR/explicit_deref_methods.rs:70:13
    |
 LL |     let b = just_return(a).deref();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:54:28
+  --> $DIR/explicit_deref_methods.rs:72:28
    |
 LL |     let b: String = concat(just_return(a).deref());
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:56:19
+  --> $DIR/explicit_deref_methods.rs:74:19
    |
 LL |     let b: &str = a.deref().deref();
    |                   ^^^^^^^^^^^^^^^^^ help: try this: `&**a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:59:13
+  --> $DIR/explicit_deref_methods.rs:77:13
    |
 LL |     let b = opt_a.unwrap().deref();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:85:31
+  --> $DIR/explicit_deref_methods.rs:114:31
    |
 LL |     let b: &str = expr_deref!(a.deref());
    |                               ^^^^^^^^^ help: try this: `&*a`
diff --git a/src/tools/clippy/tests/ui/explicit_into_iter_loop.fixed b/src/tools/clippy/tests/ui/explicit_into_iter_loop.fixed
new file mode 100644
index 00000000000..dcef6340311
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_into_iter_loop.fixed
@@ -0,0 +1,69 @@
+//@run-rustfix
+#![warn(clippy::explicit_into_iter_loop)]
+
+fn main() {
+    // Issue #4958
+    fn _takes_iterator<T>(iterator: &T)
+    where
+        for<'a> &'a T: IntoIterator<Item = &'a String>,
+    {
+        for _ in iterator {}
+    }
+
+    struct T;
+    impl IntoIterator for &T {
+        type Item = ();
+        type IntoIter = std::vec::IntoIter<Self::Item>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+
+    let mut t = T;
+    for _ in &t {}
+
+    let r = &t;
+    for _ in r {}
+
+    // No suggestion for this.
+    // We'd have to suggest `for _ in *rr {}` which is less clear.
+    let rr = &&t;
+    for _ in rr.into_iter() {}
+
+    let mr = &mut t;
+    for _ in &*mr {}
+
+    struct U;
+    impl IntoIterator for &mut U {
+        type Item = ();
+        type IntoIter = std::vec::IntoIter<Self::Item>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+
+    let mut u = U;
+    for _ in &mut u {}
+
+    let mr = &mut u;
+    for _ in &mut *mr {}
+
+    // Issue #6900
+    struct S;
+    impl S {
+        #[allow(clippy::should_implement_trait)]
+        pub fn into_iter<T>(self) -> I<T> {
+            unimplemented!()
+        }
+    }
+
+    struct I<T>(T);
+    impl<T> Iterator for I<T> {
+        type Item = T;
+        fn next(&mut self) -> Option<Self::Item> {
+            unimplemented!()
+        }
+    }
+
+    for _ in S.into_iter::<u32>() {}
+}
diff --git a/src/tools/clippy/tests/ui/explicit_into_iter_loop.rs b/src/tools/clippy/tests/ui/explicit_into_iter_loop.rs
new file mode 100644
index 00000000000..bc048ed302b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_into_iter_loop.rs
@@ -0,0 +1,69 @@
+//@run-rustfix
+#![warn(clippy::explicit_into_iter_loop)]
+
+fn main() {
+    // Issue #4958
+    fn _takes_iterator<T>(iterator: &T)
+    where
+        for<'a> &'a T: IntoIterator<Item = &'a String>,
+    {
+        for _ in iterator.into_iter() {}
+    }
+
+    struct T;
+    impl IntoIterator for &T {
+        type Item = ();
+        type IntoIter = std::vec::IntoIter<Self::Item>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+
+    let mut t = T;
+    for _ in t.into_iter() {}
+
+    let r = &t;
+    for _ in r.into_iter() {}
+
+    // No suggestion for this.
+    // We'd have to suggest `for _ in *rr {}` which is less clear.
+    let rr = &&t;
+    for _ in rr.into_iter() {}
+
+    let mr = &mut t;
+    for _ in mr.into_iter() {}
+
+    struct U;
+    impl IntoIterator for &mut U {
+        type Item = ();
+        type IntoIter = std::vec::IntoIter<Self::Item>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+
+    let mut u = U;
+    for _ in u.into_iter() {}
+
+    let mr = &mut u;
+    for _ in mr.into_iter() {}
+
+    // Issue #6900
+    struct S;
+    impl S {
+        #[allow(clippy::should_implement_trait)]
+        pub fn into_iter<T>(self) -> I<T> {
+            unimplemented!()
+        }
+    }
+
+    struct I<T>(T);
+    impl<T> Iterator for I<T> {
+        type Item = T;
+        fn next(&mut self) -> Option<Self::Item> {
+            unimplemented!()
+        }
+    }
+
+    for _ in S.into_iter::<u32>() {}
+}
diff --git a/src/tools/clippy/tests/ui/explicit_into_iter_loop.stderr b/src/tools/clippy/tests/ui/explicit_into_iter_loop.stderr
new file mode 100644
index 00000000000..fa89b884fa0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_into_iter_loop.stderr
@@ -0,0 +1,40 @@
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> $DIR/explicit_into_iter_loop.rs:10:18
+   |
+LL |         for _ in iterator.into_iter() {}
+   |                  ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator`
+   |
+   = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
+
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> $DIR/explicit_into_iter_loop.rs:23:14
+   |
+LL |     for _ in t.into_iter() {}
+   |              ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t`
+
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> $DIR/explicit_into_iter_loop.rs:26:14
+   |
+LL |     for _ in r.into_iter() {}
+   |              ^^^^^^^^^^^^^ help: to write this more concisely, try: `r`
+
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> $DIR/explicit_into_iter_loop.rs:34:14
+   |
+LL |     for _ in mr.into_iter() {}
+   |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*mr`
+
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> $DIR/explicit_into_iter_loop.rs:46:14
+   |
+LL |     for _ in u.into_iter() {}
+   |              ^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut u`
+
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> $DIR/explicit_into_iter_loop.rs:49:14
+   |
+LL |     for _ in mr.into_iter() {}
+   |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *mr`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed
new file mode 100644
index 00000000000..746ef813c04
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed
@@ -0,0 +1,154 @@
+//@run-rustfix
+#![deny(clippy::explicit_iter_loop)]
+#![allow(
+    clippy::linkedlist,
+    clippy::similar_names,
+    clippy::needless_borrow,
+    clippy::deref_addrof,
+    dead_code
+)]
+
+use core::slice;
+use std::collections::*;
+
+fn main() {
+    let mut vec = vec![1, 2, 3, 4];
+
+    for _ in &vec {}
+    for _ in &mut vec {}
+
+    let rvec = &vec;
+    for _ in rvec {}
+
+    let rmvec = &mut vec;
+    for _ in &*rmvec {}
+    for _ in &mut *rmvec {}
+
+    for _ in &vec {} // these are fine
+    for _ in &mut vec {} // these are fine
+
+    for _ in &[1, 2, 3] {}
+
+    for _ in &*(&mut [1, 2, 3]) {}
+
+    for _ in &[0; 32] {}
+    for _ in &[0; 33] {}
+
+    let ll: LinkedList<()> = LinkedList::new();
+    for _ in &ll {}
+    let rll = &ll;
+    for _ in rll {}
+
+    let vd: VecDeque<()> = VecDeque::new();
+    for _ in &vd {}
+    let rvd = &vd;
+    for _ in rvd {}
+
+    let bh: BinaryHeap<()> = BinaryHeap::new();
+    for _ in &bh {}
+
+    let hm: HashMap<(), ()> = HashMap::new();
+    for _ in &hm {}
+
+    let bt: BTreeMap<(), ()> = BTreeMap::new();
+    for _ in &bt {}
+
+    let hs: HashSet<()> = HashSet::new();
+    for _ in &hs {}
+
+    let bs: BTreeSet<()> = BTreeSet::new();
+    for _ in &bs {}
+
+    struct NoIntoIter();
+    impl NoIntoIter {
+        fn iter(&self) -> slice::Iter<u8> {
+            unimplemented!()
+        }
+
+        fn iter_mut(&mut self) -> slice::IterMut<u8> {
+            unimplemented!()
+        }
+    }
+    let mut x = NoIntoIter();
+    for _ in x.iter() {} // no error
+    for _ in x.iter_mut() {} // no error
+
+    struct IntoIterDiffTy;
+    impl IntoIterator for &'_ IntoIterDiffTy {
+        type Item = &'static ();
+        type IntoIter = core::slice::Iter<'static, ()>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl IntoIterDiffTy {
+        fn iter(&self) -> core::slice::Iter<'static, i32> {
+            unimplemented!()
+        }
+    }
+    let x = IntoIterDiffTy;
+    for _ in x.iter() {}
+
+    struct IntoIterDiffSig;
+    impl IntoIterator for &'_ IntoIterDiffSig {
+        type Item = &'static ();
+        type IntoIter = core::slice::Iter<'static, ()>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl IntoIterDiffSig {
+        fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> {
+            unimplemented!()
+        }
+    }
+    let x = IntoIterDiffSig;
+    for _ in x.iter(0) {}
+
+    struct IntoIterDiffLt<'a>(&'a ());
+    impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> {
+        type Item = &'a ();
+        type IntoIter = core::slice::Iter<'a, ()>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl<'a> IntoIterDiffLt<'a> {
+        fn iter(&self) -> core::slice::Iter<'a, ()> {
+            unimplemented!()
+        }
+    }
+    let x = IntoIterDiffLt(&());
+    for _ in x.iter() {}
+
+    struct CustomType;
+    impl<'a> IntoIterator for &'a CustomType {
+        type Item = &'a u32;
+        type IntoIter = core::slice::Iter<'a, u32>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl<'a> IntoIterator for &'a mut CustomType {
+        type Item = &'a mut u32;
+        type IntoIter = core::slice::IterMut<'a, u32>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl CustomType {
+        fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter {
+            panic!()
+        }
+
+        fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> {
+            panic!()
+        }
+    }
+    let mut x = CustomType;
+    for _ in &x {}
+    for _ in &mut x {}
+
+    let r = &x;
+    for _ in r {}
+}
diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.rs b/src/tools/clippy/tests/ui/explicit_iter_loop.rs
new file mode 100644
index 00000000000..fba230ee0ee
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_iter_loop.rs
@@ -0,0 +1,154 @@
+//@run-rustfix
+#![deny(clippy::explicit_iter_loop)]
+#![allow(
+    clippy::linkedlist,
+    clippy::similar_names,
+    clippy::needless_borrow,
+    clippy::deref_addrof,
+    dead_code
+)]
+
+use core::slice;
+use std::collections::*;
+
+fn main() {
+    let mut vec = vec![1, 2, 3, 4];
+
+    for _ in vec.iter() {}
+    for _ in vec.iter_mut() {}
+
+    let rvec = &vec;
+    for _ in rvec.iter() {}
+
+    let rmvec = &mut vec;
+    for _ in rmvec.iter() {}
+    for _ in rmvec.iter_mut() {}
+
+    for _ in &vec {} // these are fine
+    for _ in &mut vec {} // these are fine
+
+    for _ in [1, 2, 3].iter() {}
+
+    for _ in (&mut [1, 2, 3]).iter() {}
+
+    for _ in [0; 32].iter() {}
+    for _ in [0; 33].iter() {}
+
+    let ll: LinkedList<()> = LinkedList::new();
+    for _ in ll.iter() {}
+    let rll = &ll;
+    for _ in rll.iter() {}
+
+    let vd: VecDeque<()> = VecDeque::new();
+    for _ in vd.iter() {}
+    let rvd = &vd;
+    for _ in rvd.iter() {}
+
+    let bh: BinaryHeap<()> = BinaryHeap::new();
+    for _ in bh.iter() {}
+
+    let hm: HashMap<(), ()> = HashMap::new();
+    for _ in hm.iter() {}
+
+    let bt: BTreeMap<(), ()> = BTreeMap::new();
+    for _ in bt.iter() {}
+
+    let hs: HashSet<()> = HashSet::new();
+    for _ in hs.iter() {}
+
+    let bs: BTreeSet<()> = BTreeSet::new();
+    for _ in bs.iter() {}
+
+    struct NoIntoIter();
+    impl NoIntoIter {
+        fn iter(&self) -> slice::Iter<u8> {
+            unimplemented!()
+        }
+
+        fn iter_mut(&mut self) -> slice::IterMut<u8> {
+            unimplemented!()
+        }
+    }
+    let mut x = NoIntoIter();
+    for _ in x.iter() {} // no error
+    for _ in x.iter_mut() {} // no error
+
+    struct IntoIterDiffTy;
+    impl IntoIterator for &'_ IntoIterDiffTy {
+        type Item = &'static ();
+        type IntoIter = core::slice::Iter<'static, ()>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl IntoIterDiffTy {
+        fn iter(&self) -> core::slice::Iter<'static, i32> {
+            unimplemented!()
+        }
+    }
+    let x = IntoIterDiffTy;
+    for _ in x.iter() {}
+
+    struct IntoIterDiffSig;
+    impl IntoIterator for &'_ IntoIterDiffSig {
+        type Item = &'static ();
+        type IntoIter = core::slice::Iter<'static, ()>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl IntoIterDiffSig {
+        fn iter(&self, _: u32) -> core::slice::Iter<'static, ()> {
+            unimplemented!()
+        }
+    }
+    let x = IntoIterDiffSig;
+    for _ in x.iter(0) {}
+
+    struct IntoIterDiffLt<'a>(&'a ());
+    impl<'a> IntoIterator for &'a IntoIterDiffLt<'_> {
+        type Item = &'a ();
+        type IntoIter = core::slice::Iter<'a, ()>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl<'a> IntoIterDiffLt<'a> {
+        fn iter(&self) -> core::slice::Iter<'a, ()> {
+            unimplemented!()
+        }
+    }
+    let x = IntoIterDiffLt(&());
+    for _ in x.iter() {}
+
+    struct CustomType;
+    impl<'a> IntoIterator for &'a CustomType {
+        type Item = &'a u32;
+        type IntoIter = core::slice::Iter<'a, u32>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl<'a> IntoIterator for &'a mut CustomType {
+        type Item = &'a mut u32;
+        type IntoIter = core::slice::IterMut<'a, u32>;
+        fn into_iter(self) -> Self::IntoIter {
+            unimplemented!()
+        }
+    }
+    impl CustomType {
+        fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter {
+            panic!()
+        }
+
+        fn iter_mut(&mut self) -> core::slice::IterMut<'_, u32> {
+            panic!()
+        }
+    }
+    let mut x = CustomType;
+    for _ in x.iter() {}
+    for _ in x.iter_mut() {}
+
+    let r = &x;
+    for _ in r.iter() {}
+}
diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.stderr b/src/tools/clippy/tests/ui/explicit_iter_loop.stderr
new file mode 100644
index 00000000000..94a264dcea8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/explicit_iter_loop.stderr
@@ -0,0 +1,142 @@
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:17:14
+   |
+LL |     for _ in vec.iter() {}
+   |              ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
+   |
+note: the lint level is defined here
+  --> $DIR/explicit_iter_loop.rs:2:9
+   |
+LL | #![deny(clippy::explicit_iter_loop)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:18:14
+   |
+LL |     for _ in vec.iter_mut() {}
+   |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:21:14
+   |
+LL |     for _ in rvec.iter() {}
+   |              ^^^^^^^^^^^ help: to write this more concisely, try: `rvec`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:24:14
+   |
+LL |     for _ in rmvec.iter() {}
+   |              ^^^^^^^^^^^^ help: to write this more concisely, try: `&*rmvec`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:25:14
+   |
+LL |     for _ in rmvec.iter_mut() {}
+   |              ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *rmvec`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:30:14
+   |
+LL |     for _ in [1, 2, 3].iter() {}
+   |              ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:32:14
+   |
+LL |     for _ in (&mut [1, 2, 3]).iter() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])`
+
+error: the method `iter` doesn't need a mutable reference
+  --> $DIR/explicit_iter_loop.rs:32:14
+   |
+LL |     for _ in (&mut [1, 2, 3]).iter() {}
+   |              ^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:34:14
+   |
+LL |     for _ in [0; 32].iter() {}
+   |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:35:14
+   |
+LL |     for _ in [0; 33].iter() {}
+   |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:38:14
+   |
+LL |     for _ in ll.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&ll`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:40:14
+   |
+LL |     for _ in rll.iter() {}
+   |              ^^^^^^^^^^ help: to write this more concisely, try: `rll`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:43:14
+   |
+LL |     for _ in vd.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&vd`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:45:14
+   |
+LL |     for _ in rvd.iter() {}
+   |              ^^^^^^^^^^ help: to write this more concisely, try: `rvd`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:48:14
+   |
+LL |     for _ in bh.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&bh`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:51:14
+   |
+LL |     for _ in hm.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&hm`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:54:14
+   |
+LL |     for _ in bt.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&bt`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:57:14
+   |
+LL |     for _ in hs.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&hs`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:60:14
+   |
+LL |     for _ in bs.iter() {}
+   |              ^^^^^^^^^ help: to write this more concisely, try: `&bs`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:149:14
+   |
+LL |     for _ in x.iter() {}
+   |              ^^^^^^^^ help: to write this more concisely, try: `&x`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:150:14
+   |
+LL |     for _ in x.iter_mut() {}
+   |              ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x`
+
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> $DIR/explicit_iter_loop.rs:153:14
+   |
+LL |     for _ in r.iter() {}
+   |              ^^^^^^^^ help: to write this more concisely, try: `r`
+
+error: aborting due to 22 previous errors
+
diff --git a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
index cdfaf8d3afe..50abe89da89 100644
--- a/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_lifetimes.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![allow(
     unused,
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
index adcd1f6d407..8420df6634d 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
@@ -1,8 +1,12 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 
 #![allow(unused, clippy::needless_lifetimes)]
 #![warn(clippy::extra_unused_type_parameters)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn unused_ty(x: u8) {
     unimplemented!()
 }
@@ -102,4 +106,12 @@ mod issue10319 {
     }
 }
 
+with_span!(
+    span
+
+    fn should_not_lint<T>(x: u8) {
+        unimplemented!()
+    }
+);
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
index c4c5227ac91..f63535d7ae6 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
@@ -1,8 +1,12 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 
 #![allow(unused, clippy::needless_lifetimes)]
 #![warn(clippy::extra_unused_type_parameters)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn unused_ty<T>(x: u8) {
     unimplemented!()
 }
@@ -102,4 +106,12 @@ mod issue10319 {
     }
 }
 
+with_span!(
+    span
+
+    fn should_not_lint<T>(x: u8) {
+        unimplemented!()
+    }
+);
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
index c042a5a2290..b5277d49861 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
@@ -1,5 +1,5 @@
 error: type parameter `T` goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:6:13
+  --> $DIR/extra_unused_type_parameters.rs:10:13
    |
 LL | fn unused_ty<T>(x: u8) {
    |             ^^^ help: consider removing the parameter
@@ -7,19 +7,19 @@ LL | fn unused_ty<T>(x: u8) {
    = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
 
 error: type parameters go unused in function definition: T, U
-  --> $DIR/extra_unused_type_parameters.rs:10:16
+  --> $DIR/extra_unused_type_parameters.rs:14:16
    |
 LL | fn unused_multi<T, U>(x: u8) {
    |                ^^^^^^ help: consider removing the parameters
 
 error: type parameter `T` goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:14:21
+  --> $DIR/extra_unused_type_parameters.rs:18:21
    |
 LL | fn unused_with_lt<'a, T>(x: &'a u8) {
    |                     ^^^ help: consider removing the parameter
 
 error: type parameters go unused in function definition: T, V
-  --> $DIR/extra_unused_type_parameters.rs:26:19
+  --> $DIR/extra_unused_type_parameters.rs:30:19
    |
 LL | fn unused_bounded<T: Default, U, V: Default>(x: U) {
    |                   ^^^^^^^^^^^^ ^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL + fn unused_bounded<U>(x: U) {
    |
 
 error: type parameters go unused in function definition: A, D, E
-  --> $DIR/extra_unused_type_parameters.rs:30:16
+  --> $DIR/extra_unused_type_parameters.rs:34:16
    |
 LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
    |                ^^^    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,19 +43,19 @@ LL + fn some_unused<B, C>(b: B, c: C) {
    |
 
 error: type parameter `T` goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:55:22
+  --> $DIR/extra_unused_type_parameters.rs:59:22
    |
 LL |     fn unused_ty_impl<T>(&self) {
    |                      ^^^ help: consider removing the parameter
 
 error: type parameters go unused in function definition: A, B
-  --> $DIR/extra_unused_type_parameters.rs:77:17
+  --> $DIR/extra_unused_type_parameters.rs:81:17
    |
 LL | fn unused_opaque<A, B>(dummy: impl Default) {
    |                 ^^^^^^ help: consider removing the parameters
 
 error: type parameter `U` goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:90:56
+  --> $DIR/extra_unused_type_parameters.rs:94:56
    |
 LL |     fn unused_with_priv_trait_bound<T: private::Private, U>() {
    |                                                        ^^^ help: consider removing the parameter
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 2045b1eebcd..d6df114b8d2 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -1,5 +1,5 @@
-//@aux-build:proc_macro_derive.rs
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::field_reassign_with_default)]
 
diff --git a/src/tools/clippy/tests/ui/filetype_is_file.rs b/src/tools/clippy/tests/ui/filetype_is_file.rs
index 5de8fe8cdd7..d3ad36e40b5 100644
--- a/src/tools/clippy/tests/ui/filetype_is_file.rs
+++ b/src/tools/clippy/tests/ui/filetype_is_file.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::needless_if)]
 #![warn(clippy::filetype_is_file)]
 
 fn main() -> std::io::Result<()> {
diff --git a/src/tools/clippy/tests/ui/filetype_is_file.stderr b/src/tools/clippy/tests/ui/filetype_is_file.stderr
index e51a90d6cfd..36142deb309 100644
--- a/src/tools/clippy/tests/ui/filetype_is_file.stderr
+++ b/src/tools/clippy/tests/ui/filetype_is_file.stderr
@@ -1,5 +1,5 @@
 error: `FileType::is_file()` only covers regular files
-  --> $DIR/filetype_is_file.rs:8:8
+  --> $DIR/filetype_is_file.rs:9:8
    |
 LL |     if fs::metadata("foo.txt")?.file_type().is_file() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     if fs::metadata("foo.txt")?.file_type().is_file() {
    = note: `-D clippy::filetype-is-file` implied by `-D warnings`
 
 error: `!FileType::is_file()` only denies regular files
-  --> $DIR/filetype_is_file.rs:13:8
+  --> $DIR/filetype_is_file.rs:14:8
    |
 LL |     if !fs::metadata("foo.txt")?.file_type().is_file() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     if !fs::metadata("foo.txt")?.file_type().is_file() {
    = help: use `FileType::is_dir()` instead
 
 error: `FileType::is_file()` only covers regular files
-  --> $DIR/filetype_is_file.rs:18:9
+  --> $DIR/filetype_is_file.rs:19:9
    |
 LL |     if !fs::metadata("foo.txt")?.file_type().is_file().bitor(true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/find_map.rs b/src/tools/clippy/tests/ui/find_map.rs
index 88d3b0e7490..bbd395d50ef 100644
--- a/src/tools/clippy/tests/ui/find_map.rs
+++ b/src/tools/clippy/tests/ui/find_map.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::useless_vec)]
 
 #[derive(Debug, Copy, Clone)]
 enum Flavor {
diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs
index df5bc8420d5..dfdea100c8f 100644
--- a/src/tools/clippy/tests/ui/fn_null_check.rs
+++ b/src/tools/clippy/tests/ui/fn_null_check.rs
@@ -1,6 +1,7 @@
 #![allow(unused)]
 #![warn(clippy::fn_null_check)]
 #![allow(clippy::cmp_null)]
+#![allow(clippy::needless_if)]
 #![allow(clippy::ptr_eq)]
 #![allow(clippy::zero_ptr)]
 
diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr
index 660dd323979..5b9f48a961c 100644
--- a/src/tools/clippy/tests/ui/fn_null_check.stderr
+++ b/src/tools/clippy/tests/ui/fn_null_check.stderr
@@ -1,5 +1,5 @@
 error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:13:8
+  --> $DIR/fn_null_check.rs:14:8
    |
 LL |     if (fn_ptr as *mut ()).is_null() {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     if (fn_ptr as *mut ()).is_null() {}
    = note: `-D clippy::fn-null-check` implied by `-D warnings`
 
 error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:14:8
+  --> $DIR/fn_null_check.rs:15:8
    |
 LL |     if (fn_ptr as *const u8).is_null() {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     if (fn_ptr as *const u8).is_null() {}
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
 
 error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:15:8
+  --> $DIR/fn_null_check.rs:16:8
    |
 LL |     if (fn_ptr as *const ()) == std::ptr::null() {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     if (fn_ptr as *const ()) == std::ptr::null() {}
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
 
 error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:16:8
+  --> $DIR/fn_null_check.rs:17:8
    |
 LL |     if (fn_ptr as *const ()) == (0 as *const ()) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     if (fn_ptr as *const ()) == (0 as *const ()) {}
    = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
 
 error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:17:8
+  --> $DIR/fn_null_check.rs:18:8
    |
 LL |     if (fn_ptr as *const ()) == ZPTR {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.fixed b/src/tools/clippy/tests/ui/for_loop_fixable.fixed
deleted file mode 100644
index f578c98da15..00000000000
--- a/src/tools/clippy/tests/ui/for_loop_fixable.fixed
+++ /dev/null
@@ -1,309 +0,0 @@
-//@run-rustfix
-#![allow(dead_code, unused)]
-#![allow(clippy::uninlined_format_args)]
-
-use std::collections::*;
-
-#[warn(clippy::all)]
-struct Unrelated(Vec<u8>);
-impl Unrelated {
-    fn next(&self) -> std::slice::Iter<u8> {
-        self.0.iter()
-    }
-
-    fn iter(&self) -> std::slice::Iter<u8> {
-        self.0.iter()
-    }
-}
-
-#[warn(
-    clippy::needless_range_loop,
-    clippy::explicit_iter_loop,
-    clippy::explicit_into_iter_loop,
-    clippy::iter_next_loop,
-    clippy::for_kv_map
-)]
-#[allow(
-    clippy::linkedlist,
-    clippy::unnecessary_mut_passed,
-    clippy::similar_names,
-    clippy::needless_borrow
-)]
-#[allow(unused_variables)]
-fn main() {
-    let mut vec = vec![1, 2, 3, 4];
-
-    // See #601
-    for i in 0..10 {
-        // no error, id_col does not exist outside the loop
-        let mut id_col = vec![0f64; 10];
-        id_col[i] = 1f64;
-    }
-
-    for _v in &vec {}
-
-    for _v in &mut vec {}
-
-    let out_vec = vec![1, 2, 3];
-    for _v in out_vec {}
-
-    for _v in &vec {} // these are fine
-    for _v in &mut vec {} // these are fine
-
-    for _v in &[1, 2, 3] {}
-
-    for _v in (&mut [1, 2, 3]).iter() {} // no error
-
-    for _v in &[0; 32] {}
-
-    for _v in [0; 33].iter() {} // no error
-
-    let ll: LinkedList<()> = LinkedList::new();
-    for _v in &ll {}
-
-    let vd: VecDeque<()> = VecDeque::new();
-    for _v in &vd {}
-
-    let bh: BinaryHeap<()> = BinaryHeap::new();
-    for _v in &bh {}
-
-    let hm: HashMap<(), ()> = HashMap::new();
-    for _v in &hm {}
-
-    let bt: BTreeMap<(), ()> = BTreeMap::new();
-    for _v in &bt {}
-
-    let hs: HashSet<()> = HashSet::new();
-    for _v in &hs {}
-
-    let bs: BTreeSet<()> = BTreeSet::new();
-    for _v in &bs {}
-
-    let u = Unrelated(vec![]);
-    for _v in u.next() {} // no error
-    for _v in u.iter() {} // no error
-
-    let mut out = vec![];
-    vec.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>();
-    let _y = vec.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine
-
-    // Loop with explicit counter variable
-
-    // Potential false positives
-    let mut _index = 0;
-    _index = 1;
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    _index += 1;
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    if true {
-        _index = 1
-    }
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    let mut _index = 1;
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index += 1;
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index *= 2;
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index = 1;
-        _index += 1
-    }
-
-    let mut _index = 0;
-
-    for _v in &vec {
-        let mut _index = 0;
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index += 1;
-        _index = 0;
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        for _x in 0..1 {
-            _index += 1;
-        }
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for x in &vec {
-        if *x == 1 {
-            _index += 1
-        }
-    }
-
-    let mut _index = 0;
-    if true {
-        _index = 1
-    };
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 1;
-    if false {
-        _index = 0
-    };
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut index = 0;
-    {
-        let mut _x = &mut index;
-    }
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut index = 0;
-    for _v in &vec {
-        index += 1
-    }
-    println!("index: {}", index);
-
-    fn f<T>(_: &T, _: &T) -> bool {
-        unimplemented!()
-    }
-    fn g<T>(_: &mut [T], _: usize, _: usize) {
-        unimplemented!()
-    }
-    for i in 1..vec.len() {
-        if f(&vec[i - 1], &vec[i]) {
-            g(&mut vec, i - 1, i);
-        }
-    }
-
-    for mid in 1..vec.len() {
-        let (_, _) = vec.split_at(mid);
-    }
-}
-
-fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
-    let pivot = v.len() - 1;
-    let mut i = 0;
-    for j in 0..pivot {
-        if v[j] <= v[pivot] {
-            v.swap(i, j);
-            i += 1;
-        }
-    }
-    v.swap(i, pivot);
-    i
-}
-
-#[warn(clippy::needless_range_loop)]
-pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) {
-    // Same source and destination - don't trigger lint
-    for i in 0..dst.len() {
-        dst[d + i] = dst[s + i];
-    }
-}
-
-mod issue_2496 {
-    pub trait Handle {
-        fn new_for_index(index: usize) -> Self;
-        fn index(&self) -> usize;
-    }
-
-    pub fn test<H: Handle>() -> H {
-        for x in 0..5 {
-            let next_handle = H::new_for_index(x);
-            println!("{}", next_handle.index());
-        }
-        unimplemented!()
-    }
-}
-
-// explicit_into_iter_loop bad suggestions
-#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)]
-mod issue_4958 {
-    fn takes_iterator<T>(iterator: &T)
-    where
-        for<'a> &'a T: IntoIterator<Item = &'a String>,
-    {
-        for i in iterator {
-            println!("{}", i);
-        }
-    }
-
-    struct T;
-    impl IntoIterator for &T {
-        type Item = ();
-        type IntoIter = std::vec::IntoIter<Self::Item>;
-        fn into_iter(self) -> Self::IntoIter {
-            vec![].into_iter()
-        }
-    }
-
-    fn more_tests() {
-        let t = T;
-        let r = &t;
-        let rr = &&t;
-
-        // This case is handled by `explicit_iter_loop`. No idea why.
-        for _ in &t {}
-
-        for _ in r {}
-
-        // No suggestion for this.
-        // We'd have to suggest `for _ in *rr {}` which is less clear.
-        for _ in rr.into_iter() {}
-    }
-}
-
-// explicit_into_iter_loop
-#[warn(clippy::explicit_into_iter_loop)]
-mod issue_6900 {
-    struct S;
-    impl S {
-        #[allow(clippy::should_implement_trait)]
-        pub fn into_iter<T>(self) -> I<T> {
-            unimplemented!()
-        }
-    }
-
-    struct I<T>(T);
-    impl<T> Iterator for I<T> {
-        type Item = T;
-        fn next(&mut self) -> Option<Self::Item> {
-            unimplemented!()
-        }
-    }
-
-    fn f() {
-        for _ in S.into_iter::<u32>() {
-            unimplemented!()
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.rs b/src/tools/clippy/tests/ui/for_loop_fixable.rs
deleted file mode 100644
index 42bc6de0c7d..00000000000
--- a/src/tools/clippy/tests/ui/for_loop_fixable.rs
+++ /dev/null
@@ -1,309 +0,0 @@
-//@run-rustfix
-#![allow(dead_code, unused)]
-#![allow(clippy::uninlined_format_args)]
-
-use std::collections::*;
-
-#[warn(clippy::all)]
-struct Unrelated(Vec<u8>);
-impl Unrelated {
-    fn next(&self) -> std::slice::Iter<u8> {
-        self.0.iter()
-    }
-
-    fn iter(&self) -> std::slice::Iter<u8> {
-        self.0.iter()
-    }
-}
-
-#[warn(
-    clippy::needless_range_loop,
-    clippy::explicit_iter_loop,
-    clippy::explicit_into_iter_loop,
-    clippy::iter_next_loop,
-    clippy::for_kv_map
-)]
-#[allow(
-    clippy::linkedlist,
-    clippy::unnecessary_mut_passed,
-    clippy::similar_names,
-    clippy::needless_borrow
-)]
-#[allow(unused_variables)]
-fn main() {
-    let mut vec = vec![1, 2, 3, 4];
-
-    // See #601
-    for i in 0..10 {
-        // no error, id_col does not exist outside the loop
-        let mut id_col = vec![0f64; 10];
-        id_col[i] = 1f64;
-    }
-
-    for _v in vec.iter() {}
-
-    for _v in vec.iter_mut() {}
-
-    let out_vec = vec![1, 2, 3];
-    for _v in out_vec.into_iter() {}
-
-    for _v in &vec {} // these are fine
-    for _v in &mut vec {} // these are fine
-
-    for _v in [1, 2, 3].iter() {}
-
-    for _v in (&mut [1, 2, 3]).iter() {} // no error
-
-    for _v in [0; 32].iter() {}
-
-    for _v in [0; 33].iter() {} // no error
-
-    let ll: LinkedList<()> = LinkedList::new();
-    for _v in ll.iter() {}
-
-    let vd: VecDeque<()> = VecDeque::new();
-    for _v in vd.iter() {}
-
-    let bh: BinaryHeap<()> = BinaryHeap::new();
-    for _v in bh.iter() {}
-
-    let hm: HashMap<(), ()> = HashMap::new();
-    for _v in hm.iter() {}
-
-    let bt: BTreeMap<(), ()> = BTreeMap::new();
-    for _v in bt.iter() {}
-
-    let hs: HashSet<()> = HashSet::new();
-    for _v in hs.iter() {}
-
-    let bs: BTreeSet<()> = BTreeSet::new();
-    for _v in bs.iter() {}
-
-    let u = Unrelated(vec![]);
-    for _v in u.next() {} // no error
-    for _v in u.iter() {} // no error
-
-    let mut out = vec![];
-    vec.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>();
-    let _y = vec.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine
-
-    // Loop with explicit counter variable
-
-    // Potential false positives
-    let mut _index = 0;
-    _index = 1;
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    _index += 1;
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    if true {
-        _index = 1
-    }
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    let mut _index = 1;
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index += 1;
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index *= 2;
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index = 1;
-        _index += 1
-    }
-
-    let mut _index = 0;
-
-    for _v in &vec {
-        let mut _index = 0;
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        _index += 1;
-        _index = 0;
-    }
-
-    let mut _index = 0;
-    for _v in &vec {
-        for _x in 0..1 {
-            _index += 1;
-        }
-        _index += 1
-    }
-
-    let mut _index = 0;
-    for x in &vec {
-        if *x == 1 {
-            _index += 1
-        }
-    }
-
-    let mut _index = 0;
-    if true {
-        _index = 1
-    };
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut _index = 1;
-    if false {
-        _index = 0
-    };
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut index = 0;
-    {
-        let mut _x = &mut index;
-    }
-    for _v in &vec {
-        _index += 1
-    }
-
-    let mut index = 0;
-    for _v in &vec {
-        index += 1
-    }
-    println!("index: {}", index);
-
-    fn f<T>(_: &T, _: &T) -> bool {
-        unimplemented!()
-    }
-    fn g<T>(_: &mut [T], _: usize, _: usize) {
-        unimplemented!()
-    }
-    for i in 1..vec.len() {
-        if f(&vec[i - 1], &vec[i]) {
-            g(&mut vec, i - 1, i);
-        }
-    }
-
-    for mid in 1..vec.len() {
-        let (_, _) = vec.split_at(mid);
-    }
-}
-
-fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
-    let pivot = v.len() - 1;
-    let mut i = 0;
-    for j in 0..pivot {
-        if v[j] <= v[pivot] {
-            v.swap(i, j);
-            i += 1;
-        }
-    }
-    v.swap(i, pivot);
-    i
-}
-
-#[warn(clippy::needless_range_loop)]
-pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) {
-    // Same source and destination - don't trigger lint
-    for i in 0..dst.len() {
-        dst[d + i] = dst[s + i];
-    }
-}
-
-mod issue_2496 {
-    pub trait Handle {
-        fn new_for_index(index: usize) -> Self;
-        fn index(&self) -> usize;
-    }
-
-    pub fn test<H: Handle>() -> H {
-        for x in 0..5 {
-            let next_handle = H::new_for_index(x);
-            println!("{}", next_handle.index());
-        }
-        unimplemented!()
-    }
-}
-
-// explicit_into_iter_loop bad suggestions
-#[warn(clippy::explicit_into_iter_loop, clippy::explicit_iter_loop)]
-mod issue_4958 {
-    fn takes_iterator<T>(iterator: &T)
-    where
-        for<'a> &'a T: IntoIterator<Item = &'a String>,
-    {
-        for i in iterator.into_iter() {
-            println!("{}", i);
-        }
-    }
-
-    struct T;
-    impl IntoIterator for &T {
-        type Item = ();
-        type IntoIter = std::vec::IntoIter<Self::Item>;
-        fn into_iter(self) -> Self::IntoIter {
-            vec![].into_iter()
-        }
-    }
-
-    fn more_tests() {
-        let t = T;
-        let r = &t;
-        let rr = &&t;
-
-        // This case is handled by `explicit_iter_loop`. No idea why.
-        for _ in t.into_iter() {}
-
-        for _ in r.into_iter() {}
-
-        // No suggestion for this.
-        // We'd have to suggest `for _ in *rr {}` which is less clear.
-        for _ in rr.into_iter() {}
-    }
-}
-
-// explicit_into_iter_loop
-#[warn(clippy::explicit_into_iter_loop)]
-mod issue_6900 {
-    struct S;
-    impl S {
-        #[allow(clippy::should_implement_trait)]
-        pub fn into_iter<T>(self) -> I<T> {
-            unimplemented!()
-        }
-    }
-
-    struct I<T>(T);
-    impl<T> Iterator for I<T> {
-        type Item = T;
-        fn next(&mut self) -> Option<Self::Item> {
-            unimplemented!()
-        }
-    }
-
-    fn f() {
-        for _ in S.into_iter::<u32>() {
-            unimplemented!()
-        }
-    }
-}
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.stderr b/src/tools/clippy/tests/ui/for_loop_fixable.stderr
deleted file mode 100644
index ddfe66d675f..00000000000
--- a/src/tools/clippy/tests/ui/for_loop_fixable.stderr
+++ /dev/null
@@ -1,96 +0,0 @@
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:43:15
-   |
-LL |     for _v in vec.iter() {}
-   |               ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
-   |
-   = note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:45:15
-   |
-LL |     for _v in vec.iter_mut() {}
-   |               ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
-
-error: it is more concise to loop over containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:48:15
-   |
-LL |     for _v in out_vec.into_iter() {}
-   |               ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec`
-   |
-   = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:53:15
-   |
-LL |     for _v in [1, 2, 3].iter() {}
-   |               ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:57:15
-   |
-LL |     for _v in [0; 32].iter() {}
-   |               ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:62:15
-   |
-LL |     for _v in ll.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&ll`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:65:15
-   |
-LL |     for _v in vd.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&vd`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:68:15
-   |
-LL |     for _v in bh.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&bh`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:71:15
-   |
-LL |     for _v in hm.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&hm`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:74:15
-   |
-LL |     for _v in bt.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&bt`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:77:15
-   |
-LL |     for _v in hs.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&hs`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:80:15
-   |
-LL |     for _v in bs.iter() {}
-   |               ^^^^^^^^^ help: to write this more concisely, try: `&bs`
-
-error: it is more concise to loop over containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:255:18
-   |
-LL |         for i in iterator.into_iter() {
-   |                  ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator`
-
-error: it is more concise to loop over references to containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:275:18
-   |
-LL |         for _ in t.into_iter() {}
-   |                  ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t`
-
-error: it is more concise to loop over containers instead of using explicit iteration methods
-  --> $DIR/for_loop_fixable.rs:277:18
-   |
-LL |         for _ in r.into_iter() {}
-   |                  ^^^^^^^^^^^^^ help: to write this more concisely, try: `r`
-
-error: aborting due to 15 previous errors
-
diff --git a/src/tools/clippy/tests/ui/for_loop_unfixable.rs b/src/tools/clippy/tests/ui/for_loop_unfixable.rs
deleted file mode 100644
index 55fb3788a8b..00000000000
--- a/src/tools/clippy/tests/ui/for_loop_unfixable.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Tests from for_loop.rs that don't have suggestions
-
-#[warn(
-    clippy::needless_range_loop,
-    clippy::explicit_iter_loop,
-    clippy::explicit_into_iter_loop,
-    clippy::iter_next_loop,
-    clippy::for_kv_map
-)]
-#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
-#[allow(for_loops_over_fallibles)]
-fn main() {
-    let vec = vec![1, 2, 3, 4];
-
-    for _v in vec.iter().next() {}
-}
diff --git a/src/tools/clippy/tests/ui/for_loop_unfixable.stderr b/src/tools/clippy/tests/ui/for_loop_unfixable.stderr
deleted file mode 100644
index 50a86eaa68f..00000000000
--- a/src/tools/clippy/tests/ui/for_loop_unfixable.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
-  --> $DIR/for_loop_unfixable.rs:15:15
-   |
-LL |     for _v in vec.iter().next() {}
-   |               ^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::iter-next-loop` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index 9288956f513..2e24e07ea26 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -6,7 +6,9 @@
     clippy::redundant_clone,
     clippy::to_string_in_format_args,
     clippy::needless_borrow,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::needless_raw_string_hashes,
+    clippy::useless_vec
 )]
 
 struct Foo(pub String);
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index b2b817e0f4c..0e64a310b01 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -6,7 +6,9 @@
     clippy::redundant_clone,
     clippy::to_string_in_format_args,
     clippy::needless_borrow,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::needless_raw_string_hashes,
+    clippy::useless_vec
 )]
 
 struct Foo(pub String);
diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr
index 0ef0ac655d3..78a11a3354f 100644
--- a/src/tools/clippy/tests/ui/format.stderr
+++ b/src/tools/clippy/tests/ui/format.stderr
@@ -1,5 +1,5 @@
 error: useless use of `format!`
-  --> $DIR/format.rs:19:5
+  --> $DIR/format.rs:21:5
    |
 LL |     format!("foo");
    |     ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
@@ -7,19 +7,19 @@ LL |     format!("foo");
    = note: `-D clippy::useless-format` implied by `-D warnings`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:20:5
+  --> $DIR/format.rs:22:5
    |
 LL |     format!("{{}}");
    |     ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:21:5
+  --> $DIR/format.rs:23:5
    |
 LL |     format!("{{}} abc {{}}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:22:5
+  --> $DIR/format.rs:24:5
    |
 LL | /     format!(
 LL | |         r##"foo {{}}
@@ -34,67 +34,67 @@ LL ~ " bar"##.to_string();
    |
 
 error: useless use of `format!`
-  --> $DIR/format.rs:27:13
+  --> $DIR/format.rs:29:13
    |
 LL |     let _ = format!("");
    |             ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:29:5
+  --> $DIR/format.rs:31:5
    |
 LL |     format!("{}", "foo");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:37:5
+  --> $DIR/format.rs:39:5
    |
 LL |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:67:5
+  --> $DIR/format.rs:69:5
    |
 LL |     format!("{}", 42.to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:69:5
+  --> $DIR/format.rs:71:5
    |
 LL |     format!("{}", x.display().to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:73:18
+  --> $DIR/format.rs:75:18
    |
 LL |     let _ = Some(format!("{}", a + "bar"));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:77:22
+  --> $DIR/format.rs:79:22
    |
 LL |     let _s: String = format!("{}", &*v.join("/n"));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:83:13
+  --> $DIR/format.rs:85:13
    |
 LL |     let _ = format!("{x}");
    |             ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:85:13
+  --> $DIR/format.rs:87:13
    |
 LL |     let _ = format!("{y}", y = x);
    |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:89:13
+  --> $DIR/format.rs:91:13
    |
 LL |     let _ = format!("{abc}");
    |             ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:91:13
+  --> $DIR/format.rs:93:13
    |
 LL |     let _ = format!("{xx}");
    |             ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
diff --git a/src/tools/clippy/tests/ui/format_push_string.rs b/src/tools/clippy/tests/ui/format_push_string.rs
index 4db13d650eb..89423ffe1cf 100644
--- a/src/tools/clippy/tests/ui/format_push_string.rs
+++ b/src/tools/clippy/tests/ui/format_push_string.rs
@@ -5,3 +5,32 @@ fn main() {
     string += &format!("{:?}", 1234);
     string.push_str(&format!("{:?}", 5678));
 }
+
+mod issue9493 {
+    pub fn u8vec_to_hex(vector: &Vec<u8>, upper: bool) -> String {
+        let mut hex = String::with_capacity(vector.len() * 2);
+        for byte in vector {
+            hex += &(if upper {
+                format!("{byte:02X}")
+            } else {
+                format!("{byte:02x}")
+            });
+        }
+        hex
+    }
+
+    pub fn other_cases() {
+        let mut s = String::new();
+        // if let
+        s += &(if let Some(_a) = Some(1234) {
+            format!("{}", 1234)
+        } else {
+            format!("{}", 1234)
+        });
+        // match
+        s += &(match Some(1234) {
+            Some(_) => format!("{}", 1234),
+            None => format!("{}", 1234),
+        });
+    }
+}
diff --git a/src/tools/clippy/tests/ui/format_push_string.stderr b/src/tools/clippy/tests/ui/format_push_string.stderr
index d7be9a5f206..76762c4a1d1 100644
--- a/src/tools/clippy/tests/ui/format_push_string.stderr
+++ b/src/tools/clippy/tests/ui/format_push_string.stderr
@@ -15,5 +15,40 @@ LL |     string.push_str(&format!("{:?}", 5678));
    |
    = help: consider using `write!` to avoid the extra allocation
 
-error: aborting due to 2 previous errors
+error: `format!(..)` appended to existing `String`
+  --> $DIR/format_push_string.rs:13:13
+   |
+LL | /             hex += &(if upper {
+LL | |                 format!("{byte:02X}")
+LL | |             } else {
+LL | |                 format!("{byte:02x}")
+LL | |             });
+   | |______________^
+   |
+   = help: consider using `write!` to avoid the extra allocation
+
+error: `format!(..)` appended to existing `String`
+  --> $DIR/format_push_string.rs:25:9
+   |
+LL | /         s += &(if let Some(_a) = Some(1234) {
+LL | |             format!("{}", 1234)
+LL | |         } else {
+LL | |             format!("{}", 1234)
+LL | |         });
+   | |__________^
+   |
+   = help: consider using `write!` to avoid the extra allocation
+
+error: `format!(..)` appended to existing `String`
+  --> $DIR/format_push_string.rs:31:9
+   |
+LL | /         s += &(match Some(1234) {
+LL | |             Some(_) => format!("{}", 1234),
+LL | |             None => format!("{}", 1234),
+LL | |         });
+   | |__________^
+   |
+   = help: consider using `write!` to avoid the extra allocation
+
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
index 915ff4fb079..1671987cb67 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
@@ -2,6 +2,7 @@
 
 #![warn(clippy::from_iter_instead_of_collect)]
 #![allow(unused_imports, unused_tuple_struct_fields)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
index e926f8c529d..48509b32f10 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::from_iter_instead_of_collect)]
 #![allow(unused_imports, unused_tuple_struct_fields)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
index 8aa3c3c01f8..8f08ac8c3ff 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
@@ -1,5 +1,5 @@
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:18:9
+  --> $DIR/from_iter_instead_of_collect.rs:19:9
    |
 LL |         <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.into_iter().copied().collect::<Self>()`
@@ -7,85 +7,85 @@ LL |         <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied())
    = note: `-D clippy::from-iter-instead-of-collect` implied by `-D warnings`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:24:13
+  --> $DIR/from_iter_instead_of_collect.rs:25:13
    |
 LL |     let _ = Vec::from_iter(iter_expr);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:26:13
+  --> $DIR/from_iter_instead_of_collect.rs:27:13
    |
 LL |     let _ = HashMap::<usize, &i8>::from_iter(vec![5, 5, 5, 5].iter().enumerate());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::<HashMap<usize, &i8>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:31:19
+  --> $DIR/from_iter_instead_of_collect.rs:32:19
    |
 LL |     assert_eq!(a, Vec::from_iter(0..3));
    |                   ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:32:19
+  --> $DIR/from_iter_instead_of_collect.rs:33:19
    |
 LL |     assert_eq!(a, Vec::<i32>::from_iter(0..3));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:34:17
+  --> $DIR/from_iter_instead_of_collect.rs:35:17
    |
 LL |     let mut b = VecDeque::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:37:17
+  --> $DIR/from_iter_instead_of_collect.rs:38:17
    |
 LL |     let mut b = VecDeque::<i32>::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:42:21
+  --> $DIR/from_iter_instead_of_collect.rs:43:21
    |
 LL |         let mut b = collections::VecDeque::<i32>::from_iter(0..3);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::VecDeque<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:47:14
+  --> $DIR/from_iter_instead_of_collect.rs:48:14
    |
 LL |     let bm = BTreeMap::from_iter(values.iter().cloned());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::<BTreeMap<_, _>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:48:19
+  --> $DIR/from_iter_instead_of_collect.rs:49:19
    |
 LL |     let mut bar = BTreeMap::from_iter(bm.range(0..2));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::<BTreeMap<_, _>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:51:19
+  --> $DIR/from_iter_instead_of_collect.rs:52:19
    |
 LL |     let mut bts = BTreeSet::from_iter(0..3);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<BTreeSet<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:55:17
+  --> $DIR/from_iter_instead_of_collect.rs:56:17
    |
 LL |         let _ = collections::BTreeSet::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:56:17
+  --> $DIR/from_iter_instead_of_collect.rs:57:17
    |
 LL |         let _ = collections::BTreeSet::<u32>::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<u32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:59:15
+  --> $DIR/from_iter_instead_of_collect.rs:60:15
    |
 LL |     for _i in Vec::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:60:15
+  --> $DIR/from_iter_instead_of_collect.rs:61:15
    |
 LL |     for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<&i32>>()`
diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed
index 204019130ed..d96b68a9159 100644
--- a/src/tools/clippy/tests/ui/from_over_into.fixed
+++ b/src/tools/clippy/tests/ui/from_over_into.fixed
@@ -60,6 +60,15 @@ impl From<String> for A {
     }
 }
 
+struct PathInExpansion;
+
+impl From<PathInExpansion> for String {
+    fn from(val: PathInExpansion) -> Self {
+        // non self/Self paths in expansions are fine
+        panic!()
+    }
+}
+
 #[clippy::msrv = "1.40"]
 fn msrv_1_40() {
     struct FromOverInto<T>(Vec<T>);
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
index 46e02847e30..da8fe04f476 100644
--- a/src/tools/clippy/tests/ui/from_over_into.rs
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -60,6 +60,15 @@ impl From<String> for A {
     }
 }
 
+struct PathInExpansion;
+
+impl Into<String> for PathInExpansion {
+    fn into(self) -> String {
+        // non self/Self paths in expansions are fine
+        panic!()
+    }
+}
+
 #[clippy::msrv = "1.40"]
 fn msrv_1_40() {
     struct FromOverInto<T>(Vec<T>);
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
index 6039f86fe67..498b00de5ad 100644
--- a/src/tools/clippy/tests/ui/from_over_into.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -59,7 +59,21 @@ LL ~         val.0
    |
 
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:78:5
+  --> $DIR/from_over_into.rs:65:1
+   |
+LL | impl Into<String> for PathInExpansion {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+           https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+help: replace the `Into` implementation with `From<PathInExpansion>`
+   |
+LL ~ impl From<PathInExpansion> for String {
+LL ~     fn from(val: PathInExpansion) -> Self {
+   |
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into.rs:87:5
    |
 LL |     impl<T> Into<FromOverInto<T>> for Vec<T> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,5 +85,5 @@ LL ~         fn from(val: Vec<T>) -> Self {
 LL ~             FromOverInto(val)
    |
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
index 3b280b7488a..c769e38eb33 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
@@ -3,14 +3,14 @@
 struct InMacro(String);
 
 macro_rules! in_macro {
-    ($e:ident) => {
-        $e
+    () => {
+        Self::new()
     };
 }
 
 impl Into<InMacro> for String {
     fn into(self) -> InMacro {
-        InMacro(in_macro!(self))
+        InMacro(in_macro!())
     }
 }
 
@@ -32,4 +32,14 @@ impl Into<u8> for ContainsVal {
     }
 }
 
+pub struct Lval<T>(T);
+
+pub struct Rval<T>(T);
+
+impl<T> Into<Rval<Self>> for Lval<T> {
+    fn into(self) -> Rval<Self> {
+        Rval(self)
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
index 251f1d84e74..2ab9b9d6b17 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
@@ -25,5 +25,13 @@ LL | impl Into<u8> for ContainsVal {
            https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
    = help: replace the `Into` implementation with `From<ContainsVal>`
 
-error: aborting due to 3 previous errors
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:39:1
+   |
+LL | impl<T> Into<Rval<Self>> for Lval<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: replace the `Into` implementation with `From<Lval<T>>`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs
index 8484da2415a..95ef6425fad 100644
--- a/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs
+++ b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::from_raw_with_void_ptr)]
+#![allow(clippy::unnecessary_cast)]
 
 use std::ffi::c_void;
 use std::rc::Rc;
diff --git a/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr
index 96e4af12ba3..1963d08014b 100644
--- a/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr
+++ b/src/tools/clippy/tests/ui/from_raw_with_void_ptr.stderr
@@ -1,60 +1,60 @@
 error: creating a `Box` from a void raw pointer
-  --> $DIR/from_raw_with_void_ptr.rs:10:22
+  --> $DIR/from_raw_with_void_ptr.rs:11:22
    |
 LL |     let _ = unsafe { Box::from_raw(ptr) };
    |                      ^^^^^^^^^^^^^^^^^^
    |
 help: cast this to a pointer of the appropriate type
-  --> $DIR/from_raw_with_void_ptr.rs:10:36
+  --> $DIR/from_raw_with_void_ptr.rs:11:36
    |
 LL |     let _ = unsafe { Box::from_raw(ptr) };
    |                                    ^^^
    = note: `-D clippy::from-raw-with-void-ptr` implied by `-D warnings`
 
 error: creating a `Rc` from a void raw pointer
-  --> $DIR/from_raw_with_void_ptr.rs:21:22
+  --> $DIR/from_raw_with_void_ptr.rs:22:22
    |
 LL |     let _ = unsafe { Rc::from_raw(ptr) };
    |                      ^^^^^^^^^^^^^^^^^
    |
 help: cast this to a pointer of the appropriate type
-  --> $DIR/from_raw_with_void_ptr.rs:21:35
+  --> $DIR/from_raw_with_void_ptr.rs:22:35
    |
 LL |     let _ = unsafe { Rc::from_raw(ptr) };
    |                                   ^^^
 
 error: creating a `Arc` from a void raw pointer
-  --> $DIR/from_raw_with_void_ptr.rs:25:22
+  --> $DIR/from_raw_with_void_ptr.rs:26:22
    |
 LL |     let _ = unsafe { Arc::from_raw(ptr) };
    |                      ^^^^^^^^^^^^^^^^^^
    |
 help: cast this to a pointer of the appropriate type
-  --> $DIR/from_raw_with_void_ptr.rs:25:36
+  --> $DIR/from_raw_with_void_ptr.rs:26:36
    |
 LL |     let _ = unsafe { Arc::from_raw(ptr) };
    |                                    ^^^
 
 error: creating a `Weak` from a void raw pointer
-  --> $DIR/from_raw_with_void_ptr.rs:29:22
+  --> $DIR/from_raw_with_void_ptr.rs:30:22
    |
 LL |     let _ = unsafe { std::rc::Weak::from_raw(ptr) };
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: cast this to a pointer of the appropriate type
-  --> $DIR/from_raw_with_void_ptr.rs:29:46
+  --> $DIR/from_raw_with_void_ptr.rs:30:46
    |
 LL |     let _ = unsafe { std::rc::Weak::from_raw(ptr) };
    |                                              ^^^
 
 error: creating a `Weak` from a void raw pointer
-  --> $DIR/from_raw_with_void_ptr.rs:33:22
+  --> $DIR/from_raw_with_void_ptr.rs:34:22
    |
 LL |     let _ = unsafe { std::sync::Weak::from_raw(ptr) };
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: cast this to a pointer of the appropriate type
-  --> $DIR/from_raw_with_void_ptr.rs:33:48
+  --> $DIR/from_raw_with_void_ptr.rs:34:48
    |
 LL |     let _ = unsafe { std::sync::Weak::from_raw(ptr) };
    |                                                ^^^
diff --git a/src/tools/clippy/tests/ui/get_first.fixed b/src/tools/clippy/tests/ui/get_first.fixed
index ef132b79611..a29c0918a6d 100644
--- a/src/tools/clippy/tests/ui/get_first.fixed
+++ b/src/tools/clippy/tests/ui/get_first.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::get_first)]
+#![allow(clippy::useless_vec)]
 use std::collections::BTreeMap;
 use std::collections::HashMap;
 use std::collections::VecDeque;
diff --git a/src/tools/clippy/tests/ui/get_first.rs b/src/tools/clippy/tests/ui/get_first.rs
index 4d872235614..2062f3ec23a 100644
--- a/src/tools/clippy/tests/ui/get_first.rs
+++ b/src/tools/clippy/tests/ui/get_first.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::get_first)]
+#![allow(clippy::useless_vec)]
 use std::collections::BTreeMap;
 use std::collections::HashMap;
 use std::collections::VecDeque;
diff --git a/src/tools/clippy/tests/ui/get_first.stderr b/src/tools/clippy/tests/ui/get_first.stderr
index 466beff9c92..4e267ba9a3b 100644
--- a/src/tools/clippy/tests/ui/get_first.stderr
+++ b/src/tools/clippy/tests/ui/get_first.stderr
@@ -1,5 +1,5 @@
 error: accessing first element with `x.get(0)`
-  --> $DIR/get_first.rs:19:13
+  --> $DIR/get_first.rs:20:13
    |
 LL |     let _ = x.get(0); // Use x.first()
    |             ^^^^^^^^ help: try: `x.first()`
@@ -7,13 +7,13 @@ LL |     let _ = x.get(0); // Use x.first()
    = note: `-D clippy::get-first` implied by `-D warnings`
 
 error: accessing first element with `y.get(0)`
-  --> $DIR/get_first.rs:24:13
+  --> $DIR/get_first.rs:25:13
    |
 LL |     let _ = y.get(0); // Use y.first()
    |             ^^^^^^^^ help: try: `y.first()`
 
 error: accessing first element with `z.get(0)`
-  --> $DIR/get_first.rs:29:13
+  --> $DIR/get_first.rs:30:13
    |
 LL |     let _ = z.get(0); // Use z.first()
    |             ^^^^^^^^ help: try: `z.first()`
diff --git a/src/tools/clippy/tests/ui/get_last_with_len.fixed b/src/tools/clippy/tests/ui/get_last_with_len.fixed
index a58dfda7988..01a83e5bf34 100644
--- a/src/tools/clippy/tests/ui/get_last_with_len.fixed
+++ b/src/tools/clippy/tests/ui/get_last_with_len.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::get_last_with_len)]
-#![allow(unused)]
+#![allow(unused, clippy::useless_vec)]
 
 use std::collections::VecDeque;
 
diff --git a/src/tools/clippy/tests/ui/get_last_with_len.rs b/src/tools/clippy/tests/ui/get_last_with_len.rs
index d626656c78f..d82484b46d3 100644
--- a/src/tools/clippy/tests/ui/get_last_with_len.rs
+++ b/src/tools/clippy/tests/ui/get_last_with_len.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::get_last_with_len)]
-#![allow(unused)]
+#![allow(unused, clippy::useless_vec)]
 
 use std::collections::VecDeque;
 
diff --git a/src/tools/clippy/tests/ui/get_unwrap.fixed b/src/tools/clippy/tests/ui/get_unwrap.fixed
index 4950c47ddeb..56ee37f02d2 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.fixed
+++ b/src/tools/clippy/tests/ui/get_unwrap.fixed
@@ -1,6 +1,11 @@
 //@run-rustfix
 
-#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)]
+#![allow(
+    unused_mut,
+    clippy::from_iter_instead_of_collect,
+    clippy::get_first,
+    clippy::useless_vec
+)]
 #![warn(clippy::unwrap_used)]
 #![deny(clippy::get_unwrap)]
 
@@ -65,3 +70,42 @@ fn main() {
         let _ = some_vec[0..1].to_vec();
     }
 }
+mod issue9909 {
+    #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
+
+    fn reduced() {
+        let f = &[1, 2, 3];
+
+        // include a borrow in the suggestion, even if the argument is not just a numeric literal
+        let _x: &i32 = &f[1 + 2];
+
+        // don't include a borrow here
+        let _x = f[1 + 2].to_string();
+
+        // don't include a borrow here
+        let _x = f[1 + 2].abs();
+    }
+
+    // original code:
+    fn linidx(row: usize, col: usize) -> usize {
+        row * 1 + col * 3
+    }
+
+    fn main_() {
+        let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0];
+
+        for i in 0..2 {
+            for j in i + 1..3 {
+                if mat[linidx(j, 3)] > mat[linidx(i, 3)] {
+                    for k in 0..4 {
+                        let (x, rest) = mat.split_at_mut(linidx(i, k) + 1);
+                        let a = x.last_mut().unwrap();
+                        let b = &mut rest[linidx(j, k) - linidx(i, k) - 1];
+                        ::std::mem::swap(a, b);
+                    }
+                }
+            }
+        }
+        assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat);
+    }
+}
diff --git a/src/tools/clippy/tests/ui/get_unwrap.rs b/src/tools/clippy/tests/ui/get_unwrap.rs
index 6b1e8edb7bd..af3a619adc5 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.rs
+++ b/src/tools/clippy/tests/ui/get_unwrap.rs
@@ -1,6 +1,11 @@
 //@run-rustfix
 
-#![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)]
+#![allow(
+    unused_mut,
+    clippy::from_iter_instead_of_collect,
+    clippy::get_first,
+    clippy::useless_vec
+)]
 #![warn(clippy::unwrap_used)]
 #![deny(clippy::get_unwrap)]
 
@@ -65,3 +70,42 @@ fn main() {
         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
     }
 }
+mod issue9909 {
+    #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)]
+
+    fn reduced() {
+        let f = &[1, 2, 3];
+
+        // include a borrow in the suggestion, even if the argument is not just a numeric literal
+        let _x: &i32 = f.get(1 + 2).unwrap();
+
+        // don't include a borrow here
+        let _x = f.get(1 + 2).unwrap().to_string();
+
+        // don't include a borrow here
+        let _x = f.get(1 + 2).unwrap().abs();
+    }
+
+    // original code:
+    fn linidx(row: usize, col: usize) -> usize {
+        row * 1 + col * 3
+    }
+
+    fn main_() {
+        let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0];
+
+        for i in 0..2 {
+            for j in i + 1..3 {
+                if mat[linidx(j, 3)] > mat[linidx(i, 3)] {
+                    for k in 0..4 {
+                        let (x, rest) = mat.split_at_mut(linidx(i, k) + 1);
+                        let a = x.last_mut().unwrap();
+                        let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
+                        ::std::mem::swap(a, b);
+                    }
+                }
+            }
+        }
+        assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat);
+    }
+}
diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr
index 6dee4d5b4b6..fd961420dc4 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/get_unwrap.stderr
@@ -1,17 +1,17 @@
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:35:17
+  --> $DIR/get_unwrap.rs:40:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
    |
 note: the lint level is defined here
-  --> $DIR/get_unwrap.rs:5:9
+  --> $DIR/get_unwrap.rs:10:9
    |
 LL | #![deny(clippy::get_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:35:17
+  --> $DIR/get_unwrap.rs:40:17
    |
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,13 +20,13 @@ LL |         let _ = boxed_slice.get(1).unwrap();
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:36:17
+  --> $DIR/get_unwrap.rs:41:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_slice[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:36:17
+  --> $DIR/get_unwrap.rs:41:17
    |
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,13 +34,13 @@ LL |         let _ = some_slice.get(0).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:37:17
+  --> $DIR/get_unwrap.rs:42:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vec[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:37:17
+  --> $DIR/get_unwrap.rs:42:17
    |
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -48,13 +48,13 @@ LL |         let _ = some_vec.get(0).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:38:17
+  --> $DIR/get_unwrap.rs:43:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_vecdeque[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:38:17
+  --> $DIR/get_unwrap.rs:43:17
    |
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,13 +62,13 @@ LL |         let _ = some_vecdeque.get(0).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:39:17
+  --> $DIR/get_unwrap.rs:44:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_hashmap[&1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:39:17
+  --> $DIR/get_unwrap.rs:44:17
    |
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -76,13 +76,13 @@ LL |         let _ = some_hashmap.get(&1).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:40:17
+  --> $DIR/get_unwrap.rs:45:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&some_btreemap[&1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:40:17
+  --> $DIR/get_unwrap.rs:45:17
    |
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,13 +90,13 @@ LL |         let _ = some_btreemap.get(&1).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:44:21
+  --> $DIR/get_unwrap.rs:49:21
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:44:22
+  --> $DIR/get_unwrap.rs:49:22
    |
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,13 +104,13 @@ LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:49:9
+  --> $DIR/get_unwrap.rs:54:9
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `boxed_slice[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:49:10
+  --> $DIR/get_unwrap.rs:54:10
    |
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,13 +118,13 @@ LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:50:9
+  --> $DIR/get_unwrap.rs:55:9
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_slice[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:50:10
+  --> $DIR/get_unwrap.rs:55:10
    |
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -132,13 +132,13 @@ LL |         *some_slice.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:51:9
+  --> $DIR/get_unwrap.rs:56:9
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:51:10
+  --> $DIR/get_unwrap.rs:56:10
    |
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -146,13 +146,13 @@ LL |         *some_vec.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:52:9
+  --> $DIR/get_unwrap.rs:57:9
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vecdeque[0]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:52:10
+  --> $DIR/get_unwrap.rs:57:10
    |
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -160,13 +160,13 @@ LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:64:17
+  --> $DIR/get_unwrap.rs:69:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:64:17
+  --> $DIR/get_unwrap.rs:69:17
    |
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -174,18 +174,42 @@ LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
-  --> $DIR/get_unwrap.rs:65:17
+  --> $DIR/get_unwrap.rs:70:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `some_vec[0..1]`
 
 error: used `unwrap()` on an `Option` value
-  --> $DIR/get_unwrap.rs:65:17
+  --> $DIR/get_unwrap.rs:70:17
    |
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
-error: aborting due to 26 previous errors
+error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+  --> $DIR/get_unwrap.rs:80:24
+   |
+LL |         let _x: &i32 = f.get(1 + 2).unwrap();
+   |                        ^^^^^^^^^^^^^^^^^^^^^ help: try this: `&f[1 + 2]`
+
+error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+  --> $DIR/get_unwrap.rs:83:18
+   |
+LL |         let _x = f.get(1 + 2).unwrap().to_string();
+   |                  ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]`
+
+error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+  --> $DIR/get_unwrap.rs:86:18
+   |
+LL |         let _x = f.get(1 + 2).unwrap().abs();
+   |                  ^^^^^^^^^^^^^^^^^^^^^ help: try this: `f[1 + 2]`
+
+error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
+  --> $DIR/get_unwrap.rs:103:33
+   |
+LL |                         let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&mut rest[linidx(j, k) - linidx(i, k) - 1]`
+
+error: aborting due to 30 previous errors
 
diff --git a/src/tools/clippy/tests/ui/if_same_then_else.rs b/src/tools/clippy/tests/ui/if_same_then_else.rs
index 07d2002eb27..dad4543f84c 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else.rs
+++ b/src/tools/clippy/tests/ui/if_same_then_else.rs
@@ -21,6 +21,7 @@ fn foo() -> bool {
 
 fn if_same_then_else() {
     if true {
+        //~^ ERROR: this `if` has identical blocks
         Foo { bar: 42 };
         0..10;
         ..;
@@ -29,7 +30,6 @@ fn if_same_then_else() {
         0..=10;
         foo();
     } else {
-        //~ ERROR same body as `if` block
         Foo { bar: 42 };
         0..10;
         ..;
@@ -65,16 +65,16 @@ fn if_same_then_else() {
     }
 
     let _ = if true {
+        //~^ ERROR: this `if` has identical blocks
         0.0
     } else {
-        //~ ERROR same body as `if` block
         0.0
     };
 
     let _ = if true {
+        //~^ ERROR: this `if` has identical blocks
         -0.0
     } else {
-        //~ ERROR same body as `if` block
         -0.0
     };
 
@@ -88,13 +88,14 @@ fn if_same_then_else() {
     }
 
     let _ = if true {
+        //~^ ERROR: this `if` has identical blocks
         42
     } else {
-        //~ ERROR same body as `if` block
         42
     };
 
     if true {
+        //~^ ERROR: this `if` has identical blocks
         let bar = if true { 42 } else { 43 };
 
         while foo() {
@@ -102,7 +103,6 @@ fn if_same_then_else() {
         }
         bar + 1;
     } else {
-        //~ ERROR same body as `if` block
         let bar = if true { 42 } else { 43 };
 
         while foo() {
diff --git a/src/tools/clippy/tests/ui/if_same_then_else.stderr b/src/tools/clippy/tests/ui/if_same_then_else.stderr
index fb23b81d36d..a34fc565590 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else.stderr
@@ -3,22 +3,22 @@ error: this `if` has identical blocks
    |
 LL |       if true {
    |  _____________^
+LL | |
 LL | |         Foo { bar: 42 };
 LL | |         0..10;
-LL | |         ..;
 ...  |
 LL | |         foo();
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:31:12
+  --> $DIR/if_same_then_else.rs:32:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         Foo { bar: 42 };
 LL | |         0..10;
+LL | |         ..;
 ...  |
 LL | |         foo();
 LL | |     }
@@ -30,16 +30,16 @@ error: this `if` has identical blocks
    |
 LL |       let _ = if true {
    |  _____________________^
+LL | |
 LL | |         0.0
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:69:12
+  --> $DIR/if_same_then_else.rs:70:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         0.0
 LL | |     };
    | |_____^
@@ -49,16 +49,16 @@ error: this `if` has identical blocks
    |
 LL |       let _ = if true {
    |  _____________________^
+LL | |
 LL | |         -0.0
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:76:12
+  --> $DIR/if_same_then_else.rs:77:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         -0.0
 LL | |     };
    | |_____^
@@ -68,16 +68,16 @@ error: this `if` has identical blocks
    |
 LL |       let _ = if true {
    |  _____________________^
+LL | |
 LL | |         42
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:92:12
+  --> $DIR/if_same_then_else.rs:93:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         42
 LL | |     };
    | |_____^
@@ -87,22 +87,22 @@ error: this `if` has identical blocks
    |
 LL |       if true {
    |  _____________^
+LL | |
 LL | |         let bar = if true { 42 } else { 43 };
 LL | |
-LL | |         while foo() {
 ...  |
 LL | |         bar + 1;
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:104:12
+  --> $DIR/if_same_then_else.rs:105:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         let bar = if true { 42 } else { 43 };
 LL | |
+LL | |         while foo() {
 ...  |
 LL | |         bar + 1;
 LL | |     }
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.rs b/src/tools/clippy/tests/ui/if_same_then_else2.rs
index 58167f4446d..0b171f21d0c 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.rs
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.rs
@@ -5,6 +5,7 @@
     clippy::equatable_if_let,
     clippy::collapsible_if,
     clippy::ifs_same_cond,
+    clippy::needless_if,
     clippy::needless_return,
     clippy::single_element_loop,
     clippy::branches_sharing_code
@@ -12,6 +13,7 @@
 
 fn if_same_then_else2() -> Result<&'static str, ()> {
     if true {
+        //~^ ERROR: this `if` has identical blocks
         for _ in &[42] {
             let foo: &Option<_> = &Some::<u8>(42);
             if foo.is_some() {
@@ -21,7 +23,6 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
             }
         }
     } else {
-        //~ ERROR same body as `if` block
         for _ in &[42] {
             let bar: &Option<_> = &Some::<u8>(42);
             if bar.is_some() {
@@ -33,16 +34,16 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
     }
 
     if true {
+        //~^ ERROR: this `if` has identical blocks
         if let Some(a) = Some(42) {}
     } else {
-        //~ ERROR same body as `if` block
         if let Some(a) = Some(42) {}
     }
 
     if true {
+        //~^ ERROR: this `if` has identical blocks
         if let (1, .., 3) = (1, 2, 3) {}
     } else {
-        //~ ERROR same body as `if` block
         if let (1, .., 3) = (1, 2, 3) {}
     }
 
@@ -90,16 +91,16 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
 
     // Same NaNs
     let _ = if true {
+        //~^ ERROR: this `if` has identical blocks
         f32::NAN
     } else {
-        //~ ERROR same body as `if` block
         f32::NAN
     };
 
     if true {
+        //~^ ERROR: this `if` has identical blocks
         Ok("foo")?;
     } else {
-        //~ ERROR same body as `if` block
         Ok("foo")?;
     }
 
@@ -121,6 +122,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
         let foo = "bar";
         return Ok(&foo[0..]);
     } else if true {
+        //~^ ERROR: this `if` has identical blocks
         let foo = "";
         return Ok(&foo[0..]);
     } else {
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
index 704cfd9669a..56e5f3e45b2 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
@@ -1,24 +1,24 @@
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:14:13
+  --> $DIR/if_same_then_else2.rs:15:13
    |
 LL |       if true {
    |  _____________^
+LL | |
 LL | |         for _ in &[42] {
 LL | |             let foo: &Option<_> = &Some::<u8>(42);
-LL | |             if foo.is_some() {
 ...  |
 LL | |         }
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:23:12
+  --> $DIR/if_same_then_else2.rs:25:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         for _ in &[42] {
 LL | |             let bar: &Option<_> = &Some::<u8>(42);
+LL | |             if bar.is_some() {
 ...  |
 LL | |         }
 LL | |     }
@@ -26,93 +26,94 @@ LL | |     }
    = note: `-D clippy::if-same-then-else` implied by `-D warnings`
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:35:13
+  --> $DIR/if_same_then_else2.rs:36:13
    |
 LL |       if true {
    |  _____________^
+LL | |
 LL | |         if let Some(a) = Some(42) {}
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:37:12
+  --> $DIR/if_same_then_else2.rs:39:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         if let Some(a) = Some(42) {}
 LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:42:13
+  --> $DIR/if_same_then_else2.rs:43:13
    |
 LL |       if true {
    |  _____________^
+LL | |
 LL | |         if let (1, .., 3) = (1, 2, 3) {}
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:44:12
+  --> $DIR/if_same_then_else2.rs:46:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         if let (1, .., 3) = (1, 2, 3) {}
 LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:92:21
+  --> $DIR/if_same_then_else2.rs:93:21
    |
 LL |       let _ = if true {
    |  _____________________^
+LL | |
 LL | |         f32::NAN
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:94:12
+  --> $DIR/if_same_then_else2.rs:96:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         f32::NAN
 LL | |     };
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:99:13
+  --> $DIR/if_same_then_else2.rs:100:13
    |
 LL |       if true {
    |  _____________^
+LL | |
 LL | |         Ok("foo")?;
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:101:12
+  --> $DIR/if_same_then_else2.rs:103:12
    |
 LL |       } else {
    |  ____________^
-LL | |         //~ ERROR same body as `if` block
 LL | |         Ok("foo")?;
 LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:123:20
+  --> $DIR/if_same_then_else2.rs:124:20
    |
 LL |       } else if true {
    |  ____________________^
+LL | |
 LL | |         let foo = "";
 LL | |         return Ok(&foo[0..]);
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:126:12
+  --> $DIR/if_same_then_else2.rs:128:12
    |
 LL |       } else {
    |  ____________^
diff --git a/src/tools/clippy/tests/ui/ifs_same_cond.rs b/src/tools/clippy/tests/ui/ifs_same_cond.rs
index f62da157d1b..5c338e3c5c8 100644
--- a/src/tools/clippy/tests/ui/ifs_same_cond.rs
+++ b/src/tools/clippy/tests/ui/ifs_same_cond.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::ifs_same_cond)]
-#![allow(clippy::if_same_then_else, clippy::comparison_chain, clippy::needless_else)] // all empty blocks
+#![allow(
+    clippy::if_same_then_else,
+    clippy::comparison_chain,
+    clippy::needless_if,
+    clippy::needless_else
+)] // all empty blocks
 
 fn ifs_same_cond() {
     let a = 0;
@@ -7,18 +12,18 @@ fn ifs_same_cond() {
 
     if b {
     } else if b {
-        //~ ERROR ifs same condition
+        //~^ ERROR: this `if` has the same condition as a previous `if`
     }
 
     if a == 1 {
     } else if a == 1 {
-        //~ ERROR ifs same condition
+        //~^ ERROR: this `if` has the same condition as a previous `if`
     }
 
     if 2 * a == 1 {
     } else if 2 * a == 2 {
     } else if 2 * a == 1 {
-        //~ ERROR ifs same condition
+        //~^ ERROR: this `if` has the same condition as a previous `if`
     } else if a == 1 {
     }
 
@@ -47,6 +52,7 @@ fn issue10272() {
     let a = String::from("ha");
     if a.contains("ah") {
     } else if a.contains("ah") {
+        //~^ ERROR: this `if` has the same condition as a previous `if`
         // Trigger this lint
     } else if a.contains("ha") {
     } else if a == "wow" {
diff --git a/src/tools/clippy/tests/ui/ifs_same_cond.stderr b/src/tools/clippy/tests/ui/ifs_same_cond.stderr
index 9519f6904cb..8d70934476c 100644
--- a/src/tools/clippy/tests/ui/ifs_same_cond.stderr
+++ b/src/tools/clippy/tests/ui/ifs_same_cond.stderr
@@ -1,48 +1,48 @@
 error: this `if` has the same condition as a previous `if`
-  --> $DIR/ifs_same_cond.rs:9:15
+  --> $DIR/ifs_same_cond.rs:14:15
    |
 LL |     } else if b {
    |               ^
    |
 note: same as this
-  --> $DIR/ifs_same_cond.rs:8:8
+  --> $DIR/ifs_same_cond.rs:13:8
    |
 LL |     if b {
    |        ^
    = note: `-D clippy::ifs-same-cond` implied by `-D warnings`
 
 error: this `if` has the same condition as a previous `if`
-  --> $DIR/ifs_same_cond.rs:14:15
+  --> $DIR/ifs_same_cond.rs:19:15
    |
 LL |     } else if a == 1 {
    |               ^^^^^^
    |
 note: same as this
-  --> $DIR/ifs_same_cond.rs:13:8
+  --> $DIR/ifs_same_cond.rs:18:8
    |
 LL |     if a == 1 {
    |        ^^^^^^
 
 error: this `if` has the same condition as a previous `if`
-  --> $DIR/ifs_same_cond.rs:20:15
+  --> $DIR/ifs_same_cond.rs:25:15
    |
 LL |     } else if 2 * a == 1 {
    |               ^^^^^^^^^^
    |
 note: same as this
-  --> $DIR/ifs_same_cond.rs:18:8
+  --> $DIR/ifs_same_cond.rs:23:8
    |
 LL |     if 2 * a == 1 {
    |        ^^^^^^^^^^
 
 error: this `if` has the same condition as a previous `if`
-  --> $DIR/ifs_same_cond.rs:49:15
+  --> $DIR/ifs_same_cond.rs:54:15
    |
 LL |     } else if a.contains("ah") {
    |               ^^^^^^^^^^^^^^^^
    |
 note: same as this
-  --> $DIR/ifs_same_cond.rs:48:8
+  --> $DIR/ifs_same_cond.rs:53:8
    |
 LL |     if a.contains("ah") {
    |        ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.rs b/src/tools/clippy/tests/ui/implicit_hasher.rs
index ca7c1221372..7ed7bf94a4b 100644
--- a/src/tools/clippy/tests/ui/implicit_hasher.rs
+++ b/src/tools/clippy/tests/ui/implicit_hasher.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![deny(clippy::implicit_hasher)]
 #![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
index 620d45e6828..d84346e8789 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
index 10ffadcb2ba..87fba7448e3 100644
--- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
diff --git a/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.fixed b/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.fixed
new file mode 100644
index 00000000000..ac482dcda1e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.fixed
@@ -0,0 +1,97 @@
+//@run-rustfix
+#![allow(clippy::clone_on_copy, unused)]
+#![no_main]
+
+// lint
+
+struct A(u32);
+
+impl Clone for A {
+    fn clone(&self) -> Self { *self }
+
+    
+}
+
+impl Copy for A {}
+
+// do not lint
+
+struct B(u32);
+
+impl Clone for B {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl Copy for B {}
+
+// do not lint derived (clone's implementation is `*self` here anyway)
+
+#[derive(Clone, Copy)]
+struct C(u32);
+
+// do not lint derived (fr this time)
+
+struct D(u32);
+
+#[automatically_derived]
+impl Clone for D {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for D {}
+
+// do not lint if clone is not manually implemented
+
+struct E(u32);
+
+#[automatically_derived]
+impl Clone for E {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for E {}
+
+// lint since clone is not derived
+
+#[derive(Copy)]
+struct F(u32);
+
+impl Clone for F {
+    fn clone(&self) -> Self { *self }
+
+    
+}
+
+// do not lint since copy has more restrictive bounds
+
+#[derive(Eq, PartialEq)]
+struct Uwu<A: Copy>(A);
+
+impl<A: Copy> Clone for Uwu<A> {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}
diff --git a/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.rs b/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.rs
new file mode 100644
index 00000000000..00775874ff5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.rs
@@ -0,0 +1,107 @@
+//@run-rustfix
+#![allow(clippy::clone_on_copy, unused)]
+#![no_main]
+
+// lint
+
+struct A(u32);
+
+impl Clone for A {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for A {}
+
+// do not lint
+
+struct B(u32);
+
+impl Clone for B {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl Copy for B {}
+
+// do not lint derived (clone's implementation is `*self` here anyway)
+
+#[derive(Clone, Copy)]
+struct C(u32);
+
+// do not lint derived (fr this time)
+
+struct D(u32);
+
+#[automatically_derived]
+impl Clone for D {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for D {}
+
+// do not lint if clone is not manually implemented
+
+struct E(u32);
+
+#[automatically_derived]
+impl Clone for E {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for E {}
+
+// lint since clone is not derived
+
+#[derive(Copy)]
+struct F(u32);
+
+impl Clone for F {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+// do not lint since copy has more restrictive bounds
+
+#[derive(Eq, PartialEq)]
+struct Uwu<A: Copy>(A);
+
+impl<A: Copy> Clone for Uwu<A> {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}
diff --git a/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.stderr b/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.stderr
new file mode 100644
index 00000000000..0021841aa86
--- /dev/null
+++ b/src/tools/clippy/tests/ui/incorrect_clone_impl_on_copy_type.stderr
@@ -0,0 +1,40 @@
+error: incorrect implementation of `clone` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:10:29
+   |
+LL |       fn clone(&self) -> Self {
+   |  _____________________________^
+LL | |         Self(self.0)
+LL | |     }
+   | |_____^ help: change this to: `{ *self }`
+   |
+   = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default
+
+error: incorrect implementation of `clone_from` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:14:5
+   |
+LL | /     fn clone_from(&mut self, source: &Self) {
+LL | |         source.clone();
+LL | |         *self = source.clone();
+LL | |     }
+   | |_____^ help: remove this
+
+error: incorrect implementation of `clone` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:81:29
+   |
+LL |       fn clone(&self) -> Self {
+   |  _____________________________^
+LL | |         Self(self.0)
+LL | |     }
+   | |_____^ help: change this to: `{ *self }`
+
+error: incorrect implementation of `clone_from` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:85:5
+   |
+LL | /     fn clone_from(&mut self, source: &Self) {
+LL | |         source.clone();
+LL | |         *self = source.clone();
+LL | |     }
+   | |_____^ help: remove this
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
index 26abc9edb5e..16f9e47e853 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
@@ -3,7 +3,12 @@
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
 #![warn(clippy::out_of_bounds_indexing)]
-#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(
+    unconditional_panic,
+    clippy::no_effect,
+    clippy::unnecessary_operation,
+    clippy::useless_vec
+)]
 
 const ARR: [i32; 2] = [1, 2];
 const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
index 8fd77913a3f..f4357c1d592 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
@@ -1,5 +1,5 @@
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:9:20
+  --> $DIR/indexing_slicing_index.rs:14:20
    |
 LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |                    ^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
    = note: `-D clippy::indexing-slicing` implied by `-D warnings`
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:10:24
+  --> $DIR/indexing_slicing_index.rs:15:24
    |
 LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
    |                        ^^^^^^^^^^^
@@ -18,19 +18,19 @@ LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
    = note: the suggestion might not be applicable in constant blocks
 
 error[E0080]: evaluation of `main::{constant#3}` failed
-  --> $DIR/indexing_slicing_index.rs:31:14
+  --> $DIR/indexing_slicing_index.rs:36:14
    |
 LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
 note: erroneous constant used
-  --> $DIR/indexing_slicing_index.rs:31:5
+  --> $DIR/indexing_slicing_index.rs:36:5
    |
 LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:22:5
+  --> $DIR/indexing_slicing_index.rs:27:5
    |
 LL |     x[index];
    |     ^^^^^^^^
@@ -38,7 +38,7 @@ LL |     x[index];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:30:14
+  --> $DIR/indexing_slicing_index.rs:35:14
    |
 LL |     const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |              ^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     const { &ARR[idx()] }; // This should be linted, since `suppress-restri
    = note: the suggestion might not be applicable in constant blocks
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:31:14
+  --> $DIR/indexing_slicing_index.rs:36:14
    |
 LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |              ^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     const { &ARR[idx4()] }; // This should be linted, since `suppress-restr
    = note: the suggestion might not be applicable in constant blocks
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:38:5
+  --> $DIR/indexing_slicing_index.rs:43:5
    |
 LL |     v[0];
    |     ^^^^
@@ -64,7 +64,7 @@ LL |     v[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:39:5
+  --> $DIR/indexing_slicing_index.rs:44:5
    |
 LL |     v[10];
    |     ^^^^^
@@ -72,7 +72,7 @@ LL |     v[10];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:40:5
+  --> $DIR/indexing_slicing_index.rs:45:5
    |
 LL |     v[1 << 3];
    |     ^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     v[1 << 3];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:46:5
+  --> $DIR/indexing_slicing_index.rs:51:5
    |
 LL |     v[N];
    |     ^^^^
@@ -88,7 +88,7 @@ LL |     v[N];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> $DIR/indexing_slicing_index.rs:47:5
+  --> $DIR/indexing_slicing_index.rs:52:5
    |
 LL |     v[M];
    |     ^^^^
@@ -96,7 +96,7 @@ LL |     v[M];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/indexing_slicing_index.rs:10:24
+  --> $DIR/indexing_slicing_index.rs:15:24
    |
 LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
    |                        ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_slice.rs b/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
index 7b107db39f0..939b6ac36bd 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
@@ -2,7 +2,7 @@
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
 #![warn(clippy::out_of_bounds_indexing)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec)]
 
 fn main() {
     let x = [1, 2, 3, 4];
diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.fixed b/src/tools/clippy/tests/ui/into_iter_on_ref.fixed
index 9f550acb157..af197e33fd8 100644
--- a/src/tools/clippy/tests/ui/into_iter_on_ref.fixed
+++ b/src/tools/clippy/tests/ui/into_iter_on_ref.fixed
@@ -11,35 +11,35 @@ fn main() {
     for _ in &vec![X, X] {}
 
     let _ = vec![1, 2, 3].into_iter();
-    let _ = (&vec![1, 2, 3]).iter(); //~ WARN equivalent to .iter()
-    let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ WARN equivalent to .iter()
-    let _ = std::rc::Rc::from(&[X][..]).iter(); //~ WARN equivalent to .iter()
-    let _ = std::sync::Arc::from(&[X][..]).iter(); //~ WARN equivalent to .iter()
+    let _ = (&vec![1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::rc::Rc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::sync::Arc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter()
 
-    let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter()
-    let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR equivalent to .iter()
-    let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR equivalent to .iter_mut()
+    let _ = (&&&&&&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&&&&mut &&&[1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut &mut &mut [1, 2, 3]).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
 
-    let _ = (&Some(4)).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut Some(5)).iter_mut(); //~ WARN equivalent to .iter_mut()
-    let _ = (&Ok::<_, i32>(6)).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut Err::<i32, _>(7)).iter_mut(); //~ WARN equivalent to .iter_mut()
-    let _ = (&Vec::<i32>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut Vec::<i32>::new()).iter_mut(); //~ WARN equivalent to .iter_mut()
-    let _ = (&BTreeMap::<i32, u64>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut BTreeMap::<i32, u64>::new()).iter_mut(); //~ WARN equivalent to .iter_mut()
-    let _ = (&VecDeque::<i32>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut VecDeque::<i32>::new()).iter_mut(); //~ WARN equivalent to .iter_mut()
-    let _ = (&LinkedList::<i32>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut LinkedList::<i32>::new()).iter_mut(); //~ WARN equivalent to .iter_mut()
-    let _ = (&HashMap::<i32, u64>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut HashMap::<i32, u64>::new()).iter_mut(); //~ WARN equivalent to .iter_mut()
+    let _ = (&Some(4)).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut Some(5)).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&Ok::<_, i32>(6)).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut Err::<i32, _>(7)).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&Vec::<i32>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut Vec::<i32>::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&BTreeMap::<i32, u64>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut BTreeMap::<i32, u64>::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&VecDeque::<i32>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut VecDeque::<i32>::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&LinkedList::<i32>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut LinkedList::<i32>::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&HashMap::<i32, u64>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut HashMap::<i32, u64>::new()).iter_mut(); //~ ERROR: equivalent to `.iter_mut()
 
-    let _ = (&BTreeSet::<i32>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&BinaryHeap::<i32>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = (&HashSet::<i32>::new()).iter(); //~ WARN equivalent to .iter()
-    let _ = std::path::Path::new("12/34").iter(); //~ WARN equivalent to .iter()
-    let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR equivalent to .iter()
+    let _ = (&BTreeSet::<i32>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&BinaryHeap::<i32>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&HashSet::<i32>::new()).iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::path::Path::new("12/34").iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::path::PathBuf::from("12/34").iter(); //~ ERROR: equivalent to `.iter()
 
-    let _ = (&[1, 2, 3]).iter().next(); //~ WARN equivalent to .iter()
+    let _ = (&[1, 2, 3]).iter().next(); //~ ERROR: equivalent to `.iter()
 }
diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.rs b/src/tools/clippy/tests/ui/into_iter_on_ref.rs
index 3381ae04dce..3ac13d7dd3e 100644
--- a/src/tools/clippy/tests/ui/into_iter_on_ref.rs
+++ b/src/tools/clippy/tests/ui/into_iter_on_ref.rs
@@ -11,35 +11,35 @@ fn main() {
     for _ in &vec![X, X] {}
 
     let _ = vec![1, 2, 3].into_iter();
-    let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter()
-    let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter()
-    let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter()
-    let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter()
+    let _ = (&vec![1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter()
 
-    let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter()
-    let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter()
-    let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut()
+    let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter_mut()
 
-    let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut()
-    let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut Err::<i32, _>(7)).into_iter(); //~ WARN equivalent to .iter_mut()
-    let _ = (&Vec::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut Vec::<i32>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
-    let _ = (&BTreeMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut BTreeMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
-    let _ = (&VecDeque::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut VecDeque::<i32>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
-    let _ = (&LinkedList::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut LinkedList::<i32>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
-    let _ = (&HashMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&mut HashMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
+    let _ = (&Some(4)).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut Some(5)).into_iter(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&Ok::<_, i32>(6)).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut Err::<i32, _>(7)).into_iter(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&Vec::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut Vec::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&BTreeMap::<i32, u64>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut BTreeMap::<i32, u64>::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&VecDeque::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut VecDeque::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&LinkedList::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut LinkedList::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut()
+    let _ = (&HashMap::<i32, u64>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&mut HashMap::<i32, u64>::new()).into_iter(); //~ ERROR: equivalent to `.iter_mut()
 
-    let _ = (&BTreeSet::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&BinaryHeap::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = (&HashSet::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
-    let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter()
-    let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter()
+    let _ = (&BTreeSet::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&BinaryHeap::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = (&HashSet::<i32>::new()).into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::path::Path::new("12/34").into_iter(); //~ ERROR: equivalent to `.iter()
+    let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR: equivalent to `.iter()
 
-    let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter()
+    let _ = (&[1, 2, 3]).into_iter().next(); //~ ERROR: equivalent to `.iter()
 }
diff --git a/src/tools/clippy/tests/ui/into_iter_on_ref.stderr b/src/tools/clippy/tests/ui/into_iter_on_ref.stderr
index 28003b365bb..06014a93f8c 100644
--- a/src/tools/clippy/tests/ui/into_iter_on_ref.stderr
+++ b/src/tools/clippy/tests/ui/into_iter_on_ref.stderr
@@ -1,7 +1,7 @@
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec`
   --> $DIR/into_iter_on_ref.rs:14:30
    |
-LL |     let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&vec![1, 2, 3]).into_iter();
    |                              ^^^^^^^^^ help: call directly: `iter`
    |
    = note: `-D clippy::into-iter-on-ref` implied by `-D warnings`
@@ -9,157 +9,157 @@ LL |     let _ = (&vec![1, 2, 3]).into_iter(); //~ WARN equivalent to .iter()
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice`
   --> $DIR/into_iter_on_ref.rs:15:46
    |
-LL |     let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = vec![1, 2, 3].into_boxed_slice().into_iter();
    |                                              ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice`
   --> $DIR/into_iter_on_ref.rs:16:41
    |
-LL |     let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = std::rc::Rc::from(&[X][..]).into_iter();
    |                                         ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice`
   --> $DIR/into_iter_on_ref.rs:17:44
    |
-LL |     let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = std::sync::Arc::from(&[X][..]).into_iter();
    |                                            ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array`
   --> $DIR/into_iter_on_ref.rs:19:32
    |
-LL |     let _ = (&&&&&&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter()
+LL |     let _ = (&&&&&&&[1, 2, 3]).into_iter();
    |                                ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array`
   --> $DIR/into_iter_on_ref.rs:20:36
    |
-LL |     let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter()
+LL |     let _ = (&&&&mut &&&[1, 2, 3]).into_iter();
    |                                    ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `array`
   --> $DIR/into_iter_on_ref.rs:21:40
    |
-LL |     let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); //~ ERROR equivalent to .iter_mut()
+LL |     let _ = (&mut &mut &mut [1, 2, 3]).into_iter();
    |                                        ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Option`
   --> $DIR/into_iter_on_ref.rs:23:24
    |
-LL |     let _ = (&Some(4)).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&Some(4)).into_iter();
    |                        ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Option`
   --> $DIR/into_iter_on_ref.rs:24:28
    |
-LL |     let _ = (&mut Some(5)).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut Some(5)).into_iter();
    |                            ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Result`
   --> $DIR/into_iter_on_ref.rs:25:32
    |
-LL |     let _ = (&Ok::<_, i32>(6)).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&Ok::<_, i32>(6)).into_iter();
    |                                ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Result`
   --> $DIR/into_iter_on_ref.rs:26:37
    |
-LL |     let _ = (&mut Err::<i32, _>(7)).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut Err::<i32, _>(7)).into_iter();
    |                                     ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec`
   --> $DIR/into_iter_on_ref.rs:27:34
    |
-LL |     let _ = (&Vec::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&Vec::<i32>::new()).into_iter();
    |                                  ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Vec`
   --> $DIR/into_iter_on_ref.rs:28:38
    |
-LL |     let _ = (&mut Vec::<i32>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut Vec::<i32>::new()).into_iter();
    |                                      ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeMap`
   --> $DIR/into_iter_on_ref.rs:29:44
    |
-LL |     let _ = (&BTreeMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&BTreeMap::<i32, u64>::new()).into_iter();
    |                                            ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `BTreeMap`
   --> $DIR/into_iter_on_ref.rs:30:48
    |
-LL |     let _ = (&mut BTreeMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut BTreeMap::<i32, u64>::new()).into_iter();
    |                                                ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `VecDeque`
   --> $DIR/into_iter_on_ref.rs:31:39
    |
-LL |     let _ = (&VecDeque::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&VecDeque::<i32>::new()).into_iter();
    |                                       ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `VecDeque`
   --> $DIR/into_iter_on_ref.rs:32:43
    |
-LL |     let _ = (&mut VecDeque::<i32>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut VecDeque::<i32>::new()).into_iter();
    |                                           ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `LinkedList`
   --> $DIR/into_iter_on_ref.rs:33:41
    |
-LL |     let _ = (&LinkedList::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&LinkedList::<i32>::new()).into_iter();
    |                                         ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `LinkedList`
   --> $DIR/into_iter_on_ref.rs:34:45
    |
-LL |     let _ = (&mut LinkedList::<i32>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut LinkedList::<i32>::new()).into_iter();
    |                                             ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashMap`
   --> $DIR/into_iter_on_ref.rs:35:43
    |
-LL |     let _ = (&HashMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&HashMap::<i32, u64>::new()).into_iter();
    |                                           ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `HashMap`
   --> $DIR/into_iter_on_ref.rs:36:47
    |
-LL |     let _ = (&mut HashMap::<i32, u64>::new()).into_iter(); //~ WARN equivalent to .iter_mut()
+LL |     let _ = (&mut HashMap::<i32, u64>::new()).into_iter();
    |                                               ^^^^^^^^^ help: call directly: `iter_mut`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeSet`
   --> $DIR/into_iter_on_ref.rs:38:39
    |
-LL |     let _ = (&BTreeSet::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&BTreeSet::<i32>::new()).into_iter();
    |                                       ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BinaryHeap`
   --> $DIR/into_iter_on_ref.rs:39:41
    |
-LL |     let _ = (&BinaryHeap::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&BinaryHeap::<i32>::new()).into_iter();
    |                                         ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashSet`
   --> $DIR/into_iter_on_ref.rs:40:38
    |
-LL |     let _ = (&HashSet::<i32>::new()).into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = (&HashSet::<i32>::new()).into_iter();
    |                                      ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Path`
   --> $DIR/into_iter_on_ref.rs:41:43
    |
-LL |     let _ = std::path::Path::new("12/34").into_iter(); //~ WARN equivalent to .iter()
+LL |     let _ = std::path::Path::new("12/34").into_iter();
    |                                           ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `PathBuf`
   --> $DIR/into_iter_on_ref.rs:42:47
    |
-LL |     let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter()
+LL |     let _ = std::path::PathBuf::from("12/34").into_iter();
    |                                               ^^^^^^^^^ help: call directly: `iter`
 
 error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array`
   --> $DIR/into_iter_on_ref.rs:44:26
    |
-LL |     let _ = (&[1, 2, 3]).into_iter().next(); //~ WARN equivalent to .iter()
+LL |     let _ = (&[1, 2, 3]).into_iter().next();
    |                          ^^^^^^^^^ help: call directly: `iter`
 
 error: aborting due to 27 previous errors
diff --git a/src/tools/clippy/tests/ui/issue-3145.rs b/src/tools/clippy/tests/ui/issue-3145.rs
index 586d13647d1..0b07de1144c 100644
--- a/src/tools/clippy/tests/ui/issue-3145.rs
+++ b/src/tools/clippy/tests/ui/issue-3145.rs
@@ -1,3 +1,3 @@
 fn main() {
-    println!("{}" a); //~ERROR expected `,`, found `a`
+    println!("{}" a); //~ERROR: expected `,`, found `a`
 }
diff --git a/src/tools/clippy/tests/ui/issue-3145.stderr b/src/tools/clippy/tests/ui/issue-3145.stderr
index a35032aa150..d7c2c88a204 100644
--- a/src/tools/clippy/tests/ui/issue-3145.stderr
+++ b/src/tools/clippy/tests/ui/issue-3145.stderr
@@ -1,7 +1,7 @@
 error: expected `,`, found `a`
   --> $DIR/issue-3145.rs:2:19
    |
-LL |     println!("{}" a); //~ERROR expected `,`, found `a`
+LL |     println!("{}" a);
    |                   ^ expected `,`
 
 error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/issue_4266.stderr b/src/tools/clippy/tests/ui/issue_4266.stderr
index fd553aa4538..5b60646ef21 100644
--- a/src/tools/clippy/tests/ui/issue_4266.stderr
+++ b/src/tools/clippy/tests/ui/issue_4266.stderr
@@ -1,16 +1,16 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/issue_4266.rs:4:1
+  --> $DIR/issue_4266.rs:4:16
    |
 LL | async fn sink1<'a>(_: &'a str) {} // lint
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^      ^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/issue_4266.rs:8:1
+  --> $DIR/issue_4266.rs:8:21
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^      ^^
 
 error: methods called `new` usually take no `self`
   --> $DIR/issue_4266.rs:28:22
diff --git a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
index 597f1b9510c..1b625747161 100644
--- a/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
+++ b/src/tools/clippy/tests/ui/items_after_test_module/block_module.stderr
@@ -1,17 +1,2 @@
-error: items were found after the testing module
-  --> $DIR/block_module.rs:13:1
-   |
-LL | / mod tests {
-LL | |     #[test]
-LL | |     fn hi() {}
-LL | | }
-...  |
-LL | |     () => {};
-LL | | }
-   | |_^
-   |
-   = help: move the items to before the testing module was defined
-   = note: `-D clippy::items-after-test-module` implied by `-D warnings`
-
-error: aborting due to previous error
+error: Option 'test' given more than once
 
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
index 88f08bb991b..2baea06f84b 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.fixed
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::HashSet;
 use std::collections::VecDeque;
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.rs b/src/tools/clippy/tests/ui/iter_cloned_collect.rs
index d3438b7f51a..9eac94eb8d9 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.rs
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.rs
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![allow(unused)]
+#![allow(clippy::useless_vec)]
 
 use std::collections::HashSet;
 use std::collections::VecDeque;
diff --git a/src/tools/clippy/tests/ui/iter_cloned_collect.stderr b/src/tools/clippy/tests/ui/iter_cloned_collect.stderr
index b2cc497bf43..b38cf547dc5 100644
--- a/src/tools/clippy/tests/ui/iter_cloned_collect.stderr
+++ b/src/tools/clippy/tests/ui/iter_cloned_collect.stderr
@@ -1,5 +1,5 @@
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:10:27
+  --> $DIR/iter_cloned_collect.rs:11:27
    |
 LL |     let v2: Vec<isize> = v.iter().cloned().collect();
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
@@ -7,13 +7,13 @@ LL |     let v2: Vec<isize> = v.iter().cloned().collect();
    = note: `-D clippy::iter-cloned-collect` implied by `-D warnings`
 
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:15:38
+  --> $DIR/iter_cloned_collect.rs:16:38
    |
 LL |     let _: Vec<isize> = vec![1, 2, 3].iter().cloned().collect();
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
 
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:20:24
+  --> $DIR/iter_cloned_collect.rs:21:24
    |
 LL |               .to_bytes()
    |  ________________________^
@@ -23,13 +23,13 @@ LL | |             .collect();
    | |______________________^ help: try: `.to_vec()`
 
 error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:28:24
+  --> $DIR/iter_cloned_collect.rs:29:24
    |
 LL |     let _: Vec<_> = arr.iter().cloned().collect();
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
 
 error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
-  --> $DIR/iter_cloned_collect.rs:31:26
+  --> $DIR/iter_cloned_collect.rs:32:26
    |
 LL |     let _: Vec<isize> = v.iter().copied().collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()`
diff --git a/src/tools/clippy/tests/ui/iter_count.fixed b/src/tools/clippy/tests/ui/iter_count.fixed
index 4367a12f820..b6208201409 100644
--- a/src/tools/clippy/tests/ui/iter_count.fixed
+++ b/src/tools/clippy/tests/ui/iter_count.fixed
@@ -7,7 +7,8 @@
     array_into_iter,
     unused_mut,
     clippy::into_iter_on_ref,
-    clippy::unnecessary_operation
+    clippy::unnecessary_operation,
+    clippy::useless_vec
 )]
 
 extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/iter_count.rs b/src/tools/clippy/tests/ui/iter_count.rs
index 8c7543cf03b..fb216131209 100644
--- a/src/tools/clippy/tests/ui/iter_count.rs
+++ b/src/tools/clippy/tests/ui/iter_count.rs
@@ -7,7 +7,8 @@
     array_into_iter,
     unused_mut,
     clippy::into_iter_on_ref,
-    clippy::unnecessary_operation
+    clippy::unnecessary_operation,
+    clippy::useless_vec
 )]
 
 extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/iter_count.stderr b/src/tools/clippy/tests/ui/iter_count.stderr
index 2e3d7fc35de..f9aee0b7846 100644
--- a/src/tools/clippy/tests/ui/iter_count.stderr
+++ b/src/tools/clippy/tests/ui/iter_count.stderr
@@ -1,5 +1,5 @@
 error: called `.iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:54:6
+  --> $DIR/iter_count.rs:55:6
    |
 LL |     &vec[..].iter().count();
    |      ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
@@ -7,145 +7,145 @@ LL |     &vec[..].iter().count();
    = note: `-D clippy::iter-count` implied by `-D warnings`
 
 error: called `.iter().count()` on a `Vec`
-  --> $DIR/iter_count.rs:55:5
+  --> $DIR/iter_count.rs:56:5
    |
 LL |     vec.iter().count();
    |     ^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:56:5
+  --> $DIR/iter_count.rs:57:5
    |
 LL |     boxed_slice.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice.len()`
 
 error: called `.iter().count()` on a `VecDeque`
-  --> $DIR/iter_count.rs:57:5
+  --> $DIR/iter_count.rs:58:5
    |
 LL |     vec_deque.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()`
 
 error: called `.iter().count()` on a `HashSet`
-  --> $DIR/iter_count.rs:58:5
+  --> $DIR/iter_count.rs:59:5
    |
 LL |     hash_set.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()`
 
 error: called `.iter().count()` on a `HashMap`
-  --> $DIR/iter_count.rs:59:5
+  --> $DIR/iter_count.rs:60:5
    |
 LL |     hash_map.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()`
 
 error: called `.iter().count()` on a `BTreeMap`
-  --> $DIR/iter_count.rs:60:5
+  --> $DIR/iter_count.rs:61:5
    |
 LL |     b_tree_map.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()`
 
 error: called `.iter().count()` on a `BTreeSet`
-  --> $DIR/iter_count.rs:61:5
+  --> $DIR/iter_count.rs:62:5
    |
 LL |     b_tree_set.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()`
 
 error: called `.iter().count()` on a `LinkedList`
-  --> $DIR/iter_count.rs:62:5
+  --> $DIR/iter_count.rs:63:5
    |
 LL |     linked_list.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.iter().count()` on a `BinaryHeap`
-  --> $DIR/iter_count.rs:63:5
+  --> $DIR/iter_count.rs:64:5
    |
 LL |     binary_heap.iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()`
 
 error: called `.iter_mut().count()` on a `Vec`
-  --> $DIR/iter_count.rs:65:5
+  --> $DIR/iter_count.rs:66:5
    |
 LL |     vec.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.iter_mut().count()` on a `slice`
-  --> $DIR/iter_count.rs:66:6
+  --> $DIR/iter_count.rs:67:6
    |
 LL |     &vec[..].iter_mut().count();
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.iter_mut().count()` on a `VecDeque`
-  --> $DIR/iter_count.rs:67:5
+  --> $DIR/iter_count.rs:68:5
    |
 LL |     vec_deque.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()`
 
 error: called `.iter_mut().count()` on a `HashMap`
-  --> $DIR/iter_count.rs:68:5
+  --> $DIR/iter_count.rs:69:5
    |
 LL |     hash_map.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()`
 
 error: called `.iter_mut().count()` on a `BTreeMap`
-  --> $DIR/iter_count.rs:69:5
+  --> $DIR/iter_count.rs:70:5
    |
 LL |     b_tree_map.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()`
 
 error: called `.iter_mut().count()` on a `LinkedList`
-  --> $DIR/iter_count.rs:70:5
+  --> $DIR/iter_count.rs:71:5
    |
 LL |     linked_list.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.into_iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:72:6
+  --> $DIR/iter_count.rs:73:6
    |
 LL |     &vec[..].into_iter().count();
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.into_iter().count()` on a `Vec`
-  --> $DIR/iter_count.rs:73:5
+  --> $DIR/iter_count.rs:74:5
    |
 LL |     vec.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.into_iter().count()` on a `VecDeque`
-  --> $DIR/iter_count.rs:74:5
+  --> $DIR/iter_count.rs:75:5
    |
 LL |     vec_deque.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque.len()`
 
 error: called `.into_iter().count()` on a `HashSet`
-  --> $DIR/iter_count.rs:75:5
+  --> $DIR/iter_count.rs:76:5
    |
 LL |     hash_set.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_set.len()`
 
 error: called `.into_iter().count()` on a `HashMap`
-  --> $DIR/iter_count.rs:76:5
+  --> $DIR/iter_count.rs:77:5
    |
 LL |     hash_map.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `hash_map.len()`
 
 error: called `.into_iter().count()` on a `BTreeMap`
-  --> $DIR/iter_count.rs:77:5
+  --> $DIR/iter_count.rs:78:5
    |
 LL |     b_tree_map.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_map.len()`
 
 error: called `.into_iter().count()` on a `BTreeSet`
-  --> $DIR/iter_count.rs:78:5
+  --> $DIR/iter_count.rs:79:5
    |
 LL |     b_tree_set.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b_tree_set.len()`
 
 error: called `.into_iter().count()` on a `LinkedList`
-  --> $DIR/iter_count.rs:79:5
+  --> $DIR/iter_count.rs:80:5
    |
 LL |     linked_list.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.into_iter().count()` on a `BinaryHeap`
-  --> $DIR/iter_count.rs:80:5
+  --> $DIR/iter_count.rs:81:5
    |
 LL |     binary_heap.into_iter().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `binary_heap.len()`
diff --git a/src/tools/clippy/tests/ui/iter_next_loop.rs b/src/tools/clippy/tests/ui/iter_next_loop.rs
new file mode 100644
index 00000000000..548b799de44
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_next_loop.rs
@@ -0,0 +1,16 @@
+#![allow(dead_code, unused, for_loops_over_fallibles)]
+#![warn(clippy::iter_next_loop)]
+
+fn main() {
+    let x = [1, 2, 3, 4];
+    for _ in vec.iter().next() {}
+
+    struct Unrelated(&'static [u8]);
+    impl Unrelated {
+        fn next(&self) -> std::slice::Iter<u8> {
+            self.0.iter()
+        }
+    }
+    let u = Unrelated(&[0]);
+    for _v in u.next() {} // no error
+}
diff --git a/src/tools/clippy/tests/ui/iter_next_loop.stderr b/src/tools/clippy/tests/ui/iter_next_loop.stderr
new file mode 100644
index 00000000000..5bba0e635bb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_next_loop.stderr
@@ -0,0 +1,9 @@
+error[E0423]: expected value, found macro `vec`
+  --> $DIR/iter_next_loop.rs:6:14
+   |
+LL |     for _ in vec.iter().next() {}
+   |              ^^^ not a value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.fixed b/src/tools/clippy/tests/ui/iter_next_slice.fixed
index d862abc34e0..702edccdbad 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.fixed
+++ b/src/tools/clippy/tests/ui/iter_next_slice.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::iter_next_slice)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // test code goes here
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.rs b/src/tools/clippy/tests/ui/iter_next_slice.rs
index da6fc46e428..30bfc72de17 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.rs
+++ b/src/tools/clippy/tests/ui/iter_next_slice.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::iter_next_slice)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // test code goes here
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.stderr b/src/tools/clippy/tests/ui/iter_next_slice.stderr
index d8b89061ff8..0db8201a132 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.stderr
+++ b/src/tools/clippy/tests/ui/iter_next_slice.stderr
@@ -1,5 +1,5 @@
 error: using `.iter().next()` on an array
-  --> $DIR/iter_next_slice.rs:9:13
+  --> $DIR/iter_next_slice.rs:10:13
    |
 LL |     let _ = s.iter().next();
    |             ^^^^^^^^^^^^^^^ help: try calling: `s.first()`
@@ -7,19 +7,19 @@ LL |     let _ = s.iter().next();
    = note: `-D clippy::iter-next-slice` implied by `-D warnings`
 
 error: using `.iter().next()` on a Slice without end index
-  --> $DIR/iter_next_slice.rs:12:13
+  --> $DIR/iter_next_slice.rs:13:13
    |
 LL |     let _ = s[2..].iter().next();
    |             ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)`
 
 error: using `.iter().next()` on a Slice without end index
-  --> $DIR/iter_next_slice.rs:15:13
+  --> $DIR/iter_next_slice.rs:16:13
    |
 LL |     let _ = v[5..].iter().next();
    |             ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)`
 
 error: using `.iter().next()` on an array
-  --> $DIR/iter_next_slice.rs:18:13
+  --> $DIR/iter_next_slice.rs:19:13
    |
 LL |     let _ = v.iter().next();
    |             ^^^^^^^^^^^^^^^ help: try calling: `v.first()`
diff --git a/src/tools/clippy/tests/ui/iter_nth.rs b/src/tools/clippy/tests/ui/iter_nth.rs
index e7fb97d4fbc..7c567bb81d8 100644
--- a/src/tools/clippy/tests/ui/iter_nth.rs
+++ b/src/tools/clippy/tests/ui/iter_nth.rs
@@ -1,6 +1,7 @@
 //@aux-build:option_helpers.rs
 
 #![warn(clippy::iter_nth)]
+#![allow(clippy::useless_vec)]
 
 #[macro_use]
 extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/iter_nth.stderr b/src/tools/clippy/tests/ui/iter_nth.stderr
index a0fe353bcf7..24be814548a 100644
--- a/src/tools/clippy/tests/ui/iter_nth.stderr
+++ b/src/tools/clippy/tests/ui/iter_nth.stderr
@@ -1,5 +1,5 @@
-error: called `.iter().nth()` on a Vec
-  --> $DIR/iter_nth.rs:33:23
+error: called `.iter().nth()` on a `Vec`
+  --> $DIR/iter_nth.rs:34:23
    |
 LL |         let bad_vec = some_vec.iter().nth(3);
    |                       ^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |         let bad_vec = some_vec.iter().nth(3);
    = note: `-D clippy::iter-nth` implied by `-D warnings`
 
 error: called `.iter().nth()` on a slice
-  --> $DIR/iter_nth.rs:34:26
+  --> $DIR/iter_nth.rs:35:26
    |
 LL |         let bad_slice = &some_vec[..].iter().nth(3);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,23 +16,23 @@ LL |         let bad_slice = &some_vec[..].iter().nth(3);
    = help: calling `.get()` is both faster and more readable
 
 error: called `.iter().nth()` on a slice
-  --> $DIR/iter_nth.rs:35:31
+  --> $DIR/iter_nth.rs:36:31
    |
 LL |         let bad_boxed_slice = boxed_slice.iter().nth(3);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: calling `.get()` is both faster and more readable
 
-error: called `.iter().nth()` on a VecDeque
-  --> $DIR/iter_nth.rs:36:29
+error: called `.iter().nth()` on a `VecDeque`
+  --> $DIR/iter_nth.rs:37:29
    |
 LL |         let bad_vec_deque = some_vec_deque.iter().nth(3);
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: calling `.get()` is both faster and more readable
 
-error: called `.iter_mut().nth()` on a Vec
-  --> $DIR/iter_nth.rs:41:23
+error: called `.iter_mut().nth()` on a `Vec`
+  --> $DIR/iter_nth.rs:42:23
    |
 LL |         let bad_vec = some_vec.iter_mut().nth(3);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,15 +40,15 @@ LL |         let bad_vec = some_vec.iter_mut().nth(3);
    = help: calling `.get_mut()` is both faster and more readable
 
 error: called `.iter_mut().nth()` on a slice
-  --> $DIR/iter_nth.rs:44:26
+  --> $DIR/iter_nth.rs:45:26
    |
 LL |         let bad_slice = &some_vec[..].iter_mut().nth(3);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: calling `.get_mut()` is both faster and more readable
 
-error: called `.iter_mut().nth()` on a VecDeque
-  --> $DIR/iter_nth.rs:47:29
+error: called `.iter_mut().nth()` on a `VecDeque`
+  --> $DIR/iter_nth.rs:48:29
    |
 LL |         let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/iter_nth_zero.fixed b/src/tools/clippy/tests/ui/iter_nth_zero.fixed
index 587b0d1d366..91f4a7ba0d2 100644
--- a/src/tools/clippy/tests/ui/iter_nth_zero.fixed
+++ b/src/tools/clippy/tests/ui/iter_nth_zero.fixed
@@ -29,3 +29,18 @@ fn main() {
     let mut iter2 = s3.iter();
     let _unwrapped = iter2.next().unwrap();
 }
+
+struct Issue9820;
+
+impl Iterator for Issue9820 {
+    type Item = ();
+
+    fn nth(&mut self, _n: usize) -> Option<Self::Item> {
+        todo!()
+    }
+
+    // Don't lint in implementations of `next`, as calling `next` in `next` is incorrect
+    fn next(&mut self) -> Option<Self::Item> {
+        self.nth(0)
+    }
+}
diff --git a/src/tools/clippy/tests/ui/iter_nth_zero.rs b/src/tools/clippy/tests/ui/iter_nth_zero.rs
index 93b576ec56f..160a895bb7b 100644
--- a/src/tools/clippy/tests/ui/iter_nth_zero.rs
+++ b/src/tools/clippy/tests/ui/iter_nth_zero.rs
@@ -29,3 +29,18 @@ fn main() {
     let mut iter2 = s3.iter();
     let _unwrapped = iter2.nth(0).unwrap();
 }
+
+struct Issue9820;
+
+impl Iterator for Issue9820 {
+    type Item = ();
+
+    fn nth(&mut self, _n: usize) -> Option<Self::Item> {
+        todo!()
+    }
+
+    // Don't lint in implementations of `next`, as calling `next` in `next` is incorrect
+    fn next(&mut self) -> Option<Self::Item> {
+        self.nth(0)
+    }
+}
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
index bf576e9cbfb..2874513c049 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
-#![allow(dead_code, clippy::let_unit_value)]
+#![allow(dead_code, clippy::let_unit_value, clippy::useless_vec)]
 
 fn main() {
     let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()];
diff --git a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
index df42d88eff0..26f39734a51 100644
--- a/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
+++ b/src/tools/clippy/tests/ui/iter_overeager_cloned.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
-#![allow(dead_code, clippy::let_unit_value)]
+#![allow(dead_code, clippy::let_unit_value, clippy::useless_vec)]
 
 fn main() {
     let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()];
diff --git a/src/tools/clippy/tests/ui/iter_skip_next.fixed b/src/tools/clippy/tests/ui/iter_skip_next.fixed
index 8f2cefc4304..b888d965e8d 100644
--- a/src/tools/clippy/tests/ui/iter_skip_next.fixed
+++ b/src/tools/clippy/tests/ui/iter_skip_next.fixed
@@ -4,6 +4,7 @@
 #![warn(clippy::iter_skip_next)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::iter_nth)]
+#![allow(clippy::useless_vec)]
 #![allow(unused_mut, dead_code)]
 
 extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/iter_skip_next.rs b/src/tools/clippy/tests/ui/iter_skip_next.rs
index 71d83384f3a..e44efdebc47 100644
--- a/src/tools/clippy/tests/ui/iter_skip_next.rs
+++ b/src/tools/clippy/tests/ui/iter_skip_next.rs
@@ -4,6 +4,7 @@
 #![warn(clippy::iter_skip_next)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::iter_nth)]
+#![allow(clippy::useless_vec)]
 #![allow(unused_mut, dead_code)]
 
 extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/iter_skip_next.stderr b/src/tools/clippy/tests/ui/iter_skip_next.stderr
index ca6970b27f1..4ee26e088ce 100644
--- a/src/tools/clippy/tests/ui/iter_skip_next.stderr
+++ b/src/tools/clippy/tests/ui/iter_skip_next.stderr
@@ -1,5 +1,5 @@
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:16:28
+  --> $DIR/iter_skip_next.rs:17:28
    |
 LL |     let _ = some_vec.iter().skip(42).next();
    |                            ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
@@ -7,37 +7,37 @@ LL |     let _ = some_vec.iter().skip(42).next();
    = note: `-D clippy::iter-skip-next` implied by `-D warnings`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:17:36
+  --> $DIR/iter_skip_next.rs:18:36
    |
 LL |     let _ = some_vec.iter().cycle().skip(42).next();
    |                                    ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:18:20
+  --> $DIR/iter_skip_next.rs:19:20
    |
 LL |     let _ = (1..10).skip(10).next();
    |                    ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:19:33
+  --> $DIR/iter_skip_next.rs:20:33
    |
 LL |     let _ = &some_vec[..].iter().skip(3).next();
    |                                 ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:27:26
+  --> $DIR/iter_skip_next.rs:28:26
    |
 LL |     let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect();
    |                          ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:29:29
+  --> $DIR/iter_skip_next.rs:30:29
    |
 LL |         let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect();
    |                             ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
 
 error: called `skip(..).next()` on an iterator
-  --> $DIR/iter_skip_next.rs:35:29
+  --> $DIR/iter_skip_next.rs:36:29
    |
 LL |         let _: Vec<&str> = s.skip(1).next().unwrap().split(' ').collect();
    |                             ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
diff --git a/src/tools/clippy/tests/ui/iter_with_drain.fixed b/src/tools/clippy/tests/ui/iter_with_drain.fixed
index 24a95c4d0fe..7a8c6770101 100644
--- a/src/tools/clippy/tests/ui/iter_with_drain.fixed
+++ b/src/tools/clippy/tests/ui/iter_with_drain.fixed
@@ -2,7 +2,7 @@
 // will emits unused mut warnings after fixing
 #![allow(unused_mut)]
 // will emits needless collect warnings after fixing
-#![allow(clippy::needless_collect)]
+#![allow(clippy::needless_collect, clippy::drain_collect)]
 #![warn(clippy::iter_with_drain)]
 use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/iter_with_drain.rs b/src/tools/clippy/tests/ui/iter_with_drain.rs
index a118c981ee3..cf3a935c349 100644
--- a/src/tools/clippy/tests/ui/iter_with_drain.rs
+++ b/src/tools/clippy/tests/ui/iter_with_drain.rs
@@ -2,7 +2,7 @@
 // will emits unused mut warnings after fixing
 #![allow(unused_mut)]
 // will emits needless collect warnings after fixing
-#![allow(clippy::needless_collect)]
+#![allow(clippy::needless_collect, clippy::drain_collect)]
 #![warn(clippy::iter_with_drain)]
 use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/iterator_step_by_zero.rs b/src/tools/clippy/tests/ui/iterator_step_by_zero.rs
index 13d1cfd4281..33ec78e9a41 100644
--- a/src/tools/clippy/tests/ui/iterator_step_by_zero.rs
+++ b/src/tools/clippy/tests/ui/iterator_step_by_zero.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::useless_vec)]
 #[warn(clippy::iterator_step_by_zero)]
 fn main() {
     let _ = vec!["A", "B", "B"].iter().step_by(0);
diff --git a/src/tools/clippy/tests/ui/iterator_step_by_zero.stderr b/src/tools/clippy/tests/ui/iterator_step_by_zero.stderr
index d792aea11df..b470e2ed2ea 100644
--- a/src/tools/clippy/tests/ui/iterator_step_by_zero.stderr
+++ b/src/tools/clippy/tests/ui/iterator_step_by_zero.stderr
@@ -1,5 +1,5 @@
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:3:13
+  --> $DIR/iterator_step_by_zero.rs:4:13
    |
 LL |     let _ = vec!["A", "B", "B"].iter().step_by(0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL |     let _ = vec!["A", "B", "B"].iter().step_by(0);
    = note: `-D clippy::iterator-step-by-zero` implied by `-D warnings`
 
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:4:13
+  --> $DIR/iterator_step_by_zero.rs:5:13
    |
 LL |     let _ = "XXX".chars().step_by(0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:5:13
+  --> $DIR/iterator_step_by_zero.rs:6:13
    |
 LL |     let _ = (0..1).step_by(0);
    |             ^^^^^^^^^^^^^^^^^
 
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:14:13
+  --> $DIR/iterator_step_by_zero.rs:15:13
    |
 LL |     let _ = (1..).step_by(0);
    |             ^^^^^^^^^^^^^^^^
 
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:15:13
+  --> $DIR/iterator_step_by_zero.rs:16:13
    |
 LL |     let _ = (1..=2).step_by(0);
    |             ^^^^^^^^^^^^^^^^^^
 
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:18:13
+  --> $DIR/iterator_step_by_zero.rs:19:13
    |
 LL |     let _ = x.step_by(0);
    |             ^^^^^^^^^^^^
 
 error: `Iterator::step_by(0)` will panic at runtime
-  --> $DIR/iterator_step_by_zero.rs:22:13
+  --> $DIR/iterator_step_by_zero.rs:23:13
    |
 LL |     let _ = v1.iter().step_by(2 / 3);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.rs b/src/tools/clippy/tests/ui/large_enum_variant.rs
index ea8bc5b4aca..e677cc9a7b9 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.rs
+++ b/src/tools/clippy/tests/ui/large_enum_variant.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![allow(dead_code)]
 #![allow(unused_variables)]
diff --git a/src/tools/clippy/tests/ui/large_futures.rs b/src/tools/clippy/tests/ui/large_futures.rs
index 4a8ba995da5..e0f6b3d9d3b 100644
--- a/src/tools/clippy/tests/ui/large_futures.rs
+++ b/src/tools/clippy/tests/ui/large_futures.rs
@@ -1,5 +1,6 @@
 #![feature(generators)]
 #![warn(clippy::large_futures)]
+#![allow(clippy::never_loop)]
 #![allow(clippy::future_not_send)]
 #![allow(clippy::manual_async_fn)]
 
diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr
index 67e0fceff6e..5bcf054884e 100644
--- a/src/tools/clippy/tests/ui/large_futures.stderr
+++ b/src/tools/clippy/tests/ui/large_futures.stderr
@@ -1,5 +1,5 @@
 error: large future with a size of 16385 bytes
-  --> $DIR/large_futures.rs:10:9
+  --> $DIR/large_futures.rs:11:9
    |
 LL |         big_fut([0u8; 1024 * 16]).await;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
@@ -7,37 +7,37 @@ LL |         big_fut([0u8; 1024 * 16]).await;
    = note: `-D clippy::large-futures` implied by `-D warnings`
 
 error: large future with a size of 16386 bytes
-  --> $DIR/large_futures.rs:12:5
+  --> $DIR/large_futures.rs:13:5
    |
 LL |     f.await
    |     ^ help: consider `Box::pin` on it: `Box::pin(f)`
 
 error: large future with a size of 16387 bytes
-  --> $DIR/large_futures.rs:16:9
+  --> $DIR/large_futures.rs:17:9
    |
 LL |         wait().await;
    |         ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 16387 bytes
-  --> $DIR/large_futures.rs:20:13
+  --> $DIR/large_futures.rs:21:13
    |
 LL |             wait().await;
    |             ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
 
 error: large future with a size of 65540 bytes
-  --> $DIR/large_futures.rs:27:5
+  --> $DIR/large_futures.rs:28:5
    |
 LL |     foo().await;
    |     ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
 
 error: large future with a size of 49159 bytes
-  --> $DIR/large_futures.rs:28:5
+  --> $DIR/large_futures.rs:29:5
    |
 LL |     calls_fut(fut).await;
    |     ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
 
 error: large future with a size of 65540 bytes
-  --> $DIR/large_futures.rs:40:5
+  --> $DIR/large_futures.rs:41:5
    |
 LL | /     async {
 LL | |         let x = [0i32; 1024 * 16];
@@ -56,7 +56,7 @@ LL +     })
    |
 
 error: large future with a size of 65540 bytes
-  --> $DIR/large_futures.rs:51:13
+  --> $DIR/large_futures.rs:52:13
    |
 LL | /             async {
 LL | |                 let x = [0i32; 1024 * 16];
diff --git a/src/tools/clippy/tests/ui/large_stack_frames.rs b/src/tools/clippy/tests/ui/large_stack_frames.rs
new file mode 100644
index 00000000000..cd9d0c8a67a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/large_stack_frames.rs
@@ -0,0 +1,44 @@
+#![allow(unused, incomplete_features)]
+#![warn(clippy::large_stack_frames)]
+#![feature(unsized_locals)]
+
+use std::hint::black_box;
+
+fn generic<T: Default>() {
+    let x = T::default();
+    black_box(&x);
+}
+
+fn unsized_local() {
+    let x: dyn std::fmt::Display = *(Box::new(1) as Box<dyn std::fmt::Display>);
+    black_box(&x);
+}
+
+struct ArrayDefault<const N: usize>([u8; N]);
+
+impl<const N: usize> Default for ArrayDefault<N> {
+    fn default() -> Self {
+        Self([0; N])
+    }
+}
+
+fn many_small_arrays() {
+    let x = [0u8; 500_000];
+    let x2 = [0u8; 500_000];
+    let x3 = [0u8; 500_000];
+    let x4 = [0u8; 500_000];
+    let x5 = [0u8; 500_000];
+    black_box((&x, &x2, &x3, &x4, &x5));
+}
+
+fn large_return_value() -> ArrayDefault<1_000_000> {
+    Default::default()
+}
+
+fn large_fn_arg(x: ArrayDefault<1_000_000>) {
+    black_box(&x);
+}
+
+fn main() {
+    generic::<ArrayDefault<1_000_000>>();
+}
diff --git a/src/tools/clippy/tests/ui/large_stack_frames.stderr b/src/tools/clippy/tests/ui/large_stack_frames.stderr
new file mode 100644
index 00000000000..d57df8596fe
--- /dev/null
+++ b/src/tools/clippy/tests/ui/large_stack_frames.stderr
@@ -0,0 +1,37 @@
+error: this function allocates a large amount of stack space
+  --> $DIR/large_stack_frames.rs:25:1
+   |
+LL | / fn many_small_arrays() {
+LL | |     let x = [0u8; 500_000];
+LL | |     let x2 = [0u8; 500_000];
+LL | |     let x3 = [0u8; 500_000];
+...  |
+LL | |     black_box((&x, &x2, &x3, &x4, &x5));
+LL | | }
+   | |_^
+   |
+   = note: allocating large amounts of stack space can overflow the stack
+   = note: `-D clippy::large-stack-frames` implied by `-D warnings`
+
+error: this function allocates a large amount of stack space
+  --> $DIR/large_stack_frames.rs:34:1
+   |
+LL | / fn large_return_value() -> ArrayDefault<1_000_000> {
+LL | |     Default::default()
+LL | | }
+   | |_^
+   |
+   = note: allocating large amounts of stack space can overflow the stack
+
+error: this function allocates a large amount of stack space
+  --> $DIR/large_stack_frames.rs:38:1
+   |
+LL | / fn large_fn_arg(x: ArrayDefault<1_000_000>) {
+LL | |     black_box(&x);
+LL | | }
+   | |_^
+   |
+   = note: allocating large amounts of stack space can overflow the stack
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/len_zero.fixed b/src/tools/clippy/tests/ui/len_zero.fixed
index 2c22abd7e4b..fafee6a0d41 100644
--- a/src/tools/clippy/tests/ui/len_zero.fixed
+++ b/src/tools/clippy/tests/ui/len_zero.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::len_zero)]
-#![allow(dead_code, unused, clippy::len_without_is_empty)]
+#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)]
 
 extern crate core;
 use core::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/len_zero.rs b/src/tools/clippy/tests/ui/len_zero.rs
index a011ff97644..6a9006c4779 100644
--- a/src/tools/clippy/tests/ui/len_zero.rs
+++ b/src/tools/clippy/tests/ui/len_zero.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::len_zero)]
-#![allow(dead_code, unused, clippy::len_without_is_empty)]
+#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)]
 
 extern crate core;
 use core::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
index 2c313ff35d5..431d83778e3 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -1,4 +1,4 @@
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![allow(unused)]
 #![warn(clippy::let_underscore_untyped)]
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.rs b/src/tools/clippy/tests/ui/let_with_type_underscore.rs
index 7c1835e8cd1..8214176cfd5 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.rs
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.rs
@@ -1,19 +1,42 @@
+//@aux-build: proc_macros.rs:proc-macro
 #![allow(unused)]
 #![warn(clippy::let_with_type_underscore)]
-#![allow(clippy::let_unit_value)]
+#![allow(clippy::let_unit_value, clippy::needless_late_init)]
+
+extern crate proc_macros;
 
 fn func() -> &'static str {
     ""
 }
 
+#[rustfmt::skip]
 fn main() {
     // Will lint
     let x: _ = 1;
     let _: _ = 2;
     let x: _ = func();
+    let x: _;
+    x = ();
 
     let x = 1; // Will not lint, Rust infers this to an integer before Clippy
     let x = func();
     let x: Vec<_> = Vec::<u32>::new();
     let x: [_; 1] = [1];
+    let x : _ = 1;
+
+    // Do not lint from procedural macros
+    proc_macros::with_span! {
+        span
+        let x: _ = ();
+        // Late initialization
+        let x: _;
+        x = ();
+        // Ensure weird formatting will not break it (hopefully)
+        let x : _ = 1;
+        let x
+: _ = 1;
+        let                   x :              
+        _;
+        x = ();
+    };
 }
diff --git a/src/tools/clippy/tests/ui/let_with_type_underscore.stderr b/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
index 16bf83c708f..a749552c7fa 100644
--- a/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
+++ b/src/tools/clippy/tests/ui/let_with_type_underscore.stderr
@@ -1,39 +1,63 @@
 error: variable declared with type underscore
-  --> $DIR/let_with_type_underscore.rs:11:5
+  --> $DIR/let_with_type_underscore.rs:15:5
    |
 LL |     let x: _ = 1;
    |     ^^^^^^^^^^^^^
    |
 help: remove the explicit type `_` declaration
-  --> $DIR/let_with_type_underscore.rs:11:10
+  --> $DIR/let_with_type_underscore.rs:15:10
    |
 LL |     let x: _ = 1;
    |          ^^^
    = note: `-D clippy::let-with-type-underscore` implied by `-D warnings`
 
 error: variable declared with type underscore
-  --> $DIR/let_with_type_underscore.rs:12:5
+  --> $DIR/let_with_type_underscore.rs:16:5
    |
 LL |     let _: _ = 2;
    |     ^^^^^^^^^^^^^
    |
 help: remove the explicit type `_` declaration
-  --> $DIR/let_with_type_underscore.rs:12:10
+  --> $DIR/let_with_type_underscore.rs:16:10
    |
 LL |     let _: _ = 2;
    |          ^^^
 
 error: variable declared with type underscore
-  --> $DIR/let_with_type_underscore.rs:13:5
+  --> $DIR/let_with_type_underscore.rs:17:5
    |
 LL |     let x: _ = func();
    |     ^^^^^^^^^^^^^^^^^^
    |
 help: remove the explicit type `_` declaration
-  --> $DIR/let_with_type_underscore.rs:13:10
+  --> $DIR/let_with_type_underscore.rs:17:10
    |
 LL |     let x: _ = func();
    |          ^^^
 
-error: aborting due to 3 previous errors
+error: variable declared with type underscore
+  --> $DIR/let_with_type_underscore.rs:18:5
+   |
+LL |     let x: _;
+   |     ^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+  --> $DIR/let_with_type_underscore.rs:18:10
+   |
+LL |     let x: _;
+   |          ^^^
+
+error: variable declared with type underscore
+  --> $DIR/let_with_type_underscore.rs:25:5
+   |
+LL |     let x : _ = 1;
+   |     ^^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+  --> $DIR/let_with_type_underscore.rs:25:10
+   |
+LL |     let x : _ = 1;
+   |          ^^^^
+
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/lossy_float_literal.fixed b/src/tools/clippy/tests/ui/lossy_float_literal.fixed
index a2088575610..e19f4980cd7 100644
--- a/src/tools/clippy/tests/ui/lossy_float_literal.fixed
+++ b/src/tools/clippy/tests/ui/lossy_float_literal.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::lossy_float_literal)]
+#![allow(overflowing_literals, unused)]
 
 fn main() {
     // Lossy whole-number float literals
@@ -32,4 +33,7 @@ fn main() {
     let _: f64 = 1e99;
     let _: f64 = 1E99;
     let _: f32 = 0.1;
+
+    const INF1: f32 = 1000000000000000000000000000000000f32;
+    const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32;
 }
diff --git a/src/tools/clippy/tests/ui/lossy_float_literal.rs b/src/tools/clippy/tests/ui/lossy_float_literal.rs
index 1a75f214c85..a2a1cfb317e 100644
--- a/src/tools/clippy/tests/ui/lossy_float_literal.rs
+++ b/src/tools/clippy/tests/ui/lossy_float_literal.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::lossy_float_literal)]
+#![allow(overflowing_literals, unused)]
 
 fn main() {
     // Lossy whole-number float literals
@@ -32,4 +33,7 @@ fn main() {
     let _: f64 = 1e99;
     let _: f64 = 1E99;
     let _: f32 = 0.1;
+
+    const INF1: f32 = 1000000000000000000000000000000000f32;
+    const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32;
 }
diff --git a/src/tools/clippy/tests/ui/lossy_float_literal.stderr b/src/tools/clippy/tests/ui/lossy_float_literal.stderr
index d2193c0c819..2d72b16430c 100644
--- a/src/tools/clippy/tests/ui/lossy_float_literal.stderr
+++ b/src/tools/clippy/tests/ui/lossy_float_literal.stderr
@@ -1,5 +1,5 @@
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:6:18
+  --> $DIR/lossy_float_literal.rs:7:18
    |
 LL |     let _: f32 = 16_777_217.0;
    |                  ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0`
@@ -7,61 +7,61 @@ LL |     let _: f32 = 16_777_217.0;
    = note: `-D clippy::lossy-float-literal` implied by `-D warnings`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:7:18
+  --> $DIR/lossy_float_literal.rs:8:18
    |
 LL |     let _: f32 = 16_777_219.0;
    |                  ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:8:18
+  --> $DIR/lossy_float_literal.rs:9:18
    |
 LL |     let _: f32 = 16_777_219.;
    |                  ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:9:18
+  --> $DIR/lossy_float_literal.rs:10:18
    |
 LL |     let _: f32 = 16_777_219.000;
    |                  ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:10:13
+  --> $DIR/lossy_float_literal.rs:11:13
    |
 LL |     let _ = 16_777_219f32;
    |             ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:11:19
+  --> $DIR/lossy_float_literal.rs:12:19
    |
 LL |     let _: f32 = -16_777_219.0;
    |                   ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:12:18
+  --> $DIR/lossy_float_literal.rs:13:18
    |
 LL |     let _: f64 = 9_007_199_254_740_993.0;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:13:18
+  --> $DIR/lossy_float_literal.rs:14:18
    |
 LL |     let _: f64 = 9_007_199_254_740_993.;
    |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:14:18
+  --> $DIR/lossy_float_literal.rs:15:18
    |
 LL |     let _: f64 = 9_007_199_254_740_993.00;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:15:13
+  --> $DIR/lossy_float_literal.rs:16:13
    |
 LL |     let _ = 9_007_199_254_740_993f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:16:19
+  --> $DIR/lossy_float_literal.rs:17:19
    |
 LL |     let _: f64 = -9_007_199_254_740_993.0;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed
index b4dabe3cae5..53b6a0250f9 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.fixed
+++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed
@@ -1,6 +1,6 @@
 //@aux-build:macro_rules.rs
 //@aux-build:macro_use_helper.rs
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 //@run-rustfix
 //@ignore-32bit
 
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs
index 925a2c61f8d..a40fa389895 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports.rs
@@ -1,6 +1,6 @@
 //@aux-build:macro_rules.rs
 //@aux-build:macro_use_helper.rs
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 //@run-rustfix
 //@ignore-32bit
 
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr
index 6fd338cef86..67a833e85e0 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.stderr
+++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr
@@ -1,28 +1,28 @@
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:25:5
+  --> $DIR/macro_use_imports.rs:19:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};`
    |
    = note: `-D clippy::macro-use-imports` implied by `-D warnings`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:21:5
+  --> $DIR/macro_use_imports.rs:23:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:23:5
+  --> $DIR/macro_use_imports.rs:25:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:19:5
+  --> $DIR/macro_use_imports.rs:21:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
index b9677851b92..3971aadbef8 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
@@ -1,6 +1,6 @@
 //@aux-build:macro_rules.rs
 //@aux-build:macro_use_helper.rs
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 //@ignore-32bit
 
 #![feature(lint_reasons)]
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index ab9b375dc03..d8dde0236ea 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -5,7 +5,7 @@
 
 #![warn(clippy::manual_assert)]
 #![allow(dead_code, unused_doc_comments)]
-#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)]
+#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
 
 macro_rules! one {
     () => {
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
index ab9b375dc03..d8dde0236ea 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
@@ -5,7 +5,7 @@
 
 #![warn(clippy::manual_assert)]
 #![allow(dead_code, unused_doc_comments)]
-#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)]
+#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
 
 macro_rules! one {
     () => {
diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs
index eac52d1b5de..0f87d6e2d2c 100644
--- a/src/tools/clippy/tests/ui/manual_assert.rs
+++ b/src/tools/clippy/tests/ui/manual_assert.rs
@@ -5,7 +5,7 @@
 
 #![warn(clippy::manual_assert)]
 #![allow(dead_code, unused_doc_comments)]
-#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)]
+#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args, clippy::useless_vec)]
 
 macro_rules! one {
     () => {
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.fixed b/src/tools/clippy/tests/ui/manual_async_fn.fixed
index e458f0d254f..e609b4b1bdb 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.fixed
+++ b/src/tools/clippy/tests/ui/manual_async_fn.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::manual_async_fn)]
-#![allow(unused)]
+#![allow(clippy::needless_pub_self, unused)]
 
 use std::future::Future;
 
diff --git a/src/tools/clippy/tests/ui/manual_async_fn.rs b/src/tools/clippy/tests/ui/manual_async_fn.rs
index dd5ca1c9b5b..6c1a9edaa11 100644
--- a/src/tools/clippy/tests/ui/manual_async_fn.rs
+++ b/src/tools/clippy/tests/ui/manual_async_fn.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::manual_async_fn)]
-#![allow(unused)]
+#![allow(clippy::needless_pub_self, unused)]
 
 use std::future::Future;
 
diff --git a/src/tools/clippy/tests/ui/manual_filter.fixed b/src/tools/clippy/tests/ui/manual_filter.fixed
index 755caa664d5..5e3b12e510b 100644
--- a/src/tools/clippy/tests/ui/manual_filter.fixed
+++ b/src/tools/clippy/tests/ui/manual_filter.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::manual_filter)]
-#![allow(unused_variables, dead_code)]
+#![allow(unused_variables, dead_code, clippy::useless_vec)]
 
 fn main() {
     Some(0).filter(|&x| x <= 0);
diff --git a/src/tools/clippy/tests/ui/manual_filter.rs b/src/tools/clippy/tests/ui/manual_filter.rs
index faccfe9db12..b81604b0372 100644
--- a/src/tools/clippy/tests/ui/manual_filter.rs
+++ b/src/tools/clippy/tests/ui/manual_filter.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::manual_filter)]
-#![allow(unused_variables, dead_code)]
+#![allow(unused_variables, dead_code, clippy::useless_vec)]
 
 fn main() {
     match Some(0) {
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.fixed b/src/tools/clippy/tests/ui/manual_filter_map.fixed
index 831323089e7..9dd376df2b4 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.fixed
+++ b/src/tools/clippy/tests/ui/manual_filter_map.fixed
@@ -2,6 +2,7 @@
 #![allow(dead_code)]
 #![warn(clippy::manual_filter_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.rs b/src/tools/clippy/tests/ui/manual_filter_map.rs
index 2692303d313..6dd1e066aeb 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.rs
+++ b/src/tools/clippy/tests/ui/manual_filter_map.rs
@@ -2,6 +2,7 @@
 #![allow(dead_code)]
 #![warn(clippy::manual_filter_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_filter_map.stderr b/src/tools/clippy/tests/ui/manual_filter_map.stderr
index 6e5bbe8f2aa..882468b0f5f 100644
--- a/src/tools/clippy/tests/ui/manual_filter_map.stderr
+++ b/src/tools/clippy/tests/ui/manual_filter_map.stderr
@@ -1,5 +1,5 @@
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:8:19
+  --> $DIR/manual_filter_map.rs:9:19
    |
 LL |     let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))`
@@ -7,19 +7,19 @@ LL |     let _ = (0..).filter(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap
    = note: `-D clippy::manual-filter-map` implied by `-D warnings`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:11:19
+  --> $DIR/manual_filter_map.rs:12:19
    |
 LL |     let _ = (0..).filter(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi"));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_opt(a))`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:14:19
+  --> $DIR/manual_filter_map.rs:15:19
    |
 LL |     let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:17:10
+  --> $DIR/manual_filter_map.rs:18:10
    |
 LL |           .filter(|&x| to_ref(to_opt(x)).is_some())
    |  __________^
@@ -27,7 +27,7 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:20:10
+  --> $DIR/manual_filter_map.rs:21:10
    |
 LL |           .filter(|x| to_ref(to_opt(*x)).is_some())
    |  __________^
@@ -35,7 +35,7 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| *to_ref(to_opt(y)))`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:24:10
+  --> $DIR/manual_filter_map.rs:25:10
    |
 LL |           .filter(|&x| to_ref(to_res(x)).is_ok())
    |  __________^
@@ -43,7 +43,7 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:27:10
+  --> $DIR/manual_filter_map.rs:28:10
    |
 LL |           .filter(|x| to_ref(to_res(*x)).is_ok())
    |  __________^
@@ -51,7 +51,7 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `filter_map(|y| to_ref(to_res(y)).ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:33:27
+  --> $DIR/manual_filter_map.rs:34:27
    |
 LL |     iter::<Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
@@ -59,67 +59,67 @@ LL |     iter::<Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap()
    = note: `-D clippy::manual-find-map` implied by `-D warnings`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:34:28
+  --> $DIR/manual_filter_map.rs:35:28
    |
 LL |     iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:35:31
+  --> $DIR/manual_filter_map.rs:36:31
    |
 LL |     iter::<&Option<String>>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:36:31
+  --> $DIR/manual_filter_map.rs:37:31
    |
 LL |     iter::<Option<&String>>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:38:30
+  --> $DIR/manual_filter_map.rs:39:30
    |
 LL |     iter::<Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:39:31
+  --> $DIR/manual_filter_map.rs:40:31
    |
 LL |     iter::<&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:40:32
+  --> $DIR/manual_filter_map.rs:41:32
    |
 LL |     iter::<&&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:41:31
+  --> $DIR/manual_filter_map.rs:42:31
    |
 LL |     iter::<Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:42:32
+  --> $DIR/manual_filter_map.rs:43:32
    |
 LL |     iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:43:35
+  --> $DIR/manual_filter_map.rs:44:35
    |
 LL |     iter::<&Result<String, ()>>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_filter_map.rs:44:35
+  --> $DIR/manual_filter_map.rs:45:35
    |
 LL |     iter::<Result<&String, ()>>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:92:10
+  --> $DIR/manual_filter_map.rs:93:10
    |
 LL |           .filter(|f| f.option_field.is_some())
    |  __________^
@@ -127,7 +127,7 @@ LL | |         .map(|f| f.option_field.clone().unwrap());
    | |_________________________________________________^ help: try: `filter_map(|f| f.option_field.clone())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:97:10
+  --> $DIR/manual_filter_map.rs:98:10
    |
 LL |           .filter(|f| f.ref_field.is_some())
    |  __________^
@@ -135,7 +135,7 @@ LL | |         .map(|f| f.ref_field.cloned().unwrap());
    | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.cloned())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:102:10
+  --> $DIR/manual_filter_map.rs:103:10
    |
 LL |           .filter(|f| f.ref_field.is_some())
    |  __________^
@@ -143,7 +143,7 @@ LL | |         .map(|f| f.ref_field.copied().unwrap());
    | |_______________________________________________^ help: try: `filter_map(|f| f.ref_field.copied())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:107:10
+  --> $DIR/manual_filter_map.rs:108:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -151,7 +151,7 @@ LL | |         .map(|f| f.result_field.clone().unwrap());
    | |_________________________________________________^ help: try: `filter_map(|f| f.result_field.clone().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:112:10
+  --> $DIR/manual_filter_map.rs:113:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -159,7 +159,7 @@ LL | |         .map(|f| f.result_field.as_ref().unwrap());
    | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_ref().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:117:10
+  --> $DIR/manual_filter_map.rs:118:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -167,7 +167,7 @@ LL | |         .map(|f| f.result_field.as_deref().unwrap());
    | |____________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:122:10
+  --> $DIR/manual_filter_map.rs:123:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -175,7 +175,7 @@ LL | |         .map(|f| f.result_field.as_mut().unwrap());
    | |__________________________________________________^ help: try: `filter_map(|f| f.result_field.as_mut().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:127:10
+  --> $DIR/manual_filter_map.rs:128:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
@@ -183,7 +183,7 @@ LL | |         .map(|f| f.result_field.as_deref_mut().unwrap());
    | |________________________________________________________^ help: try: `filter_map(|f| f.result_field.as_deref_mut().ok())`
 
 error: `filter(..).map(..)` can be simplified as `filter_map(..)`
-  --> $DIR/manual_filter_map.rs:132:10
+  --> $DIR/manual_filter_map.rs:133:10
    |
 LL |           .filter(|f| f.result_field.is_ok())
    |  __________^
diff --git a/src/tools/clippy/tests/ui/manual_find_map.fixed b/src/tools/clippy/tests/ui/manual_find_map.fixed
index 554613a30a9..0c8eebf04b5 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_map.fixed
@@ -2,6 +2,7 @@
 #![allow(dead_code)]
 #![warn(clippy::manual_find_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_find_map.rs b/src/tools/clippy/tests/ui/manual_find_map.rs
index d6245758f9d..b2feb48a839 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.rs
+++ b/src/tools/clippy/tests/ui/manual_find_map.rs
@@ -2,6 +2,7 @@
 #![allow(dead_code)]
 #![warn(clippy::manual_find_map)]
 #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // is_some(), unwrap()
diff --git a/src/tools/clippy/tests/ui/manual_find_map.stderr b/src/tools/clippy/tests/ui/manual_find_map.stderr
index c1ac499f7c6..693a06bb559 100644
--- a/src/tools/clippy/tests/ui/manual_find_map.stderr
+++ b/src/tools/clippy/tests/ui/manual_find_map.stderr
@@ -1,5 +1,5 @@
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:8:19
+  --> $DIR/manual_find_map.rs:9:19
    |
 LL |     let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))`
@@ -7,19 +7,19 @@ LL |     let _ = (0..).find(|n| to_opt(*n).is_some()).map(|a| to_opt(a).unwrap()
    = note: `-D clippy::manual-find-map` implied by `-D warnings`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:11:19
+  --> $DIR/manual_find_map.rs:12:19
    |
 LL |     let _ = (0..).find(|&n| to_opt(n).is_some()).map(|a| to_opt(a).expect("hi"));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_opt(a))`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:14:19
+  --> $DIR/manual_find_map.rs:15:19
    |
 LL |     let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:17:10
+  --> $DIR/manual_find_map.rs:18:10
    |
 LL |           .find(|&x| to_ref(to_opt(x)).is_some())
    |  __________^
@@ -27,7 +27,7 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:20:10
+  --> $DIR/manual_find_map.rs:21:10
    |
 LL |           .find(|x| to_ref(to_opt(*x)).is_some())
    |  __________^
@@ -35,7 +35,7 @@ LL | |         .map(|y| to_ref(to_opt(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| *to_ref(to_opt(y)))`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:24:10
+  --> $DIR/manual_find_map.rs:25:10
    |
 LL |           .find(|&x| to_ref(to_res(x)).is_ok())
    |  __________^
@@ -43,7 +43,7 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:27:10
+  --> $DIR/manual_find_map.rs:28:10
    |
 LL |           .find(|x| to_ref(to_res(*x)).is_ok())
    |  __________^
@@ -51,91 +51,91 @@ LL | |         .map(|y| to_ref(to_res(y)).unwrap());
    | |____________________________________________^ help: try: `find_map(|y| to_ref(to_res(y)).ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:33:26
+  --> $DIR/manual_find_map.rs:34:26
    |
 LL |     iter::<Option<u8>>().find(|x| x.is_some()).map(|x| x.unwrap());
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x)`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:34:27
+  --> $DIR/manual_find_map.rs:35:27
    |
 LL |     iter::<&Option<u8>>().find(|x| x.is_some()).map(|x| x.unwrap());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| *x)`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:35:28
+  --> $DIR/manual_find_map.rs:36:28
    |
 LL |     iter::<&&Option<u8>>().find(|x| x.is_some()).map(|x| x.unwrap());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| **x)`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:36:27
+  --> $DIR/manual_find_map.rs:37:27
    |
 LL |     iter::<Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:37:28
+  --> $DIR/manual_find_map.rs:38:28
    |
 LL |     iter::<&Option<&u8>>().find(|x| x.is_some()).map(|x| x.cloned().unwrap());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:38:31
+  --> $DIR/manual_find_map.rs:39:31
    |
 LL |     iter::<&Option<String>>().find(|x| x.is_some()).map(|x| x.as_deref().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:39:31
+  --> $DIR/manual_find_map.rs:40:31
    |
 LL |     iter::<Option<&String>>().find(|&x| to_ref(x).is_some()).map(|y| to_ref(y).cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:41:30
+  --> $DIR/manual_find_map.rs:42:30
    |
 LL |     iter::<Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:42:31
+  --> $DIR/manual_find_map.rs:43:31
    |
 LL |     iter::<&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:43:32
+  --> $DIR/manual_find_map.rs:44:32
    |
 LL |     iter::<&&Result<u8, ()>>().find(|x| x.is_ok()).map(|x| x.unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:44:31
+  --> $DIR/manual_find_map.rs:45:31
    |
 LL |     iter::<Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:45:32
+  --> $DIR/manual_find_map.rs:46:32
    |
 LL |     iter::<&Result<&u8, ()>>().find(|x| x.is_ok()).map(|x| x.cloned().unwrap());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:46:35
+  --> $DIR/manual_find_map.rs:47:35
    |
 LL |     iter::<&Result<String, ()>>().find(|x| x.is_ok()).map(|x| x.as_deref().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|x| x.as_deref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:47:35
+  --> $DIR/manual_find_map.rs:48:35
    |
 LL |     iter::<Result<&String, ()>>().find(|&x| to_ref(x).is_ok()).map(|y| to_ref(y).cloned().unwrap());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|y| to_ref(y).cloned().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:95:10
+  --> $DIR/manual_find_map.rs:96:10
    |
 LL |           .find(|f| f.option_field.is_some())
    |  __________^
@@ -143,7 +143,7 @@ LL | |         .map(|f| f.option_field.clone().unwrap());
    | |_________________________________________________^ help: try: `find_map(|f| f.option_field.clone())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:100:10
+  --> $DIR/manual_find_map.rs:101:10
    |
 LL |           .find(|f| f.ref_field.is_some())
    |  __________^
@@ -151,7 +151,7 @@ LL | |         .map(|f| f.ref_field.cloned().unwrap());
    | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.cloned())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:105:10
+  --> $DIR/manual_find_map.rs:106:10
    |
 LL |           .find(|f| f.ref_field.is_some())
    |  __________^
@@ -159,7 +159,7 @@ LL | |         .map(|f| f.ref_field.copied().unwrap());
    | |_______________________________________________^ help: try: `find_map(|f| f.ref_field.copied())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:110:10
+  --> $DIR/manual_find_map.rs:111:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -167,7 +167,7 @@ LL | |         .map(|f| f.result_field.clone().unwrap());
    | |_________________________________________________^ help: try: `find_map(|f| f.result_field.clone().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:115:10
+  --> $DIR/manual_find_map.rs:116:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -175,7 +175,7 @@ LL | |         .map(|f| f.result_field.as_ref().unwrap());
    | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_ref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:120:10
+  --> $DIR/manual_find_map.rs:121:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -183,7 +183,7 @@ LL | |         .map(|f| f.result_field.as_deref().unwrap());
    | |____________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:125:10
+  --> $DIR/manual_find_map.rs:126:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -191,7 +191,7 @@ LL | |         .map(|f| f.result_field.as_mut().unwrap());
    | |__________________________________________________^ help: try: `find_map(|f| f.result_field.as_mut().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:130:10
+  --> $DIR/manual_find_map.rs:131:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
@@ -199,7 +199,7 @@ LL | |         .map(|f| f.result_field.as_deref_mut().unwrap());
    | |________________________________________________________^ help: try: `find_map(|f| f.result_field.as_deref_mut().ok())`
 
 error: `find(..).map(..)` can be simplified as `find_map(..)`
-  --> $DIR/manual_find_map.rs:135:10
+  --> $DIR/manual_find_map.rs:136:10
    |
 LL |           .find(|f| f.result_field.is_ok())
    |  __________^
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index 351ea0e4f50..46241afec94 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -4,7 +4,8 @@
     clippy::unused_unit,
     clippy::let_unit_value,
     clippy::match_single_binding,
-    clippy::never_loop
+    clippy::never_loop,
+    clippy::needless_if
 )]
 #![warn(clippy::manual_let_else)]
 
@@ -127,8 +128,8 @@ fn fire() {
         return;
     };
 
-    // Tuples supported for the identity block and pattern
-    let v = if let (Some(v_some), w_some) = (g(), 0) {
+    // Tuples supported with multiple bindings
+    let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
         (w_some, v_some)
     } else {
         return;
@@ -160,6 +161,30 @@ fn fire() {
     };
     // dot dot works
     let v = if let Variant::A(.., a) = e() { a } else { return };
+
+    // () is preserved: a bit of an edge case but make sure it stays around
+    let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
+
+    // Tuple structs work
+    let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
+        x
+    } else {
+        return;
+    };
+
+    // Field init shorthand is suggested
+    let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
+        x
+    } else {
+        return;
+    };
+
+    // Multi-field structs also work
+    let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
+        (x, v, w)
+    } else {
+        return;
+    };
 }
 
 fn not_fire() {
@@ -284,4 +309,23 @@ fn not_fire() {
         };
         1
     };
+
+    // This would require creation of a suggestion of the form
+    // let v @ (Some(_), _) = (...) else { return };
+    // Which is too advanced for our code, so we just bail.
+    let v = if let (Some(v_some), w_some) = (g(), 0) {
+        (w_some, v_some)
+    } else {
+        return;
+    };
+}
+
+struct S<T> {
+    v: T,
+}
+
+struct U<T> {
+    v: T,
+    w: T,
+    x: T,
 }
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 0e876797134..1eada4f992e 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,5 +1,5 @@
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:24:5
+  --> $DIR/manual_let_else.rs:25:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
@@ -7,7 +7,7 @@ LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:25:5
+  --> $DIR/manual_let_else.rs:26:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -24,7 +24,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:31:5
+  --> $DIR/manual_let_else.rs:32:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |         // Blocks around the identity should have no impact
@@ -45,25 +45,25 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:44:9
+  --> $DIR/manual_let_else.rs:45:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:45:9
+  --> $DIR/manual_let_else.rs:46:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:49:5
+  --> $DIR/manual_let_else.rs:50:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:52:5
+  --> $DIR/manual_let_else.rs:53:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -80,7 +80,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:59:5
+  --> $DIR/manual_let_else.rs:60:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -97,7 +97,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:66:5
+  --> $DIR/manual_let_else.rs:67:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -116,7 +116,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:76:5
+  --> $DIR/manual_let_else.rs:77:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -138,13 +138,13 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:86:5
+  --> $DIR/manual_let_else.rs:87:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:89:5
+  --> $DIR/manual_let_else.rs:90:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -165,7 +165,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:98:5
+  --> $DIR/manual_let_else.rs:99:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -186,7 +186,7 @@ LL +     } };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:107:5
+  --> $DIR/manual_let_else.rs:108:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -215,7 +215,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:124:5
+  --> $DIR/manual_let_else.rs:125:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |         v_some
@@ -232,9 +232,9 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:131:5
+  --> $DIR/manual_let_else.rs:132:5
    |
-LL | /     let v = if let (Some(v_some), w_some) = (g(), 0) {
+LL | /     let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
 LL | |         (w_some, v_some)
 LL | |     } else {
 LL | |         return;
@@ -243,13 +243,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let (Some(v_some), w_some) = (g(), 0) else {
+LL ~     let (Some(S { v }), w) = (g().map(|_| S { v: 0 }), 0) else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:140:13
+  --> $DIR/manual_let_else.rs:141:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
@@ -260,19 +260,19 @@ LL |     create_binding_if_some!(w, g());
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:149:5
+  --> $DIR/manual_let_else.rs:150:5
    |
 LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:152:5
+  --> $DIR/manual_let_else.rs:153:5
    |
 LL |     let mut v = if let Variant::B(b) = e() { b } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:156:5
+  --> $DIR/manual_let_else.rs:157:5
    |
 LL | /     let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
 LL | |         b
@@ -289,13 +289,70 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:162:5
+  --> $DIR/manual_let_else.rs:163:5
    |
 LL |     let v = if let Variant::A(.., a) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:272:5
+  --> $DIR/manual_let_else.rs:166:5
+   |
+LL |     let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:169:5
+   |
+LL | /     let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
+LL | |         x
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(S { v: w }) = Some(S { v: 0 }) else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:176:5
+   |
+LL | /     let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
+LL | |         x
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(S { v }) = Some(S { v: 0 }) else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:183:5
+   |
+LL | /     let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
+LL | |         (x, v, w)
+LL | |     } else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+help: consider writing
+   |
+LL ~     let Some(U { v: S { v }, w, x }) = None::<U<S<()>>> else {
+LL +         return;
+LL +     };
+   |
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:297:5
    |
 LL | /     let _ = match ff {
 LL | |         Some(value) => value,
@@ -303,5 +360,5 @@ LL | |         _ => macro_call!(),
 LL | |     };
    | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
-error: aborting due to 22 previous errors
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs
index dfca3b023cd..73ff69eec4e 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs
@@ -1,5 +1,9 @@
 #![allow(unused_braces, unused_variables, dead_code)]
-#![allow(clippy::collapsible_else_if, clippy::let_unit_value)]
+#![allow(
+    clippy::collapsible_else_if,
+    clippy::let_unit_value,
+    clippy::redundant_at_rest_pattern
+)]
 #![warn(clippy::manual_let_else)]
 // Ensure that we don't conflict with match -> if let lints
 #![warn(clippy::single_match_else, clippy::single_match)]
@@ -72,6 +76,11 @@ fn fire() {
         _ => return,
     };
 
+    let _value = match Some(build_enum()) {
+        Some(Variant::Bar(v) | Variant::Baz(v)) => v,
+        _ => return,
+    };
+
     let data = [1_u8, 2, 3, 4, 0, 0, 0, 0];
     let data = match data.as_slice() {
         [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 13ed35bc1d5..3fd9a637605 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -1,5 +1,5 @@
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:32:5
+  --> $DIR/manual_let_else_match.rs:36:5
    |
 LL | /     let v = match g() {
 LL | |         Some(v_some) => v_some,
@@ -10,7 +10,7 @@ LL | |     };
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:37:5
+  --> $DIR/manual_let_else_match.rs:41:5
    |
 LL | /     let v = match g() {
 LL | |         Some(v_some) => v_some,
@@ -19,7 +19,7 @@ LL | |     };
    | |______^ help: consider writing: `let Some(v) = g() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:44:9
+  --> $DIR/manual_let_else_match.rs:48:9
    |
 LL | /         let v = match h() {
 LL | |             (Some(v), None) | (None, Some(v)) => v,
@@ -28,7 +28,7 @@ LL | |         };
    | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:49:9
+  --> $DIR/manual_let_else_match.rs:53:9
    |
 LL | /         let v = match build_enum() {
 LL | |             Variant::Bar(v) | Variant::Baz(v) => v,
@@ -37,7 +37,7 @@ LL | |         };
    | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:57:5
+  --> $DIR/manual_let_else_match.rs:61:5
    |
 LL | /     let v = match f() {
 LL | |         Ok(v) => v,
@@ -46,7 +46,7 @@ LL | |     };
    | |______^ help: consider writing: `let Ok(v) = f() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:63:5
+  --> $DIR/manual_let_else_match.rs:67:5
    |
 LL | /     let v = match f().map_err(|_| ()) {
 LL | |         Ok(v) => v,
@@ -55,7 +55,7 @@ LL | |     };
    | |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:70:5
+  --> $DIR/manual_let_else_match.rs:74:5
    |
 LL | /     let _value = match f {
 LL | |         Variant::Bar(v) | Variant::Baz(v) => v,
@@ -64,7 +64,16 @@ LL | |     };
    | |______^ help: consider writing: `let (Variant::Bar(_value) | Variant::Baz(_value)) = f else { return };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else_match.rs:76:5
+  --> $DIR/manual_let_else_match.rs:79:5
+   |
+LL | /     let _value = match Some(build_enum()) {
+LL | |         Some(Variant::Bar(v) | Variant::Baz(v)) => v,
+LL | |         _ => return,
+LL | |     };
+   | |______^ help: consider writing: `let Some(Variant::Bar(_value) | Variant::Baz(_value)) = Some(build_enum()) else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:85:5
    |
 LL | /     let data = match data.as_slice() {
 LL | |         [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
@@ -72,5 +81,5 @@ LL | |         _ => return,
 LL | |     };
    | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
index ea0535d076b..4d5c70f19a0 100644
--- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
+++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::needless_range_loop, clippy::manual_memcpy)]
+#![allow(clippy::useless_vec)]
 
 const LOOP_OFFSET: usize = 5000;
 
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
index c163ae061df..1c6a7d5c04e 100644
--- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
+++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
@@ -1,5 +1,5 @@
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:7:5
+  --> $DIR/without_loop_counters.rs:8:5
    |
 LL | /     for i in 0..src.len() {
 LL | |         dst[i] = src[i];
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::manual-memcpy` implied by `-D warnings`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:12:5
+  --> $DIR/without_loop_counters.rs:13:5
    |
 LL | /     for i in 0..src.len() {
 LL | |         dst[i + 10] = src[i];
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:17:5
+  --> $DIR/without_loop_counters.rs:18:5
    |
 LL | /     for i in 0..src.len() {
 LL | |         dst[i] = src[i + 10];
@@ -25,7 +25,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:22:5
+  --> $DIR/without_loop_counters.rs:23:5
    |
 LL | /     for i in 11..src.len() {
 LL | |         dst[i] = src[i - 10];
@@ -33,7 +33,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:27:5
+  --> $DIR/without_loop_counters.rs:28:5
    |
 LL | /     for i in 0..dst.len() {
 LL | |         dst[i] = src[i];
@@ -41,7 +41,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:40:5
+  --> $DIR/without_loop_counters.rs:41:5
    |
 LL | /     for i in 10..256 {
 LL | |         dst[i] = src[i - 5];
@@ -56,7 +56,7 @@ LL +     dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]);
    |
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:52:5
+  --> $DIR/without_loop_counters.rs:53:5
    |
 LL | /     for i in 10..LOOP_OFFSET {
 LL | |         dst[i + LOOP_OFFSET] = src[i - some_var];
@@ -64,7 +64,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:65:5
+  --> $DIR/without_loop_counters.rs:66:5
    |
 LL | /     for i in 0..src_vec.len() {
 LL | |         dst_vec[i] = src_vec[i];
@@ -72,7 +72,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:94:5
+  --> $DIR/without_loop_counters.rs:95:5
    |
 LL | /     for i in from..from + src.len() {
 LL | |         dst[i] = src[i - from];
@@ -80,7 +80,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:98:5
+  --> $DIR/without_loop_counters.rs:99:5
    |
 LL | /     for i in from..from + 3 {
 LL | |         dst[i] = src[i - from];
@@ -88,7 +88,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:103:5
+  --> $DIR/without_loop_counters.rs:104:5
    |
 LL | /     for i in 0..5 {
 LL | |         dst[i - 0] = src[i];
@@ -96,7 +96,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src[..5]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:108:5
+  --> $DIR/without_loop_counters.rs:109:5
    |
 LL | /     for i in 0..0 {
 LL | |         dst[i] = src[i];
@@ -104,7 +104,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);`
 
 error: it looks like you're manually copying between slices
-  --> $DIR/without_loop_counters.rs:131:5
+  --> $DIR/without_loop_counters.rs:132:5
    |
 LL | /     for i in 0..src.len() {
 LL | |         dst[i] = src[i].clone();
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.fixed b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
new file mode 100644
index 00000000000..9eee8f37187
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
@@ -0,0 +1,35 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let f = 6;
+
+    let _ = matches!(f, 1..=10);
+    let _ = matches!(f, 1..=10);
+    let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing
+    let _ = matches!(f, | 4);
+    let _ = matches!(f, 4 | 5);
+    let _ = matches!(f, 1 | 2147483647);
+    let _ = matches!(f, 0 | 2147483647);
+    let _ = matches!(f, -2147483647 | 2147483647);
+    let _ = matches!(f, 1 | (2..=4));
+    let _ = matches!(f, 1 | (2..4));
+    let _ = matches!(f, 1..=48324729);
+    let _ = matches!(f, 0..=48324730);
+    let _ = matches!(f, 0..=3);
+    #[allow(clippy::match_like_matches_macro)]
+    let _ = match f {
+        1..=10 => true,
+        _ => false,
+    };
+
+    macro_rules! mac {
+        ($e:expr) => {
+            matches!($e, 1..=10)
+        };
+    }
+    mac!(f);
+}
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.rs b/src/tools/clippy/tests/ui/manual_range_patterns.rs
new file mode 100644
index 00000000000..10743a7d04c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.rs
@@ -0,0 +1,35 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+    let f = 6;
+
+    let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
+    let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10);
+    let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 8 | 10); // 7 is missing
+    let _ = matches!(f, | 4);
+    let _ = matches!(f, 4 | 5);
+    let _ = matches!(f, 1 | 2147483647);
+    let _ = matches!(f, 0 | 2147483647);
+    let _ = matches!(f, -2147483647 | 2147483647);
+    let _ = matches!(f, 1 | (2..=4));
+    let _ = matches!(f, 1 | (2..4));
+    let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729);
+    let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729);
+    let _ = matches!(f, 0..=1 | 0..=2 | 0..=3);
+    #[allow(clippy::match_like_matches_macro)]
+    let _ = match f {
+        1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
+        _ => false,
+    };
+
+    macro_rules! mac {
+        ($e:expr) => {
+            matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
+        };
+    }
+    mac!(f);
+}
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.stderr b/src/tools/clippy/tests/ui/manual_range_patterns.stderr
new file mode 100644
index 00000000000..bc9e3350164
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.stderr
@@ -0,0 +1,51 @@
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:10:25
+   |
+LL |     let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
+   |
+   = note: `-D clippy::manual-range-patterns` implied by `-D warnings`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:11:25
+   |
+LL |     let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:20:25
+   |
+LL |     let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:21:25
+   |
+LL |     let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:22:25
+   |
+LL |     let _ = matches!(f, 0..=1 | 0..=2 | 0..=3);
+   |                         ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:25:9
+   |
+LL |         1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
+
+error: this OR pattern can be rewritten using a range
+  --> $DIR/manual_range_patterns.rs:31:26
+   |
+LL |             matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
+...
+LL |     mac!(f);
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
index f2e44e56f02..594a76897bb 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::manual_rem_euclid)]
 #![allow(clippy::let_with_type_underscore)]
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.rs b/src/tools/clippy/tests/ui/manual_rem_euclid.rs
index b2329c33a47..d5f98e71517 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.rs
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::manual_rem_euclid)]
 #![allow(clippy::let_with_type_underscore)]
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed b/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed
index ac85bd8d3ac..5b9629f4bc1 100644
--- a/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![allow(unused)]
 #![warn(clippy::manual_slice_size_calculation)]
 
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs b/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
index 1f824b12bc2..297887a9cfc 100644
--- a/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![allow(unused)]
 #![warn(clippy::manual_slice_size_calculation)]
 
diff --git a/src/tools/clippy/tests/ui/manual_try_fold.rs b/src/tools/clippy/tests/ui/manual_try_fold.rs
new file mode 100644
index 00000000000..4521e9fa1a5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_try_fold.rs
@@ -0,0 +1,100 @@
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(clippy::unnecessary_fold, unused)]
+#![warn(clippy::manual_try_fold)]
+#![feature(try_trait_v2)]
+
+use std::ops::ControlFlow;
+use std::ops::FromResidual;
+use std::ops::Try;
+
+#[macro_use]
+extern crate proc_macros;
+
+// Test custom `Try` with more than 1 argument
+struct NotOption(i32, i32);
+
+impl<R> FromResidual<R> for NotOption {
+    fn from_residual(_: R) -> Self {
+        todo!()
+    }
+}
+
+impl Try for NotOption {
+    type Output = ();
+    type Residual = ();
+
+    fn from_output(_: Self::Output) -> Self {
+        todo!()
+    }
+
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+        todo!()
+    }
+}
+
+// Test custom `Try` with only 1 argument
+#[derive(Default)]
+struct NotOptionButWorse(i32);
+
+impl<R> FromResidual<R> for NotOptionButWorse {
+    fn from_residual(_: R) -> Self {
+        todo!()
+    }
+}
+
+impl Try for NotOptionButWorse {
+    type Output = ();
+    type Residual = ();
+
+    fn from_output(_: Self::Output) -> Self {
+        todo!()
+    }
+
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+        todo!()
+    }
+}
+
+fn main() {
+    [1, 2, 3]
+        .iter()
+        .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
+        .unwrap();
+    [1, 2, 3]
+        .iter()
+        .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32));
+    [1, 2, 3]
+        .iter()
+        .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32));
+    // Do not lint
+    [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap();
+    [1, 2, 3].iter().fold(0i32, |sum, i| sum + i);
+    [1, 2, 3]
+        .iter()
+        .fold(NotOptionButWorse::default(), |sum, i| NotOptionButWorse::default());
+    external! {
+        [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap();
+        [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap();
+    }
+    with_span! {
+        span
+        [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap();
+        [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap();
+    }
+}
+
+#[clippy::msrv = "1.26.0"]
+fn msrv_too_low() {
+    [1, 2, 3]
+        .iter()
+        .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
+        .unwrap();
+}
+
+#[clippy::msrv = "1.27.0"]
+fn msrv_juust_right() {
+    [1, 2, 3]
+        .iter()
+        .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
+        .unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/manual_try_fold.stderr b/src/tools/clippy/tests/ui/manual_try_fold.stderr
new file mode 100644
index 00000000000..a0cf5b3b5fc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_try_fold.stderr
@@ -0,0 +1,28 @@
+error: usage of `Iterator::fold` on a type that implements `Try`
+  --> $DIR/manual_try_fold.rs:61:10
+   |
+LL |         .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)`
+   |
+   = note: `-D clippy::manual-try-fold` implied by `-D warnings`
+
+error: usage of `Iterator::fold` on a type that implements `Try`
+  --> $DIR/manual_try_fold.rs:65:10
+   |
+LL |         .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32));
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(..., |sum, i| ...)`
+
+error: usage of `Iterator::fold` on a type that implements `Try`
+  --> $DIR/manual_try_fold.rs:68:10
+   |
+LL |         .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32));
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)`
+
+error: usage of `Iterator::fold` on a type that implements `Try`
+  --> $DIR/manual_try_fold.rs:98:10
+   |
+LL |         .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `try_fold` instead: `try_fold(0i32, |sum, i| ...)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
index c17634bffe3..20560b87c1a 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![allow(dead_code)]
-#![allow(unused_variables, clippy::unnecessary_wraps)]
+#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)]
 
 fn option_unwrap_or() {
     // int case
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
index 6d49a6949fa..5dbc57565bf 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![allow(dead_code)]
-#![allow(unused_variables, clippy::unnecessary_wraps)]
+#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)]
 
 fn option_unwrap_or() {
     // int case
diff --git a/src/tools/clippy/tests/ui/map_clone.fixed b/src/tools/clippy/tests/ui/map_clone.fixed
index d7474f35719..50c0eb1a810 100644
--- a/src/tools/clippy/tests/ui/map_clone.fixed
+++ b/src/tools/clippy/tests/ui/map_clone.fixed
@@ -4,7 +4,8 @@
     clippy::clone_on_copy,
     clippy::iter_cloned_collect,
     clippy::many_single_char_names,
-    clippy::redundant_clone
+    clippy::redundant_clone,
+    clippy::useless_vec
 )]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/map_clone.rs b/src/tools/clippy/tests/ui/map_clone.rs
index 74978ae8006..91a084f2844 100644
--- a/src/tools/clippy/tests/ui/map_clone.rs
+++ b/src/tools/clippy/tests/ui/map_clone.rs
@@ -4,7 +4,8 @@
     clippy::clone_on_copy,
     clippy::iter_cloned_collect,
     clippy::many_single_char_names,
-    clippy::redundant_clone
+    clippy::redundant_clone,
+    clippy::useless_vec
 )]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/map_clone.stderr b/src/tools/clippy/tests/ui/map_clone.stderr
index d84a5bf8d4d..d768af1f48c 100644
--- a/src/tools/clippy/tests/ui/map_clone.stderr
+++ b/src/tools/clippy/tests/ui/map_clone.stderr
@@ -1,5 +1,5 @@
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:11:22
+  --> $DIR/map_clone.rs:12:22
    |
 LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()`
@@ -7,31 +7,31 @@ LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    = note: `-D clippy::map-clone` implied by `-D warnings`
 
 error: you are using an explicit closure for cloning elements
-  --> $DIR/map_clone.rs:12:26
+  --> $DIR/map_clone.rs:13:26
    |
 LL |     let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:13:23
+  --> $DIR/map_clone.rs:14:23
    |
 LL |     let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect();
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:15:26
+  --> $DIR/map_clone.rs:16:26
    |
 LL |     let _: Option<u64> = Some(&16).map(|b| *b);
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:16:25
+  --> $DIR/map_clone.rs:17:25
    |
 LL |     let _: Option<u8> = Some(&1).map(|x| x.clone());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()`
 
 error: you are needlessly cloning iterator elements
-  --> $DIR/map_clone.rs:27:29
+  --> $DIR/map_clone.rs:28:29
    |
 LL |     let _ = std::env::args().map(|v| v.clone());
    |                             ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.rs b/src/tools/clippy/tests/ui/map_unwrap_or.rs
index cb25d8567aa..bb36cb2c598 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/map_unwrap_or.rs
@@ -56,6 +56,10 @@ fn option_methods() {
         .unwrap_or_else(||
             0
         );
+
+    // Check for `map(f).unwrap_or(false)` use.
+    let _ = opt.map(|x| x > 5).unwrap_or(false);
+
 }
 
 #[rustfmt::skip]
@@ -94,3 +98,46 @@ fn msrv_1_41() {
 
     let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0);
 }
+
+#[clippy::msrv = "1.69"]
+fn msrv_1_69() {
+    let opt: Option<i32> = Some(1);
+
+    let _ = opt.map(|x| x > 5).unwrap_or(false);
+}
+
+#[clippy::msrv = "1.70"]
+fn msrv_1_70() {
+    let opt: Option<i32> = Some(1);
+
+    let _ = opt.map(|x| x > 5).unwrap_or(false);
+}
+
+mod issue_10579 {
+    // Different variations of the same issue.
+    fn v1() {
+        let x = vec![1, 2, 3, 0];
+        let y = x.strip_suffix(&[0]).map(|s| s.to_vec()).unwrap_or(x);
+        println!("{y:?}");
+    }
+    fn v2() {
+        let x = vec![1, 2, 3, 0];
+        let y = Some(()).map(|_| x.to_vec()).unwrap_or(x);
+        println!("{y:?}");
+    }
+    fn v3() {
+        let x = vec![1, 2, 3, 0];
+        let xref = &x;
+        let y = Some(()).map(|_| xref.to_vec()).unwrap_or(x);
+        println!("{y:?}");
+    }
+    fn v4() {
+        struct VecInStruct {
+            v: Vec<u8>,
+        }
+        let s = VecInStruct { v: vec![1, 2, 3, 0] };
+
+        let y = Some(()).map(|_| s.v.clone()).unwrap_or(s.v);
+        println!("{y:?}");
+    }
+}
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.stderr b/src/tools/clippy/tests/ui/map_unwrap_or.stderr
index 41781b050fa..9f4a4a9ae6b 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or.stderr
+++ b/src/tools/clippy/tests/ui/map_unwrap_or.stderr
@@ -126,8 +126,20 @@ LL | |             0
 LL | |         );
    | |_________^
 
+error: called `map(<f>).unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and(<f>)` instead
+  --> $DIR/map_unwrap_or.rs:61:13
+   |
+LL |     let _ = opt.map(|x| x > 5).unwrap_or(false);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `is_some_and(<f>)` instead
+   |
+LL -     let _ = opt.map(|x| x > 5).unwrap_or(false);
+LL +     let _ = opt.is_some_and(|x| x > 5);
+   |
+
 error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
-  --> $DIR/map_unwrap_or.rs:67:13
+  --> $DIR/map_unwrap_or.rs:71:13
    |
 LL |       let _ = res.map(|x| {
    |  _____________^
@@ -137,7 +149,7 @@ LL | |     ).unwrap_or_else(|_e| 0);
    | |____________________________^
 
 error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
-  --> $DIR/map_unwrap_or.rs:71:13
+  --> $DIR/map_unwrap_or.rs:75:13
    |
 LL |       let _ = res.map(|x| x + 1)
    |  _____________^
@@ -147,10 +159,34 @@ LL | |         });
    | |__________^
 
 error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
-  --> $DIR/map_unwrap_or.rs:95:13
+  --> $DIR/map_unwrap_or.rs:99:13
    |
 LL |     let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)`
 
-error: aborting due to 12 previous errors
+error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:106:13
+   |
+LL |     let _ = opt.map(|x| x > 5).unwrap_or(false);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `map_or(<a>, <f>)` instead
+   |
+LL -     let _ = opt.map(|x| x > 5).unwrap_or(false);
+LL +     let _ = opt.map_or(false, |x| x > 5);
+   |
+
+error: called `map(<f>).unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and(<f>)` instead
+  --> $DIR/map_unwrap_or.rs:113:13
+   |
+LL |     let _ = opt.map(|x| x > 5).unwrap_or(false);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `is_some_and(<f>)` instead
+   |
+LL -     let _ = opt.map(|x| x > 5).unwrap_or(false);
+LL +     let _ = opt.is_some_and(|x| x > 5);
+   |
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_on_vec_items.rs b/src/tools/clippy/tests/ui/match_on_vec_items.rs
index 30415e3b94d..cf9c279cd2f 100644
--- a/src/tools/clippy/tests/ui/match_on_vec_items.rs
+++ b/src/tools/clippy/tests/ui/match_on_vec_items.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::match_on_vec_items)]
+#![allow(clippy::redundant_at_rest_pattern, clippy::useless_vec)]
 
 fn match_with_wildcard() {
     let arr = vec![0, 1, 2, 3];
diff --git a/src/tools/clippy/tests/ui/match_on_vec_items.stderr b/src/tools/clippy/tests/ui/match_on_vec_items.stderr
index 49446d715ab..9b1f052867e 100644
--- a/src/tools/clippy/tests/ui/match_on_vec_items.stderr
+++ b/src/tools/clippy/tests/ui/match_on_vec_items.stderr
@@ -1,5 +1,5 @@
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:9:11
+  --> $DIR/match_on_vec_items.rs:10:11
    |
 LL |     match arr[idx] {
    |           ^^^^^^^^ help: try this: `arr.get(idx)`
@@ -7,43 +7,43 @@ LL |     match arr[idx] {
    = note: `-D clippy::match-on-vec-items` implied by `-D warnings`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:16:11
+  --> $DIR/match_on_vec_items.rs:17:11
    |
 LL |     match arr[range] {
    |           ^^^^^^^^^^ help: try this: `arr.get(range)`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:29:11
+  --> $DIR/match_on_vec_items.rs:30:11
    |
 LL |     match arr[idx] {
    |           ^^^^^^^^ help: try this: `arr.get(idx)`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:36:11
+  --> $DIR/match_on_vec_items.rs:37:11
    |
 LL |     match arr[range] {
    |           ^^^^^^^^^^ help: try this: `arr.get(range)`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:49:11
+  --> $DIR/match_on_vec_items.rs:50:11
    |
 LL |     match arr[idx] {
    |           ^^^^^^^^ help: try this: `arr.get(idx)`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:56:11
+  --> $DIR/match_on_vec_items.rs:57:11
    |
 LL |     match arr[range] {
    |           ^^^^^^^^^^ help: try this: `arr.get(range)`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:69:11
+  --> $DIR/match_on_vec_items.rs:70:11
    |
 LL |     match arr[idx] {
    |           ^^^^^^^^ help: try this: `arr.get(idx)`
 
 error: indexing into a vector may panic
-  --> $DIR/match_on_vec_items.rs:76:11
+  --> $DIR/match_on_vec_items.rs:77:11
    |
 LL |     match arr[range] {
    |           ^^^^^^^^^^ help: try this: `arr.get(range)`
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.rs b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
index b4097fa9604..b78c1fd06d4 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.rs
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
@@ -1,7 +1,7 @@
 #![feature(exclusive_range_pattern)]
 #![warn(clippy::match_overlapping_arm)]
 #![allow(clippy::redundant_pattern_matching)]
-#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
+#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_if)]
 
 /// Tests for match_overlapping_arm
 
diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs
index 3914b45464c..fad6a7db988 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms.rs
@@ -8,29 +8,30 @@ pub enum Abc {
 
 fn match_same_arms() {
     let _ = match Abc::A {
-        Abc::A => 0,
+        Abc::A => 0, //~ ERROR: this match arm has an identical body to the `_` wildcard arm
         Abc::B => 1,
-        _ => 0, //~ ERROR match arms have same body
+        _ => 0,
     };
 
     match (1, 2, 3) {
-        (1, .., 3) => 42,
-        (.., 3) => 42, //~ ERROR match arms have same body
+        (1, .., 3) => 42, //~ ERROR: this match arm has an identical body to another arm
+        (.., 3) => 42,
         _ => 0,
     };
 
     let _ = match 42 {
         42 => 1,
-        51 => 1, //~ ERROR match arms have same body
-        41 => 2,
-        52 => 2, //~ ERROR match arms have same body
+        51 => 1, //~ ERROR: this match arm has an identical body to another arm
+        41 => 2, //~ ERROR: this match arm has an identical body to another arm
+        52 => 2,
         _ => 0,
     };
 
     let _ = match 42 {
         1 => 2,
-        2 => 2, //~ ERROR 2nd matched arms have same body
-        3 => 2, //~ ERROR 3rd matched arms have same body
+        2 => 2, //~ ERROR: this match arm has an identical body to another arm
+        //~^ ERROR: this match arm has an identical body to another arm
+        3 => 2, //~ ERROR: this match arm has an identical body to another arm
         4 => 3,
         _ => 0,
     };
@@ -48,6 +49,7 @@ mod issue4244 {
             match self {
                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
                 CommandInfo::External { name, .. } => name.to_string(),
+                //~^ ERROR: this match arm has an identical body to another arm
             }
         }
     }
diff --git a/src/tools/clippy/tests/ui/match_same_arms.stderr b/src/tools/clippy/tests/ui/match_same_arms.stderr
index db85b5964e8..88b9a20a372 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms.stderr
@@ -8,7 +8,7 @@ LL |         Abc::A => 0,
 note: `_` wildcard arm here
   --> $DIR/match_same_arms.rs:13:9
    |
-LL |         _ => 0, //~ ERROR match arms have same body
+LL |         _ => 0,
    |         ^^^^^^
    = note: `-D clippy::match-same-arms` implied by `-D warnings`
 
@@ -24,13 +24,13 @@ LL |         (1, .., 3) => 42,
 note: other arm here
   --> $DIR/match_same_arms.rs:18:9
    |
-LL |         (.., 3) => 42, //~ ERROR match arms have same body
+LL |         (.., 3) => 42,
    |         ^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
   --> $DIR/match_same_arms.rs:24:9
    |
-LL |         51 => 1, //~ ERROR match arms have same body
+LL |         51 => 1,
    |         --^^^^^
    |         |
    |         help: try merging the arm patterns: `51 | 42`
@@ -54,13 +54,13 @@ LL |         41 => 2,
 note: other arm here
   --> $DIR/match_same_arms.rs:26:9
    |
-LL |         52 => 2, //~ ERROR match arms have same body
+LL |         52 => 2,
    |         ^^^^^^^
 
 error: this match arm has an identical body to another arm
   --> $DIR/match_same_arms.rs:32:9
    |
-LL |         2 => 2, //~ ERROR 2nd matched arms have same body
+LL |         2 => 2,
    |         -^^^^^
    |         |
    |         help: try merging the arm patterns: `2 | 1`
@@ -73,9 +73,9 @@ LL |         1 => 2,
    |         ^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> $DIR/match_same_arms.rs:33:9
+  --> $DIR/match_same_arms.rs:34:9
    |
-LL |         3 => 2, //~ ERROR 3rd matched arms have same body
+LL |         3 => 2,
    |         -^^^^^
    |         |
    |         help: try merging the arm patterns: `3 | 1`
@@ -90,20 +90,20 @@ LL |         1 => 2,
 error: this match arm has an identical body to another arm
   --> $DIR/match_same_arms.rs:32:9
    |
-LL |         2 => 2, //~ ERROR 2nd matched arms have same body
+LL |         2 => 2,
    |         -^^^^^
    |         |
    |         help: try merging the arm patterns: `2 | 3`
    |
    = help: or try changing either arm body
 note: other arm here
-  --> $DIR/match_same_arms.rs:33:9
+  --> $DIR/match_same_arms.rs:34:9
    |
-LL |         3 => 2, //~ ERROR 3rd matched arms have same body
+LL |         3 => 2,
    |         ^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> $DIR/match_same_arms.rs:50:17
+  --> $DIR/match_same_arms.rs:51:17
    |
 LL |                 CommandInfo::External { name, .. } => name.to_string(),
    |                 ----------------------------------^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +112,7 @@ LL |                 CommandInfo::External { name, .. } => name.to_string(),
    |
    = help: or try changing either arm body
 note: other arm here
-  --> $DIR/match_same_arms.rs:49:17
+  --> $DIR/match_same_arms.rs:50:17
    |
 LL |                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 60b2975be04..b1b9a6ae3e8 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -13,6 +13,7 @@ fn foo() -> bool {
 fn match_same_arms() {
     let _ = match 42 {
         42 => {
+            //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
             foo();
             let mut a = 42 + [23].len() as i32;
             if true {
@@ -22,7 +23,6 @@ fn match_same_arms() {
             a
         },
         _ => {
-            //~ ERROR match arms have same body
             foo();
             let mut a = 42 + [23].len() as i32;
             if true {
@@ -35,13 +35,13 @@ fn match_same_arms() {
 
     let _ = match 42 {
         42 => foo(),
-        51 => foo(), //~ ERROR match arms have same body
+        51 => foo(), //~ ERROR: this match arm has an identical body to another arm
         _ => true,
     };
 
     let _ = match Some(42) {
         Some(_) => 24,
-        None => 24, //~ ERROR match arms have same body
+        None => 24, //~ ERROR: this match arm has an identical body to another arm
     };
 
     let _ = match Some(42) {
@@ -63,13 +63,13 @@ fn match_same_arms() {
 
     match (Some(42), Some(42)) {
         (Some(a), None) => bar(a),
-        (None, Some(a)) => bar(a), //~ ERROR match arms have same body
+        (None, Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm
         _ => (),
     }
 
     match (Some(42), Some(42)) {
-        (Some(a), ..) => bar(a),
-        (.., Some(a)) => bar(a), //~ ERROR match arms have same body
+        (Some(a), ..) => bar(a), //~ ERROR: this match arm has an identical body to another arm
+        (.., Some(a)) => bar(a),
         _ => (),
     }
 
@@ -102,7 +102,7 @@ fn match_same_arms() {
     }
 
     match (x, Some(1i32)) {
-        (Ok(x), Some(_)) => println!("ok {}", x),
+        (Ok(x), Some(_)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm
         (Ok(_), Some(x)) => println!("ok {}", x),
         _ => println!("err"),
     }
@@ -118,7 +118,7 @@ fn match_same_arms() {
     match x {
         Ok(_tmp) => println!("ok"),
         Ok(3) => println!("ok"),
-        Ok(_) => println!("ok"),
+        Ok(_) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm
         Err(_) => {
             unreachable!();
         },
@@ -146,6 +146,7 @@ fn match_same_arms() {
             empty!(0);
         },
         1 => {
+            //~^ ERROR: this match arm has an identical body to another arm
             empty!(0);
         },
         x => {
@@ -195,7 +196,7 @@ fn main() {
 
     // Suggest moving `Foo::Z(_)` up.
     let _ = match Foo::X(0) {
-        Foo::X(0) => 1,
+        Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm
         Foo::X(_) | Foo::Y(_) => 2,
         Foo::Z(_) => 1,
         _ => 0,
@@ -205,7 +206,7 @@ fn main() {
     let _ = match Foo::X(0) {
         Foo::X(0) => 1,
         Foo::Y(_) | Foo::Z(0) => 2,
-        Foo::Z(_) => 1,
+        Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm
         _ => 0,
     };
 
@@ -228,7 +229,7 @@ fn main() {
         Some(Bar { x: 0, y: 5, .. }) => 1,
         Some(Bar { y: 10, z: 0, .. }) => 2,
         None => 50,
-        Some(Bar { y: 0, x: 5, .. }) => 1,
+        Some(Bar { y: 0, x: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm
         _ => 200,
     };
 
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 8fb461bd286..7f0c70745ac 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -2,9 +2,9 @@ error: this match arm has an identical body to the `_` wildcard arm
   --> $DIR/match_same_arms2.rs:15:9
    |
 LL | /         42 => {
+LL | |
 LL | |             foo();
 LL | |             let mut a = 42 + [23].len() as i32;
-LL | |             if true {
 ...  |
 LL | |             a
 LL | |         },
@@ -12,12 +12,12 @@ LL | |         },
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> $DIR/match_same_arms2.rs:24:9
+  --> $DIR/match_same_arms2.rs:25:9
    |
 LL | /         _ => {
-LL | |             //~ ERROR match arms have same body
 LL | |             foo();
 LL | |             let mut a = 42 + [23].len() as i32;
+LL | |             if true {
 ...  |
 LL | |             a
 LL | |         },
@@ -27,7 +27,7 @@ LL | |         },
 error: this match arm has an identical body to another arm
   --> $DIR/match_same_arms2.rs:38:9
    |
-LL |         51 => foo(), //~ ERROR match arms have same body
+LL |         51 => foo(),
    |         --^^^^^^^^^
    |         |
    |         help: try merging the arm patterns: `51 | 42`
@@ -42,7 +42,7 @@ LL |         42 => foo(),
 error: this match arm has an identical body to another arm
   --> $DIR/match_same_arms2.rs:44:9
    |
-LL |         None => 24, //~ ERROR match arms have same body
+LL |         None => 24,
    |         ----^^^^^^
    |         |
    |         help: try merging the arm patterns: `None | Some(_)`
@@ -57,7 +57,7 @@ LL |         Some(_) => 24,
 error: this match arm has an identical body to another arm
   --> $DIR/match_same_arms2.rs:66:9
    |
-LL |         (None, Some(a)) => bar(a), //~ ERROR match arms have same body
+LL |         (None, Some(a)) => bar(a),
    |         ---------------^^^^^^^^^^
    |         |
    |         help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)`
@@ -81,7 +81,7 @@ LL |         (Some(a), ..) => bar(a),
 note: other arm here
   --> $DIR/match_same_arms2.rs:72:9
    |
-LL |         (.., Some(a)) => bar(a), //~ ERROR match arms have same body
+LL |         (.., Some(a)) => bar(a),
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
@@ -121,6 +121,7 @@ LL |           1 => {
    |           ^ help: try merging the arm patterns: `1 | 0`
    |  _________|
    | |
+LL | |
 LL | |             empty!(0);
 LL | |         },
    | |_________^
@@ -135,7 +136,7 @@ LL | |         },
    | |_________^
 
 error: match expression looks like `matches!` macro
-  --> $DIR/match_same_arms2.rs:166:16
+  --> $DIR/match_same_arms2.rs:167:16
    |
 LL |       let _ans = match x {
    |  ________________^
@@ -148,7 +149,7 @@ LL | |     };
    = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
 
 error: this match arm has an identical body to another arm
-  --> $DIR/match_same_arms2.rs:198:9
+  --> $DIR/match_same_arms2.rs:199:9
    |
 LL |         Foo::X(0) => 1,
    |         ---------^^^^^
@@ -157,13 +158,13 @@ LL |         Foo::X(0) => 1,
    |
    = help: or try changing either arm body
 note: other arm here
-  --> $DIR/match_same_arms2.rs:200:9
+  --> $DIR/match_same_arms2.rs:201:9
    |
 LL |         Foo::Z(_) => 1,
    |         ^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> $DIR/match_same_arms2.rs:208:9
+  --> $DIR/match_same_arms2.rs:209:9
    |
 LL |         Foo::Z(_) => 1,
    |         ---------^^^^^
@@ -172,13 +173,13 @@ LL |         Foo::Z(_) => 1,
    |
    = help: or try changing either arm body
 note: other arm here
-  --> $DIR/match_same_arms2.rs:206:9
+  --> $DIR/match_same_arms2.rs:207:9
    |
 LL |         Foo::X(0) => 1,
    |         ^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> $DIR/match_same_arms2.rs:231:9
+  --> $DIR/match_same_arms2.rs:232:9
    |
 LL |         Some(Bar { y: 0, x: 5, .. }) => 1,
    |         ----------------------------^^^^^
@@ -187,13 +188,13 @@ LL |         Some(Bar { y: 0, x: 5, .. }) => 1,
    |
    = help: or try changing either arm body
 note: other arm here
-  --> $DIR/match_same_arms2.rs:228:9
+  --> $DIR/match_same_arms2.rs:229:9
    |
 LL |         Some(Bar { x: 0, y: 5, .. }) => 1,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this match arm has an identical body to another arm
-  --> $DIR/match_same_arms2.rs:245:9
+  --> $DIR/match_same_arms2.rs:246:9
    |
 LL |         1 => cfg!(not_enable),
    |         -^^^^^^^^^^^^^^^^^^^^
@@ -202,7 +203,7 @@ LL |         1 => cfg!(not_enable),
    |
    = help: or try changing either arm body
 note: other arm here
-  --> $DIR/match_same_arms2.rs:244:9
+  --> $DIR/match_same_arms2.rs:245:9
    |
 LL |         0 => cfg!(not_enable),
    |         ^^^^^^^^^^^^^^^^^^^^^
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
new file mode 100644
index 00000000000..07421173a33
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
@@ -0,0 +1,58 @@
+#![feature(non_exhaustive_omitted_patterns_lint)]
+#![warn(clippy::match_same_arms)]
+#![no_main]
+
+use std::sync::atomic::Ordering; // #[non_exhaustive] enum
+
+pub fn f(x: Ordering) {
+    match x {
+        Ordering::Relaxed => println!("relaxed"),
+        Ordering::Release => println!("release"),
+        Ordering::Acquire => println!("acquire"),
+        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => panic!(),
+    }
+}
+
+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 => panic!(),
+            _ => panic!(),
+        }
+    }
+}
+
+// Below should still lint
+
+pub fn g(x: Ordering) {
+    match x {
+        Ordering::Relaxed => println!("relaxed"),
+        Ordering::Release => println!("release"),
+        Ordering::Acquire => println!("acquire"),
+        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        _ => panic!(),
+    }
+}
+
+mod g {
+    use super::*;
+
+    pub fn g(x: Ordering) {
+        match x {
+            Ordering::Relaxed => println!("relaxed"),
+            Ordering::Release => println!("release"),
+            Ordering::Acquire => println!("acquire"),
+            Ordering::AcqRel | Ordering::SeqCst => panic!(),
+            _ => panic!(),
+        }
+    }
+}
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
new file mode 100644
index 00000000000..088f7d5c062
--- /dev/null
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
@@ -0,0 +1,29 @@
+error: this match arm has an identical body to the `_` wildcard arm
+  --> $DIR/match_same_arms_non_exhaustive.rs:41:9
+   |
+LL |         Ordering::AcqRel | Ordering::SeqCst => panic!(),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
+   |
+   = help: or try changing either arm body
+note: `_` wildcard arm here
+  --> $DIR/match_same_arms_non_exhaustive.rs:42:9
+   |
+LL |         _ => panic!(),
+   |         ^^^^^^^^^^^^^
+   = note: `-D clippy::match-same-arms` implied by `-D warnings`
+
+error: this match arm has an identical body to the `_` wildcard arm
+  --> $DIR/match_same_arms_non_exhaustive.rs:54:13
+   |
+LL |             Ordering::AcqRel | Ordering::SeqCst => panic!(),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
+   |
+   = help: or try changing either arm body
+note: `_` wildcard arm here
+  --> $DIR/match_same_arms_non_exhaustive.rs:55:13
+   |
+LL |             _ => panic!(),
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed
index 7c29bb08e64..f59ff456bf2 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding.fixed
@@ -5,7 +5,8 @@
     clippy::let_unit_value,
     clippy::no_effect,
     clippy::toplevel_ref_arg,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 struct Point {
diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs
index c068d5e17c3..e293bc33c8a 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding.rs
@@ -5,7 +5,8 @@
     clippy::let_unit_value,
     clippy::no_effect,
     clippy::toplevel_ref_arg,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 struct Point {
diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr
index 9d16af76c6a..8998786de7e 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.stderr
+++ b/src/tools/clippy/tests/ui/match_single_binding.stderr
@@ -1,5 +1,5 @@
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:33:5
+  --> $DIR/match_single_binding.rs:34:5
    |
 LL | /     match (a, b, c) {
 LL | |         (x, y, z) => {
@@ -18,7 +18,7 @@ LL +     }
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:39:5
+  --> $DIR/match_single_binding.rs:40:5
    |
 LL | /     match (a, b, c) {
 LL | |         (x, y, z) => println!("{} {} {}", x, y, z),
@@ -32,7 +32,7 @@ LL +     println!("{} {} {}", x, y, z);
    |
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:56:5
+  --> $DIR/match_single_binding.rs:57:5
    |
 LL | /     match a {
 LL | |         _ => println!("whatever"),
@@ -40,7 +40,7 @@ LL | |     }
    | |_____^ help: consider using the match body instead: `println!("whatever");`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:60:5
+  --> $DIR/match_single_binding.rs:61:5
    |
 LL | /     match a {
 LL | |         _ => {
@@ -59,7 +59,7 @@ LL +     }
    |
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:67:5
+  --> $DIR/match_single_binding.rs:68:5
    |
 LL | /     match a {
 LL | |         _ => {
@@ -81,7 +81,7 @@ LL +     }
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:77:5
+  --> $DIR/match_single_binding.rs:78:5
    |
 LL | /     match p {
 LL | |         Point { x, y } => println!("Coords: ({}, {})", x, y),
@@ -95,7 +95,7 @@ LL +     println!("Coords: ({}, {})", x, y);
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:81:5
+  --> $DIR/match_single_binding.rs:82:5
    |
 LL | /     match p {
 LL | |         Point { x: x1, y: y1 } => println!("Coords: ({}, {})", x1, y1),
@@ -109,7 +109,7 @@ LL +     println!("Coords: ({}, {})", x1, y1);
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:86:5
+  --> $DIR/match_single_binding.rs:87:5
    |
 LL | /     match x {
 LL | |         ref r => println!("Got a reference to {}", r),
@@ -123,7 +123,7 @@ LL +     println!("Got a reference to {}", r);
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:91:5
+  --> $DIR/match_single_binding.rs:92:5
    |
 LL | /     match x {
 LL | |         ref mut mr => println!("Got a mutable reference to {}", mr),
@@ -137,7 +137,7 @@ LL +     println!("Got a mutable reference to {}", mr);
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:95:5
+  --> $DIR/match_single_binding.rs:96:5
    |
 LL | /     let product = match coords() {
 LL | |         Point { x, y } => x * y,
@@ -151,7 +151,7 @@ LL +     let product = x * y;
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:103:18
+  --> $DIR/match_single_binding.rs:104:18
    |
 LL |           .map(|i| match i.unwrap() {
    |  __________________^
@@ -168,7 +168,7 @@ LL ~         })
    |
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:129:5
+  --> $DIR/match_single_binding.rs:130:5
    |
 LL | /     match x {
 LL | |         // =>
@@ -177,7 +177,7 @@ LL | |     }
    | |_____^ help: consider using the match body instead: `println!("Not an array index start")`
 
 error: this assignment could be simplified
-  --> $DIR/match_single_binding.rs:138:5
+  --> $DIR/match_single_binding.rs:139:5
    |
 LL | /     val = match val.split_at(idx) {
 LL | |         (pre, suf) => {
@@ -197,7 +197,7 @@ LL ~     };
    |
 
 error: this match could be replaced by its scrutinee and body
-  --> $DIR/match_single_binding.rs:151:16
+  --> $DIR/match_single_binding.rs:152:16
    |
 LL |       let _ = || match side_effects() {
    |  ________________^
@@ -214,7 +214,7 @@ LL ~     };
    |
 
 error: this match could be written as a `let` statement
-  --> $DIR/match_single_binding.rs:157:5
+  --> $DIR/match_single_binding.rs:158:5
    |
 LL | /     match r {
 LL | |         x => match x {
@@ -239,7 +239,7 @@ LL ~     };
    |
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:170:5
+  --> $DIR/match_single_binding.rs:171:5
    |
 LL | /     match 1 {
 LL | |         _ => (),
@@ -247,7 +247,7 @@ LL | |     }
    | |_____^ help: consider using the match body instead: `();`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:174:13
+  --> $DIR/match_single_binding.rs:175:13
    |
 LL |       let a = match 1 {
    |  _____________^
@@ -256,7 +256,7 @@ LL | |     };
    | |_____^ help: consider using the match body instead: `()`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:178:5
+  --> $DIR/match_single_binding.rs:179:5
    |
 LL | /     match 1 {
 LL | |         _ => side_effects(),
@@ -264,7 +264,7 @@ LL | |     }
    | |_____^ help: consider using the match body instead: `side_effects();`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:182:13
+  --> $DIR/match_single_binding.rs:183:13
    |
 LL |       let b = match 1 {
    |  _____________^
@@ -273,7 +273,7 @@ LL | |     };
    | |_____^ help: consider using the match body instead: `side_effects()`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:186:5
+  --> $DIR/match_single_binding.rs:187:5
    |
 LL | /     match 1 {
 LL | |         _ => println!("1"),
@@ -281,7 +281,7 @@ LL | |     }
    | |_____^ help: consider using the match body instead: `println!("1");`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:190:13
+  --> $DIR/match_single_binding.rs:191:13
    |
 LL |       let c = match 1 {
    |  _____________^
@@ -290,7 +290,7 @@ LL | |     };
    | |_____^ help: consider using the match body instead: `println!("1")`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:195:9
+  --> $DIR/match_single_binding.rs:196:9
    |
 LL | /         match 1 {
 LL | |             _ => (),
@@ -298,7 +298,7 @@ LL | |         },
    | |_________^ help: consider using the match body instead: `()`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:198:9
+  --> $DIR/match_single_binding.rs:199:9
    |
 LL | /         match 1 {
 LL | |             _ => side_effects(),
@@ -306,7 +306,7 @@ LL | |         },
    | |_________^ help: consider using the match body instead: `side_effects()`
 
 error: this match could be replaced by its body itself
-  --> $DIR/match_single_binding.rs:201:9
+  --> $DIR/match_single_binding.rs:202:9
    |
 LL | /         match 1 {
 LL | |             _ => println!("1"),
diff --git a/src/tools/clippy/tests/ui/mem_forget.rs b/src/tools/clippy/tests/ui/mem_forget.rs
index edb9d87d032..b6c8d9e53d8 100644
--- a/src/tools/clippy/tests/ui/mem_forget.rs
+++ b/src/tools/clippy/tests/ui/mem_forget.rs
@@ -19,5 +19,8 @@ fn main() {
     let eight: Vec<i32> = vec![8];
     forgetSomething(eight);
 
+    let string = String::new();
+    std::mem::forget(string);
+
     std::mem::forget(7);
 }
diff --git a/src/tools/clippy/tests/ui/mem_forget.stderr b/src/tools/clippy/tests/ui/mem_forget.stderr
index a90d8b1655d..8004b2aa8db 100644
--- a/src/tools/clippy/tests/ui/mem_forget.stderr
+++ b/src/tools/clippy/tests/ui/mem_forget.stderr
@@ -4,6 +4,7 @@ error: usage of `mem::forget` on `Drop` type
 LL |     memstuff::forget(six);
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: argument has type `std::sync::Arc<i32>`
    = note: `-D clippy::mem-forget` implied by `-D warnings`
 
 error: usage of `mem::forget` on `Drop` type
@@ -11,12 +12,24 @@ error: usage of `mem::forget` on `Drop` type
    |
 LL |     std::mem::forget(seven);
    |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: argument has type `std::rc::Rc<i32>`
 
 error: usage of `mem::forget` on `Drop` type
   --> $DIR/mem_forget.rs:20:5
    |
 LL |     forgetSomething(eight);
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: argument has type `std::vec::Vec<i32>`
+
+error: usage of `mem::forget` on type with `Drop` fields
+  --> $DIR/mem_forget.rs:23:5
+   |
+LL |     std::mem::forget(string);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: argument has type `std::string::String`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mem_replace_macro.rs b/src/tools/clippy/tests/ui/mem_replace_macro.rs
index 132873858b7..e53342f2ed3 100644
--- a/src/tools/clippy/tests/ui/mem_replace_macro.rs
+++ b/src/tools/clippy/tests/ui/mem_replace_macro.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::mem_replace_with_default)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index e0e2cac30a2..589eab5cdfc 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -18,6 +18,7 @@
     clippy::wrong_self_convention,
     clippy::unused_async,
     clippy::unused_self,
+    clippy::useless_vec,
     unused
 )]
 
diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr
index 4643e09e270..73ec48643e0 100644
--- a/src/tools/clippy/tests/ui/methods.stderr
+++ b/src/tools/clippy/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> $DIR/methods.rs:105:5
+  --> $DIR/methods.rs:106:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> $DIR/methods.rs:126:13
+  --> $DIR/methods.rs:127:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/methods_fixable.fixed b/src/tools/clippy/tests/ui/methods_fixable.fixed
index dcbed5a4d99..ce5d19a8b6e 100644
--- a/src/tools/clippy/tests/ui/methods_fixable.fixed
+++ b/src/tools/clippy/tests/ui/methods_fixable.fixed
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::filter_next)]
+#![allow(clippy::useless_vec)]
 
 /// Checks implementation of `FILTER_NEXT` lint.
 fn main() {
diff --git a/src/tools/clippy/tests/ui/methods_fixable.rs b/src/tools/clippy/tests/ui/methods_fixable.rs
index 3a976d23527..0615817ec92 100644
--- a/src/tools/clippy/tests/ui/methods_fixable.rs
+++ b/src/tools/clippy/tests/ui/methods_fixable.rs
@@ -1,6 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::filter_next)]
+#![allow(clippy::useless_vec)]
 
 /// Checks implementation of `FILTER_NEXT` lint.
 fn main() {
diff --git a/src/tools/clippy/tests/ui/methods_fixable.stderr b/src/tools/clippy/tests/ui/methods_fixable.stderr
index 852f48e32d6..187714c75fb 100644
--- a/src/tools/clippy/tests/ui/methods_fixable.stderr
+++ b/src/tools/clippy/tests/ui/methods_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> $DIR/methods_fixable.rs:10:13
+  --> $DIR/methods_fixable.rs:11:13
    |
 LL |     let _ = v.iter().filter(|&x| *x < 0).next();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `v.iter().find(|&x| *x < 0)`
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.rs b/src/tools/clippy/tests/ui/min_ident_chars.rs
new file mode 100644
index 00000000000..b5b9e66aa7a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/min_ident_chars.rs
@@ -0,0 +1,84 @@
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(irrefutable_let_patterns, nonstandard_style, unused)]
+#![warn(clippy::min_ident_chars)]
+
+extern crate proc_macros;
+use proc_macros::external;
+use proc_macros::with_span;
+
+struct A {
+    a: u32,
+    i: u32,
+    A: u32,
+    I: u32,
+}
+
+struct B(u32);
+
+struct O {
+    o: u32,
+}
+
+struct i;
+
+enum C {
+    D,
+    E,
+    F,
+    j,
+}
+
+struct Vec4 {
+    x: u32,
+    y: u32,
+    z: u32,
+    w: u32,
+}
+
+struct AA<T, E>(T, E);
+
+fn main() {
+    // Allowed idents
+    let w = 1;
+    // Ok, not this one
+    // let i = 1;
+    let j = 1;
+    let n = 1;
+    let z = 1;
+    let y = 1;
+    let z = 1;
+    // Implicitly disallowed idents
+    let h = 1;
+    let e = 2;
+    let l = 3;
+    let l = 4;
+    let o = 6;
+    // 2 len does not lint
+    let hi = 0;
+    // Lint
+    let (h, o, w) = (1, 2, 3);
+    for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
+    let you = Vec4 { x: 1, y: 2, z: 3, w: 4 };
+    while let (d, o, _i, n, g) = (true, true, false, false, true) {}
+    let today = true;
+    // Ideally this wouldn't lint, but this would (likely) require global analysis, outta scope
+    // of this lint regardless
+    let o = 1;
+    let o = O { o };
+
+    for j in 0..1000 {}
+    for _ in 0..10 {}
+
+    // Do not lint code from external macros
+    external! { for j in 0..1000 {} }
+    // Do not lint code from procedural macros
+    with_span! {
+        span
+        for j in 0..1000 {}
+    }
+}
+
+fn b() {}
+fn wrong_pythagoras(a: f32, b: f32) -> f32 {
+    a * a + a * b
+}
diff --git a/src/tools/clippy/tests/ui/min_ident_chars.stderr b/src/tools/clippy/tests/ui/min_ident_chars.stderr
new file mode 100644
index 00000000000..66a63f65756
--- /dev/null
+++ b/src/tools/clippy/tests/ui/min_ident_chars.stderr
@@ -0,0 +1,178 @@
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:9:8
+   |
+LL | struct A {
+   |        ^
+   |
+   = note: `-D clippy::min-ident-chars` implied by `-D warnings`
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:10:5
+   |
+LL |     a: u32,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:12:5
+   |
+LL |     A: u32,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:13:5
+   |
+LL |     I: u32,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:16:8
+   |
+LL | struct B(u32);
+   |        ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:18:8
+   |
+LL | struct O {
+   |        ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:19:5
+   |
+LL |     o: u32,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:24:6
+   |
+LL | enum C {
+   |      ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:25:5
+   |
+LL |     D,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:26:5
+   |
+LL |     E,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:27:5
+   |
+LL |     F,
+   |     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:51:9
+   |
+LL |     let h = 1;
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:52:9
+   |
+LL |     let e = 2;
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:53:9
+   |
+LL |     let l = 3;
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:54:9
+   |
+LL |     let l = 4;
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:55:9
+   |
+LL |     let o = 6;
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:59:10
+   |
+LL |     let (h, o, w) = (1, 2, 3);
+   |          ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:59:13
+   |
+LL |     let (h, o, w) = (1, 2, 3);
+   |             ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:60:10
+   |
+LL |     for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
+   |          ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:60:14
+   |
+LL |     for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
+   |              ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:60:17
+   |
+LL |     for (a, (r, e)) in (0..1000).enumerate().enumerate() {}
+   |                 ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:62:16
+   |
+LL |     while let (d, o, _i, n, g) = (true, true, false, false, true) {}
+   |                ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:62:19
+   |
+LL |     while let (d, o, _i, n, g) = (true, true, false, false, true) {}
+   |                   ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:62:29
+   |
+LL |     while let (d, o, _i, n, g) = (true, true, false, false, true) {}
+   |                             ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:66:9
+   |
+LL |     let o = 1;
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:67:9
+   |
+LL |     let o = O { o };
+   |         ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:81:4
+   |
+LL | fn b() {}
+   |    ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:82:21
+   |
+LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
+   |                     ^
+
+error: this ident consists of a single char
+  --> $DIR/min_ident_chars.rs:82:29
+   |
+LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
+   |                             ^
+
+error: aborting due to 29 previous errors
+
diff --git a/src/tools/clippy/tests/ui/missing_assert_message.rs b/src/tools/clippy/tests/ui/missing_assert_message.rs
index 89404ca8827..af1358f61b5 100644
--- a/src/tools/clippy/tests/ui/missing_assert_message.rs
+++ b/src/tools/clippy/tests/ui/missing_assert_message.rs
@@ -7,8 +7,6 @@ macro_rules! bar {
     };
 }
 
-fn main() {}
-
 // Should trigger warning
 fn asserts_without_message() {
     assert!(foo());
@@ -66,9 +64,14 @@ fn asserts_without_message_but_inside_a_test_function() {
     debug_assert_ne!(foo(), foo());
 }
 
+fn foo() -> bool {
+    true
+}
+
 // Should not trigger warning
 #[cfg(test)]
 mod tests {
+    use super::foo;
     fn asserts_without_message_but_inside_a_test_module() {
         assert!(foo());
         assert_eq!(foo(), foo());
@@ -78,7 +81,3 @@ mod tests {
         debug_assert_ne!(foo(), foo());
     }
 }
-
-fn foo() -> bool {
-    true
-}
diff --git a/src/tools/clippy/tests/ui/missing_assert_message.stderr b/src/tools/clippy/tests/ui/missing_assert_message.stderr
index ecd03801277..33a5c1f8e05 100644
--- a/src/tools/clippy/tests/ui/missing_assert_message.stderr
+++ b/src/tools/clippy/tests/ui/missing_assert_message.stderr
@@ -1,5 +1,5 @@
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:14:5
+  --> $DIR/missing_assert_message.rs:12:5
    |
 LL |     assert!(foo());
    |     ^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     assert!(foo());
    = note: `-D clippy::missing-assert-message` implied by `-D warnings`
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:15:5
+  --> $DIR/missing_assert_message.rs:13:5
    |
 LL |     assert_eq!(foo(), foo());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     assert_eq!(foo(), foo());
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:16:5
+  --> $DIR/missing_assert_message.rs:14:5
    |
 LL |     assert_ne!(foo(), foo());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     assert_ne!(foo(), foo());
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:17:5
+  --> $DIR/missing_assert_message.rs:15:5
    |
 LL |     debug_assert!(foo());
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     debug_assert!(foo());
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:18:5
+  --> $DIR/missing_assert_message.rs:16:5
    |
 LL |     debug_assert_eq!(foo(), foo());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     debug_assert_eq!(foo(), foo());
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:19:5
+  --> $DIR/missing_assert_message.rs:17:5
    |
 LL |     debug_assert_ne!(foo(), foo());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     debug_assert_ne!(foo(), foo());
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:24:5
+  --> $DIR/missing_assert_message.rs:22:5
    |
 LL |     assert!(bar!(true));
    |     ^^^^^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     assert!(bar!(true));
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:25:5
+  --> $DIR/missing_assert_message.rs:23:5
    |
 LL |     assert!(bar!(true, false));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     assert!(bar!(true, false));
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:26:5
+  --> $DIR/missing_assert_message.rs:24:5
    |
 LL |     assert_eq!(bar!(true), foo());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL |     assert_eq!(bar!(true), foo());
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:27:5
+  --> $DIR/missing_assert_message.rs:25:5
    |
 LL |     assert_ne!(bar!(true, true), bar!(true));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     assert_ne!(bar!(true, true), bar!(true));
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:32:5
+  --> $DIR/missing_assert_message.rs:30:5
    |
 LL |     assert!(foo(),);
    |     ^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     assert!(foo(),);
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:33:5
+  --> $DIR/missing_assert_message.rs:31:5
    |
 LL |     assert_eq!(foo(), foo(),);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     assert_eq!(foo(), foo(),);
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:34:5
+  --> $DIR/missing_assert_message.rs:32:5
    |
 LL |     assert_ne!(foo(), foo(),);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@ LL |     assert_ne!(foo(), foo(),);
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:35:5
+  --> $DIR/missing_assert_message.rs:33:5
    |
 LL |     debug_assert!(foo(),);
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +112,7 @@ LL |     debug_assert!(foo(),);
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:36:5
+  --> $DIR/missing_assert_message.rs:34:5
    |
 LL |     debug_assert_eq!(foo(), foo(),);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL |     debug_assert_eq!(foo(), foo(),);
    = help: consider describing why the failing assert is problematic
 
 error: assert without any message
-  --> $DIR/missing_assert_message.rs:37:5
+  --> $DIR/missing_assert_message.rs:35:5
    |
 LL |     debug_assert_ne!(foo(), foo(),);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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 5db73a7b8ea..06e05352479 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
@@ -3,7 +3,7 @@
 //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere.
 
 //@aux-build:helper.rs
-//@aux-build:../../auxiliary/proc_macros.rs
+//@aux-build:../auxiliary/proc_macros.rs:proc-macro
 
 #![warn(clippy::missing_const_for_fn)]
 #![feature(start)]
@@ -13,7 +13,7 @@ extern crate proc_macros;
 
 use proc_macros::with_span;
 
-struct Game;
+struct Game; // You just lost.
 
 // This should not be linted because it's already const
 const fn already_const() -> i32 {
@@ -44,7 +44,6 @@ static Y: u32 = 0;
 // refer to a static variable
 fn get_y() -> u32 {
     Y
-    //~^ ERROR E0013
 }
 
 // Don't lint entrypoint functions
@@ -126,3 +125,43 @@ with_span! {
     span
     fn dont_check_in_proc_macro() {}
 }
+
+// Do not lint `String` has `Vec<u8>`, which cannot be dropped in const contexts
+fn a(this: String) {}
+
+enum A {
+    F(String),
+    N,
+}
+
+// Same here.
+fn b(this: A) {}
+
+// Minimized version of `a`.
+fn c(this: Vec<u16>) {}
+
+struct F(A);
+
+// Do not lint
+fn f(this: F) {}
+
+// Do not lint
+fn g<T>(this: T) {}
+
+struct Issue10617(String);
+
+impl Issue10617 {
+    // Do not lint
+    pub fn name(self) -> String {
+        self.0
+    }
+}
+
+union U {
+    f: u32,
+}
+
+// Do not lint because accessing union fields from const functions is unstable
+fn h(u: U) -> u32 {
+    unsafe { u.f }
+}
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 0246c8622ed..b1980b1b523 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
@@ -1,5 +1,7 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return)]
+#![feature(const_mut_refs)]
+#![feature(const_trait_impl)]
 
 use std::mem::transmute;
 
@@ -87,3 +89,14 @@ fn msrv_1_46() -> i32 {
 
 // Should not be const
 fn main() {}
+
+struct D;
+
+impl const Drop for D {
+    fn drop(&mut self) {
+        todo!();
+    }
+}
+
+// Lint this, since it can be dropped in const contexts
+fn d(this: D) {}
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 955e1ed2634..7be2cc0ca93 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
@@ -1,5 +1,5 @@
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:12:5
+  --> $DIR/could_be_const.rs:14:5
    |
 LL | /     pub fn new() -> Self {
 LL | |         Self { guess: 42 }
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::missing-const-for-fn` implied by `-D warnings`
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:16:5
+  --> $DIR/could_be_const.rs:18:5
    |
 LL | /     fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
 LL | |         b
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:22:1
+  --> $DIR/could_be_const.rs:24:1
    |
 LL | / fn one() -> i32 {
 LL | |     1
@@ -25,7 +25,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:27:1
+  --> $DIR/could_be_const.rs:29:1
    |
 LL | / fn two() -> i32 {
 LL | |     let abc = 2;
@@ -34,7 +34,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:33:1
+  --> $DIR/could_be_const.rs:35:1
    |
 LL | / fn string() -> String {
 LL | |     String::new()
@@ -42,7 +42,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:38:1
+  --> $DIR/could_be_const.rs:40:1
    |
 LL | / unsafe fn four() -> i32 {
 LL | |     4
@@ -50,7 +50,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:43:1
+  --> $DIR/could_be_const.rs:45:1
    |
 LL | / fn generic<T>(t: T) -> T {
 LL | |     t
@@ -58,7 +58,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:51:1
+  --> $DIR/could_be_const.rs:53:1
    |
 LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T {
 LL | |     t[0]
@@ -66,7 +66,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:64:9
+  --> $DIR/could_be_const.rs:66:9
    |
 LL | /         pub fn b(self, a: &A) -> B {
 LL | |             B
@@ -74,7 +74,7 @@ LL | |         }
    | |_________^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:73:5
+  --> $DIR/could_be_const.rs:75:5
    |
 LL | /     fn const_fn_stabilized_before_msrv(byte: u8) {
 LL | |         byte.is_ascii_digit();
@@ -82,12 +82,18 @@ LL | |     }
    | |_____^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:84:1
+  --> $DIR/could_be_const.rs:86:1
    |
 LL | / fn msrv_1_46() -> i32 {
 LL | |     46
 LL | | }
    | |_^
 
-error: aborting due to 11 previous errors
+error: this could be a `const fn`
+  --> $DIR/could_be_const.rs:102:1
+   |
+LL | fn d(this: D) {}
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_doc.rs b/src/tools/clippy/tests/ui/missing_doc.rs
index bf587e774f7..cff1706a842 100644
--- a/src/tools/clippy/tests/ui/missing_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_doc.rs
@@ -1,5 +1,5 @@
 //@needs-asm-support
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![warn(clippy::missing_docs_in_private_items)]
 // When denying at the crate level, be sure to not get random warnings from the
diff --git a/src/tools/clippy/tests/ui/missing_doc_impl.rs b/src/tools/clippy/tests/ui/missing_doc_impl.rs
index 520ddbe16b8..2d45132f968 100644
--- a/src/tools/clippy/tests/ui/missing_doc_impl.rs
+++ b/src/tools/clippy/tests/ui/missing_doc_impl.rs
@@ -1,4 +1,4 @@
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![warn(clippy::missing_docs_in_private_items)]
 #![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/missing_inline_proc_macro.rs b/src/tools/clippy/tests/ui/missing_inline_proc_macro.rs
index 3c68fb905f1..e47a198c6ae 100644
--- a/src/tools/clippy/tests/ui/missing_inline_proc_macro.rs
+++ b/src/tools/clippy/tests/ui/missing_inline_proc_macro.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::missing_inline_in_public_items)]
-#![crate_type = "proc-macro"]
 
 extern crate proc_macro;
 
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.rs b/src/tools/clippy/tests/ui/missing_panics_doc.rs
index 7dc44529206..0e1533fc1ab 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.rs
@@ -1,5 +1,12 @@
+//@aux-build:macro_rules.rs
 #![warn(clippy::missing_panics_doc)]
-#![allow(clippy::option_map_unit_fn)]
+#![allow(clippy::option_map_unit_fn, clippy::unnecessary_literal_unwrap)]
+
+#[macro_use]
+extern crate macro_rules;
+
+use macro_rules::macro_with_panic;
+
 fn main() {}
 
 /// This needs to be documented
@@ -14,11 +21,6 @@ pub fn panic() {
 }
 
 /// This needs to be documented
-pub fn todo() {
-    todo!()
-}
-
-/// This needs to be documented
 pub fn inner_body(opt: Option<u32>) {
     opt.map(|x| {
         if x == 10 {
@@ -81,15 +83,6 @@ pub fn inner_body_documented(opt: Option<u32>) {
 /// # Panics
 ///
 /// We still need to do this part
-pub fn todo_documented() {
-    todo!()
-}
-
-/// This is documented
-///
-/// # Panics
-///
-/// We still need to do this part
 pub fn unreachable_amd_panic_documented() {
     if true { unreachable!() } else { panic!() }
 }
@@ -114,6 +107,11 @@ pub fn assert_ne_documented() {
     assert_ne!(x, 0);
 }
 
+/// `todo!()` is fine
+pub fn todo() {
+    todo!()
+}
+
 /// This is okay because it is private
 fn unwrap_private() {
     let result = Err("Hi");
@@ -126,11 +124,6 @@ fn panic_private() {
 }
 
 /// This is okay because it is private
-fn todo_private() {
-    todo!()
-}
-
-/// This is okay because it is private
 fn inner_body_private(opt: Option<u32>) {
     opt.map(|x| {
         if x == 10 {
@@ -151,3 +144,50 @@ pub fn debug_assertions() {
     debug_assert_eq!(1, 2);
     debug_assert_ne!(1, 2);
 }
+
+// all function must be triggered the lint.
+// `pub` is required, because the lint does not consider unreachable items
+pub mod issue10240 {
+    pub fn option_unwrap<T>(v: &[T]) -> &T {
+        let o: Option<&T> = v.last();
+        o.unwrap()
+    }
+
+    pub fn option_expect<T>(v: &[T]) -> &T {
+        let o: Option<&T> = v.last();
+        o.expect("passed an empty thing")
+    }
+
+    pub fn result_unwrap<T>(v: &[T]) -> &T {
+        let res: Result<&T, &str> = v.last().ok_or("oh noes");
+        res.unwrap()
+    }
+
+    pub fn result_expect<T>(v: &[T]) -> &T {
+        let res: Result<&T, &str> = v.last().ok_or("oh noes");
+        res.expect("passed an empty thing")
+    }
+
+    pub fn last_unwrap(v: &[u32]) -> u32 {
+        *v.last().unwrap()
+    }
+
+    pub fn last_expect(v: &[u32]) -> u32 {
+        *v.last().expect("passed an empty thing")
+    }
+}
+
+fn from_external_macro_should_not_lint() {
+    macro_with_panic!()
+}
+
+macro_rules! some_macro_that_panics {
+    () => {
+        panic!()
+    };
+}
+
+fn from_declared_macro_should_lint_at_macrosite() {
+    // Not here.
+    some_macro_that_panics!()
+}
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
index 183c262ce0b..3dbe2dfbd88 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
@@ -1,87 +1,147 @@
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:6:1
+  --> $DIR/missing_panics_doc.rs:13:1
    |
 LL | pub fn unwrap() {
    | ^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:8:5
+  --> $DIR/missing_panics_doc.rs:15:5
    |
 LL |     result.unwrap()
    |     ^^^^^^^^^^^^^^^
    = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:12:1
+  --> $DIR/missing_panics_doc.rs:19:1
    |
 LL | pub fn panic() {
    | ^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:13:5
+  --> $DIR/missing_panics_doc.rs:20:5
    |
 LL |     panic!("This function panics")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:17:1
-   |
-LL | pub fn todo() {
-   | ^^^^^^^^^^^^^
-   |
-note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:18:5
-   |
-LL |     todo!()
-   |     ^^^^^^^
-
-error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:22:1
+  --> $DIR/missing_panics_doc.rs:24:1
    |
 LL | pub fn inner_body(opt: Option<u32>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:25:13
+  --> $DIR/missing_panics_doc.rs:27:13
    |
 LL |             panic!()
    |             ^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:31:1
+  --> $DIR/missing_panics_doc.rs:33:1
    |
 LL | pub fn unreachable_and_panic() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:32:39
+  --> $DIR/missing_panics_doc.rs:34:39
    |
 LL |     if true { unreachable!() } else { panic!() }
    |                                       ^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:36:1
+  --> $DIR/missing_panics_doc.rs:38:1
    |
 LL | pub fn assert_eq() {
    | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:38:5
+  --> $DIR/missing_panics_doc.rs:40:5
    |
 LL |     assert_eq!(x, 0);
    |     ^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:42:1
+  --> $DIR/missing_panics_doc.rs:44:1
    |
 LL | pub fn assert_ne() {
    | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:44:5
+  --> $DIR/missing_panics_doc.rs:46:5
    |
 LL |     assert_ne!(x, 0);
    |     ^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:151:5
+   |
+LL |     pub fn option_unwrap<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:153:9
+   |
+LL |         o.unwrap()
+   |         ^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:156:5
+   |
+LL |     pub fn option_expect<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:158:9
+   |
+LL |         o.expect("passed an empty thing")
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:161:5
+   |
+LL |     pub fn result_unwrap<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:163:9
+   |
+LL |         res.unwrap()
+   |         ^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:166:5
+   |
+LL |     pub fn result_expect<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:168:9
+   |
+LL |         res.expect("passed an empty thing")
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:171:5
+   |
+LL |     pub fn last_unwrap(v: &[u32]) -> u32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:172:10
+   |
+LL |         *v.last().unwrap()
+   |          ^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:175:5
+   |
+LL |     pub fn last_expect(v: &[u32]) -> u32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:176:10
+   |
+LL |         *v.last().expect("passed an empty thing")
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
index 62cfeafdc49..9c2ffcb02ea 100644
--- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
+++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![allow(
     dead_code,
diff --git a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
index f83b7c3dbda..a0a1e96a775 100644
--- a/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
+++ b/src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 
 #![allow(
     dead_code,
diff --git a/src/tools/clippy/tests/ui/module_inception.rs b/src/tools/clippy/tests/ui/module_inception.rs
index a23aba9164a..802c3ec39b6 100644
--- a/src/tools/clippy/tests/ui/module_inception.rs
+++ b/src/tools/clippy/tests/ui/module_inception.rs
@@ -1,5 +1,17 @@
 #![warn(clippy::module_inception)]
 
+pub mod foo2 {
+    pub mod bar2 {
+        pub mod bar2 {
+            pub mod foo2 {}
+        }
+        pub mod foo2 {}
+    }
+    pub mod foo2 {
+        pub mod bar2 {}
+    }
+}
+
 mod foo {
     mod bar {
         mod bar {
diff --git a/src/tools/clippy/tests/ui/module_inception.stderr b/src/tools/clippy/tests/ui/module_inception.stderr
index 77564dce9eb..ebb8e296f46 100644
--- a/src/tools/clippy/tests/ui/module_inception.stderr
+++ b/src/tools/clippy/tests/ui/module_inception.stderr
@@ -1,8 +1,8 @@
 error: module has the same name as its containing module
   --> $DIR/module_inception.rs:5:9
    |
-LL | /         mod bar {
-LL | |             mod foo {}
+LL | /         pub mod bar2 {
+LL | |             pub mod foo2 {}
 LL | |         }
    | |_________^
    |
@@ -11,10 +11,26 @@ LL | |         }
 error: module has the same name as its containing module
   --> $DIR/module_inception.rs:10:5
    |
+LL | /     pub mod foo2 {
+LL | |         pub mod bar2 {}
+LL | |     }
+   | |_____^
+
+error: module has the same name as its containing module
+  --> $DIR/module_inception.rs:17:9
+   |
+LL | /         mod bar {
+LL | |             mod foo {}
+LL | |         }
+   | |_________^
+
+error: module has the same name as its containing module
+  --> $DIR/module_inception.rs:22:5
+   |
 LL | /     mod foo {
 LL | |         mod bar {}
 LL | |     }
    | |_____^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index 4ef6f0ca92f..23ad36bb473 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![allow(unused)]
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/must_use_unit.fixed b/src/tools/clippy/tests/ui/must_use_unit.fixed
index 4f7cf4e56d1..c460fd7c6b0 100644
--- a/src/tools/clippy/tests/ui/must_use_unit.fixed
+++ b/src/tools/clippy/tests/ui/must_use_unit.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::must_use_unit)]
 #![allow(clippy::unused_unit)]
diff --git a/src/tools/clippy/tests/ui/must_use_unit.rs b/src/tools/clippy/tests/ui/must_use_unit.rs
index 3a814ce1685..fe95624f799 100644
--- a/src/tools/clippy/tests/ui/must_use_unit.rs
+++ b/src/tools/clippy/tests/ui/must_use_unit.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::must_use_unit)]
 #![allow(clippy::unused_unit)]
diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs
index d838098de11..b7213428367 100644
--- a/src/tools/clippy/tests/ui/mut_mut.rs
+++ b/src/tools/clippy/tests/ui/mut_mut.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::mut_mut)]
 #![allow(unused)]
 #![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)]
diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
index 00871f9f450..876f16a3854 100644
--- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
+++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_attr.rs
+//@aux-build:proc_macro_attr.rs:proc-macro
 
 #![warn(clippy::needless_arbitrary_self_type)]
 
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index bf1911881c8..7d0e556528f 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -7,6 +7,7 @@
     clippy::no_effect,
     clippy::if_same_then_else,
     clippy::equatable_if_let,
+    clippy::needless_if,
     clippy::needless_return,
     clippy::self_named_constructors
 )]
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index a6c465d4fbd..88bfe8af733 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -7,6 +7,7 @@
     clippy::no_effect,
     clippy::if_same_then_else,
     clippy::equatable_if_let,
+    clippy::needless_if,
     clippy::needless_return,
     clippy::self_named_constructors
 )]
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index fa906374fb3..1476aea439f 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -1,5 +1,5 @@
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:41:5
+  --> $DIR/fixable.rs:42:5
    |
 LL | /     if x {
 LL | |         true
@@ -11,7 +11,7 @@ LL | |     };
    = note: `-D clippy::needless-bool` implied by `-D warnings`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:46:5
+  --> $DIR/fixable.rs:47:5
    |
 LL | /     if x {
 LL | |         false
@@ -21,7 +21,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:51:5
+  --> $DIR/fixable.rs:52:5
    |
 LL | /     if x && y {
 LL | |         false
@@ -31,7 +31,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!(x && y)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:59:5
+  --> $DIR/fixable.rs:60:5
    |
 LL | /     if a == b {
 LL | |         false
@@ -41,7 +41,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a != b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:64:5
+  --> $DIR/fixable.rs:65:5
    |
 LL | /     if a != b {
 LL | |         false
@@ -51,7 +51,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a == b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:69:5
+  --> $DIR/fixable.rs:70:5
    |
 LL | /     if a < b {
 LL | |         false
@@ -61,7 +61,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a >= b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:74:5
+  --> $DIR/fixable.rs:75:5
    |
 LL | /     if a <= b {
 LL | |         false
@@ -71,7 +71,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a > b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:79:5
+  --> $DIR/fixable.rs:80:5
    |
 LL | /     if a > b {
 LL | |         false
@@ -81,7 +81,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a <= b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:84:5
+  --> $DIR/fixable.rs:85:5
    |
 LL | /     if a >= b {
 LL | |         false
@@ -91,7 +91,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a < b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:112:5
+  --> $DIR/fixable.rs:113:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -101,7 +101,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:120:5
+  --> $DIR/fixable.rs:121:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -111,7 +111,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:128:5
+  --> $DIR/fixable.rs:129:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -121,7 +121,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:136:5
+  --> $DIR/fixable.rs:137:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -131,7 +131,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:144:8
+  --> $DIR/fixable.rs:145:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -139,25 +139,25 @@ LL |     if x == true {};
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:148:8
+  --> $DIR/fixable.rs:149:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:158:8
+  --> $DIR/fixable.rs:159:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:159:8
+  --> $DIR/fixable.rs:160:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:168:12
+  --> $DIR/fixable.rs:169:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
@@ -168,7 +168,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `{ !returns_bool() }`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:181:5
+  --> $DIR/fixable.rs:182:5
    |
 LL | /     if unsafe { no(4) } & 1 != 0 {
 LL | |         true
@@ -178,13 +178,13 @@ LL | |     };
    | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:186:30
+  --> $DIR/fixable.rs:187:30
    |
 LL |     let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:189:9
+  --> $DIR/fixable.rs:190:9
    |
 LL |         if unsafe { no(4) } & 1 != 0 { true } else { false }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index 425e6eb6200..80cdb4e472d 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -4,7 +4,8 @@
     unused,
     clippy::uninlined_format_args,
     clippy::unnecessary_mut_passed,
-    clippy::unnecessary_to_owned
+    clippy::unnecessary_to_owned,
+    clippy::unnecessary_literal_unwrap
 )]
 #![warn(clippy::needless_borrow)]
 
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index 3f7fa4a9d7d..99f735127eb 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -4,7 +4,8 @@
     unused,
     clippy::uninlined_format_args,
     clippy::unnecessary_mut_passed,
-    clippy::unnecessary_to_owned
+    clippy::unnecessary_to_owned,
+    clippy::unnecessary_literal_unwrap
 )]
 #![warn(clippy::needless_borrow)]
 
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index d26c317124b..f85b4fb46a6 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -1,5 +1,5 @@
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:15:15
+  --> $DIR/needless_borrow.rs:16:15
    |
 LL |     let _ = x(&&a); // warn
    |               ^^^ help: change this to: `&a`
@@ -7,211 +7,211 @@ LL |     let _ = x(&&a); // warn
    = note: `-D clippy::needless-borrow` implied by `-D warnings`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:19:13
+  --> $DIR/needless_borrow.rs:20:13
    |
 LL |     mut_ref(&mut &mut b); // warn
    |             ^^^^^^^^^^^ help: change this to: `&mut b`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:31:13
+  --> $DIR/needless_borrow.rs:32:13
    |
 LL |             &&a
    |             ^^^ help: change this to: `&a`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:33:15
+  --> $DIR/needless_borrow.rs:34:15
    |
 LL |         46 => &&a,
    |               ^^^ help: change this to: `&a`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:39:27
+  --> $DIR/needless_borrow.rs:40:27
    |
 LL |                     break &ref_a;
    |                           ^^^^^^ help: change this to: `ref_a`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:46:15
+  --> $DIR/needless_borrow.rs:47:15
    |
 LL |     let _ = x(&&&a);
    |               ^^^^ help: change this to: `&a`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:47:15
+  --> $DIR/needless_borrow.rs:48:15
    |
 LL |     let _ = x(&mut &&a);
    |               ^^^^^^^^ help: change this to: `&a`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:48:15
+  --> $DIR/needless_borrow.rs:49:15
    |
 LL |     let _ = x(&&&mut b);
    |               ^^^^^^^^ help: change this to: `&mut b`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:49:15
+  --> $DIR/needless_borrow.rs:50:15
    |
 LL |     let _ = x(&&ref_a);
    |               ^^^^^^^ help: change this to: `ref_a`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:52:11
+  --> $DIR/needless_borrow.rs:53:11
    |
 LL |         x(&b);
    |           ^^ help: change this to: `b`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:59:13
+  --> $DIR/needless_borrow.rs:60:13
    |
 LL |     mut_ref(&mut x);
    |             ^^^^^^ help: change this to: `x`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:60:13
+  --> $DIR/needless_borrow.rs:61:13
    |
 LL |     mut_ref(&mut &mut x);
    |             ^^^^^^^^^^^ help: change this to: `x`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:61:23
+  --> $DIR/needless_borrow.rs:62:23
    |
 LL |     let y: &mut i32 = &mut x;
    |                       ^^^^^^ help: change this to: `x`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:62:23
+  --> $DIR/needless_borrow.rs:63:23
    |
 LL |     let y: &mut i32 = &mut &mut x;
    |                       ^^^^^^^^^^^ help: change this to: `x`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:71:14
+  --> $DIR/needless_borrow.rs:72:14
    |
 LL |         0 => &mut x,
    |              ^^^^^^ help: change this to: `x`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:77:14
+  --> $DIR/needless_borrow.rs:78:14
    |
 LL |         0 => &mut x,
    |              ^^^^^^ help: change this to: `x`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> $DIR/needless_borrow.rs:89:13
+  --> $DIR/needless_borrow.rs:90:13
    |
 LL |     let _ = (&x).0;
    |             ^^^^ help: change this to: `x`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> $DIR/needless_borrow.rs:91:22
+  --> $DIR/needless_borrow.rs:92:22
    |
 LL |     let _ = unsafe { (&*x).0 };
    |                      ^^^^^ help: change this to: `(*x)`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:101:5
+  --> $DIR/needless_borrow.rs:102:5
    |
 LL |     (&&()).foo();
    |     ^^^^^^ help: change this to: `(&())`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:110:5
+  --> $DIR/needless_borrow.rs:111:5
    |
 LL |     (&&5).foo();
    |     ^^^^^ help: change this to: `(&5)`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:135:51
+  --> $DIR/needless_borrow.rs:136:51
    |
 LL |     let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
    |                                                   ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:136:44
+  --> $DIR/needless_borrow.rs:137:44
    |
 LL |     let _ = std::path::Path::new(".").join(&&".");
    |                                            ^^^^^ help: change this to: `"."`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:137:23
+  --> $DIR/needless_borrow.rs:138:23
    |
 LL |     deref_target_is_x(&X);
    |                       ^^ help: change this to: `X`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:138:26
+  --> $DIR/needless_borrow.rs:139:26
    |
 LL |     multiple_constraints(&[[""]]);
    |                          ^^^^^^^ help: change this to: `[[""]]`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:139:45
+  --> $DIR/needless_borrow.rs:140:45
    |
 LL |     multiple_constraints_normalizes_to_same(&X, X);
    |                                             ^^ help: change this to: `X`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:140:32
+  --> $DIR/needless_borrow.rs:141:32
    |
 LL |     let _ = Some("").unwrap_or(&"");
    |                                ^^^ help: change this to: `""`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:141:33
+  --> $DIR/needless_borrow.rs:142:33
    |
 LL |     let _ = std::fs::write("x", &"".to_string());
    |                                 ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> $DIR/needless_borrow.rs:190:13
+  --> $DIR/needless_borrow.rs:191:13
    |
 LL |             (&self.f)()
    |             ^^^^^^^^^ help: change this to: `(self.f)`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> $DIR/needless_borrow.rs:199:13
+  --> $DIR/needless_borrow.rs:200:13
    |
 LL |             (&mut self.f)()
    |             ^^^^^^^^^^^^^ help: change this to: `(self.f)`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:283:20
+  --> $DIR/needless_borrow.rs:284:20
    |
 LL |         takes_iter(&mut x)
    |                    ^^^^^^ help: change this to: `x`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:297:55
+  --> $DIR/needless_borrow.rs:298:55
    |
 LL |         let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
    |                                                       ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:335:37
+  --> $DIR/needless_borrow.rs:336:37
    |
 LL |         let _ = std::fs::write("x", &arg);
    |                                     ^^^^ help: change this to: `arg`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:336:37
+  --> $DIR/needless_borrow.rs:337:37
    |
 LL |         let _ = std::fs::write("x", &loc);
    |                                     ^^^^ help: change this to: `loc`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:354:15
+  --> $DIR/needless_borrow.rs:355:15
    |
 LL |         debug(&x);
    |               ^^ help: change this to: `x`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:363:15
+  --> $DIR/needless_borrow.rs:364:15
    |
 LL |         use_x(&x);
    |               ^^ help: change this to: `x`
 
 error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:457:13
+  --> $DIR/needless_borrow.rs:458:13
    |
 LL |         foo(&a);
    |             ^^ help: change this to: `a`
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
index 6663520da8a..59a38425b06 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
@@ -5,7 +5,8 @@
     unused,
     irrefutable_let_patterns,
     non_shorthand_field_patterns,
-    clippy::needless_borrow
+    clippy::needless_borrow,
+    clippy::needless_if
 )]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
index 6c8efd2ce18..e48b19cb19d 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
@@ -5,7 +5,8 @@
     unused,
     irrefutable_let_patterns,
     non_shorthand_field_patterns,
-    clippy::needless_borrow
+    clippy::needless_borrow,
+    clippy::needless_if
 )]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr b/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
index 8d0f0c258dd..35497a01ec2 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
@@ -1,5 +1,5 @@
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:31:34
+  --> $DIR/needless_borrowed_ref.rs:32:34
    |
 LL |     let _ = v.iter_mut().filter(|&ref a| a.is_empty());
    |                                  ^^^^^^
@@ -12,7 +12,7 @@ LL +     let _ = v.iter_mut().filter(|a| a.is_empty());
    |
 
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:35:17
+  --> $DIR/needless_borrowed_ref.rs:36:17
    |
 LL |     if let Some(&ref v) = thingy {}
    |                 ^^^^^^
@@ -24,7 +24,7 @@ LL +     if let Some(v) = thingy {}
    |
 
 error: this pattern takes a reference on something that is being dereferenced
-  --> $DIR/needless_borrowed_ref.rs:37:14
+  --> $DIR/needless_borrowed_ref.rs:38:14
    |
 LL |     if let &[&ref a, ref b] = slice_of_refs {}
    |              ^^^^^^
@@ -36,7 +36,7 @@ LL +     if let &[a, ref b] = slice_of_refs {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:39:9
+  --> $DIR/needless_borrowed_ref.rs:40:9
    |
 LL |     let &[ref a, ..] = &array;
    |         ^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL +     let [a, ..] = &array;
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:40:9
+  --> $DIR/needless_borrowed_ref.rs:41:9
    |
 LL |     let &[ref a, ref b, ..] = &array;
    |         ^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL +     let [a, b, ..] = &array;
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:42:12
+  --> $DIR/needless_borrowed_ref.rs:43:12
    |
 LL |     if let &[ref a, ref b] = slice {}
    |            ^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL +     if let [a, b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:43:12
+  --> $DIR/needless_borrowed_ref.rs:44:12
    |
 LL |     if let &[ref a, ref b] = &vec[..] {}
    |            ^^^^^^^^^^^^^^^
@@ -84,7 +84,7 @@ LL +     if let [a, b] = &vec[..] {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:45:12
+  --> $DIR/needless_borrowed_ref.rs:46:12
    |
 LL |     if let &[ref a, ref b, ..] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL +     if let [a, b, ..] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:46:12
+  --> $DIR/needless_borrowed_ref.rs:47:12
    |
 LL |     if let &[ref a, .., ref b] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -108,7 +108,7 @@ LL +     if let [a, .., b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:47:12
+  --> $DIR/needless_borrowed_ref.rs:48:12
    |
 LL |     if let &[.., ref a, ref b] = slice {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@ LL +     if let [.., a, b] = slice {}
    |
 
 error: dereferencing a slice pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:49:12
+  --> $DIR/needless_borrowed_ref.rs:50:12
    |
 LL |     if let &[ref a, _] = slice {}
    |            ^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL +     if let [a, _] = slice {}
    |
 
 error: dereferencing a tuple pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:51:12
+  --> $DIR/needless_borrowed_ref.rs:52:12
    |
 LL |     if let &(ref a, ref b, ref c) = &tuple {}
    |            ^^^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +144,7 @@ LL +     if let (a, b, c) = &tuple {}
    |
 
 error: dereferencing a tuple pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:52:12
+  --> $DIR/needless_borrowed_ref.rs:53:12
    |
 LL |     if let &(ref a, _, ref c) = &tuple {}
    |            ^^^^^^^^^^^^^^^^^^
@@ -156,7 +156,7 @@ LL +     if let (a, _, c) = &tuple {}
    |
 
 error: dereferencing a tuple pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:53:12
+  --> $DIR/needless_borrowed_ref.rs:54:12
    |
 LL |     if let &(ref a, ..) = &tuple {}
    |            ^^^^^^^^^^^^
@@ -168,7 +168,7 @@ LL +     if let (a, ..) = &tuple {}
    |
 
 error: dereferencing a tuple pattern where every element takes a reference
-  --> $DIR/needless_borrowed_ref.rs:55:12
+  --> $DIR/needless_borrowed_ref.rs:56:12
    |
 LL |     if let &TupleStruct(ref a, ..) = &tuple_struct {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^
@@ -180,7 +180,7 @@ LL +     if let TupleStruct(a, ..) = &tuple_struct {}
    |
 
 error: dereferencing a struct pattern where every field's pattern takes a reference
-  --> $DIR/needless_borrowed_ref.rs:57:12
+  --> $DIR/needless_borrowed_ref.rs:58:12
    |
 LL |       if let &Struct {
    |  ____________^
@@ -199,7 +199,7 @@ LL ~         c: renamed,
    |
 
 error: dereferencing a struct pattern where every field's pattern takes a reference
-  --> $DIR/needless_borrowed_ref.rs:64:12
+  --> $DIR/needless_borrowed_ref.rs:65:12
    |
 LL |     if let &Struct { ref a, b: _, .. } = &s {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index b7e80af5015..0f0aaad17b4 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused, clippy::suspicious_map, clippy::iter_count)]
+#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)]
 
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList};
 
@@ -70,6 +70,11 @@ fn main() {
         bar((0..10).collect::<Vec<_>>(), (0..10));
         baz((0..10), (), ('a'..='z'))
     }
+
+    let values = [1, 2, 3, 4];
+    let mut out = vec![];
+    values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>();
+    let _y = values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine
 }
 
 fn foo(_: impl IntoIterator<Item = usize>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 680b6fa5b55..4f48f24b17b 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused, clippy::suspicious_map, clippy::iter_count)]
+#![allow(unused, clippy::needless_if, clippy::suspicious_map, clippy::iter_count)]
 
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList};
 
@@ -70,6 +70,11 @@ fn main() {
         bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
         baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
     }
+
+    let values = [1, 2, 3, 4];
+    let mut out = vec![];
+    values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>();
+    let _y = values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine
 }
 
 fn foo(_: impl IntoIterator<Item = usize>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
index fe4209e99b2..d3d856c2c65 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
@@ -1,4 +1,5 @@
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::useless_vec)]
+#![allow(clippy::needless_if, clippy::uninlined_format_args)]
 #![warn(clippy::needless_collect)]
 
 use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
index 790d725907f..8f84c559688 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
@@ -1,5 +1,5 @@
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:8:39
+  --> $DIR/needless_collect_indirect.rs:9:39
    |
 LL |     let indirect_iter = sample.iter().collect::<Vec<_>>();
    |                                       ^^^^^^^
@@ -14,7 +14,7 @@ LL ~     sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:10:38
+  --> $DIR/needless_collect_indirect.rs:11:38
    |
 LL |     let indirect_len = sample.iter().collect::<VecDeque<_>>();
    |                                      ^^^^^^^
@@ -28,7 +28,7 @@ LL ~     sample.iter().count();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:12:40
+  --> $DIR/needless_collect_indirect.rs:13:40
    |
 LL |     let indirect_empty = sample.iter().collect::<VecDeque<_>>();
    |                                        ^^^^^^^
@@ -42,7 +42,7 @@ LL ~     sample.iter().next().is_none();
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:14:43
+  --> $DIR/needless_collect_indirect.rs:15:43
    |
 LL |     let indirect_contains = sample.iter().collect::<VecDeque<_>>();
    |                                           ^^^^^^^
@@ -56,7 +56,7 @@ LL ~     sample.iter().any(|x| x == &5);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:26:48
+  --> $DIR/needless_collect_indirect.rs:27:48
    |
 LL |     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
    |                                                ^^^^^^^
@@ -70,7 +70,7 @@ LL ~     sample.into_iter().any(|x| x == a);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:55:51
+  --> $DIR/needless_collect_indirect.rs:56:51
    |
 LL |         let buffer: Vec<&str> = string.split('/').collect();
    |                                                   ^^^^^^^
@@ -84,7 +84,7 @@ LL ~         string.split('/').count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:60:55
+  --> $DIR/needless_collect_indirect.rs:61:55
    |
 LL |         let indirect_len: VecDeque<_> = sample.iter().collect();
    |                                                       ^^^^^^^
@@ -98,7 +98,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:65:57
+  --> $DIR/needless_collect_indirect.rs:66:57
    |
 LL |         let indirect_len: LinkedList<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -112,7 +112,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:70:57
+  --> $DIR/needless_collect_indirect.rs:71:57
    |
 LL |         let indirect_len: BinaryHeap<_> = sample.iter().collect();
    |                                                         ^^^^^^^
@@ -126,7 +126,7 @@ LL ~         sample.iter().count()
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:130:59
+  --> $DIR/needless_collect_indirect.rs:131:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -143,7 +143,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == i);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:155:59
+  --> $DIR/needless_collect_indirect.rs:156:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -160,7 +160,7 @@ LL ~             vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:184:63
+  --> $DIR/needless_collect_indirect.rs:185:63
    |
 LL |                 let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                               ^^^^^^^
@@ -177,7 +177,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:220:59
+  --> $DIR/needless_collect_indirect.rs:221:59
    |
 LL |             let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
    |                                                           ^^^^^^^
@@ -195,7 +195,7 @@ LL ~                 vec.iter().map(|k| k * k).any(|x| x == n);
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:245:26
+  --> $DIR/needless_collect_indirect.rs:246:26
    |
 LL |         let w = v.iter().collect::<Vec<_>>();
    |                          ^^^^^^^
@@ -211,7 +211,7 @@ LL ~         for _ in 0..v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:267:30
+  --> $DIR/needless_collect_indirect.rs:268:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
@@ -227,7 +227,7 @@ LL ~         while 1 == v.iter().count() {
    |
 
 error: avoid using `collect()` when not needed
-  --> $DIR/needless_collect_indirect.rs:289:30
+  --> $DIR/needless_collect_indirect.rs:290:30
    |
 LL |         let mut w = v.iter().collect::<Vec<_>>();
    |                              ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_if.fixed b/src/tools/clippy/tests/ui/needless_if.fixed
new file mode 100644
index 00000000000..5e6e140c2db
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_if.fixed
@@ -0,0 +1,93 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(let_chains)]
+#![allow(
+    clippy::blocks_in_if_conditions,
+    clippy::if_same_then_else,
+    clippy::ifs_same_cond,
+    clippy::let_unit_value,
+    clippy::needless_else,
+    clippy::no_effect,
+    clippy::nonminimal_bool,
+    clippy::short_circuit_statement,
+    clippy::unnecessary_operation,
+    unused
+)]
+#![warn(clippy::needless_if)]
+
+extern crate proc_macros;
+use proc_macros::external;
+use proc_macros::with_span;
+
+fn maybe_side_effect() -> bool {
+    true
+}
+
+fn main() {
+    // Lint
+    
+    // Do not remove the condition
+    maybe_side_effect();
+    // Do not lint
+    if (true) {
+    } else {
+    }
+    ({
+        return;
+    });
+    // Do not lint if `else if` is present
+    if (true) {
+    } else if (true) {
+    }
+    // Do not lint `if let` or let chains
+    if let true = true {}
+    if let true = true && true {}
+    if true && let true = true {}
+    // Can lint nested `if let`s
+    ({
+        if let true = true && true { true } else { false }
+    } && true);
+    external! { if (true) {} }
+    with_span! {
+        span
+        if (true) {}
+    }
+
+    if true {
+        // comment
+    }
+
+    if true {
+        #[cfg(any())]
+        foo;
+    }
+
+    macro_rules! empty_expansion {
+        () => {};
+    }
+
+    if true {
+        empty_expansion!();
+    }
+
+    macro_rules! empty_repetition {
+        ($($t:tt)*) => {
+            if true {
+                $($t)*
+            }
+        }
+    }
+
+    empty_repetition!();
+
+    // Must be placed into an expression context to not be interpreted as a block
+    ({ maybe_side_effect() });
+    // Would be a block followed by `&&true` - a double reference to `true`
+    ({ maybe_side_effect() } && true);
+
+    // Don't leave trailing attributes
+    #[allow(unused)]
+    true;
+
+    let () = if maybe_side_effect() {};
+}
diff --git a/src/tools/clippy/tests/ui/needless_if.rs b/src/tools/clippy/tests/ui/needless_if.rs
new file mode 100644
index 00000000000..eb28ce73be8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_if.rs
@@ -0,0 +1,94 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(let_chains)]
+#![allow(
+    clippy::blocks_in_if_conditions,
+    clippy::if_same_then_else,
+    clippy::ifs_same_cond,
+    clippy::let_unit_value,
+    clippy::needless_else,
+    clippy::no_effect,
+    clippy::nonminimal_bool,
+    clippy::short_circuit_statement,
+    clippy::unnecessary_operation,
+    unused
+)]
+#![warn(clippy::needless_if)]
+
+extern crate proc_macros;
+use proc_macros::external;
+use proc_macros::with_span;
+
+fn maybe_side_effect() -> bool {
+    true
+}
+
+fn main() {
+    // Lint
+    if (true) {}
+    // Do not remove the condition
+    if maybe_side_effect() {}
+    // Do not lint
+    if (true) {
+    } else {
+    }
+    if {
+        return;
+    } {}
+    // Do not lint if `else if` is present
+    if (true) {
+    } else if (true) {
+    }
+    // Do not lint `if let` or let chains
+    if let true = true {}
+    if let true = true && true {}
+    if true && let true = true {}
+    // Can lint nested `if let`s
+    if {
+        if let true = true && true { true } else { false }
+    } && true
+    {}
+    external! { if (true) {} }
+    with_span! {
+        span
+        if (true) {}
+    }
+
+    if true {
+        // comment
+    }
+
+    if true {
+        #[cfg(any())]
+        foo;
+    }
+
+    macro_rules! empty_expansion {
+        () => {};
+    }
+
+    if true {
+        empty_expansion!();
+    }
+
+    macro_rules! empty_repetition {
+        ($($t:tt)*) => {
+            if true {
+                $($t)*
+            }
+        }
+    }
+
+    empty_repetition!();
+
+    // Must be placed into an expression context to not be interpreted as a block
+    if { maybe_side_effect() } {}
+    // Would be a block followed by `&&true` - a double reference to `true`
+    if { maybe_side_effect() } && true {}
+
+    // Don't leave trailing attributes
+    #[allow(unused)]
+    if true {}
+
+    let () = if maybe_side_effect() {};
+}
diff --git a/src/tools/clippy/tests/ui/needless_if.stderr b/src/tools/clippy/tests/ui/needless_if.stderr
new file mode 100644
index 00000000000..5cb42c36921
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_if.stderr
@@ -0,0 +1,65 @@
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:28:5
+   |
+LL |     if (true) {}
+   |     ^^^^^^^^^^^^ help: you can remove it
+   |
+   = note: `-D clippy::needless-if` implied by `-D warnings`
+
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:30:5
+   |
+LL |     if maybe_side_effect() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `maybe_side_effect();`
+
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:35:5
+   |
+LL | /     if {
+LL | |         return;
+LL | |     } {}
+   | |________^
+   |
+help: you can remove it
+   |
+LL ~     ({
+LL +         return;
+LL +     });
+   |
+
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:47:5
+   |
+LL | /     if {
+LL | |         if let true = true && true { true } else { false }
+LL | |     } && true
+LL | |     {}
+   | |______^
+   |
+help: you can remove it
+   |
+LL ~     ({
+LL +         if let true = true && true { true } else { false }
+LL +     } && true);
+   |
+
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:85:5
+   |
+LL |     if { maybe_side_effect() } {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });`
+
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:87:5
+   |
+LL |     if { maybe_side_effect() } && true {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);`
+
+error: this `if` branch is empty
+  --> $DIR/needless_if.rs:91:5
+   |
+LL |     if true {}
+   |     ^^^^^^^^^^ help: you can remove it: `true;`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_late_init.fixed b/src/tools/clippy/tests/ui/needless_late_init.fixed
index 92f7b3f777a..933dd8bed2a 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.fixed
+++ b/src/tools/clippy/tests/ui/needless_late_init.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![feature(let_chains)]
 #![allow(unused)]
 #![allow(
@@ -8,7 +8,8 @@
     clippy::let_and_return,
     clippy::let_unit_value,
     clippy::nonminimal_bool,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/needless_late_init.rs b/src/tools/clippy/tests/ui/needless_late_init.rs
index be378c42f95..ba3a04e0825 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.rs
+++ b/src/tools/clippy/tests/ui/needless_late_init.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![feature(let_chains)]
 #![allow(unused)]
 #![allow(
@@ -8,7 +8,8 @@
     clippy::let_and_return,
     clippy::let_unit_value,
     clippy::nonminimal_bool,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr
index eff782f8bf1..78ba8e11c57 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.stderr
+++ b/src/tools/clippy/tests/ui/needless_late_init.stderr
@@ -1,5 +1,5 @@
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:27:5
+  --> $DIR/needless_late_init.rs:28:5
    |
 LL |     let a;
    |     ^^^^^^ created here
@@ -13,7 +13,7 @@ LL |     let a = "zero";
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:30:5
+  --> $DIR/needless_late_init.rs:31:5
    |
 LL |     let b;
    |     ^^^^^^ created here
@@ -27,7 +27,7 @@ LL |     let b = 1;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:31:5
+  --> $DIR/needless_late_init.rs:32:5
    |
 LL |     let c;
    |     ^^^^^^ created here
@@ -41,7 +41,7 @@ LL |     let c = 2;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:35:5
+  --> $DIR/needless_late_init.rs:36:5
    |
 LL |     let d: usize;
    |     ^^^^^^^^^^^^^ created here
@@ -54,7 +54,7 @@ LL |     let d: usize = 1;
    |     ~~~~~~~~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:38:5
+  --> $DIR/needless_late_init.rs:39:5
    |
 LL |     let e;
    |     ^^^^^^ created here
@@ -67,7 +67,7 @@ LL |     let e = format!("{}", d);
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:43:5
+  --> $DIR/needless_late_init.rs:44:5
    |
 LL |     let a;
    |     ^^^^^^
@@ -88,7 +88,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:52:5
+  --> $DIR/needless_late_init.rs:53:5
    |
 LL |     let b;
    |     ^^^^^^
@@ -109,7 +109,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:59:5
+  --> $DIR/needless_late_init.rs:60:5
    |
 LL |     let d;
    |     ^^^^^^
@@ -130,7 +130,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:67:5
+  --> $DIR/needless_late_init.rs:68:5
    |
 LL |     let e;
    |     ^^^^^^
@@ -151,7 +151,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:74:5
+  --> $DIR/needless_late_init.rs:75:5
    |
 LL |     let f;
    |     ^^^^^^
@@ -167,7 +167,7 @@ LL +         1 => "three",
    |
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:80:5
+  --> $DIR/needless_late_init.rs:81:5
    |
 LL |     let g: usize;
    |     ^^^^^^^^^^^^^
@@ -187,7 +187,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:88:5
+  --> $DIR/needless_late_init.rs:89:5
    |
 LL |     let x;
    |     ^^^^^^ created here
@@ -201,7 +201,7 @@ LL |     let x = 1;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:92:5
+  --> $DIR/needless_late_init.rs:93:5
    |
 LL |     let x;
    |     ^^^^^^ created here
@@ -215,7 +215,7 @@ LL |     let x = SignificantDrop;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:96:5
+  --> $DIR/needless_late_init.rs:97:5
    |
 LL |     let x;
    |     ^^^^^^ created here
@@ -229,7 +229,7 @@ LL |     let x = SignificantDrop;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:115:5
+  --> $DIR/needless_late_init.rs:116:5
    |
 LL |     let a;
    |     ^^^^^^
@@ -250,7 +250,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:132:5
+  --> $DIR/needless_late_init.rs:133:5
    |
 LL |     let a;
    |     ^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
index 7b99042f744..302a3f9edbe 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::needless_lifetimes)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index 6fcf1efc2ee..b15477c92e8 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::needless_lifetimes)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
index 86acc4e0046..0da67b600a3 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
@@ -1,8 +1,8 @@
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:18:1
+  --> $DIR/needless_lifetimes.rs:18:23
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^  ^^       ^^          ^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 help: elide the lifetimes
@@ -12,10 +12,10 @@ LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:20:1
+  --> $DIR/needless_lifetimes.rs:20:24
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^  ^^       ^^          ^^
    |
 help: elide the lifetimes
    |
@@ -24,10 +24,10 @@ LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:30:1
+  --> $DIR/needless_lifetimes.rs:30:15
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               ^^      ^^                 ^^
    |
 help: elide the lifetimes
    |
@@ -36,10 +36,10 @@ LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:42:1
+  --> $DIR/needless_lifetimes.rs:42:31
    |
 LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^                  ^^
    |
 help: elide the lifetimes
    |
@@ -48,10 +48,10 @@ LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:49:1
+  --> $DIR/needless_lifetimes.rs:49:27
    |
 LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -60,10 +60,10 @@ LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:66:1
+  --> $DIR/needless_lifetimes.rs:66:26
    |
 LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^                  ^^
    |
 help: elide the lifetimes
    |
@@ -72,10 +72,10 @@ LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:73:1
+  --> $DIR/needless_lifetimes.rs:73:22
    |
 LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -84,10 +84,10 @@ LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:82:1
+  --> $DIR/needless_lifetimes.rs:82:21
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^      ^^                        ^^
    |
 help: elide the lifetimes
    |
@@ -96,10 +96,10 @@ LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:87:1
+  --> $DIR/needless_lifetimes.rs:87:28
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^         ^^                        ^^
    |
 help: elide the lifetimes
    |
@@ -108,10 +108,10 @@ LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
    |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:99:1
+  --> $DIR/needless_lifetimes.rs:99:21
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^  ^^          ^^        ^^
    |
 help: elide the lifetimes
    |
@@ -120,10 +120,10 @@ LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:123:1
+  --> $DIR/needless_lifetimes.rs:123:15
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               ^^               ^^                   ^^
    |
 help: elide the lifetimes
    |
@@ -132,10 +132,10 @@ LL + fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> $DIR/needless_lifetimes.rs:153:5
+  --> $DIR/needless_lifetimes.rs:153:21
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -144,10 +144,10 @@ LL +     fn self_and_out(&self) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 't
-  --> $DIR/needless_lifetimes.rs:160:5
+  --> $DIR/needless_lifetimes.rs:160:30
    |
 LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^                 ^^
    |
 help: elide the lifetimes
    |
@@ -156,10 +156,10 @@ LL +     fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> $DIR/needless_lifetimes.rs:167:5
+  --> $DIR/needless_lifetimes.rs:167:26
    |
 LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -168,10 +168,10 @@ LL +     fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's, 't
-  --> $DIR/needless_lifetimes.rs:171:5
+  --> $DIR/needless_lifetimes.rs:171:29
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^  ^^   ^^            ^^
    |
 help: elide the lifetimes
    |
@@ -180,10 +180,10 @@ LL +     fn distinct_self_and_in(&self, _x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:190:1
+  --> $DIR/needless_lifetimes.rs:190:19
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^            ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -192,10 +192,10 @@ LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:208:1
+  --> $DIR/needless_lifetimes.rs:208:25
    |
 LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^                ^^
    |
 help: elide the lifetimes
    |
@@ -204,10 +204,10 @@ LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:216:1
+  --> $DIR/needless_lifetimes.rs:216:21
    |
 LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^             ^^
    |
 help: elide the lifetimes
    |
@@ -216,10 +216,10 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:231:1
+  --> $DIR/needless_lifetimes.rs:231:22
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^         ^^               ^^
    |
 help: elide the lifetimes
    |
@@ -228,10 +228,10 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:237:1
+  --> $DIR/needless_lifetimes.rs:237:18
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^                 ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -240,10 +240,10 @@ LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:255:1
+  --> $DIR/needless_lifetimes.rs:255:24
    |
 LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^                     ^^
    |
 help: elide the lifetimes
    |
@@ -252,10 +252,10 @@ LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:263:1
+  --> $DIR/needless_lifetimes.rs:263:20
    |
 LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^             ^^
    |
 help: elide the lifetimes
    |
@@ -264,10 +264,10 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:267:1
+  --> $DIR/needless_lifetimes.rs:267:30
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^         ^^          ^
    |
 help: elide the lifetimes
    |
@@ -276,10 +276,10 @@ LL + fn named_input_elided_output(_arg: &str) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:275:1
+  --> $DIR/needless_lifetimes.rs:275:19
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^                                ^^
    |
 help: elide the lifetimes
    |
@@ -288,10 +288,10 @@ LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:311:1
+  --> $DIR/needless_lifetimes.rs:311:24
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^      ^^             ^^
    |
 help: elide the lifetimes
    |
@@ -300,10 +300,10 @@ LL + fn out_return_type_lts(e: &str) -> Cow<'_> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:318:9
+  --> $DIR/needless_lifetimes.rs:318:24
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -312,10 +312,10 @@ LL +         fn needless_lt(x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:322:9
+  --> $DIR/needless_lifetimes.rs:322:24
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -324,10 +324,10 @@ LL +         fn needless_lt(_x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:335:9
+  --> $DIR/needless_lifetimes.rs:335:16
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^   ^^                     ^^
    |
 help: elide the lifetimes
    |
@@ -336,10 +336,10 @@ LL +         fn baz(&self) -> impl Foo + '_ {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:367:5
+  --> $DIR/needless_lifetimes.rs:367:55
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                       ^^      ^^                                    ^^
    |
 help: elide the lifetimes
    |
@@ -348,10 +348,10 @@ LL +     fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:376:5
+  --> $DIR/needless_lifetimes.rs:376:26
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^                           ^^                ^^
    |
 help: elide the lifetimes
    |
@@ -360,10 +360,10 @@ LL +     fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:388:5
+  --> $DIR/needless_lifetimes.rs:388:32
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                ^^         ^^                ^^
    |
 help: elide the lifetimes
    |
@@ -372,10 +372,10 @@ LL +     fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:403:5
+  --> $DIR/needless_lifetimes.rs:403:28
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^      ^^                               ^^
    |
 help: elide the lifetimes
    |
@@ -384,10 +384,10 @@ LL +     fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:416:5
+  --> $DIR/needless_lifetimes.rs:416:28
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -396,10 +396,10 @@ LL +     fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:419:5
+  --> $DIR/needless_lifetimes.rs:419:28
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -408,10 +408,10 @@ LL +     fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:441:9
+  --> $DIR/needless_lifetimes.rs:441:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -420,10 +420,10 @@ LL +         fn implicit(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:444:9
+  --> $DIR/needless_lifetimes.rs:444:25
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^   ^^               ^^
    |
 help: elide the lifetimes
    |
@@ -432,10 +432,10 @@ LL +         fn implicit_mut(&mut self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:455:9
+  --> $DIR/needless_lifetimes.rs:455:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^                          ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -444,10 +444,10 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:461:9
+  --> $DIR/needless_lifetimes.rs:461:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -456,10 +456,10 @@ LL +         fn implicit(&self) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:462:9
+  --> $DIR/needless_lifetimes.rs:462:30
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -468,10 +468,10 @@ LL +         fn implicit_provided(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:471:9
+  --> $DIR/needless_lifetimes.rs:471:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^                          ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -480,10 +480,10 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:472:9
+  --> $DIR/needless_lifetimes.rs:472:40
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        ^^                          ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -492,10 +492,10 @@ LL +         fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:481:5
+  --> $DIR/needless_lifetimes.rs:481:12
    |
 LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -504,10 +504,10 @@ LL +     fn foo(x: &u8, y: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:483:5
+  --> $DIR/needless_lifetimes.rs:483:12
    |
 LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -516,10 +516,10 @@ LL +     fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:490:5
+  --> $DIR/needless_lifetimes.rs:490:18
    |
 LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^      ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -528,10 +528,10 @@ LL +     fn one_input(x: &u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:495:5
+  --> $DIR/needless_lifetimes.rs:495:42
    |
 LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          ^^          ^^
    |
 help: elide the lifetimes
    |
@@ -540,10 +540,10 @@ LL +     fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8)
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:511:9
+  --> $DIR/needless_lifetimes.rs:511:22
    |
 LL |         fn one_input<'a>(x: &'a u8) -> &'a u8 {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^      ^^         ^^
    |
    = note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: elide the lifetimes
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
index 70015fccf9e..ec981ad97e3 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
@@ -2,6 +2,7 @@
 
 #![allow(unused)]
 #![warn(clippy::needless_option_as_deref)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // should lint
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.rs b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
index e2e35360cb3..6360874f623 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.rs
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
@@ -2,6 +2,7 @@
 
 #![allow(unused)]
 #![warn(clippy::needless_option_as_deref)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // should lint
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.stderr b/src/tools/clippy/tests/ui/needless_option_as_deref.stderr
index bc07db5b38e..20d28a968c9 100644
--- a/src/tools/clippy/tests/ui/needless_option_as_deref.stderr
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.stderr
@@ -1,5 +1,5 @@
 error: derefed type is same as origin
-  --> $DIR/needless_option_as_deref.rs:8:29
+  --> $DIR/needless_option_as_deref.rs:9:29
    |
 LL |     let _: Option<&usize> = Some(&1).as_deref();
    |                             ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)`
@@ -7,13 +7,13 @@ LL |     let _: Option<&usize> = Some(&1).as_deref();
    = note: `-D clippy::needless-option-as-deref` implied by `-D warnings`
 
 error: derefed type is same as origin
-  --> $DIR/needless_option_as_deref.rs:9:33
+  --> $DIR/needless_option_as_deref.rs:10:33
    |
 LL |     let _: Option<&mut usize> = Some(&mut 1).as_deref_mut();
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)`
 
 error: derefed type is same as origin
-  --> $DIR/needless_option_as_deref.rs:13:13
+  --> $DIR/needless_option_as_deref.rs:14:13
    |
 LL |     let _ = x.as_deref_mut();
    |             ^^^^^^^^^^^^^^^^ help: try this: `x`
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value_proc_macro.rs b/src/tools/clippy/tests/ui/needless_pass_by_value_proc_macro.rs
index 78a0e92d179..c603163c145 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_value_proc_macro.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_value_proc_macro.rs
@@ -1,4 +1,3 @@
-#![crate_type = "proc-macro"]
 #![warn(clippy::needless_pass_by_value)]
 
 extern crate proc_macro;
diff --git a/src/tools/clippy/tests/ui/needless_pub_self.fixed b/src/tools/clippy/tests/ui/needless_pub_self.fixed
new file mode 100644
index 00000000000..672b4c318a8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_pub_self.fixed
@@ -0,0 +1,33 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
+#![warn(clippy::needless_pub_self)]
+#![no_main]
+#![rustfmt::skip] // rustfmt will remove `in`, understandable
+                  // but very annoying for our purposes!
+
+#[macro_use]
+extern crate proc_macros;
+
+ fn a() {}
+ fn b() {}
+
+pub fn c() {}
+mod a {
+    pub(in super) fn d() {}
+    pub(super) fn e() {}
+     fn f() {}
+}
+
+external! {
+    pub(self) fn g() {}
+    pub(in self) fn h() {}
+}
+with_span! {
+    span
+    pub(self) fn i() {}
+    pub(in self) fn j() {}
+}
+
+// not really anything more to test. just a really simple lint overall
diff --git a/src/tools/clippy/tests/ui/needless_pub_self.rs b/src/tools/clippy/tests/ui/needless_pub_self.rs
new file mode 100644
index 00000000000..5ac1edf8e99
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_pub_self.rs
@@ -0,0 +1,33 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
+#![warn(clippy::needless_pub_self)]
+#![no_main]
+#![rustfmt::skip] // rustfmt will remove `in`, understandable
+                  // but very annoying for our purposes!
+
+#[macro_use]
+extern crate proc_macros;
+
+pub(self) fn a() {}
+pub(in self) fn b() {}
+
+pub fn c() {}
+mod a {
+    pub(in super) fn d() {}
+    pub(super) fn e() {}
+    pub(self) fn f() {}
+}
+
+external! {
+    pub(self) fn g() {}
+    pub(in self) fn h() {}
+}
+with_span! {
+    span
+    pub(self) fn i() {}
+    pub(in self) fn j() {}
+}
+
+// not really anything more to test. just a really simple lint overall
diff --git a/src/tools/clippy/tests/ui/needless_pub_self.stderr b/src/tools/clippy/tests/ui/needless_pub_self.stderr
new file mode 100644
index 00000000000..3aa2feb5ecd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_pub_self.stderr
@@ -0,0 +1,22 @@
+error: unnecessary `pub(self)`
+  --> $DIR/needless_pub_self.rs:13:1
+   |
+LL | pub(self) fn a() {}
+   | ^^^^^^^^^ help: remove it
+   |
+   = note: `-D clippy::needless-pub-self` implied by `-D warnings`
+
+error: unnecessary `pub(in self)`
+  --> $DIR/needless_pub_self.rs:14:1
+   |
+LL | pub(in self) fn b() {}
+   | ^^^^^^^^^^^^ help: remove it
+
+error: unnecessary `pub(self)`
+  --> $DIR/needless_pub_self.rs:20:5
+   |
+LL |     pub(self) fn f() {}
+   |     ^^^^^^^^^ help: remove it
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.rs b/src/tools/clippy/tests/ui/needless_range_loop.rs
index 921801138a9..a16ef5a5bca 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.rs
+++ b/src/tools/clippy/tests/ui/needless_range_loop.rs
@@ -1,5 +1,9 @@
 #![warn(clippy::needless_range_loop)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap,
+    clippy::useless_vec
+)]
 
 static STATIC: [usize; 4] = [0, 1, 8, 16];
 const CONST: [usize; 4] = [0, 1, 8, 16];
@@ -82,6 +86,29 @@ fn main() {
     for i in 0..2 {
         println!("{}", test[i]);
     }
+
+    // See #601
+    for i in 0..10 {
+        // no error, id_col does not exist outside the loop
+        let mut id_col = [0f64; 10];
+        id_col[i] = 1f64;
+    }
+
+    fn f<T>(_: &T, _: &T) -> bool {
+        unimplemented!()
+    }
+    fn g<T>(_: &mut [T], _: usize, _: usize) {
+        unimplemented!()
+    }
+    for i in 1..vec.len() {
+        if f(&vec[i - 1], &vec[i]) {
+            g(&mut vec, i - 1, i);
+        }
+    }
+
+    for mid in 1..vec.len() {
+        let (_, _) = vec.split_at(mid);
+    }
 }
 
 struct Test {
@@ -94,3 +121,38 @@ impl std::ops::Index<usize> for Test {
         &self.inner[index]
     }
 }
+
+fn partition<T: PartialOrd + Send>(v: &mut [T]) -> usize {
+    let pivot = v.len() - 1;
+    let mut i = 0;
+    for j in 0..pivot {
+        if v[j] <= v[pivot] {
+            v.swap(i, j);
+            i += 1;
+        }
+    }
+    v.swap(i, pivot);
+    i
+}
+
+pub fn manual_copy_same_destination(dst: &mut [i32], d: usize, s: usize) {
+    // Same source and destination - don't trigger lint
+    for i in 0..dst.len() {
+        dst[d + i] = dst[s + i];
+    }
+}
+
+mod issue_2496 {
+    pub trait Handle {
+        fn new_for_index(index: usize) -> Self;
+        fn index(&self) -> usize;
+    }
+
+    pub fn test<H: Handle>() -> H {
+        for x in 0..5 {
+            let next_handle = H::new_for_index(x);
+            println!("{}", next_handle.index());
+        }
+        unimplemented!()
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.stderr b/src/tools/clippy/tests/ui/needless_range_loop.stderr
index cffa19bec3a..8ca6b880cea 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.stderr
+++ b/src/tools/clippy/tests/ui/needless_range_loop.stderr
@@ -1,5 +1,5 @@
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:11:14
+  --> $DIR/needless_range_loop.rs:15:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL |     for <item> in &vec {
    |         ~~~~~~    ~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:20:14
+  --> $DIR/needless_range_loop.rs:24:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     for <item> in &vec {
    |         ~~~~~~    ~~~~
 
 error: the loop variable `j` is only used to index `STATIC`
-  --> $DIR/needless_range_loop.rs:25:14
+  --> $DIR/needless_range_loop.rs:29:14
    |
 LL |     for j in 0..4 {
    |              ^^^^
@@ -33,7 +33,7 @@ LL |     for <item> in &STATIC {
    |         ~~~~~~    ~~~~~~~
 
 error: the loop variable `j` is only used to index `CONST`
-  --> $DIR/needless_range_loop.rs:29:14
+  --> $DIR/needless_range_loop.rs:33:14
    |
 LL |     for j in 0..4 {
    |              ^^^^
@@ -44,7 +44,7 @@ LL |     for <item> in &CONST {
    |         ~~~~~~    ~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> $DIR/needless_range_loop.rs:33:14
+  --> $DIR/needless_range_loop.rs:37:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     for (i, <item>) in vec.iter().enumerate() {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec2`
-  --> $DIR/needless_range_loop.rs:41:14
+  --> $DIR/needless_range_loop.rs:45:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     for <item> in vec2.iter().take(vec.len()) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:45:14
+  --> $DIR/needless_range_loop.rs:49:14
    |
 LL |     for i in 5..vec.len() {
    |              ^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     for <item> in vec.iter().skip(5) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:49:14
+  --> $DIR/needless_range_loop.rs:53:14
    |
 LL |     for i in 0..MAX_LEN {
    |              ^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     for <item> in vec.iter().take(MAX_LEN) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:53:14
+  --> $DIR/needless_range_loop.rs:57:14
    |
 LL |     for i in 0..=MAX_LEN {
    |              ^^^^^^^^^^^
@@ -99,7 +99,7 @@ LL |     for <item> in vec.iter().take(MAX_LEN + 1) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:57:14
+  --> $DIR/needless_range_loop.rs:61:14
    |
 LL |     for i in 5..10 {
    |              ^^^^^
@@ -110,7 +110,7 @@ LL |     for <item> in vec.iter().take(10).skip(5) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop.rs:61:14
+  --> $DIR/needless_range_loop.rs:65:14
    |
 LL |     for i in 5..=10 {
    |              ^^^^^^
@@ -121,7 +121,7 @@ LL |     for <item> in vec.iter().take(10 + 1).skip(5) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> $DIR/needless_range_loop.rs:65:14
+  --> $DIR/needless_range_loop.rs:69:14
    |
 LL |     for i in 5..vec.len() {
    |              ^^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL |     for (i, <item>) in vec.iter().enumerate().skip(5) {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> $DIR/needless_range_loop.rs:69:14
+  --> $DIR/needless_range_loop.rs:73:14
    |
 LL |     for i in 5..10 {
    |              ^^^^^
@@ -143,7 +143,7 @@ LL |     for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> $DIR/needless_range_loop.rs:74:14
+  --> $DIR/needless_range_loop.rs:78:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_range_loop2.rs b/src/tools/clippy/tests/ui/needless_range_loop2.rs
index 7633316e0f8..516d99a3532 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop2.rs
+++ b/src/tools/clippy/tests/ui/needless_range_loop2.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::needless_range_loop)]
+#![allow(clippy::useless_vec)]
 
 fn calc_idx(i: usize) -> usize {
     (i + i + 20) % 4
diff --git a/src/tools/clippy/tests/ui/needless_range_loop2.stderr b/src/tools/clippy/tests/ui/needless_range_loop2.stderr
index 1e6ec5e667a..8c4f5d954a9 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop2.stderr
+++ b/src/tools/clippy/tests/ui/needless_range_loop2.stderr
@@ -1,5 +1,5 @@
 error: the loop variable `i` is only used to index `ns`
-  --> $DIR/needless_range_loop2.rs:10:14
+  --> $DIR/needless_range_loop2.rs:11:14
    |
 LL |     for i in 3..10 {
    |              ^^^^^
@@ -11,7 +11,7 @@ LL |     for <item> in ns.iter().take(10).skip(3) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `ms`
-  --> $DIR/needless_range_loop2.rs:31:14
+  --> $DIR/needless_range_loop2.rs:32:14
    |
 LL |     for i in 0..ms.len() {
    |              ^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     for <item> in &mut ms {
    |         ~~~~~~    ~~~~~~~
 
 error: the loop variable `i` is only used to index `ms`
-  --> $DIR/needless_range_loop2.rs:37:14
+  --> $DIR/needless_range_loop2.rs:38:14
    |
 LL |     for i in 0..ms.len() {
    |              ^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     for <item> in &mut ms {
    |         ~~~~~~    ~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop2.rs:61:14
+  --> $DIR/needless_range_loop2.rs:62:14
    |
 LL |     for i in x..x + 4 {
    |              ^^^^^^^^
@@ -44,7 +44,7 @@ LL |     for <item> in vec.iter_mut().skip(x).take(4) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> $DIR/needless_range_loop2.rs:68:14
+  --> $DIR/needless_range_loop2.rs:69:14
    |
 LL |     for i in x..=x + 4 {
    |              ^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     for <item> in vec.iter_mut().skip(x).take(4 + 1) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `arr`
-  --> $DIR/needless_range_loop2.rs:74:14
+  --> $DIR/needless_range_loop2.rs:75:14
    |
 LL |     for i in 0..3 {
    |              ^^^^
@@ -66,7 +66,7 @@ LL |     for <item> in &arr {
    |         ~~~~~~    ~~~~
 
 error: the loop variable `i` is only used to index `arr`
-  --> $DIR/needless_range_loop2.rs:78:14
+  --> $DIR/needless_range_loop2.rs:79:14
    |
 LL |     for i in 0..2 {
    |              ^^^^
@@ -77,7 +77,7 @@ LL |     for <item> in arr.iter().take(2) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `arr`
-  --> $DIR/needless_range_loop2.rs:82:14
+  --> $DIR/needless_range_loop2.rs:83:14
    |
 LL |     for i in 1..3 {
    |              ^^^^
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.fixed b/src/tools/clippy/tests/ui/needless_raw_string.fixed
new file mode 100644
index 00000000000..6438e46977b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_raw_string.fixed
@@ -0,0 +1,16 @@
+//@run-rustfix
+#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)]
+#![warn(clippy::needless_raw_strings)]
+#![feature(c_str_literals)]
+
+fn main() {
+    "aaa";
+    r#""aaa""#;
+    r#"\s"#;
+    b"aaa";
+    br#""aaa""#;
+    br#"\s"#;
+    c"aaa";
+    cr#""aaa""#;
+    cr#"\s"#;
+}
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.rs b/src/tools/clippy/tests/ui/needless_raw_string.rs
new file mode 100644
index 00000000000..f7ddc68265e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_raw_string.rs
@@ -0,0 +1,16 @@
+//@run-rustfix
+#![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)]
+#![warn(clippy::needless_raw_strings)]
+#![feature(c_str_literals)]
+
+fn main() {
+    r#"aaa"#;
+    r#""aaa""#;
+    r#"\s"#;
+    br#"aaa"#;
+    br#""aaa""#;
+    br#"\s"#;
+    cr#"aaa"#;
+    cr#""aaa""#;
+    cr#"\s"#;
+}
diff --git a/src/tools/clippy/tests/ui/needless_raw_string.stderr b/src/tools/clippy/tests/ui/needless_raw_string.stderr
new file mode 100644
index 00000000000..0179978b7b0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_raw_string.stderr
@@ -0,0 +1,22 @@
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:7:5
+   |
+LL |     r#"aaa"#;
+   |     ^^^^^^^^ help: try: `"aaa"`
+   |
+   = note: `-D clippy::needless-raw-strings` implied by `-D warnings`
+
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:10:5
+   |
+LL |     br#"aaa"#;
+   |     ^^^^^^^^^ help: try: `b"aaa"`
+
+error: unnecessary raw string literal
+  --> $DIR/needless_raw_string.rs:13:5
+   |
+LL |     cr#"aaa"#;
+   |     ^^^^^^^^^ help: try: `c"aaa"`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed
new file mode 100644
index 00000000000..e4d7d8fb017
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed
@@ -0,0 +1,19 @@
+//@run-rustfix
+#![allow(clippy::no_effect, unused)]
+#![warn(clippy::needless_raw_string_hashes)]
+#![feature(c_str_literals)]
+
+fn main() {
+    r#"aaa"#;
+    r#"Hello "world"!"#;
+    r####" "### "## "# "####;
+    r###" "aa" "# "## "###;
+    br#"aaa"#;
+    br#"Hello "world"!"#;
+    br####" "### "## "# "####;
+    br###" "aa" "# "## "###;
+    cr#"aaa"#;
+    cr#"Hello "world"!"#;
+    cr####" "### "## "# "####;
+    cr###" "aa" "# "## "###;
+}
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs
new file mode 100644
index 00000000000..e2d85c52e78
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs
@@ -0,0 +1,19 @@
+//@run-rustfix
+#![allow(clippy::no_effect, unused)]
+#![warn(clippy::needless_raw_string_hashes)]
+#![feature(c_str_literals)]
+
+fn main() {
+    r#"aaa"#;
+    r##"Hello "world"!"##;
+    r######" "### "## "# "######;
+    r######" "aa" "# "## "######;
+    br#"aaa"#;
+    br##"Hello "world"!"##;
+    br######" "### "## "# "######;
+    br######" "aa" "# "## "######;
+    cr#"aaa"#;
+    cr##"Hello "world"!"##;
+    cr######" "### "## "# "######;
+    cr######" "aa" "# "## "######;
+}
diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
new file mode 100644
index 00000000000..dff47a2d042
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr
@@ -0,0 +1,58 @@
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:8:5
+   |
+LL |     r##"Hello "world"!"##;
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: try: `r#"Hello "world"!"#`
+   |
+   = note: `-D clippy::needless-raw-string-hashes` implied by `-D warnings`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:9:5
+   |
+LL |     r######" "### "## "# "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r####" "### "## "# "####`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:10:5
+   |
+LL |     r######" "aa" "# "## "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r###" "aa" "# "## "###`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:12:5
+   |
+LL |     br##"Hello "world"!"##;
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `br#"Hello "world"!"#`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:13:5
+   |
+LL |     br######" "### "## "# "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br####" "### "## "# "####`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:14:5
+   |
+LL |     br######" "aa" "# "## "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `br###" "aa" "# "## "###`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:16:5
+   |
+LL |     cr##"Hello "world"!"##;
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr#"Hello "world"!"#`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:17:5
+   |
+LL |     cr######" "### "## "# "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr####" "### "## "# "####`
+
+error: unnecessary hashes around raw string literal
+  --> $DIR/needless_raw_string_hashes.rs:18:5
+   |
+LL |     cr######" "aa" "# "## "######;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cr###" "aa" "# "## "###`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs
index 29821ff96fc..eb179f30e75 100644
--- a/src/tools/clippy/tests/ui/never_loop.rs
+++ b/src/tools/clippy/tests/ui/never_loop.rs
@@ -1,4 +1,6 @@
+#![feature(inline_const)]
 #![allow(
+    clippy::eq_op,
     clippy::single_match,
     unused_assignments,
     unused_variables,
@@ -295,6 +297,42 @@ pub fn test24() {
     }
 }
 
+// Do not lint, we can evaluate `true` to always succeed thus can short-circuit before the `return`
+pub fn test25() {
+    loop {
+        'label: {
+            if const { true } {
+                break 'label;
+            }
+            return;
+        }
+    }
+}
+
+pub fn test26() {
+    loop {
+        'label: {
+            if 1 == 1 {
+                break 'label;
+            }
+            return;
+        }
+    }
+}
+
+pub fn test27() {
+    loop {
+        'label: {
+            let x = true;
+            // Lints because we cannot prove it's always `true`
+            if x {
+                break 'label;
+            }
+            return;
+        }
+    }
+}
+
 fn main() {
     test1();
     test2();
diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr
index 704d448644e..0446c09cd5b 100644
--- a/src/tools/clippy/tests/ui/never_loop.stderr
+++ b/src/tools/clippy/tests/ui/never_loop.stderr
@@ -1,5 +1,5 @@
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:10:5
+  --> $DIR/never_loop.rs:12:5
    |
 LL | /     loop {
 LL | |         // clippy::never_loop
@@ -13,7 +13,7 @@ LL | |     }
    = note: `#[deny(clippy::never_loop)]` on by default
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:32:5
+  --> $DIR/never_loop.rs:34:5
    |
 LL | /     loop {
 LL | |         // never loops
@@ -23,7 +23,7 @@ LL | |     }
    | |_____^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:52:5
+  --> $DIR/never_loop.rs:54:5
    |
 LL | /     loop {
 LL | |         // never loops
@@ -35,7 +35,7 @@ LL | |     }
    | |_____^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:54:9
+  --> $DIR/never_loop.rs:56:9
    |
 LL | /         while i == 0 {
 LL | |             // never loops
@@ -44,7 +44,7 @@ LL | |         }
    | |_________^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:66:9
+  --> $DIR/never_loop.rs:68:9
    |
 LL | /         loop {
 LL | |             // never loops
@@ -56,7 +56,7 @@ LL | |         }
    | |_________^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:102:5
+  --> $DIR/never_loop.rs:104:5
    |
 LL | /     while let Some(y) = x {
 LL | |         // never loops
@@ -65,7 +65,7 @@ LL | |     }
    | |_____^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:109:5
+  --> $DIR/never_loop.rs:111:5
    |
 LL | /     for x in 0..10 {
 LL | |         // never loops
@@ -82,7 +82,7 @@ LL |     if let Some(x) = (0..10).next() {
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:157:5
+  --> $DIR/never_loop.rs:159:5
    |
 LL | /     'outer: while a {
 LL | |         // never loops
@@ -94,7 +94,7 @@ LL | |     }
    | |_____^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:172:9
+  --> $DIR/never_loop.rs:174:9
    |
 LL | /         while false {
 LL | |             break 'label;
@@ -102,7 +102,7 @@ LL | |         }
    | |_________^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:223:13
+  --> $DIR/never_loop.rs:225:13
    |
 LL |       let _ = loop {
    |  _____________^
@@ -115,7 +115,7 @@ LL | |     };
    | |_____^
 
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:244:5
+  --> $DIR/never_loop.rs:246:5
    |
 LL | /     'a: loop {
 LL | |         'b: {
@@ -126,8 +126,16 @@ LL | |         }
 LL | |     }
    | |_____^
 
+error: sub-expression diverges
+  --> $DIR/never_loop.rs:249:17
+   |
+LL |                 break 'a;
+   |                 ^^^^^^^^
+   |
+   = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
+
 error: this loop never actually loops
-  --> $DIR/never_loop.rs:278:13
+  --> $DIR/never_loop.rs:280:13
    |
 LL | /             for _ in 0..20 {
 LL | |                 break 'block;
@@ -139,5 +147,17 @@ help: if you need the first element of the iterator, try writing
 LL |             if let Some(_) = (0..20).next() {
    |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 12 previous errors
+error: this loop never actually loops
+  --> $DIR/never_loop.rs:324:5
+   |
+LL | /     loop {
+LL | |         'label: {
+LL | |             let x = true;
+LL | |             // Lints because we cannot prove it's always `true`
+...  |
+LL | |         }
+LL | |     }
+   | |_____^
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs
index 1e42e1fbabf..6a726941be8 100644
--- a/src/tools/clippy/tests/ui/no_effect.rs
+++ b/src/tools/clippy/tests/ui/no_effect.rs
@@ -5,7 +5,8 @@
     clippy::deref_addrof,
     clippy::redundant_field_names,
     clippy::uninlined_format_args,
-    clippy::unnecessary_struct_initialization
+    clippy::unnecessary_struct_initialization,
+    clippy::useless_vec
 )]
 
 struct Unit;
diff --git a/src/tools/clippy/tests/ui/no_effect.stderr b/src/tools/clippy/tests/ui/no_effect.stderr
index f10f2bcf2a8..64edfc32504 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
-  --> $DIR/no_effect.rs:97:5
+  --> $DIR/no_effect.rs:98:5
    |
 LL |     0;
    |     ^^
@@ -7,151 +7,151 @@ LL |     0;
    = note: `-D clippy::no-effect` implied by `-D warnings`
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:98:5
+  --> $DIR/no_effect.rs:99:5
    |
 LL |     s2;
    |     ^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:99:5
+  --> $DIR/no_effect.rs:100:5
    |
 LL |     Unit;
    |     ^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:100:5
+  --> $DIR/no_effect.rs:101:5
    |
 LL |     Tuple(0);
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:101:5
+  --> $DIR/no_effect.rs:102:5
    |
 LL |     Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:102:5
+  --> $DIR/no_effect.rs:103:5
    |
 LL |     Struct { ..s };
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:103:5
+  --> $DIR/no_effect.rs:104:5
    |
 LL |     Union { a: 0 };
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:104:5
+  --> $DIR/no_effect.rs:105:5
    |
 LL |     Enum::Tuple(0);
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:105:5
+  --> $DIR/no_effect.rs:106:5
    |
 LL |     Enum::Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:106:5
+  --> $DIR/no_effect.rs:107:5
    |
 LL |     5 + 6;
    |     ^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:107:5
+  --> $DIR/no_effect.rs:108:5
    |
 LL |     *&42;
    |     ^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:108:5
+  --> $DIR/no_effect.rs:109:5
    |
 LL |     &6;
    |     ^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:109:5
+  --> $DIR/no_effect.rs:110:5
    |
 LL |     (5, 6, 7);
    |     ^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:110:5
+  --> $DIR/no_effect.rs:111:5
    |
 LL |     ..;
    |     ^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:111:5
+  --> $DIR/no_effect.rs:112:5
    |
 LL |     5..;
    |     ^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:112:5
+  --> $DIR/no_effect.rs:113:5
    |
 LL |     ..5;
    |     ^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:113:5
+  --> $DIR/no_effect.rs:114:5
    |
 LL |     5..6;
    |     ^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:114:5
+  --> $DIR/no_effect.rs:115:5
    |
 LL |     5..=6;
    |     ^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:115:5
+  --> $DIR/no_effect.rs:116:5
    |
 LL |     [42, 55];
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:116:5
+  --> $DIR/no_effect.rs:117:5
    |
 LL |     [42, 55][1];
    |     ^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:117:5
+  --> $DIR/no_effect.rs:118:5
    |
 LL |     (42, 55).1;
    |     ^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:118:5
+  --> $DIR/no_effect.rs:119:5
    |
 LL |     [42; 55];
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:119:5
+  --> $DIR/no_effect.rs:120:5
    |
 LL |     [42; 55][13];
    |     ^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:121:5
+  --> $DIR/no_effect.rs:122:5
    |
 LL |     || x += 5;
    |     ^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:123:5
+  --> $DIR/no_effect.rs:124:5
    |
 LL |     FooString { s: s };
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:124:5
+  --> $DIR/no_effect.rs:125:5
    |
 LL |     let _unused = 1;
    |     ^^^^^^^^^^^^^^^^
@@ -159,19 +159,19 @@ LL |     let _unused = 1;
    = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:125:5
+  --> $DIR/no_effect.rs:126:5
    |
 LL |     let _penguin = || println!("Some helpful closure");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:126:5
+  --> $DIR/no_effect.rs:127:5
    |
 LL |     let _duck = Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:127:5
+  --> $DIR/no_effect.rs:128:5
    |
 LL |     let _cat = [2, 4, 6, 8][2];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/no_effect_return.rs b/src/tools/clippy/tests/ui/no_effect_return.rs
new file mode 100644
index 00000000000..231dd063ad8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_effect_return.rs
@@ -0,0 +1,81 @@
+#![allow(clippy::unused_unit, dead_code, unused)]
+#![no_main]
+
+use std::ops::ControlFlow;
+
+fn a() -> u32 {
+    {
+        0u32;
+    }
+    0
+}
+
+async fn b() -> u32 {
+    {
+        0u32;
+    }
+    0
+}
+
+type C = i32;
+async fn c() -> C {
+    {
+        0i32 as C;
+    }
+    0
+}
+
+fn d() -> u128 {
+    {
+        // not last stmt
+        0u128;
+        println!("lol");
+    }
+    0
+}
+
+fn e() -> u32 {
+    {
+        // mismatched types
+        0u16;
+    }
+    0
+}
+
+fn f() -> [u16; 1] {
+    {
+        [1u16];
+    }
+    [1]
+}
+
+fn g() -> ControlFlow<()> {
+    {
+        ControlFlow::Break::<()>(());
+    }
+    ControlFlow::Continue(())
+}
+
+fn h() -> Vec<u16> {
+    {
+        // function call, so this won't trigger `no_effect`. not an issue with this change, but the
+        // lint itself (but also not really.)
+        vec![0u16];
+    }
+    vec![]
+}
+
+fn i() -> () {
+    {
+        ();
+    }
+    ()
+}
+
+fn j() {
+    {
+        // does not suggest on function without explicit return type
+        ();
+    }
+    ()
+}
diff --git a/src/tools/clippy/tests/ui/no_effect_return.stderr b/src/tools/clippy/tests/ui/no_effect_return.stderr
new file mode 100644
index 00000000000..779900e1859
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_effect_return.stderr
@@ -0,0 +1,70 @@
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:8:9
+   |
+LL |         0u32;
+   |         -^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+   |
+   = note: `-D clippy::no-effect` implied by `-D warnings`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:15:9
+   |
+LL |         0u32;
+   |         -^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:23:9
+   |
+LL |         0i32 as C;
+   |         -^^^^^^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:31:9
+   |
+LL |         0u128;
+   |         ^^^^^^
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:40:9
+   |
+LL |         0u16;
+   |         ^^^^^
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:47:9
+   |
+LL |         [1u16];
+   |         -^^^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:54:9
+   |
+LL |         ControlFlow::Break::<()>(());
+   |         -^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:70:9
+   |
+LL |         ();
+   |         -^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:78:9
+   |
+LL |         ();
+   |         ^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/non_expressive_names.rs b/src/tools/clippy/tests/ui/non_expressive_names.rs
index 583096ac054..987a4775ef0 100644
--- a/src/tools/clippy/tests/ui/non_expressive_names.rs
+++ b/src/tools/clippy/tests/ui/non_expressive_names.rs
@@ -25,9 +25,9 @@ impl MaybeInst {
 }
 
 fn underscores_and_numbers() {
-    let _1 = 1; //~ERROR Consider a more descriptive name
-    let ____1 = 1; //~ERROR Consider a more descriptive name
-    let __1___2 = 12; //~ERROR Consider a more descriptive name
+    let _1 = 1; //~ERROR: consider choosing a more descriptive name
+    let ____1 = 1; //~ERROR: consider choosing a more descriptive name
+    let __1___2 = 12; //~ERROR: consider choosing a more descriptive name
     let _1_ok = 1;
 }
 
@@ -48,9 +48,9 @@ struct Bar;
 
 impl Bar {
     fn bar() {
-        let _1 = 1;
-        let ____1 = 1;
-        let __1___2 = 12;
+        let _1 = 1; //~ERROR: consider choosing a more descriptive name
+        let ____1 = 1; //~ERROR: consider choosing a more descriptive name
+        let __1___2 = 12; //~ERROR: consider choosing a more descriptive name
         let _1_ok = 1;
     }
 }
diff --git a/src/tools/clippy/tests/ui/non_expressive_names.stderr b/src/tools/clippy/tests/ui/non_expressive_names.stderr
index 116d5da8729..b62748d4989 100644
--- a/src/tools/clippy/tests/ui/non_expressive_names.stderr
+++ b/src/tools/clippy/tests/ui/non_expressive_names.stderr
@@ -1,7 +1,7 @@
 error: consider choosing a more descriptive name
   --> $DIR/non_expressive_names.rs:28:9
    |
-LL |     let _1 = 1; //~ERROR Consider a more descriptive name
+LL |     let _1 = 1;
    |         ^^
    |
    = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings`
@@ -9,13 +9,13 @@ LL |     let _1 = 1; //~ERROR Consider a more descriptive name
 error: consider choosing a more descriptive name
   --> $DIR/non_expressive_names.rs:29:9
    |
-LL |     let ____1 = 1; //~ERROR Consider a more descriptive name
+LL |     let ____1 = 1;
    |         ^^^^^
 
 error: consider choosing a more descriptive name
   --> $DIR/non_expressive_names.rs:30:9
    |
-LL |     let __1___2 = 12; //~ERROR Consider a more descriptive name
+LL |     let __1___2 = 12;
    |         ^^^^^^^
 
 error: consider choosing a more descriptive name
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
index 89d12752834..5d0da8dce67 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
@@ -1,4 +1,4 @@
-//@ignore-windows
+//@ignore-target-windows
 //@run-rustfix
 #![warn(clippy::non_octal_unix_permissions)]
 use std::fs::{DirBuilder, File, OpenOptions, Permissions};
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
index 1b3a322d726..04a3643050e 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
@@ -1,4 +1,4 @@
-//@ignore-windows
+//@ignore-target-windows
 //@run-rustfix
 #![warn(clippy::non_octal_unix_permissions)]
 use std::fs::{DirBuilder, File, OpenOptions, Permissions};
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index fec6b7713ee..e4aa0937b97 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -1,6 +1,7 @@
 #![feature(lint_reasons)]
-#![allow(unused, clippy::diverging_sub_expression)]
+#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     let a: bool = unimplemented!();
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
index 91b5805aa97..e2e4d6477c9 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
@@ -1,5 +1,5 @@
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:11:13
+  --> $DIR/nonminimal_bool.rs:12:13
    |
 LL |     let _ = !true;
    |             ^^^^^ help: try: `false`
@@ -7,43 +7,43 @@ LL |     let _ = !true;
    = note: `-D clippy::nonminimal-bool` implied by `-D warnings`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:12:13
+  --> $DIR/nonminimal_bool.rs:13:13
    |
 LL |     let _ = !false;
    |             ^^^^^^ help: try: `true`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:13:13
+  --> $DIR/nonminimal_bool.rs:14:13
    |
 LL |     let _ = !!a;
    |             ^^^ help: try: `a`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:14:13
+  --> $DIR/nonminimal_bool.rs:15:13
    |
 LL |     let _ = false || a;
    |             ^^^^^^^^^^ help: try: `a`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:18:13
+  --> $DIR/nonminimal_bool.rs:19:13
    |
 LL |     let _ = !(!a && b);
    |             ^^^^^^^^^^ help: try: `a || !b`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:19:13
+  --> $DIR/nonminimal_bool.rs:20:13
    |
 LL |     let _ = !(!a || b);
    |             ^^^^^^^^^^ help: try: `a && !b`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:20:13
+  --> $DIR/nonminimal_bool.rs:21:13
    |
 LL |     let _ = !a && !(b && c);
    |             ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)`
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:28:13
+  --> $DIR/nonminimal_bool.rs:29:13
    |
 LL |     let _ = a == b && c == 5 && a == b;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     let _ = a == b && c == 5;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:29:13
+  --> $DIR/nonminimal_bool.rs:30:13
    |
 LL |     let _ = a == b || c == 5 || a == b;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL |     let _ = a == b || c == 5;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:30:13
+  --> $DIR/nonminimal_bool.rs:31:13
    |
 LL |     let _ = a == b && c == 5 && b == a;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +82,7 @@ LL |     let _ = a == b && c == 5;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:31:13
+  --> $DIR/nonminimal_bool.rs:32:13
    |
 LL |     let _ = a != b || !(a != b || c == d);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL |     let _ = a != b || c != d;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:32:13
+  --> $DIR/nonminimal_bool.rs:33:13
    |
 LL |     let _ = a != b && !(a != b && c == d);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -108,7 +108,7 @@ LL |     let _ = a != b && c != d;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> $DIR/nonminimal_bool.rs:62:8
+  --> $DIR/nonminimal_bool.rs:63:8
    |
 LL |     if matches!(true, true) && true {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)`
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
index 05802a2c865..294f2aa48f1 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(unused, clippy::diverging_sub_expression)]
+#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
 fn methods_with_negation() {
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
index cd5b576fa07..a165368ab17 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(unused, clippy::diverging_sub_expression)]
+#![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
 fn methods_with_negation() {
diff --git a/src/tools/clippy/tests/ui/octal_escapes.stderr b/src/tools/clippy/tests/ui/octal_escapes.stderr
index aa362e96321..63fdfe486e8 100644
--- a/src/tools/clippy/tests/ui/octal_escapes.stderr
+++ b/src/tools/clippy/tests/ui/octal_escapes.stderr
@@ -34,17 +34,17 @@ LL |     let _bad2 = b"/x0033[0m";
 error: octal-looking escape in string literal
   --> $DIR/octal_escapes.rs:6:17
    |
-LL |     let _bad3 = "//033[0m";
+LL |     let _bad3 = "///033[0m";
    |                 ^^^^^^^^^^^
    |
    = help: octal escapes are not supported, `/0` is always a null character
 help: if an octal escape was intended, use the hexadecimal representation instead
    |
-LL |     let _bad3 = "//x1b[0m";
+LL |     let _bad3 = "///x1b[0m";
    |                 ~~~~~~~~~~~
 help: if the null character is intended, disambiguate using
    |
-LL |     let _bad3 = "//x0033[0m";
+LL |     let _bad3 = "///x0033[0m";
    |                 ~~~~~~~~~~~~~
 
 error: octal-looking escape in string literal
diff --git a/src/tools/clippy/tests/ui/ok_expect.rs b/src/tools/clippy/tests/ui/ok_expect.rs
index ff68d38c73b..2047ee689d9 100644
--- a/src/tools/clippy/tests/ui/ok_expect.rs
+++ b/src/tools/clippy/tests/ui/ok_expect.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::unnecessary_literal_unwrap)]
+
 use std::io;
 
 struct MyError(()); // doesn't implement Debug
diff --git a/src/tools/clippy/tests/ui/ok_expect.stderr b/src/tools/clippy/tests/ui/ok_expect.stderr
index 6c40adbb53d..ab9df26ebc3 100644
--- a/src/tools/clippy/tests/ui/ok_expect.stderr
+++ b/src/tools/clippy/tests/ui/ok_expect.stderr
@@ -1,5 +1,5 @@
 error: called `ok().expect()` on a `Result` value
-  --> $DIR/ok_expect.rs:14:5
+  --> $DIR/ok_expect.rs:16:5
    |
 LL |     res.ok().expect("disaster!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     res.ok().expect("disaster!");
    = note: `-D clippy::ok-expect` implied by `-D warnings`
 
 error: called `ok().expect()` on a `Result` value
-  --> $DIR/ok_expect.rs:20:5
+  --> $DIR/ok_expect.rs:22:5
    |
 LL |     res3.ok().expect("whoof");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     res3.ok().expect("whoof");
    = help: you can call `expect()` directly on the `Result`
 
 error: called `ok().expect()` on a `Result` value
-  --> $DIR/ok_expect.rs:22:5
+  --> $DIR/ok_expect.rs:24:5
    |
 LL |     res4.ok().expect("argh");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     res4.ok().expect("argh");
    = help: you can call `expect()` directly on the `Result`
 
 error: called `ok().expect()` on a `Result` value
-  --> $DIR/ok_expect.rs:24:5
+  --> $DIR/ok_expect.rs:26:5
    |
 LL |     res5.ok().expect("oops");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     res5.ok().expect("oops");
    = help: you can call `expect()` directly on the `Result`
 
 error: called `ok().expect()` on a `Result` value
-  --> $DIR/ok_expect.rs:26:5
+  --> $DIR/ok_expect.rs:28:5
    |
 LL |     res6.ok().expect("meh");
    |     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.fixed b/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
index e1c0fa3f7fd..4d1a6a1ab98 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused, clippy::redundant_clone)]
+#![allow(unused, clippy::redundant_clone, clippy::useless_vec)]
 #![warn(clippy::option_as_ref_deref)]
 
 use std::ffi::{CString, OsString};
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.rs b/src/tools/clippy/tests/ui/option_as_ref_deref.rs
index 6f4917fd149..66d5a125036 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.rs
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused, clippy::redundant_clone)]
+#![allow(unused, clippy::redundant_clone, clippy::useless_vec)]
 #![warn(clippy::option_as_ref_deref)]
 
 use std::ffi::{CString, OsString};
diff --git a/src/tools/clippy/tests/ui/option_env_unwrap.rs b/src/tools/clippy/tests/ui/option_env_unwrap.rs
index ee1fe3f1fc0..65a1b467f81 100644
--- a/src/tools/clippy/tests/ui/option_env_unwrap.rs
+++ b/src/tools/clippy/tests/ui/option_env_unwrap.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::option_env_unwrap)]
 #![allow(clippy::map_flatten)]
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 2b8ce5477cc..8e59e4375d2 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -208,3 +208,19 @@ fn issue9742() -> Option<&'static str> {
         _ => None,
     }
 }
+
+mod issue10729 {
+    #![allow(clippy::unit_arg, dead_code)]
+
+    pub fn reproduce(initial: &Option<String>) {
+        // 👇 needs `.as_ref()` because initial is an `&Option<_>`
+        initial.as_ref().map_or({}, |value| do_something(value))
+    }
+
+    pub fn reproduce2(initial: &mut Option<String>) {
+        initial.as_mut().map_or({}, |value| do_something2(value))
+    }
+
+    fn do_something(_value: &str) {}
+    fn do_something2(_value: &mut str) {}
+}
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index cfbec8cb27d..e72edf2a8e3 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -249,3 +249,25 @@ fn issue9742() -> Option<&'static str> {
         _ => None,
     }
 }
+
+mod issue10729 {
+    #![allow(clippy::unit_arg, dead_code)]
+
+    pub fn reproduce(initial: &Option<String>) {
+        // 👇 needs `.as_ref()` because initial is an `&Option<_>`
+        match initial {
+            Some(value) => do_something(value),
+            None => {},
+        }
+    }
+
+    pub fn reproduce2(initial: &mut Option<String>) {
+        match initial {
+            Some(value) => do_something2(value),
+            None => {},
+        }
+    }
+
+    fn do_something(_value: &str) {}
+    fn do_something2(_value: &mut str) {}
+}
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index 91d52fc79b8..aa2da217400 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -271,5 +271,23 @@ error: use Option::map_or instead of an if let/else
 LL |     let _ = if let Ok(a) = res { a + 1 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
 
-error: aborting due to 21 previous errors
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:258:9
+   |
+LL | /         match initial {
+LL | |             Some(value) => do_something(value),
+LL | |             None => {},
+LL | |         }
+   | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))`
+
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:265:9
+   |
+LL | /         match initial {
+LL | |             Some(value) => do_something2(value),
+LL | |             None => {},
+LL | |         }
+   | |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))`
+
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index f723a55f77f..703debb7a26 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -1,7 +1,13 @@
 //@run-rustfix
 #![warn(clippy::or_fun_call)]
 #![allow(dead_code)]
-#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
+#![allow(
+    clippy::borrow_as_ptr,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_wraps,
+    clippy::unnecessary_literal_unwrap,
+    clippy::useless_vec
+)]
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index 61ef6e27f32..bb86fe0d45f 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -1,7 +1,13 @@
 //@run-rustfix
 #![warn(clippy::or_fun_call)]
 #![allow(dead_code)]
-#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
+#![allow(
+    clippy::borrow_as_ptr,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_wraps,
+    clippy::unnecessary_literal_unwrap,
+    clippy::useless_vec
+)]
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index ba3001db7a5..0b5c686bec0 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -1,5 +1,5 @@
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:48:22
+  --> $DIR/or_fun_call.rs:54:22
    |
 LL |     with_constructor.unwrap_or(make());
    |                      ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)`
@@ -7,163 +7,163 @@ LL |     with_constructor.unwrap_or(make());
    = note: `-D clippy::or-fun-call` implied by `-D warnings`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:51:14
+  --> $DIR/or_fun_call.rs:57:14
    |
 LL |     with_new.unwrap_or(Vec::new());
    |              ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:54:21
+  --> $DIR/or_fun_call.rs:60:21
    |
 LL |     with_const_args.unwrap_or(Vec::with_capacity(12));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:57:14
+  --> $DIR/or_fun_call.rs:63:14
    |
 LL |     with_err.unwrap_or(make());
    |              ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:60:19
+  --> $DIR/or_fun_call.rs:66:19
    |
 LL |     with_err_args.unwrap_or(Vec::with_capacity(12));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:63:24
+  --> $DIR/or_fun_call.rs:69:24
    |
 LL |     with_default_trait.unwrap_or(Default::default());
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:66:23
+  --> $DIR/or_fun_call.rs:72:23
    |
 LL |     with_default_type.unwrap_or(u64::default());
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:69:18
+  --> $DIR/or_fun_call.rs:75:18
    |
 LL |     self_default.unwrap_or(<FakeDefault>::default());
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(<FakeDefault>::default)`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:72:18
+  --> $DIR/or_fun_call.rs:78:18
    |
 LL |     real_default.unwrap_or(<FakeDefault as Default>::default());
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:75:14
+  --> $DIR/or_fun_call.rs:81:14
    |
 LL |     with_vec.unwrap_or(vec![]);
    |              ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:78:21
+  --> $DIR/or_fun_call.rs:84:21
    |
 LL |     without_default.unwrap_or(Foo::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
 
 error: use of `or_insert` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:81:19
+  --> $DIR/or_fun_call.rs:87:19
    |
 LL |     map.entry(42).or_insert(String::new());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
 
 error: use of `or_insert` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:84:23
+  --> $DIR/or_fun_call.rs:90:23
    |
 LL |     map_vec.entry(42).or_insert(vec![]);
    |                       ^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
 
 error: use of `or_insert` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:87:21
+  --> $DIR/or_fun_call.rs:93:21
    |
 LL |     btree.entry(42).or_insert(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
 
 error: use of `or_insert` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:90:25
+  --> $DIR/or_fun_call.rs:96:25
    |
 LL |     btree_vec.entry(42).or_insert(vec![]);
    |                         ^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:93:21
+  --> $DIR/or_fun_call.rs:99:21
    |
 LL |     let _ = stringy.unwrap_or(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:101:21
+  --> $DIR/or_fun_call.rs:107:21
    |
 LL |     let _ = Some(1).unwrap_or(map[&1]);
    |                     ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:103:21
+  --> $DIR/or_fun_call.rs:109:21
    |
 LL |     let _ = Some(1).unwrap_or(map[&1]);
    |                     ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
 
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:127:35
+  --> $DIR/or_fun_call.rs:133:35
    |
 LL |     let _ = Some("a".to_string()).or(Some("b".to_string()));
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:166:14
+  --> $DIR/or_fun_call.rs:172:14
    |
 LL |         None.unwrap_or(ptr_to_ref(s));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| ptr_to_ref(s))`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:172:14
+  --> $DIR/or_fun_call.rs:178:14
    |
 LL |         None.unwrap_or(unsafe { ptr_to_ref(s) });
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:174:14
+  --> $DIR/or_fun_call.rs:180:14
    |
 LL |         None.unwrap_or( unsafe { ptr_to_ref(s) }    );
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:188:14
+  --> $DIR/or_fun_call.rs:194:14
    |
 LL |             .unwrap_or(String::new());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:201:14
+  --> $DIR/or_fun_call.rs:207:14
    |
 LL |             .unwrap_or(String::new());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:213:14
+  --> $DIR/or_fun_call.rs:219:14
    |
 LL |             .unwrap_or(String::new());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:224:10
+  --> $DIR/or_fun_call.rs:230:10
    |
 LL |         .unwrap_or(String::new());
    |          ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
 
 error: use of `map_or` followed by a function call
-  --> $DIR/or_fun_call.rs:249:25
+  --> $DIR/or_fun_call.rs:255:25
    |
 LL |         let _ = Some(4).map_or(g(), |v| v);
    |                         ^^^^^^^^^^^^^^^^^^ help: try this: `map_or_else(g, |v| v)`
 
 error: use of `map_or` followed by a function call
-  --> $DIR/or_fun_call.rs:250:25
+  --> $DIR/or_fun_call.rs:256:25
    |
 LL |         let _ = Some(4).map_or(g(), f);
    |                         ^^^^^^^^^^^^^^ help: try this: `map_or_else(g, f)`
diff --git a/src/tools/clippy/tests/ui/or_then_unwrap.fixed b/src/tools/clippy/tests/ui/or_then_unwrap.fixed
index 40badac4424..773dfc3c5d1 100644
--- a/src/tools/clippy/tests/ui/or_then_unwrap.fixed
+++ b/src/tools/clippy/tests/ui/or_then_unwrap.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::or_then_unwrap)]
-#![allow(clippy::map_identity, clippy::let_unit_value)]
+#![allow(clippy::map_identity, clippy::let_unit_value, clippy::unnecessary_literal_unwrap)]
 
 struct SomeStruct;
 impl SomeStruct {
diff --git a/src/tools/clippy/tests/ui/or_then_unwrap.rs b/src/tools/clippy/tests/ui/or_then_unwrap.rs
index 76c9942fe6c..5867e014878 100644
--- a/src/tools/clippy/tests/ui/or_then_unwrap.rs
+++ b/src/tools/clippy/tests/ui/or_then_unwrap.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::or_then_unwrap)]
-#![allow(clippy::map_identity, clippy::let_unit_value)]
+#![allow(clippy::map_identity, clippy::let_unit_value, clippy::unnecessary_literal_unwrap)]
 
 struct SomeStruct;
 impl SomeStruct {
diff --git a/src/tools/clippy/tests/ui/overflow_check_conditional.rs b/src/tools/clippy/tests/ui/overflow_check_conditional.rs
index e1e30114081..14a6b98d07d 100644
--- a/src/tools/clippy/tests/ui/overflow_check_conditional.rs
+++ b/src/tools/clippy/tests/ui/overflow_check_conditional.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::overflow_check_conditional)]
+#![allow(clippy::needless_if)]
 
 fn test(a: u32, b: u32, c: u32) {
     if a + b < a {}
diff --git a/src/tools/clippy/tests/ui/overflow_check_conditional.stderr b/src/tools/clippy/tests/ui/overflow_check_conditional.stderr
index 92d1d8ef911..3ec2298f828 100644
--- a/src/tools/clippy/tests/ui/overflow_check_conditional.stderr
+++ b/src/tools/clippy/tests/ui/overflow_check_conditional.stderr
@@ -1,5 +1,5 @@
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:4:8
+  --> $DIR/overflow_check_conditional.rs:5:8
    |
 LL |     if a + b < a {}
    |        ^^^^^^^^^
@@ -7,43 +7,43 @@ LL |     if a + b < a {}
    = note: `-D clippy::overflow-check-conditional` implied by `-D warnings`
 
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:5:8
+  --> $DIR/overflow_check_conditional.rs:6:8
    |
 LL |     if a > a + b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:6:8
+  --> $DIR/overflow_check_conditional.rs:7:8
    |
 LL |     if a + b < b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:7:8
+  --> $DIR/overflow_check_conditional.rs:8:8
    |
 LL |     if b > a + b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:8:8
+  --> $DIR/overflow_check_conditional.rs:9:8
    |
 LL |     if a - b > b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:9:8
+  --> $DIR/overflow_check_conditional.rs:10:8
    |
 LL |     if b < a - b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:10:8
+  --> $DIR/overflow_check_conditional.rs:11:8
    |
 LL |     if a - b > a {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:11:8
+  --> $DIR/overflow_check_conditional.rs:12:8
    |
 LL |     if a < a - b {}
    |        ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.fixed b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
index 2df87a26d6d..95e184b1de6 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.fixed
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
-#![allow(clippy::eq_op)]
+#![allow(clippy::eq_op, clippy::needless_if)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.rs b/src/tools/clippy/tests/ui/partialeq_to_none.rs
index df6233b9afd..4fa50dcc11b 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.rs
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
-#![allow(clippy::eq_op)]
+#![allow(clippy::eq_op, clippy::needless_if)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/patterns.fixed b/src/tools/clippy/tests/ui/patterns.fixed
index a1da47d84fd..714143e7586 100644
--- a/src/tools/clippy/tests/ui/patterns.fixed
+++ b/src/tools/clippy/tests/ui/patterns.fixed
@@ -1,8 +1,12 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::all)]
 #![allow(unused)]
 #![allow(clippy::uninlined_format_args)]
 
+#[macro_use]
+extern crate proc_macros;
+
 fn main() {
     let v = Some(true);
     let s = [0, 1, 2, 3, 4];
@@ -34,4 +38,11 @@ fn main() {
         ref x => println!("vec: {:?}", x),
         ref y if y == &vec![0] => (),
     }
+    external! {
+        let v = Some(true);
+        match v {
+            Some(x) => (),
+            y @ _ => (),
+        }
+    }
 }
diff --git a/src/tools/clippy/tests/ui/patterns.rs b/src/tools/clippy/tests/ui/patterns.rs
index 399066b813e..153e2640701 100644
--- a/src/tools/clippy/tests/ui/patterns.rs
+++ b/src/tools/clippy/tests/ui/patterns.rs
@@ -1,8 +1,12 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::all)]
 #![allow(unused)]
 #![allow(clippy::uninlined_format_args)]
 
+#[macro_use]
+extern crate proc_macros;
+
 fn main() {
     let v = Some(true);
     let s = [0, 1, 2, 3, 4];
@@ -34,4 +38,11 @@ fn main() {
         ref x @ _ => println!("vec: {:?}", x),
         ref y if y == &vec![0] => (),
     }
+    external! {
+        let v = Some(true);
+        match v {
+            Some(x) => (),
+            y @ _ => (),
+        }
+    }
 }
diff --git a/src/tools/clippy/tests/ui/patterns.stderr b/src/tools/clippy/tests/ui/patterns.stderr
index 2c46b4eb593..276330d21c4 100644
--- a/src/tools/clippy/tests/ui/patterns.stderr
+++ b/src/tools/clippy/tests/ui/patterns.stderr
@@ -1,5 +1,5 @@
 error: the `y @ _` pattern can be written as just `y`
-  --> $DIR/patterns.rs:11:9
+  --> $DIR/patterns.rs:15:9
    |
 LL |         y @ _ => (),
    |         ^^^^^ help: try: `y`
@@ -7,13 +7,13 @@ LL |         y @ _ => (),
    = note: `-D clippy::redundant-pattern` implied by `-D warnings`
 
 error: the `x @ _` pattern can be written as just `x`
-  --> $DIR/patterns.rs:26:9
+  --> $DIR/patterns.rs:30:9
    |
 LL |         ref mut x @ _ => {
    |         ^^^^^^^^^^^^^ help: try: `ref mut x`
 
 error: the `x @ _` pattern can be written as just `x`
-  --> $DIR/patterns.rs:34:9
+  --> $DIR/patterns.rs:38:9
    |
 LL |         ref x @ _ => println!("vec: {:?}", x),
    |         ^^^^^^^^^ help: try: `ref x`
diff --git a/src/tools/clippy/tests/ui/print_with_newline.fixed b/src/tools/clippy/tests/ui/print_with_newline.fixed
new file mode 100644
index 00000000000..6098dea3991
--- /dev/null
+++ b/src/tools/clippy/tests/ui/print_with_newline.fixed
@@ -0,0 +1,58 @@
+// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
+//@run-rustfix
+
+#![allow(clippy::print_literal)]
+#![warn(clippy::print_with_newline)]
+
+fn main() {
+    println!("Hello");
+    println!("Hello {}", "world");
+    println!("Hello {} {}", "world", "#2");
+    println!("{}", 1265);
+    println!();
+
+    // these are all fine
+    print!("");
+    print!("Hello");
+    println!("Hello");
+    println!("Hello\n");
+    println!("Hello {}\n", "world");
+    print!("Issue\n{}", 1265);
+    print!("{}", 1265);
+    print!("\n{}", 1275);
+    print!("\n\n");
+    print!("like eof\n\n");
+    print!("Hello {} {}\n\n", "world", "#2");
+    println!("\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
+    println!("\nbla\n\n"); // #3126
+
+    // Escaping
+    print!("\\n"); // #3514
+    println!("\\"); // should fail
+    print!("\\\\n");
+
+    // Raw strings
+    print!(r"\n"); // #3778
+
+    // Literal newlines should also fail
+    println!(
+        
+    );
+    println!(
+        
+    );
+
+    // Don't warn on CRLF (#4208)
+    print!("\r\n");
+    print!("foo\r\n");
+    println!("\\r"); // should fail
+    print!("foo\rbar\n");
+
+    // Ignore expanded format strings
+    macro_rules! newline {
+        () => {
+            "\n"
+        };
+    }
+    print!(newline!());
+}
diff --git a/src/tools/clippy/tests/ui/print_with_newline.rs b/src/tools/clippy/tests/ui/print_with_newline.rs
index ff79ca75ffa..d9c7acc2748 100644
--- a/src/tools/clippy/tests/ui/print_with_newline.rs
+++ b/src/tools/clippy/tests/ui/print_with_newline.rs
@@ -47,7 +47,7 @@ fn main() {
     // Don't warn on CRLF (#4208)
     print!("\r\n");
     print!("foo\r\n");
-    print!("\\r\n"); //~ ERROR
+    print!("\\r\n"); // should fail
     print!("foo\rbar\n");
 
     // Ignore expanded format strings
diff --git a/src/tools/clippy/tests/ui/print_with_newline.stderr b/src/tools/clippy/tests/ui/print_with_newline.stderr
index b9f5675faec..b97711e777d 100644
--- a/src/tools/clippy/tests/ui/print_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/print_with_newline.stderr
@@ -62,13 +62,13 @@ LL +     println!();
 error: using `print!()` with a format string that ends in a single newline
   --> $DIR/print_with_newline.rs:31:5
    |
-LL |     print!("//n"); // should fail
+LL |     print!("///n"); // should fail
    |     ^^^^^^^^^^^^^^
    |
 help: use `println!` instead
    |
-LL -     print!("//n"); // should fail
-LL +     println!("/"); // should fail
+LL -     print!("///n"); // should fail
+LL +     println!("//"); // should fail
    |
 
 error: using `print!()` with a format string that ends in a single newline
@@ -104,13 +104,13 @@ LL ~
 error: using `print!()` with a format string that ends in a single newline
   --> $DIR/print_with_newline.rs:50:5
    |
-LL |     print!("/r/n"); //~ ERROR
+LL |     print!("//r/n"); // should fail
    |     ^^^^^^^^^^^^^^^
    |
 help: use `println!` instead
    |
-LL -     print!("/r/n"); //~ ERROR
-LL +     println!("/r"); //~ ERROR
+LL -     print!("//r/n"); // should fail
+LL +     println!("//r"); // should fail
    |
 
 error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/proc_macro.rs b/src/tools/clippy/tests/ui/proc_macro.rs
index 59914b8b8f6..b77874034d0 100644
--- a/src/tools/clippy/tests/ui/proc_macro.rs
+++ b/src/tools/clippy/tests/ui/proc_macro.rs
@@ -1,5 +1,4 @@
 //! Check that we correctly lint procedural macros.
-#![crate_type = "proc-macro"]
 
 extern crate proc_macro;
 
diff --git a/src/tools/clippy/tests/ui/proc_macro.stderr b/src/tools/clippy/tests/ui/proc_macro.stderr
index c795f6ad0d2..d912b502755 100644
--- a/src/tools/clippy/tests/ui/proc_macro.stderr
+++ b/src/tools/clippy/tests/ui/proc_macro.stderr
@@ -1,5 +1,5 @@
 error: approximate value of `f{32, 64}::consts::PI` found
-  --> $DIR/proc_macro.rs:10:14
+  --> $DIR/proc_macro.rs:9:14
    |
 LL |     let _x = 3.14;
    |              ^^^^
diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs
index 5f54101ca15..709f74ee6aa 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.rs
+++ b/src/tools/clippy/tests/ui/ptr_arg.rs
@@ -1,5 +1,10 @@
 #![feature(lint_reasons)]
-#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)]
+#![allow(
+    unused,
+    clippy::many_single_char_names,
+    clippy::needless_lifetimes,
+    clippy::redundant_clone
+)]
 #![warn(clippy::ptr_arg)]
 
 use std::borrow::Cow;
@@ -235,3 +240,29 @@ fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
     takes_dyn(b);
     takes_dyn(c);
 }
+
+mod issue_9218 {
+    use std::borrow::Cow;
+
+    fn cow_non_elided_lifetime<'a>(input: &Cow<'a, str>) -> &'a str {
+        todo!()
+    }
+
+    // This one has an anonymous lifetime so it's not okay
+    fn cow_elided_lifetime<'a>(input: &'a Cow<str>) -> &'a str {
+        todo!()
+    }
+
+    // These two's return types don't use use 'a so it's not okay
+    fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str {
+        todo!()
+    }
+    fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
+        todo!()
+    }
+
+    // Inferred to be `&'a str`, afaik.
+    fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str {
+        todo!()
+    }
+}
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 6b4de98ce88..d663b070b9c 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -1,5 +1,5 @@
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:8:14
+  --> $DIR/ptr_arg.rs:13:14
    |
 LL | fn do_vec(x: &Vec<i64>) {
    |              ^^^^^^^^^ help: change this to: `&[i64]`
@@ -7,43 +7,43 @@ LL | fn do_vec(x: &Vec<i64>) {
    = note: `-D clippy::ptr-arg` implied by `-D warnings`
 
 error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:12:18
+  --> $DIR/ptr_arg.rs:17:18
    |
 LL | fn do_vec_mut(x: &mut Vec<i64>) {
    |                  ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:16:14
+  --> $DIR/ptr_arg.rs:21:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
 error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:20:18
+  --> $DIR/ptr_arg.rs:25:18
    |
 LL | fn do_str_mut(x: &mut String) {
    |                  ^^^^^^^^^^^ help: change this to: `&mut str`
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:24:15
+  --> $DIR/ptr_arg.rs:29:15
    |
 LL | fn do_path(x: &PathBuf) {
    |               ^^^^^^^^ help: change this to: `&Path`
 
 error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:28:19
+  --> $DIR/ptr_arg.rs:33:19
    |
 LL | fn do_path_mut(x: &mut PathBuf) {
    |                   ^^^^^^^^^^^^ help: change this to: `&mut Path`
 
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:36:18
+  --> $DIR/ptr_arg.rs:41:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:49:14
+  --> $DIR/ptr_arg.rs:54:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
@@ -60,7 +60,7 @@ LL ~     x.to_owned()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:58:18
+  --> $DIR/ptr_arg.rs:63:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
@@ -76,7 +76,7 @@ LL ~     x.to_owned()
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:66:19
+  --> $DIR/ptr_arg.rs:71:19
    |
 LL | fn path_cloned(x: &PathBuf) -> PathBuf {
    |                   ^^^^^^^^
@@ -92,7 +92,7 @@ LL ~     x.to_path_buf()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:74:44
+  --> $DIR/ptr_arg.rs:79:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
@@ -106,19 +106,19 @@ LL ~     let c = y;
    |
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:88:25
+  --> $DIR/ptr_arg.rs:93:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:117:66
+  --> $DIR/ptr_arg.rs:122:66
    |
 LL |     fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {}
    |                                                                  ^^^^^^^ help: change this to: `&str`
 
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:146:21
+  --> $DIR/ptr_arg.rs:151:21
    |
 LL |     fn foo_vec(vec: &Vec<u8>) {
    |                     ^^^^^^^^
@@ -131,7 +131,7 @@ LL ~         let _ = vec.to_owned().clone();
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:151:23
+  --> $DIR/ptr_arg.rs:156:23
    |
 LL |     fn foo_path(path: &PathBuf) {
    |                       ^^^^^^^^
@@ -144,7 +144,7 @@ LL ~         let _ = path.to_path_buf().clone();
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:156:21
+  --> $DIR/ptr_arg.rs:161:21
    |
 LL |     fn foo_str(str: &PathBuf) {
    |                     ^^^^^^^^
@@ -157,28 +157,46 @@ LL ~         let _ = str.to_path_buf().clone();
    |
 
 error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:162:29
+  --> $DIR/ptr_arg.rs:167:29
    |
 LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) {
    |                             ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
 
 error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:224:17
+  --> $DIR/ptr_arg.rs:229:17
    |
 LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
    |                 ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
 
 error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:224:35
+  --> $DIR/ptr_arg.rs:229:35
    |
 LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
    |                                   ^^^^^^^^^^^ help: change this to: `&mut str`
 
 error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:224:51
+  --> $DIR/ptr_arg.rs:229:51
    |
 LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
    |                                                   ^^^^^^^^^^^^ help: change this to: `&mut Path`
 
-error: aborting due to 20 previous errors
+error: using a reference to `Cow` is not recommended
+  --> $DIR/ptr_arg.rs:252:39
+   |
+LL |     fn cow_elided_lifetime<'a>(input: &'a Cow<str>) -> &'a str {
+   |                                       ^^^^^^^^^^^^ help: change this to: `&str`
+
+error: using a reference to `Cow` is not recommended
+  --> $DIR/ptr_arg.rs:257:36
+   |
+LL |     fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str {
+   |                                    ^^^^^^^^^^^^^^^^ help: change this to: `&str`
+
+error: using a reference to `Cow` is not recommended
+  --> $DIR/ptr_arg.rs:260:40
+   |
+LL |     fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
+   |                                        ^^^^^^^^^^^^^^^^ help: change this to: `&str`
+
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
index 2c2567d67cd..26a64c861cf 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::ptr_as_ptr)]
 
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.rs b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
index 6000e5c08ac..ea40d494733 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::ptr_as_ptr)]
 
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
index 24de573d083..1ef1809d153 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
@@ -1,18 +1,25 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::ptr_cast_constness)]
+#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)]
 
 extern crate proc_macros;
 use proc_macros::{external, inline_macros};
 
+unsafe fn ptr_to_ref<T, U>(p: *const T, om: *mut U) {
+    let _: &mut T = std::mem::transmute(p.cast_mut());
+    let _ = &mut *p.cast_mut();
+    let _: &T = &*(om as *const T);
+}
+
 #[inline_macros]
 fn main() {
     let ptr: *const u32 = &42_u32;
     let mut_ptr: *mut u32 = &mut 42_u32;
 
-    let _ = ptr as *const i32;
-    let _ = mut_ptr as *mut i32;
+    let _ = ptr as *const u32;
+    let _ = mut_ptr as *mut u32;
 
     // Make sure the lint can handle the difference in their operator precedences.
     unsafe {
@@ -29,10 +36,10 @@ fn main() {
     let _ = ptr_of_array as *const dyn std::fmt::Debug;
 
     // Make sure the lint is triggered inside a macro
-    let _ = inline!($ptr as *const i32);
+    let _ = inline!($ptr as *const u32);
 
     // Do not lint inside macros from external crates
-    let _ = external!($ptr as *const i32);
+    let _ = external!($ptr as *const u32);
 }
 
 #[clippy::msrv = "1.64"]
@@ -41,8 +48,8 @@ fn _msrv_1_64() {
     let mut_ptr: *mut u32 = &mut 42_u32;
 
     // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this
-    let _ = ptr as *mut i32;
-    let _ = mut_ptr as *const i32;
+    let _ = ptr as *mut u32;
+    let _ = mut_ptr as *const u32;
 }
 
 #[clippy::msrv = "1.65"]
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.rs b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
index 63d973a9fca..2c15cd429da 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.rs
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
@@ -1,27 +1,34 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::ptr_cast_constness)]
+#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)]
 
 extern crate proc_macros;
 use proc_macros::{external, inline_macros};
 
+unsafe fn ptr_to_ref<T, U>(p: *const T, om: *mut U) {
+    let _: &mut T = std::mem::transmute(p as *mut T);
+    let _ = &mut *(p as *mut T);
+    let _: &T = &*(om as *const T);
+}
+
 #[inline_macros]
 fn main() {
     let ptr: *const u32 = &42_u32;
     let mut_ptr: *mut u32 = &mut 42_u32;
 
-    let _ = ptr as *const i32;
-    let _ = mut_ptr as *mut i32;
+    let _ = ptr as *const u32;
+    let _ = mut_ptr as *mut u32;
 
     // Make sure the lint can handle the difference in their operator precedences.
     unsafe {
         let ptr_ptr: *const *const u32 = &ptr;
-        let _ = *ptr_ptr as *mut i32;
+        let _ = *ptr_ptr as *mut u32;
     }
 
-    let _ = ptr as *mut i32;
-    let _ = mut_ptr as *const i32;
+    let _ = ptr as *mut u32;
+    let _ = mut_ptr as *const u32;
 
     // Lint this, since pointer::cast_mut and pointer::cast_const have ?Sized
     let ptr_of_array: *const [u32; 4] = &[1, 2, 3, 4];
@@ -29,10 +36,10 @@ fn main() {
     let _ = ptr_of_array as *const dyn std::fmt::Debug;
 
     // Make sure the lint is triggered inside a macro
-    let _ = inline!($ptr as *const i32);
+    let _ = inline!($ptr as *const u32);
 
     // Do not lint inside macros from external crates
-    let _ = external!($ptr as *const i32);
+    let _ = external!($ptr as *const u32);
 }
 
 #[clippy::msrv = "1.64"]
@@ -41,8 +48,8 @@ fn _msrv_1_64() {
     let mut_ptr: *mut u32 = &mut 42_u32;
 
     // `pointer::cast_const` and `pointer::cast_mut` were stabilized in 1.65. Do not lint this
-    let _ = ptr as *mut i32;
-    let _ = mut_ptr as *const i32;
+    let _ = ptr as *mut u32;
+    let _ = mut_ptr as *const u32;
 }
 
 #[clippy::msrv = "1.65"]
@@ -50,6 +57,6 @@ fn _msrv_1_65() {
     let ptr: *const u32 = &42_u32;
     let mut_ptr: *mut u32 = &mut 42_u32;
 
-    let _ = ptr as *mut i32;
-    let _ = mut_ptr as *const i32;
+    let _ = ptr as *mut u32;
+    let _ = mut_ptr as *const u32;
 }
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
index 43816c87c19..0c3ff863685 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
@@ -1,34 +1,46 @@
-error: `as` casting between raw pointers while changing its constness
-  --> $DIR/ptr_cast_constness.rs:20:17
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:11:41
    |
-LL |         let _ = *ptr_ptr as *mut i32;
-   |                 ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()`
+LL |     let _: &mut T = std::mem::transmute(p as *mut T);
+   |                                         ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
    |
    = note: `-D clippy::ptr-cast-constness` implied by `-D warnings`
 
-error: `as` casting between raw pointers while changing its constness
-  --> $DIR/ptr_cast_constness.rs:23:13
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:12:19
+   |
+LL |     let _ = &mut *(p as *mut T);
+   |                   ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
+
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:27:17
+   |
+LL |         let _ = *ptr_ptr as *mut u32;
+   |                 ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()`
+
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:30:13
    |
-LL |     let _ = ptr as *mut i32;
+LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
-error: `as` casting between raw pointers while changing its constness
-  --> $DIR/ptr_cast_constness.rs:24:13
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:31:13
    |
-LL |     let _ = mut_ptr as *const i32;
+LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
-error: `as` casting between raw pointers while changing its constness
-  --> $DIR/ptr_cast_constness.rs:53:13
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:60:13
    |
-LL |     let _ = ptr as *mut i32;
+LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
-error: `as` casting between raw pointers while changing its constness
-  --> $DIR/ptr_cast_constness.rs:54:13
+error: `as` casting between raw pointers while changing only its constness
+  --> $DIR/ptr_cast_constness.rs:61:13
    |
-LL |     let _ = mut_ptr as *const i32;
+LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed b/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
index f69bc131898..6ffa401d761 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(clippy::unnecessary_cast)]
+#![allow(clippy::unnecessary_cast, clippy::useless_vec)]
 
 fn main() {
     let vec = vec![b'a', b'b', b'c'];
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs b/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
index eae36c27729..de1f86cb855 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(clippy::unnecessary_cast)]
+#![allow(clippy::unnecessary_cast, clippy::useless_vec)]
 
 fn main() {
     let vec = vec![b'a', b'b', b'c'];
diff --git a/src/tools/clippy/tests/ui/pub_with_shorthand.fixed b/src/tools/clippy/tests/ui/pub_with_shorthand.fixed
new file mode 100644
index 00000000000..a774faa0a67
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pub_with_shorthand.fixed
@@ -0,0 +1,38 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(custom_inner_attributes)]
+#![allow(clippy::needless_pub_self, unused)]
+#![warn(clippy::pub_with_shorthand)]
+#![no_main]
+#![rustfmt::skip] // rustfmt will remove `in`, understandable
+                  // but very annoying for our purposes!
+
+#[macro_use]
+extern crate proc_macros;
+
+pub(in self) fn a() {}
+pub(in self) fn b() {}
+
+pub fn c() {}
+mod a {
+    pub(in super) fn d() {}
+    pub(in super) fn e() {}
+    pub(in self) fn f() {}
+    pub(in crate) fn k() {}
+    pub(in crate) fn m() {}
+    mod b {
+        pub(in crate::a) fn l() {}
+    }
+}
+
+external! {
+    pub(self) fn g() {}
+    pub(in self) fn h() {}
+}
+with_span! {
+    span
+    pub(self) fn i() {}
+    pub(in self) fn j() {}
+}
+
+// not really anything more to test. just a really simple lint overall
diff --git a/src/tools/clippy/tests/ui/pub_with_shorthand.rs b/src/tools/clippy/tests/ui/pub_with_shorthand.rs
new file mode 100644
index 00000000000..4a4bbc18728
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pub_with_shorthand.rs
@@ -0,0 +1,38 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(custom_inner_attributes)]
+#![allow(clippy::needless_pub_self, unused)]
+#![warn(clippy::pub_with_shorthand)]
+#![no_main]
+#![rustfmt::skip] // rustfmt will remove `in`, understandable
+                  // but very annoying for our purposes!
+
+#[macro_use]
+extern crate proc_macros;
+
+pub(self) fn a() {}
+pub(in self) fn b() {}
+
+pub fn c() {}
+mod a {
+    pub(in super) fn d() {}
+    pub(super) fn e() {}
+    pub(self) fn f() {}
+    pub(crate) fn k() {}
+    pub(in crate) fn m() {}
+    mod b {
+        pub(in crate::a) fn l() {}
+    }
+}
+
+external! {
+    pub(self) fn g() {}
+    pub(in self) fn h() {}
+}
+with_span! {
+    span
+    pub(self) fn i() {}
+    pub(in self) fn j() {}
+}
+
+// not really anything more to test. just a really simple lint overall
diff --git a/src/tools/clippy/tests/ui/pub_with_shorthand.stderr b/src/tools/clippy/tests/ui/pub_with_shorthand.stderr
new file mode 100644
index 00000000000..323b5a23b24
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pub_with_shorthand.stderr
@@ -0,0 +1,28 @@
+error: usage of `pub` without `in`
+  --> $DIR/pub_with_shorthand.rs:13:1
+   |
+LL | pub(self) fn a() {}
+   | ^^^^^^^^^ help: add it: `pub(in self)`
+   |
+   = note: `-D clippy::pub-with-shorthand` implied by `-D warnings`
+
+error: usage of `pub` without `in`
+  --> $DIR/pub_with_shorthand.rs:19:5
+   |
+LL |     pub(super) fn e() {}
+   |     ^^^^^^^^^^ help: add it: `pub(in super)`
+
+error: usage of `pub` without `in`
+  --> $DIR/pub_with_shorthand.rs:20:5
+   |
+LL |     pub(self) fn f() {}
+   |     ^^^^^^^^^ help: add it: `pub(in self)`
+
+error: usage of `pub` without `in`
+  --> $DIR/pub_with_shorthand.rs:21:5
+   |
+LL |     pub(crate) fn k() {}
+   |     ^^^^^^^^^^ help: add it: `pub(in crate)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/pub_without_shorthand.fixed b/src/tools/clippy/tests/ui/pub_without_shorthand.fixed
new file mode 100644
index 00000000000..fdb49ac4d90
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pub_without_shorthand.fixed
@@ -0,0 +1,38 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(custom_inner_attributes)]
+#![allow(clippy::needless_pub_self, unused)]
+#![warn(clippy::pub_without_shorthand)]
+#![no_main]
+#![rustfmt::skip] // rustfmt will remove `in`, understandable
+                  // but very annoying for our purposes!
+
+#[macro_use]
+extern crate proc_macros;
+
+pub(self) fn a() {}
+pub(self) fn b() {}
+
+pub fn c() {}
+mod a {
+    pub(super) fn d() {}
+    pub(super) fn e() {}
+    pub(self) fn f() {}
+    pub(crate) fn k() {}
+    pub(crate) fn m() {}
+    mod b {
+        pub(in crate::a) fn l() {}
+    }
+}
+
+external! {
+    pub(self) fn g() {}
+    pub(in self) fn h() {}
+}
+with_span! {
+    span
+    pub(self) fn i() {}
+    pub(in self) fn j() {}
+}
+
+// not really anything more to test. just a really simple lint overall
diff --git a/src/tools/clippy/tests/ui/pub_without_shorthand.rs b/src/tools/clippy/tests/ui/pub_without_shorthand.rs
new file mode 100644
index 00000000000..1f2ef7ece39
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pub_without_shorthand.rs
@@ -0,0 +1,38 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![feature(custom_inner_attributes)]
+#![allow(clippy::needless_pub_self, unused)]
+#![warn(clippy::pub_without_shorthand)]
+#![no_main]
+#![rustfmt::skip] // rustfmt will remove `in`, understandable
+                  // but very annoying for our purposes!
+
+#[macro_use]
+extern crate proc_macros;
+
+pub(self) fn a() {}
+pub(in self) fn b() {}
+
+pub fn c() {}
+mod a {
+    pub(in super) fn d() {}
+    pub(super) fn e() {}
+    pub(self) fn f() {}
+    pub(crate) fn k() {}
+    pub(in crate) fn m() {}
+    mod b {
+        pub(in crate::a) fn l() {}
+    }
+}
+
+external! {
+    pub(self) fn g() {}
+    pub(in self) fn h() {}
+}
+with_span! {
+    span
+    pub(self) fn i() {}
+    pub(in self) fn j() {}
+}
+
+// not really anything more to test. just a really simple lint overall
diff --git a/src/tools/clippy/tests/ui/pub_without_shorthand.stderr b/src/tools/clippy/tests/ui/pub_without_shorthand.stderr
new file mode 100644
index 00000000000..a18c9bf8934
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pub_without_shorthand.stderr
@@ -0,0 +1,22 @@
+error: usage of `pub` with `in`
+  --> $DIR/pub_without_shorthand.rs:14:1
+   |
+LL | pub(in self) fn b() {}
+   | ^^^^^^^^^^^^ help: remove it: `pub(self)`
+   |
+   = note: `-D clippy::pub-without-shorthand` implied by `-D warnings`
+
+error: usage of `pub` with `in`
+  --> $DIR/pub_without_shorthand.rs:18:5
+   |
+LL |     pub(in super) fn d() {}
+   |     ^^^^^^^^^^^^^ help: remove it: `pub(super)`
+
+error: usage of `pub` with `in`
+  --> $DIR/pub_without_shorthand.rs:22:5
+   |
+LL |     pub(in crate) fn m() {}
+   |     ^^^^^^^^^^^^^ help: remove it: `pub(crate)`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 7f1660f31fa..2d8920ccc42 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -1,4 +1,5 @@
 //@run-rustfix
+#![feature(try_blocks)]
 #![allow(unreachable_code)]
 #![allow(dead_code)]
 #![allow(clippy::unnecessary_wraps)]
@@ -227,6 +228,27 @@ fn pattern() -> Result<(), PatternedError> {
 
 fn main() {}
 
+// `?` is not the same as `return None;` if inside of a try block
+fn issue8628(a: Option<u32>) -> Option<u32> {
+    let b: Option<u32> = try {
+        if a.is_none() {
+            return None;
+        }
+        32
+    };
+    b.or(Some(128))
+}
+
+fn issue6828_nested_body() -> Option<u32> {
+    try {
+        fn f2(a: Option<i32>) -> Option<i32> {
+            a?;
+            Some(32)
+        }
+        123
+    }
+}
+
 // should not lint, `?` operator not available in const context
 const fn issue9175(option: Option<()>) -> Option<()> {
     if option.is_none() {
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index a90eae50ed4..69451c17ee7 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -1,4 +1,5 @@
 //@run-rustfix
+#![feature(try_blocks)]
 #![allow(unreachable_code)]
 #![allow(dead_code)]
 #![allow(clippy::unnecessary_wraps)]
@@ -263,6 +264,31 @@ fn pattern() -> Result<(), PatternedError> {
 
 fn main() {}
 
+// `?` is not the same as `return None;` if inside of a try block
+fn issue8628(a: Option<u32>) -> Option<u32> {
+    let b: Option<u32> = try {
+        if a.is_none() {
+            return None;
+        }
+        32
+    };
+    b.or(Some(128))
+}
+
+fn issue6828_nested_body() -> Option<u32> {
+    try {
+        fn f2(a: Option<i32>) -> Option<i32> {
+            if a.is_none() {
+                return None;
+                // do lint here, the outer `try` is not relevant here
+                // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867
+            }
+            Some(32)
+        }
+        123
+    }
+}
+
 // should not lint, `?` operator not available in const context
 const fn issue9175(option: Option<()>) -> Option<()> {
     if option.is_none() {
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 23172d7e535..2cfd7586308 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -1,5 +1,5 @@
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:7:5
+  --> $DIR/question_mark.rs:8:5
    |
 LL | /     if a.is_none() {
 LL | |         return None;
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::question-mark` implied by `-D warnings`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:52:9
+  --> $DIR/question_mark.rs:53:9
    |
 LL | /         if (self.opt).is_none() {
 LL | |             return None;
@@ -17,7 +17,7 @@ LL | |         }
    | |_________^ help: replace it with: `(self.opt)?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:56:9
+  --> $DIR/question_mark.rs:57:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None
@@ -25,7 +25,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:60:17
+  --> $DIR/question_mark.rs:61:17
    |
 LL |           let _ = if self.opt.is_none() {
    |  _________________^
@@ -36,7 +36,7 @@ LL | |         };
    | |_________^ help: replace it with: `Some(self.opt?)`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:66:17
+  --> $DIR/question_mark.rs:67:17
    |
 LL |           let _ = if let Some(x) = self.opt {
    |  _________________^
@@ -47,7 +47,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:83:9
+  --> $DIR/question_mark.rs:84:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -55,7 +55,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:91:9
+  --> $DIR/question_mark.rs:92:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -63,7 +63,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:99:9
+  --> $DIR/question_mark.rs:100:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -71,7 +71,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:106:26
+  --> $DIR/question_mark.rs:107:26
    |
 LL |           let v: &Vec<_> = if let Some(ref v) = self.opt {
    |  __________________________^
@@ -82,7 +82,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt.as_ref()?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:116:17
+  --> $DIR/question_mark.rs:117:17
    |
 LL |           let v = if let Some(v) = self.opt {
    |  _________________^
@@ -93,7 +93,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:131:5
+  --> $DIR/question_mark.rs:132:5
    |
 LL | /     if f().is_none() {
 LL | |         return None;
@@ -101,13 +101,13 @@ LL | |     }
    | |_____^ help: replace it with: `f()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:143:13
+  --> $DIR/question_mark.rs:144:13
    |
 LL |     let _ = if let Ok(x) = x { x } else { return x };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:145:5
+  --> $DIR/question_mark.rs:146:5
    |
 LL | /     if x.is_err() {
 LL | |         return x;
@@ -115,7 +115,7 @@ LL | |     }
    | |_____^ help: replace it with: `x?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:196:5
+  --> $DIR/question_mark.rs:197:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -123,12 +123,22 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:203:5
+  --> $DIR/question_mark.rs:204:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
 LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
-error: aborting due to 15 previous errors
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:281:13
+   |
+LL | /             if a.is_none() {
+LL | |                 return None;
+LL | |                 // do lint here, the outer `try` is not relevant here
+LL | |                 // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867
+LL | |             }
+   | |_____________^ help: replace it with: `a?;`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/range.rs b/src/tools/clippy/tests/ui/range.rs
index 628282509c1..46edf0921bf 100644
--- a/src/tools/clippy/tests/ui/range.rs
+++ b/src/tools/clippy/tests/ui/range.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::useless_vec)]
 #[warn(clippy::range_zip_with_len)]
 fn main() {
     let v1 = vec![1, 2, 3];
diff --git a/src/tools/clippy/tests/ui/range.stderr b/src/tools/clippy/tests/ui/range.stderr
index dcb5061371f..ac83b67fde3 100644
--- a/src/tools/clippy/tests/ui/range.stderr
+++ b/src/tools/clippy/tests/ui/range.stderr
@@ -1,5 +1,5 @@
 error: it is more idiomatic to use `v1.iter().enumerate()`
-  --> $DIR/range.rs:5:14
+  --> $DIR/range.rs:6:14
    |
 LL |     let _x = v1.iter().zip(0..v1.len());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.rs b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.rs
index 384060e6eae..53fcbf3c49b 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.rs
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::rc_clone_in_vec_init)]
+#![allow(clippy::useless_vec)]
 use std::sync::{Arc, Mutex};
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr
index 7814f5b5403..a8fd28b84b3 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr
@@ -1,5 +1,5 @@
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/arc.rs:7:13
+  --> $DIR/arc.rs:8:13
    |
 LL |     let v = vec![Arc::new("x".to_string()); 2];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/arc.rs:15:21
+  --> $DIR/arc.rs:16:21
    |
 LL |             let v = vec![Arc::new("x".to_string()); 2];
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL ~             };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/arc.rs:21:13
+  --> $DIR/arc.rs:22:13
    |
 LL |       let v = vec![
    |  _____________^
@@ -76,7 +76,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/arc.rs:30:14
+  --> $DIR/arc.rs:31:14
    |
 LL |       let v1 = vec![
    |  ______________^
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.rs b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.rs
index 0394457fe17..88ea39bf908 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.rs
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::rc_clone_in_vec_init)]
+#![allow(clippy::useless_vec)]
 use std::rc::Rc;
 use std::sync::Mutex;
 
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr
index 80deb7cb9f2..eab464800ca 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr
@@ -1,5 +1,5 @@
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/rc.rs:8:13
+  --> $DIR/rc.rs:9:13
    |
 LL |     let v = vec![Rc::new("x".to_string()); 2];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/rc.rs:16:21
+  --> $DIR/rc.rs:17:21
    |
 LL |             let v = vec![Rc::new("x".to_string()); 2];
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL ~             };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/rc.rs:22:13
+  --> $DIR/rc.rs:23:13
    |
 LL |       let v = vec![
    |  _____________^
@@ -76,7 +76,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/rc.rs:31:14
+  --> $DIR/rc.rs:32:14
    |
 LL |       let v1 = vec![
    |  ______________^
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.rs b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.rs
index 693c9b553c5..03142165057 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.rs
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::rc_clone_in_vec_init)]
+#![allow(clippy::useless_vec)]
 use std::rc::{Rc, Weak as UnSyncWeak};
 use std::sync::{Arc, Mutex, Weak as SyncWeak};
 
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr
index 789e14a302f..1f7a849b180 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr
@@ -1,5 +1,5 @@
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:8:13
+  --> $DIR/weak.rs:9:13
    |
 LL |     let v = vec![SyncWeak::<u32>::new(); 2];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:9:14
+  --> $DIR/weak.rs:10:14
    |
 LL |     let v2 = vec![UnSyncWeak::<u32>::new(); 2];
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:11:13
+  --> $DIR/weak.rs:12:13
    |
 LL |     let v = vec![Rc::downgrade(&Rc::new("x".to_string())); 2];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:12:13
+  --> $DIR/weak.rs:13:13
    |
 LL |     let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,7 +92,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:20:21
+  --> $DIR/weak.rs:21:21
    |
 LL |             let v = vec![Arc::downgrade(&Arc::new("x".to_string())); 2];
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -115,7 +115,7 @@ LL ~             };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:21:22
+  --> $DIR/weak.rs:22:22
    |
 LL |             let v2 = vec![Rc::downgrade(&Rc::new("x".to_string())); 2];
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,7 +138,7 @@ LL ~             };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:27:13
+  --> $DIR/weak.rs:28:13
    |
 LL |       let v = vec![
    |  _____________^
@@ -168,7 +168,7 @@ LL ~     };
    |
 
 error: initializing a reference-counted pointer in `vec![elem; len]`
-  --> $DIR/weak.rs:36:14
+  --> $DIR/weak.rs:37:14
    |
 LL |       let v1 = vec![
    |  ______________^
diff --git a/src/tools/clippy/tests/ui/redundant_at_rest_pattern.fixed b/src/tools/clippy/tests/ui/redundant_at_rest_pattern.fixed
new file mode 100644
index 00000000000..080cf13b5da
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_at_rest_pattern.fixed
@@ -0,0 +1,27 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(irrefutable_let_patterns, unused)]
+#![warn(clippy::redundant_at_rest_pattern)]
+
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+    if let a = [()] {}
+    if let ref a = [()] {}
+    if let mut a = [()] {}
+    if let ref mut a = [()] {}
+    let v = vec![()];
+    if let a = &*v {}
+    let s = &[()];
+    if let a = s {}
+    // Don't lint
+    if let [..] = &*v {}
+    if let [a] = &*v {}
+    if let [()] = &*v {}
+    if let [first, rest @ ..] = &*v {}
+    if let a = [()] {}
+    external! {
+        if let [a @ ..] = [()] {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/redundant_at_rest_pattern.rs b/src/tools/clippy/tests/ui/redundant_at_rest_pattern.rs
new file mode 100644
index 00000000000..a8a80282956
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_at_rest_pattern.rs
@@ -0,0 +1,27 @@
+//@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(irrefutable_let_patterns, unused)]
+#![warn(clippy::redundant_at_rest_pattern)]
+
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+    if let [a @ ..] = [()] {}
+    if let [ref a @ ..] = [()] {}
+    if let [mut a @ ..] = [()] {}
+    if let [ref mut a @ ..] = [()] {}
+    let v = vec![()];
+    if let [a @ ..] = &*v {}
+    let s = &[()];
+    if let [a @ ..] = s {}
+    // Don't lint
+    if let [..] = &*v {}
+    if let [a] = &*v {}
+    if let [()] = &*v {}
+    if let [first, rest @ ..] = &*v {}
+    if let a = [()] {}
+    external! {
+        if let [a @ ..] = [()] {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/redundant_at_rest_pattern.stderr b/src/tools/clippy/tests/ui/redundant_at_rest_pattern.stderr
new file mode 100644
index 00000000000..e2a4d9ffd57
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_at_rest_pattern.stderr
@@ -0,0 +1,40 @@
+error: using a rest pattern to bind an entire slice to a local
+  --> $DIR/redundant_at_rest_pattern.rs:10:12
+   |
+LL |     if let [a @ ..] = [()] {}
+   |            ^^^^^^^^ help: this is better represented with just the binding: `a`
+   |
+   = note: `-D clippy::redundant-at-rest-pattern` implied by `-D warnings`
+
+error: using a rest pattern to bind an entire slice to a local
+  --> $DIR/redundant_at_rest_pattern.rs:11:12
+   |
+LL |     if let [ref a @ ..] = [()] {}
+   |            ^^^^^^^^^^^^ help: this is better represented with just the binding: `ref a`
+
+error: using a rest pattern to bind an entire slice to a local
+  --> $DIR/redundant_at_rest_pattern.rs:12:12
+   |
+LL |     if let [mut a @ ..] = [()] {}
+   |            ^^^^^^^^^^^^ help: this is better represented with just the binding: `mut a`
+
+error: using a rest pattern to bind an entire slice to a local
+  --> $DIR/redundant_at_rest_pattern.rs:13:12
+   |
+LL |     if let [ref mut a @ ..] = [()] {}
+   |            ^^^^^^^^^^^^^^^^ help: this is better represented with just the binding: `ref mut a`
+
+error: using a rest pattern to bind an entire slice to a local
+  --> $DIR/redundant_at_rest_pattern.rs:15:12
+   |
+LL |     if let [a @ ..] = &*v {}
+   |            ^^^^^^^^ help: this is better represented with just the binding: `a`
+
+error: using a rest pattern to bind an entire slice to a local
+  --> $DIR/redundant_at_rest_pattern.rs:17:12
+   |
+LL |     if let [a @ ..] = s {}
+   |            ^^^^^^^^ help: this is better represented with just the binding: `a`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index 8bebb5183bc..5037c08ebd5 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -1,7 +1,13 @@
 //@run-rustfix
 // rustfix-only-machine-applicable
 #![feature(lint_reasons)]
-#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
+#![warn(clippy::redundant_clone)]
+#![allow(
+    clippy::drop_non_drop,
+    clippy::implicit_clone,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap
+)]
 
 use std::ffi::OsString;
 use std::path::Path;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs
index b4bd5d16b1a..501898bf113 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.rs
+++ b/src/tools/clippy/tests/ui/redundant_clone.rs
@@ -1,7 +1,13 @@
 //@run-rustfix
 // rustfix-only-machine-applicable
 #![feature(lint_reasons)]
-#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
+#![warn(clippy::redundant_clone)]
+#![allow(
+    clippy::drop_non_drop,
+    clippy::implicit_clone,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_literal_unwrap
+)]
 
 use std::ffi::OsString;
 use std::path::Path;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr
index 782590034d0..8660c0e1f6a 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.stderr
+++ b/src/tools/clippy/tests/ui/redundant_clone.stderr
@@ -1,180 +1,180 @@
 error: redundant clone
-  --> $DIR/redundant_clone.rs:10:42
+  --> $DIR/redundant_clone.rs:16:42
    |
 LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
    |                                          ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:10:14
+  --> $DIR/redundant_clone.rs:16:14
    |
 LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: `-D clippy::redundant-clone` implied by `-D warnings`
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:13:15
+  --> $DIR/redundant_clone.rs:19:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:13:14
+  --> $DIR/redundant_clone.rs:19:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:16:15
+  --> $DIR/redundant_clone.rs:22:15
    |
 LL |     let _s = s.to_string();
    |               ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:16:14
+  --> $DIR/redundant_clone.rs:22:14
    |
 LL |     let _s = s.to_string();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:19:15
+  --> $DIR/redundant_clone.rs:25:15
    |
 LL |     let _s = s.to_owned();
    |               ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:19:14
+  --> $DIR/redundant_clone.rs:25:14
    |
 LL |     let _s = s.to_owned();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:21:42
+  --> $DIR/redundant_clone.rs:27:42
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_owned();
    |                                          ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:21:14
+  --> $DIR/redundant_clone.rs:27:14
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_owned();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:23:42
+  --> $DIR/redundant_clone.rs:29:42
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_path_buf();
    |                                          ^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:23:14
+  --> $DIR/redundant_clone.rs:29:14
    |
 LL |     let _s = Path::new("/a/b/").join("c").to_path_buf();
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:25:29
+  --> $DIR/redundant_clone.rs:31:29
    |
 LL |     let _s = OsString::new().to_owned();
    |                             ^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:25:14
+  --> $DIR/redundant_clone.rs:31:14
    |
 LL |     let _s = OsString::new().to_owned();
    |              ^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:27:29
+  --> $DIR/redundant_clone.rs:33:29
    |
 LL |     let _s = OsString::new().to_os_string();
    |                             ^^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:27:14
+  --> $DIR/redundant_clone.rs:33:14
    |
 LL |     let _s = OsString::new().to_os_string();
    |              ^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:38:19
+  --> $DIR/redundant_clone.rs:44:19
    |
 LL |     let _t = tup.0.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:38:14
+  --> $DIR/redundant_clone.rs:44:14
    |
 LL |     let _t = tup.0.clone();
    |              ^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:70:25
+  --> $DIR/redundant_clone.rs:76:25
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                         ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:70:24
+  --> $DIR/redundant_clone.rs:76:24
    |
 LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
    |                        ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:127:15
+  --> $DIR/redundant_clone.rs:133:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:127:14
+  --> $DIR/redundant_clone.rs:133:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:128:15
+  --> $DIR/redundant_clone.rs:134:15
    |
 LL |     let _t = t.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:128:14
+  --> $DIR/redundant_clone.rs:134:14
    |
 LL |     let _t = t.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:138:19
+  --> $DIR/redundant_clone.rs:144:19
    |
 LL |         let _f = f.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:138:18
+  --> $DIR/redundant_clone.rs:144:18
    |
 LL |         let _f = f.clone();
    |                  ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:150:14
+  --> $DIR/redundant_clone.rs:156:14
    |
 LL |     let y = x.clone().join("matthias");
    |              ^^^^^^^^ help: remove this
    |
 note: cloned value is neither consumed nor mutated
-  --> $DIR/redundant_clone.rs:150:13
+  --> $DIR/redundant_clone.rs:156:13
    |
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:204:11
+  --> $DIR/redundant_clone.rs:210:11
    |
 LL |     foo(&x.clone(), move || {
    |           ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:204:10
+  --> $DIR/redundant_clone.rs:210:10
    |
 LL |     foo(&x.clone(), move || {
    |          ^
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
index 61aed2733fe..f3669a669ea 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
@@ -3,6 +3,7 @@
 #![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(clippy::redundant_async_block)]
+#![allow(clippy::type_complexity)]
 #![allow(unused)]
 
 async fn something() -> u32 {
@@ -38,4 +39,50 @@ fn main() {
         };
     }
     m2!();
+    issue9956();
+}
+
+fn issue9956() {
+    assert_eq!(43, 42);
+
+    // ... and some more interesting cases I've found while implementing the fix
+
+    // not actually immediately calling the closure:
+    let a = (|| 42);
+    dbg!(a());
+
+    // immediately calling it inside of a macro
+    dbg!(42);
+
+    // immediately calling only one closure, so we can't remove the other ones
+    let a = (|| || 123);
+    dbg!(a()());
+
+    // nested async closures
+    let a = async { 1 };
+    let h = async { a.await };
+
+    // macro expansion tests
+    macro_rules! echo {
+        ($e:expr) => {
+            $e
+        };
+    }
+    let a = 1;
+    assert_eq!(a, 1);
+    let a = 123;
+    assert_eq!(a, 123);
+
+    // chaining calls, but not closures
+    fn x() -> fn() -> fn() -> fn() -> i32 {
+        || || || 42
+    }
+    let _ = x()()()();
+
+    fn bar() -> fn(i32, i32) {
+        foo
+    }
+    fn foo(_: i32, _: i32) {}
+    bar()(42, 5);
+    foo(42, 5);
 }
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
index 56b28663539..db8c7f80df4 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
@@ -3,6 +3,7 @@
 #![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(clippy::redundant_async_block)]
+#![allow(clippy::type_complexity)]
 #![allow(unused)]
 
 async fn something() -> u32 {
@@ -38,4 +39,50 @@ fn main() {
         };
     }
     m2!();
+    issue9956();
+}
+
+fn issue9956() {
+    assert_eq!((|| || 43)()(), 42);
+
+    // ... and some more interesting cases I've found while implementing the fix
+
+    // not actually immediately calling the closure:
+    let a = (|| 42);
+    dbg!(a());
+
+    // immediately calling it inside of a macro
+    dbg!((|| 42)());
+
+    // immediately calling only one closure, so we can't remove the other ones
+    let a = (|| || || 123)();
+    dbg!(a()());
+
+    // nested async closures
+    let a = (|| || || || async || 1)()()()()();
+    let h = async { a.await };
+
+    // macro expansion tests
+    macro_rules! echo {
+        ($e:expr) => {
+            $e
+        };
+    }
+    let a = (|| echo!(|| echo!(|| 1)))()()();
+    assert_eq!(a, 1);
+    let a = (|| echo!((|| 123)))()();
+    assert_eq!(a, 123);
+
+    // chaining calls, but not closures
+    fn x() -> fn() -> fn() -> fn() -> i32 {
+        || || || 42
+    }
+    let _ = x()()()();
+
+    fn bar() -> fn(i32, i32) {
+        foo
+    }
+    fn foo(_: i32, _: i32) {}
+    bar()((|| || 42)()(), 5);
+    foo((|| || 42)()(), 5);
 }
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
index 8a1f0771659..618f5e071d6 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
@@ -1,5 +1,5 @@
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:17:13
+  --> $DIR/redundant_closure_call_fixable.rs:18:13
    |
 LL |     let a = (|| 42)();
    |             ^^^^^^^^^ help: try doing something like: `42`
@@ -7,7 +7,7 @@ LL |     let a = (|| 42)();
    = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:18:13
+  --> $DIR/redundant_closure_call_fixable.rs:19:13
    |
 LL |       let b = (async || {
    |  _____________^
@@ -27,7 +27,7 @@ LL ~     };
    |
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:23:13
+  --> $DIR/redundant_closure_call_fixable.rs:24:13
    |
 LL |       let c = (|| {
    |  _____________^
@@ -47,13 +47,13 @@ LL ~     };
    |
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:28:13
+  --> $DIR/redundant_closure_call_fixable.rs:29:13
    |
 LL |     let d = (async || something().await)();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:37:13
+  --> $DIR/redundant_closure_call_fixable.rs:38:13
    |
 LL |             (|| m!())()
    |             ^^^^^^^^^^^ help: try doing something like: `m!()`
@@ -64,7 +64,7 @@ LL |     m2!();
    = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:32:13
+  --> $DIR/redundant_closure_call_fixable.rs:33:13
    |
 LL |             (|| 0)()
    |             ^^^^^^^^ help: try doing something like: `0`
@@ -74,5 +74,53 @@ LL |     m2!();
    |
    = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 6 previous errors
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:46:16
+   |
+LL |     assert_eq!((|| || 43)()(), 42);
+   |                ^^^^^^^^^^^^^^ help: try doing something like: `43`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:55:10
+   |
+LL |     dbg!((|| 42)());
+   |          ^^^^^^^^^ help: try doing something like: `42`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:58:13
+   |
+LL |     let a = (|| || || 123)();
+   |             ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:62:13
+   |
+LL |     let a = (|| || || || async || 1)()()()()();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:71:13
+   |
+LL |     let a = (|| echo!(|| echo!(|| 1)))()()();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:73:13
+   |
+LL |     let a = (|| echo!((|| 123)))()();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:86:11
+   |
+LL |     bar()((|| || 42)()(), 5);
+   |           ^^^^^^^^^^^^^^ help: try doing something like: `42`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:87:9
+   |
+LL |     foo((|| || 42)()(), 5);
+   |         ^^^^^^^^^^^^^^ help: try doing something like: `42`
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed
index 481c9b263fb..d1134de5ab4 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.fixed
@@ -2,7 +2,12 @@
 
 // Issue #5746
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::equatable_if_let,
+    clippy::needless_if,
+    clippy::needless_else
+)]
 use std::task::Poll::{Pending, Ready};
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs
index 86e46d41e65..d144086e791 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.rs
@@ -2,7 +2,12 @@
 
 // Issue #5746
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_else)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::equatable_if_let,
+    clippy::needless_if,
+    clippy::needless_else
+)]
 use std::task::Poll::{Pending, Ready};
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr
index 23f08103f35..e9ea3f2e688 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:12:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:17:12
    |
 LL |     if let Ok(_) = m.lock() {}
    |     -------^^^^^----------- help: try this: `if m.lock().is_ok()`
@@ -9,7 +9,7 @@ LL |     if let Ok(_) = m.lock() {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:13:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:18:12
    |
 LL |     if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {}
    |     -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>(m.lock().unwrap().0).is_err()`
@@ -18,7 +18,7 @@ LL |     if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:16:16
+  --> $DIR/redundant_pattern_matching_drop_order.rs:21:16
    |
 LL |         if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
    |         -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()`
@@ -27,7 +27,7 @@ LL |         if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:18:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:23:12
    |
 LL |     if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {
    |     -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()`
@@ -36,31 +36,31 @@ LL |     if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:21:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:26:12
    |
 LL |     if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
    |     -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:22:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:27:12
    |
 LL |     if let Err(_) = Err::<std::sync::MutexGuard<()>, _>(()) {}
    |     -------^^^^^^------------------------------------------ help: try this: `if Err::<std::sync::MutexGuard<()>, _>(()).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:24:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:29:12
    |
 LL |     if let Ok(_) = Ok::<_, ()>(String::new()) {}
    |     -------^^^^^----------------------------- help: try this: `if Ok::<_, ()>(String::new()).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:25:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:30:12
    |
 LL |     if let Err(_) = Err::<(), _>((String::new(), ())) {}
    |     -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>((String::new(), ())).is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:28:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:33:12
    |
 LL |     if let Some(_) = Some(m.lock()) {}
    |     -------^^^^^^^----------------- help: try this: `if Some(m.lock()).is_some()`
@@ -69,7 +69,7 @@ LL |     if let Some(_) = Some(m.lock()) {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:29:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:34:12
    |
 LL |     if let Some(_) = Some(m.lock().unwrap().0) {}
    |     -------^^^^^^^---------------------------- help: try this: `if Some(m.lock().unwrap().0).is_some()`
@@ -78,7 +78,7 @@ LL |     if let Some(_) = Some(m.lock().unwrap().0) {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:32:16
+  --> $DIR/redundant_pattern_matching_drop_order.rs:37:16
    |
 LL |         if let None = None::<std::sync::MutexGuard<()>> {}
    |         -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()`
@@ -87,7 +87,7 @@ LL |         if let None = None::<std::sync::MutexGuard<()>> {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:34:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:39:12
    |
 LL |     if let None = None::<std::sync::MutexGuard<()>> {
    |     -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()`
@@ -96,25 +96,25 @@ LL |     if let None = None::<std::sync::MutexGuard<()>> {
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:38:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:43:12
    |
 LL |     if let None = None::<std::sync::MutexGuard<()>> {}
    |     -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:40:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:45:12
    |
 LL |     if let Some(_) = Some(String::new()) {}
    |     -------^^^^^^^---------------------- help: try this: `if Some(String::new()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:41:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:46:12
    |
 LL |     if let Some(_) = Some((String::new(), ())) {}
    |     -------^^^^^^^---------------------------- help: try this: `if Some((String::new(), ())).is_some()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:44:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:49:12
    |
 LL |     if let Ready(_) = Ready(m.lock()) {}
    |     -------^^^^^^^^------------------ help: try this: `if Ready(m.lock()).is_ready()`
@@ -123,7 +123,7 @@ LL |     if let Ready(_) = Ready(m.lock()) {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:45:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:50:12
    |
 LL |     if let Ready(_) = Ready(m.lock().unwrap().0) {}
    |     -------^^^^^^^^----------------------------- help: try this: `if Ready(m.lock().unwrap().0).is_ready()`
@@ -132,7 +132,7 @@ LL |     if let Ready(_) = Ready(m.lock().unwrap().0) {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:48:16
+  --> $DIR/redundant_pattern_matching_drop_order.rs:53:16
    |
 LL |         if let Pending = Pending::<std::sync::MutexGuard<()>> {}
    |         -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()`
@@ -141,7 +141,7 @@ LL |         if let Pending = Pending::<std::sync::MutexGuard<()>> {}
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:50:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:55:12
    |
 LL |     if let Pending = Pending::<std::sync::MutexGuard<()>> {
    |     -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()`
@@ -150,19 +150,19 @@ LL |     if let Pending = Pending::<std::sync::MutexGuard<()>> {
    = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:54:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:59:12
    |
 LL |     if let Pending = Pending::<std::sync::MutexGuard<()>> {}
    |     -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:56:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:61:12
    |
 LL |     if let Ready(_) = Ready(String::new()) {}
    |     -------^^^^^^^^----------------------- help: try this: `if Ready(String::new()).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_drop_order.rs:57:12
+  --> $DIR/redundant_pattern_matching_drop_order.rs:62:12
    |
 LL |     if let Ready(_) = Ready((String::new(), ())) {}
    |     -------^^^^^^^^----------------------------- help: try this: `if Ready((String::new(), ())).is_ready()`
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
index a9faf12cd5a..75ed143446c 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
@@ -4,6 +4,7 @@
 #![allow(
     clippy::match_like_matches_macro,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::uninlined_format_args
 )]
 
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
index 574671d03d1..9ac77409f79 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
@@ -4,6 +4,7 @@
 #![allow(
     clippy::match_like_matches_macro,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::uninlined_format_args
 )]
 
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
index 536b589de54..6d1fb296463 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:17:12
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12
    |
 LL |     if let V4(_) = &ipaddr {}
    |     -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()`
@@ -7,31 +7,31 @@ LL |     if let V4(_) = &ipaddr {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:19:12
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:20:12
    |
 LL |     if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:21:12
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:22:12
    |
 LL |     if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:23:15
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:24:15
    |
 LL |     while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:25:15
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:26:15
    |
 LL |     while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:35:5
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:36:5
    |
 LL | /     match V4(Ipv4Addr::LOCALHOST) {
 LL | |         V4(_) => true,
@@ -40,7 +40,7 @@ LL | |     };
    | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:40:5
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:41:5
    |
 LL | /     match V4(Ipv4Addr::LOCALHOST) {
 LL | |         V4(_) => false,
@@ -49,7 +49,7 @@ LL | |     };
    | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:45:5
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:46:5
    |
 LL | /     match V6(Ipv6Addr::LOCALHOST) {
 LL | |         V4(_) => false,
@@ -58,7 +58,7 @@ LL | |     };
    | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:50:5
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:51:5
    |
 LL | /     match V6(Ipv6Addr::LOCALHOST) {
 LL | |         V4(_) => true,
@@ -67,49 +67,49 @@ LL | |     };
    | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:55:20
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:56:20
    |
 LL |     let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) {
    |             -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:63:20
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:64:20
    |
 LL |     let _ = if let V4(_) = gen_ipaddr() {
    |             -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:65:19
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:66:19
    |
 LL |     } else if let V6(_) = gen_ipaddr() {
    |            -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:77:12
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:78:12
    |
 LL |     if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:79:12
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:80:12
    |
 LL |     if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:81:15
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:82:15
    |
 LL |     while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:83:15
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:84:15
    |
 LL |     while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
    |     ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
 
 error: redundant pattern matching, consider using `is_ipv4()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:85:5
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:86:5
    |
 LL | /     match V4(Ipv4Addr::LOCALHOST) {
 LL | |         V4(_) => true,
@@ -118,7 +118,7 @@ LL | |     };
    | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
 
 error: redundant pattern matching, consider using `is_ipv6()`
-  --> $DIR/redundant_pattern_matching_ipaddr.rs:90:5
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:91:5
    |
 LL | /     match V6(Ipv6Addr::LOCALHOST) {
 LL | |         V4(_) => false,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
index dae931541d4..a63ba5809e4 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
@@ -5,6 +5,7 @@
 #![allow(
     unused_must_use,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::match_like_matches_macro,
     clippy::equatable_if_let,
     clippy::if_same_then_else
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
index 3f2fa3f53ce..631f9091672 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
@@ -5,6 +5,7 @@
 #![allow(
     unused_must_use,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::match_like_matches_macro,
     clippy::equatable_if_let,
     clippy::if_same_then_else
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
index 93760ce97a8..717b603c496 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:14:12
+  --> $DIR/redundant_pattern_matching_option.rs:15:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
@@ -7,43 +7,43 @@ LL |     if let None = None::<()> {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:16:12
+  --> $DIR/redundant_pattern_matching_option.rs:17:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:18:12
+  --> $DIR/redundant_pattern_matching_option.rs:19:12
    |
 LL |     if let Some(_) = Some(42) {
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:24:15
+  --> $DIR/redundant_pattern_matching_option.rs:25:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:26:15
+  --> $DIR/redundant_pattern_matching_option.rs:27:15
    |
 LL |     while let None = Some(42) {}
    |     ----------^^^^----------- help: try this: `while Some(42).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:28:15
+  --> $DIR/redundant_pattern_matching_option.rs:29:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:31:15
+  --> $DIR/redundant_pattern_matching_option.rs:32:15
    |
 LL |     while let Some(_) = v.pop() {
    |     ----------^^^^^^^---------- help: try this: `while v.pop().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:39:5
+  --> $DIR/redundant_pattern_matching_option.rs:40:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -52,7 +52,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:44:5
+  --> $DIR/redundant_pattern_matching_option.rs:45:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -61,7 +61,7 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:49:13
+  --> $DIR/redundant_pattern_matching_option.rs:50:13
    |
 LL |       let _ = match None::<()> {
    |  _____________^
@@ -71,55 +71,55 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:55:20
+  --> $DIR/redundant_pattern_matching_option.rs:56:20
    |
 LL |     let _ = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:61:20
+  --> $DIR/redundant_pattern_matching_option.rs:62:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:63:19
+  --> $DIR/redundant_pattern_matching_option.rs:64:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:69:12
+  --> $DIR/redundant_pattern_matching_option.rs:70:12
    |
 LL |     if let Some(..) = gen_opt() {}
    |     -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:84:12
+  --> $DIR/redundant_pattern_matching_option.rs:85:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:86:12
+  --> $DIR/redundant_pattern_matching_option.rs:87:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:88:15
+  --> $DIR/redundant_pattern_matching_option.rs:89:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:90:15
+  --> $DIR/redundant_pattern_matching_option.rs:91:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:92:5
+  --> $DIR/redundant_pattern_matching_option.rs:93:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -128,7 +128,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:97:5
+  --> $DIR/redundant_pattern_matching_option.rs:98:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -137,19 +137,19 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:105:12
+  --> $DIR/redundant_pattern_matching_option.rs:106:12
    |
 LL |     if let None = *(&None::<()>) {}
    |     -------^^^^----------------- help: try this: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:106:12
+  --> $DIR/redundant_pattern_matching_option.rs:107:12
    |
 LL |     if let None = *&None::<()> {}
    |     -------^^^^--------------- help: try this: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:112:5
+  --> $DIR/redundant_pattern_matching_option.rs:113:5
    |
 LL | /     match x {
 LL | |         Some(_) => true,
@@ -158,7 +158,7 @@ LL | |     };
    | |_____^ help: try this: `x.is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:117:5
+  --> $DIR/redundant_pattern_matching_option.rs:118:5
    |
 LL | /     match x {
 LL | |         None => true,
@@ -167,7 +167,7 @@ LL | |     };
    | |_____^ help: try this: `x.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:122:5
+  --> $DIR/redundant_pattern_matching_option.rs:123:5
    |
 LL | /     match x {
 LL | |         Some(_) => false,
@@ -176,7 +176,7 @@ LL | |     };
    | |_____^ help: try this: `x.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:127:5
+  --> $DIR/redundant_pattern_matching_option.rs:128:5
    |
 LL | /     match x {
 LL | |         None => false,
@@ -185,13 +185,13 @@ LL | |     };
    | |_____^ help: try this: `x.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:142:13
+  --> $DIR/redundant_pattern_matching_option.rs:143:13
    |
 LL |     let _ = matches!(x, Some(_));
    |             ^^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:144:13
+  --> $DIR/redundant_pattern_matching_option.rs:145:13
    |
 LL |     let _ = matches!(x, None);
    |             ^^^^^^^^^^^^^^^^^ help: try this: `x.is_none()`
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
index bf3e692202c..f739deaf58e 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
@@ -5,6 +5,7 @@
 #![allow(
     unused_must_use,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::match_like_matches_macro,
     clippy::equatable_if_let,
     clippy::if_same_then_else
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
index 892a21d9d29..88dde02b38b 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
@@ -5,6 +5,7 @@
 #![allow(
     unused_must_use,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::match_like_matches_macro,
     clippy::equatable_if_let,
     clippy::if_same_then_else
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
index 1b480f3157f..b89fde35fcf 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:16:12
+  --> $DIR/redundant_pattern_matching_poll.rs:17:12
    |
 LL |     if let Pending = Pending::<()> {}
    |     -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
@@ -7,37 +7,37 @@ LL |     if let Pending = Pending::<()> {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:18:12
+  --> $DIR/redundant_pattern_matching_poll.rs:19:12
    |
 LL |     if let Ready(_) = Ready(42) {}
    |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:20:12
+  --> $DIR/redundant_pattern_matching_poll.rs:21:12
    |
 LL |     if let Ready(_) = Ready(42) {
    |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:26:15
+  --> $DIR/redundant_pattern_matching_poll.rs:27:15
    |
 LL |     while let Ready(_) = Ready(42) {}
    |     ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:28:15
+  --> $DIR/redundant_pattern_matching_poll.rs:29:15
    |
 LL |     while let Pending = Ready(42) {}
    |     ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:30:15
+  --> $DIR/redundant_pattern_matching_poll.rs:31:15
    |
 LL |     while let Pending = Pending::<()> {}
    |     ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:36:5
+  --> $DIR/redundant_pattern_matching_poll.rs:37:5
    |
 LL | /     match Ready(42) {
 LL | |         Ready(_) => true,
@@ -46,7 +46,7 @@ LL | |     };
    | |_____^ help: try this: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:41:5
+  --> $DIR/redundant_pattern_matching_poll.rs:42:5
    |
 LL | /     match Pending::<()> {
 LL | |         Ready(_) => false,
@@ -55,7 +55,7 @@ LL | |     };
    | |_____^ help: try this: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:46:13
+  --> $DIR/redundant_pattern_matching_poll.rs:47:13
    |
 LL |       let _ = match Pending::<()> {
    |  _____________^
@@ -65,49 +65,49 @@ LL | |     };
    | |_____^ help: try this: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:52:20
+  --> $DIR/redundant_pattern_matching_poll.rs:53:20
    |
 LL |     let _ = if let Ready(_) = poll { true } else { false };
    |             -------^^^^^^^^------- help: try this: `if poll.is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:56:20
+  --> $DIR/redundant_pattern_matching_poll.rs:57:20
    |
 LL |     let _ = if let Ready(_) = gen_poll() {
    |             -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:58:19
+  --> $DIR/redundant_pattern_matching_poll.rs:59:19
    |
 LL |     } else if let Pending = gen_poll() {
    |            -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:74:12
+  --> $DIR/redundant_pattern_matching_poll.rs:75:12
    |
 LL |     if let Ready(_) = Ready(42) {}
    |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:76:12
+  --> $DIR/redundant_pattern_matching_poll.rs:77:12
    |
 LL |     if let Pending = Pending::<()> {}
    |     -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:78:15
+  --> $DIR/redundant_pattern_matching_poll.rs:79:15
    |
 LL |     while let Ready(_) = Ready(42) {}
    |     ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:80:15
+  --> $DIR/redundant_pattern_matching_poll.rs:81:15
    |
 LL |     while let Pending = Pending::<()> {}
    |     ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:82:5
+  --> $DIR/redundant_pattern_matching_poll.rs:83:5
    |
 LL | /     match Ready(42) {
 LL | |         Ready(_) => true,
@@ -116,7 +116,7 @@ LL | |     };
    | |_____^ help: try this: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:87:5
+  --> $DIR/redundant_pattern_matching_poll.rs:88:5
    |
 LL | /     match Pending::<()> {
 LL | |         Ready(_) => false,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index d77a2af7616..343e0d04340 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -6,6 +6,7 @@
     clippy::if_same_then_else,
     clippy::match_like_matches_macro,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::uninlined_format_args,
     clippy::unnecessary_wraps
 )]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index aa884ac6bb1..4d64eafe590 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -6,6 +6,7 @@
     clippy::if_same_then_else,
     clippy::match_like_matches_macro,
     clippy::needless_bool,
+    clippy::needless_if,
     clippy::uninlined_format_args,
     clippy::unnecessary_wraps
 )]
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index b462f7f41b9..f6ce666bb4f 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:15:12
+  --> $DIR/redundant_pattern_matching_result.rs:16:12
    |
 LL |     if let Ok(_) = &result {}
    |     -------^^^^^---------- help: try this: `if result.is_ok()`
@@ -7,31 +7,31 @@ LL |     if let Ok(_) = &result {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:17:12
+  --> $DIR/redundant_pattern_matching_result.rs:18:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:19:12
+  --> $DIR/redundant_pattern_matching_result.rs:20:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:21:15
+  --> $DIR/redundant_pattern_matching_result.rs:22:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:23:15
+  --> $DIR/redundant_pattern_matching_result.rs:24:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:33:5
+  --> $DIR/redundant_pattern_matching_result.rs:34:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -40,7 +40,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:38:5
+  --> $DIR/redundant_pattern_matching_result.rs:39:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -49,7 +49,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:43:5
+  --> $DIR/redundant_pattern_matching_result.rs:44:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -58,7 +58,7 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:48:5
+  --> $DIR/redundant_pattern_matching_result.rs:49:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -67,73 +67,73 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:53:20
+  --> $DIR/redundant_pattern_matching_result.rs:54:20
    |
 LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
    |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:61:20
+  --> $DIR/redundant_pattern_matching_result.rs:62:20
    |
 LL |     let _ = if let Ok(_) = gen_res() {
    |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:63:19
+  --> $DIR/redundant_pattern_matching_result.rs:64:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:86:19
+  --> $DIR/redundant_pattern_matching_result.rs:87:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:87:16
+  --> $DIR/redundant_pattern_matching_result.rs:88:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:93:12
+  --> $DIR/redundant_pattern_matching_result.rs:94:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try this: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:94:15
+  --> $DIR/redundant_pattern_matching_result.rs:95:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:112:12
+  --> $DIR/redundant_pattern_matching_result.rs:113:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:114:12
+  --> $DIR/redundant_pattern_matching_result.rs:115:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:116:15
+  --> $DIR/redundant_pattern_matching_result.rs:117:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:118:15
+  --> $DIR/redundant_pattern_matching_result.rs:119:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:120:5
+  --> $DIR/redundant_pattern_matching_result.rs:121:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -142,7 +142,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:125:5
+  --> $DIR/redundant_pattern_matching_result.rs:126:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -151,7 +151,7 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:135:5
+  --> $DIR/redundant_pattern_matching_result.rs:136:5
    |
 LL | /     match x {
 LL | |         Ok(_) => true,
@@ -160,7 +160,7 @@ LL | |     };
    | |_____^ help: try this: `x.is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:140:5
+  --> $DIR/redundant_pattern_matching_result.rs:141:5
    |
 LL | /     match x {
 LL | |         Ok(_) => false,
@@ -169,7 +169,7 @@ LL | |     };
    | |_____^ help: try this: `x.is_err()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:145:5
+  --> $DIR/redundant_pattern_matching_result.rs:146:5
    |
 LL | /     match x {
 LL | |         Err(_) => true,
@@ -178,7 +178,7 @@ LL | |     };
    | |_____^ help: try this: `x.is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:150:5
+  --> $DIR/redundant_pattern_matching_result.rs:151:5
    |
 LL | /     match x {
 LL | |         Err(_) => false,
@@ -187,13 +187,13 @@ LL | |     };
    | |_____^ help: try this: `x.is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:171:13
+  --> $DIR/redundant_pattern_matching_result.rs:172:13
    |
 LL |     let _ = matches!(x, Ok(_));
    |             ^^^^^^^^^^^^^^^^^^ help: try this: `x.is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:173:13
+  --> $DIR/redundant_pattern_matching_result.rs:174:13
    |
 LL |     let _ = matches!(x, Err(_));
    |             ^^^^^^^^^^^^^^^^^^^ help: try this: `x.is_err()`
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.fixed b/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
index f65c0fdd35d..a1ed491bbc6 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.fixed
@@ -14,7 +14,7 @@ mod m1 {
     }
 
     pub mod m1_2 {
-        // ^ private due to m1
+        //:^ private due to m1
         fn f() {}
         pub fn g() {} // private due to m1_2 and m1
         pub fn h() {}
@@ -39,7 +39,7 @@ pub(crate) mod m2 {
     }
 
     pub mod m2_2 {
-        // ^ already crate visible due to m2
+        //:^ already crate visible due to m2
         fn f() {}
         pub fn g() {} // already crate visible due to m2_2 and m2
         pub fn h() {}
@@ -64,7 +64,7 @@ pub mod m3 {
     }
 
     pub(crate) mod m3_2 {
-        // ^ ok
+        //:^ ok
         fn f() {}
         pub fn g() {} // already crate visible due to m3_2
         pub fn h() {}
@@ -89,7 +89,7 @@ mod m4 {
     }
 
     pub mod m4_2 {
-        // ^ private: not re-exported by `pub use m4::*`
+        //:^ private: not re-exported by `pub use m4::*`
         fn f() {}
         pub fn g() {} // private due to m4_2
         pub fn h() {}
diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.rs b/src/tools/clippy/tests/ui/redundant_pub_crate.rs
index fb07fed98be..9accd297fc9 100644
--- a/src/tools/clippy/tests/ui/redundant_pub_crate.rs
+++ b/src/tools/clippy/tests/ui/redundant_pub_crate.rs
@@ -14,7 +14,7 @@ mod m1 {
     }
 
     pub(crate) mod m1_2 {
-        // ^ private due to m1
+        //:^ private due to m1
         fn f() {}
         pub(crate) fn g() {} // private due to m1_2 and m1
         pub fn h() {}
@@ -39,7 +39,7 @@ pub(crate) mod m2 {
     }
 
     pub(crate) mod m2_2 {
-        // ^ already crate visible due to m2
+        //:^ already crate visible due to m2
         fn f() {}
         pub(crate) fn g() {} // already crate visible due to m2_2 and m2
         pub fn h() {}
@@ -64,7 +64,7 @@ pub mod m3 {
     }
 
     pub(crate) mod m3_2 {
-        // ^ ok
+        //:^ ok
         fn f() {}
         pub(crate) fn g() {} // already crate visible due to m3_2
         pub fn h() {}
@@ -89,7 +89,7 @@ mod m4 {
     }
 
     pub(crate) mod m4_2 {
-        // ^ private: not re-exported by `pub use m4::*`
+        //:^ private: not re-exported by `pub use m4::*`
         fn f() {}
         pub(crate) fn g() {} // private due to m4_2
         pub fn h() {}
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
index 2651735d103..a83699ec68d 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
@@ -5,39 +5,39 @@
 #[derive(Debug)]
 struct Foo;
 
-const VAR_ONE: &str = "Test constant #1"; // ERROR Consider removing 'static.
+const VAR_ONE: &str = "Test constant #1"; // ERROR: Consider removing 'static.
 
 const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning.
 
-const VAR_THREE: &[&str] = &["one", "two"]; // ERROR Consider removing 'static
+const VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static
 
-const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+const VAR_FOUR: (&str, (&str, &str), &str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
 
 const VAR_SIX: &u8 = &5;
 
 const VAR_HEIGHT: &Foo = &Foo {};
 
-const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR Consider removing 'static.
+const VAR_SLICE: &[u8] = b"Test constant #1"; // ERROR: Consider removing 'static.
 
-const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static.
+const VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
 
-const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static.
+const VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static.
 
-static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR Consider removing 'static.
+static STATIC_VAR_ONE: &str = "Test static #1"; // ERROR: Consider removing 'static.
 
 static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning.
 
-static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR Consider removing 'static
+static STATIC_VAR_THREE: &[&str] = &["one", "two"]; // ERROR: Consider removing 'static
 
 static STATIC_VAR_SIX: &u8 = &5;
 
 static STATIC_VAR_HEIGHT: &Foo = &Foo {};
 
-static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR Consider removing 'static.
+static STATIC_VAR_SLICE: &[u8] = b"Test static #3"; // ERROR: Consider removing 'static.
 
-static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static.
+static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
 
-static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static.
+static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR: Consider removing 'static.
 
 static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0];
 
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
index 7286652899d..b165cbaa3aa 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
@@ -5,39 +5,39 @@
 #[derive(Debug)]
 struct Foo;
 
-const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static.
+const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static.
 
 const VAR_TWO: &str = "Test constant #2"; // This line should not raise a warning.
 
-const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
+const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
 
-const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
 
 const VAR_SIX: &'static u8 = &5;
 
 const VAR_HEIGHT: &'static Foo = &Foo {};
 
-const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static.
+const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static.
 
-const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
+const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
 
-const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
+const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
 
-static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static.
+static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static.
 
 static STATIC_VAR_TWO: &str = "Test static #2"; // This line should not raise a warning.
 
-static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
+static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
 
 static STATIC_VAR_SIX: &'static u8 = &5;
 
 static STATIC_VAR_HEIGHT: &'static Foo = &Foo {};
 
-static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static.
+static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static.
 
-static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
+static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
 
-static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
+static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
 
 static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
 
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
index b2cbd2d9d01..a13e5eadf15 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
@@ -1,7 +1,7 @@
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:8:17
    |
-LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static.
+LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static.
    |                -^^^^^^^---- help: consider removing `'static`: `&str`
    |
    = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings`
@@ -9,19 +9,19 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:12:21
    |
-LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
+LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
    |                    -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:14:32
    |
-LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                               -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:14:47
    |
-LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                                              -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
@@ -39,31 +39,31 @@ LL | const VAR_HEIGHT: &'static Foo = &Foo {};
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:20:19
    |
-LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static.
+LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static.
    |                  -^^^^^^^----- help: consider removing `'static`: `&[u8]`
 
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:22:19
    |
-LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
+LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
    |                  -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
 
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:24:19
    |
-LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
+LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
    |                  -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:26:25
    |
-LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static.
+LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static.
    |                        -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:30:29
    |
-LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
+LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
    |                            -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
@@ -81,19 +81,19 @@ LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {};
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:36:27
    |
-LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static.
+LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static.
    |                          -^^^^^^^----- help: consider removing `'static`: `&[u8]`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:38:27
    |
-LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
+LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
    |                          -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes.rs:40:27
    |
-LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
+LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
    |                          -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.rs
index f57dd58e230..b3f263a7d66 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.rs
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.rs
@@ -1,12 +1,12 @@
 // these are rustfixable, but run-rustfix tests cannot handle them
 
-const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
+const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static
 
 const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
 
-static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
 
-static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
+static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static
 
 static STATIC_VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
 
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.stderr b/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.stderr
index cc7e55a757a..4e7500903f8 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.stderr
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes_multiple.stderr
@@ -1,7 +1,7 @@
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes_multiple.rs:3:18
    |
-LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
+LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static
    |                 -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]`
    |
    = note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings`
@@ -9,7 +9,7 @@ LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]];
 error: constants have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes_multiple.rs:3:30
    |
-LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
+LL | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static
    |                             -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
@@ -27,25 +27,25 @@ LL | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes_multiple.rs:7:40
    |
-LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                                       -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes_multiple.rs:7:55
    |
-LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
+LL | static STATIC_VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                                                      -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes_multiple.rs:9:26
    |
-LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
+LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static
    |                         -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]`
 
 error: statics have by default a `'static` lifetime
   --> $DIR/redundant_static_lifetimes_multiple.rs:9:38
    |
-LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
+LL | static STATIC_VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR: Consider removing 'static
    |                                     -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.rs b/src/tools/clippy/tests/ui/redundant_type_annotations.rs
new file mode 100644
index 00000000000..cc507b8d658
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_type_annotations.rs
@@ -0,0 +1,176 @@
+#![allow(unused)]
+#![warn(clippy::redundant_type_annotations)]
+
+#[derive(Debug, Default)]
+struct Cake<T> {
+    _data: T,
+}
+
+fn make_something<T: Default>() -> T {
+    T::default()
+}
+
+fn make_cake<T: Default>() -> Cake<T> {
+    Cake::<T>::default()
+}
+
+fn plus_one<T: std::ops::Add<u8, Output = T>>(val: T) -> T {
+    val + 1
+}
+
+#[derive(Default)]
+struct Slice {
+    inner: u32,
+}
+
+#[derive(Default)]
+struct Pie {
+    inner: u32,
+    inner_struct: Slice,
+}
+
+enum Pizza {
+    One,
+    Two,
+}
+
+fn return_a_string() -> String {
+    String::new()
+}
+
+fn return_a_struct() -> Pie {
+    Pie::default()
+}
+
+fn return_an_enum() -> Pizza {
+    Pizza::One
+}
+
+fn return_an_int() -> u32 {
+    5
+}
+
+impl Pie {
+    fn return_an_int(&self) -> u32 {
+        self.inner
+    }
+
+    fn return_a_ref(&self) -> &u32 {
+        &self.inner
+    }
+
+    fn return_a_ref_to_struct(&self) -> &Slice {
+        &self.inner_struct
+    }
+
+    fn associated_return_an_int() -> u32 {
+        5
+    }
+
+    fn new() -> Self {
+        Self::default()
+    }
+
+    fn associated_return_a_string() -> String {
+        String::from("")
+    }
+
+    fn test_method_call(&self) {
+        // Everything here should be lint
+
+        let v: u32 = self.return_an_int();
+        let v: &u32 = self.return_a_ref();
+        let v: &Slice = self.return_a_ref_to_struct();
+    }
+}
+
+fn test_generics() {
+    // The type annotation is needed to determine T
+    let _c: Cake<i32> = make_something();
+
+    // The type annotation is needed to determine the topic
+    let _c: Cake<u8> = make_cake();
+
+    // This could be lint, but currently doesn't
+    let _c: Cake<u8> = make_cake::<u8>();
+
+    // This could be lint, but currently doesn't
+    let _c: u8 = make_something::<u8>();
+
+    // This could be lint, but currently doesn't
+    let _c: u8 = plus_one(5_u8);
+
+    // Annotation needed otherwise T is i32
+    let _c: u8 = plus_one(5);
+
+    // This could be lint, but currently doesn't
+    let _return: String = String::from("test");
+}
+
+fn test_non_locals() {
+    // This shouldn't be lint
+    fn _arg(x: u32) -> u32 {
+        x
+    }
+
+    // This could lint, but probably shouldn't
+    let _closure_arg = |x: u32| x;
+}
+
+fn test_complex_types() {
+    // Shouldn't be lint, since the literal will be i32 otherwise
+    let _u8: u8 = 128;
+
+    // This could be lint, but currently doesn't
+    let _tuple_i32: (i32, i32) = (12, 13);
+
+    // Shouldn't be lint, since the tuple will be i32 otherwise
+    let _tuple_u32: (u32, u32) = (1, 2);
+
+    // Should be lint, since the type is determined by the init value, but currently doesn't
+    let _tuple_u32: (u32, u32) = (3_u32, 4_u32);
+
+    // This could be lint, but currently doesn't
+    let _array: [i32; 3] = [5, 6, 7];
+
+    // Shouldn't be lint
+    let _array: [u32; 2] = [8, 9];
+}
+
+fn test_functions() {
+    // Everything here should be lint
+
+    let _return: String = return_a_string();
+
+    let _return: Pie = return_a_struct();
+
+    let _return: Pizza = return_an_enum();
+
+    let _return: u32 = return_an_int();
+
+    let _return: String = String::new();
+
+    let new_pie: Pie = Pie::new();
+
+    let _return: u32 = new_pie.return_an_int();
+
+    let _return: u32 = Pie::associated_return_an_int();
+
+    let _return: String = Pie::associated_return_a_string();
+}
+
+fn test_simple_types() {
+    // Everything here should be lint
+
+    let _var: u32 = u32::MAX;
+
+    let _var: u32 = 5_u32;
+
+    let _var: &str = "test";
+
+    let _var: &[u8] = b"test";
+
+    let _var: bool = false;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr
new file mode 100644
index 00000000000..e8b2fe5c384
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr
@@ -0,0 +1,106 @@
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:81:9
+   |
+LL |         let v: u32 = self.return_an_int();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::redundant-type-annotations` implied by `-D warnings`
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:82:9
+   |
+LL |         let v: &u32 = self.return_a_ref();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:83:9
+   |
+LL |         let v: &Slice = self.return_a_ref_to_struct();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:143:5
+   |
+LL |     let _return: String = return_a_string();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:145:5
+   |
+LL |     let _return: Pie = return_a_struct();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:147:5
+   |
+LL |     let _return: Pizza = return_an_enum();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:149:5
+   |
+LL |     let _return: u32 = return_an_int();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:151:5
+   |
+LL |     let _return: String = String::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:153:5
+   |
+LL |     let new_pie: Pie = Pie::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:155:5
+   |
+LL |     let _return: u32 = new_pie.return_an_int();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:157:5
+   |
+LL |     let _return: u32 = Pie::associated_return_an_int();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:159:5
+   |
+LL |     let _return: String = Pie::associated_return_a_string();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:165:5
+   |
+LL |     let _var: u32 = u32::MAX;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:167:5
+   |
+LL |     let _var: u32 = 5_u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:169:5
+   |
+LL |     let _var: &str = "test";
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:171:5
+   |
+LL |     let _var: &[u8] = b"test";
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: redundant type annotation
+  --> $DIR/redundant_type_annotations.rs:173:5
+   |
+LL |     let _var: bool = false;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 17 previous errors
+
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index 1c8e47ab594..89d1d949454 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -1,4 +1,9 @@
-#![allow(unused, clippy::needless_borrow)]
+#![allow(
+    unused,
+    clippy::needless_raw_strings,
+    clippy::needless_raw_string_hashes,
+    clippy::needless_borrow
+)]
 #![warn(clippy::invalid_regex, clippy::trivial_regex)]
 
 extern crate regex;
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index 1e8a21283cd..21f1cb44460 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -1,5 +1,5 @@
 error: trivial regex
-  --> $DIR/regex.rs:13:45
+  --> $DIR/regex.rs:18:45
    |
 LL |     let pipe_in_wrong_position = Regex::new("|");
    |                                             ^^^
@@ -8,7 +8,7 @@ LL |     let pipe_in_wrong_position = Regex::new("|");
    = note: `-D clippy::trivial-regex` implied by `-D warnings`
 
 error: trivial regex
-  --> $DIR/regex.rs:14:60
+  --> $DIR/regex.rs:19:60
    |
 LL |     let pipe_in_wrong_position_builder = RegexBuilder::new("|");
    |                                                            ^^^
@@ -16,7 +16,7 @@ LL |     let pipe_in_wrong_position_builder = RegexBuilder::new("|");
    = help: the regex is unlikely to be useful as it is
 
 error: regex syntax error: invalid character class range, the start must be <= the end
-  --> $DIR/regex.rs:15:42
+  --> $DIR/regex.rs:20:42
    |
 LL |     let wrong_char_ranice = Regex::new("[z-a]");
    |                                          ^^^
@@ -24,7 +24,7 @@ LL |     let wrong_char_ranice = Regex::new("[z-a]");
    = note: `-D clippy::invalid-regex` implied by `-D warnings`
 
 error: regex syntax error: invalid character class range, the start must be <= the end
-  --> $DIR/regex.rs:16:37
+  --> $DIR/regex.rs:21:37
    |
 LL |     let some_unicode = Regex::new("[é-è]");
    |                                     ^^^
@@ -33,13 +33,13 @@ error: regex parse error:
            (
            ^
        error: unclosed group
-  --> $DIR/regex.rs:18:33
+  --> $DIR/regex.rs:23:33
    |
 LL |     let some_regex = Regex::new(OPENING_PAREN);
    |                                 ^^^^^^^^^^^^^
 
 error: trivial regex
-  --> $DIR/regex.rs:20:53
+  --> $DIR/regex.rs:25:53
    |
 LL |     let binary_pipe_in_wrong_position = BRegex::new("|");
    |                                                     ^^^
@@ -50,7 +50,7 @@ error: regex parse error:
            (
            ^
        error: unclosed group
-  --> $DIR/regex.rs:21:41
+  --> $DIR/regex.rs:26:41
    |
 LL |     let some_binary_regex = BRegex::new(OPENING_PAREN);
    |                                         ^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ error: regex parse error:
            (
            ^
        error: unclosed group
-  --> $DIR/regex.rs:22:56
+  --> $DIR/regex.rs:27:56
    |
 LL |     let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN);
    |                                                        ^^^^^^^^^^^^^
@@ -68,7 +68,7 @@ error: regex parse error:
            (
            ^
        error: unclosed group
-  --> $DIR/regex.rs:34:37
+  --> $DIR/regex.rs:39:37
    |
 LL |     let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
    |                                     ^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ error: regex parse error:
            (
            ^
        error: unclosed group
-  --> $DIR/regex.rs:35:39
+  --> $DIR/regex.rs:40:39
    |
 LL |     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
    |                                       ^^^^^^^^^^^^^
@@ -86,27 +86,27 @@ error: regex parse error:
            /b/c
              ^^
        error: unrecognized escape sequence
-  --> $DIR/regex.rs:42:42
+  --> $DIR/regex.rs:47:42
    |
-LL |     let escaped_string_span = Regex::new("/b/c");
+LL |     let escaped_string_span = Regex::new("//b//c");
    |                                          ^^^^^^^^
    |
    = help: consider using a raw string literal: `r".."`
 
 error: regex syntax error: duplicate flag
-  --> $DIR/regex.rs:44:34
+  --> $DIR/regex.rs:49:34
    |
 LL |     let aux_span = Regex::new("(?ixi)");
    |                                  ^ ^
 
 error: regex syntax error: pattern can match invalid UTF-8
-  --> $DIR/regex.rs:49:53
+  --> $DIR/regex.rs:54:53
    |
 LL |     let invalid_utf8_should_lint = Regex::new("(?-u).");
    |                                                     ^
 
 error: trivial regex
-  --> $DIR/regex.rs:53:33
+  --> $DIR/regex.rs:58:33
    |
 LL |     let trivial_eq = Regex::new("^foobar$");
    |                                 ^^^^^^^^^^
@@ -114,7 +114,7 @@ LL |     let trivial_eq = Regex::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:55:48
+  --> $DIR/regex.rs:60:48
    |
 LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    |                                                ^^^^^^^^^^
@@ -122,7 +122,7 @@ LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:57:42
+  --> $DIR/regex.rs:62:42
    |
 LL |     let trivial_starts_with = Regex::new("^foobar");
    |                                          ^^^^^^^^^
@@ -130,7 +130,7 @@ LL |     let trivial_starts_with = Regex::new("^foobar");
    = help: consider using `str::starts_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:59:40
+  --> $DIR/regex.rs:64:40
    |
 LL |     let trivial_ends_with = Regex::new("foobar$");
    |                                        ^^^^^^^^^
@@ -138,7 +138,7 @@ LL |     let trivial_ends_with = Regex::new("foobar$");
    = help: consider using `str::ends_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:61:39
+  --> $DIR/regex.rs:66:39
    |
 LL |     let trivial_contains = Regex::new("foobar");
    |                                       ^^^^^^^^
@@ -146,7 +146,7 @@ LL |     let trivial_contains = Regex::new("foobar");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:63:39
+  --> $DIR/regex.rs:68:39
    |
 LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    |                                       ^^^^^^^^^^^^^^^^
@@ -154,15 +154,15 @@ LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:65:40
+  --> $DIR/regex.rs:70:40
    |
-LL |     let trivial_backslash = Regex::new("a/.b");
+LL |     let trivial_backslash = Regex::new("a//.b");
    |                                        ^^^^^^^
    |
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:68:36
+  --> $DIR/regex.rs:73:36
    |
 LL |     let trivial_empty = Regex::new("");
    |                                    ^^
@@ -170,7 +170,7 @@ LL |     let trivial_empty = Regex::new("");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:70:36
+  --> $DIR/regex.rs:75:36
    |
 LL |     let trivial_empty = Regex::new("^");
    |                                    ^^^
@@ -178,7 +178,7 @@ LL |     let trivial_empty = Regex::new("^");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:72:36
+  --> $DIR/regex.rs:77:36
    |
 LL |     let trivial_empty = Regex::new("^$");
    |                                    ^^^^
@@ -186,7 +186,7 @@ LL |     let trivial_empty = Regex::new("^$");
    = help: consider using `str::is_empty`
 
 error: trivial regex
-  --> $DIR/regex.rs:74:44
+  --> $DIR/regex.rs:79:44
    |
 LL |     let binary_trivial_empty = BRegex::new("^$");
    |                                            ^^^^
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index f1b25dc094e..b24c83d9a0d 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -30,7 +30,7 @@
 #![allow(clippy::invisible_characters)]
 #![allow(cast_ref_to_mut)]
 #![allow(suspicious_double_ref_op)]
-#![allow(cast_ref_to_mut)]
+#![allow(invalid_nan_comparisons)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
@@ -41,12 +41,10 @@
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
 #![allow(invalid_from_utf8_unchecked)]
-#![allow(invalid_nan_comparisons)]
 #![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
 #![allow(named_arguments_used_positionally)]
-#![allow(suspicious_double_ref_op)]
 #![allow(temporary_cstring_as_ptr)]
 #![allow(undropped_manually_drops)]
 #![allow(unknown_lints)]
@@ -56,7 +54,6 @@
 #![warn(clippy::blocks_in_if_conditions)]
 #![warn(clippy::blocks_in_if_conditions)]
 #![warn(clippy::box_collection)]
-#![warn(invalid_nan_comparisons)]
 #![warn(clippy::redundant_static_lifetimes)]
 #![warn(clippy::cognitive_complexity)]
 #![warn(clippy::derived_hash_with_manual_eq)]
@@ -83,6 +80,7 @@
 #![warn(clippy::invisible_characters)]
 #![warn(cast_ref_to_mut)]
 #![warn(suspicious_double_ref_op)]
+#![warn(invalid_nan_comparisons)]
 #![warn(drop_bounds)]
 #![warn(dropping_copy_types)]
 #![warn(dropping_references)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 4af511c344c..baa6345a64f 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -30,7 +30,7 @@
 #![allow(clippy::invisible_characters)]
 #![allow(cast_ref_to_mut)]
 #![allow(suspicious_double_ref_op)]
-#![allow(cast_ref_to_mut)]
+#![allow(invalid_nan_comparisons)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
@@ -41,12 +41,10 @@
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
 #![allow(invalid_from_utf8_unchecked)]
-#![allow(invalid_nan_comparisons)]
 #![allow(let_underscore_drop)]
 #![allow(enum_intrinsics_non_enums)]
 #![allow(non_fmt_panics)]
 #![allow(named_arguments_used_positionally)]
-#![allow(suspicious_double_ref_op)]
 #![allow(temporary_cstring_as_ptr)]
 #![allow(undropped_manually_drops)]
 #![allow(unknown_lints)]
@@ -56,7 +54,6 @@
 #![warn(clippy::block_in_if_condition_expr)]
 #![warn(clippy::block_in_if_condition_stmt)]
 #![warn(clippy::box_vec)]
-#![warn(clippy::cmp_nan)]
 #![warn(clippy::const_static_lifetime)]
 #![warn(clippy::cyclomatic_complexity)]
 #![warn(clippy::derive_hash_xor_eq)]
@@ -83,6 +80,7 @@
 #![warn(clippy::zero_width_space)]
 #![warn(clippy::cast_ref_to_mut)]
 #![warn(clippy::clone_double_ref)]
+#![warn(clippy::cmp_nan)]
 #![warn(clippy::drop_bounds)]
 #![warn(clippy::drop_copy)]
 #![warn(clippy::drop_ref)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 156a8f96b50..ae25c3b46bd 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,307 +7,307 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
-error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> $DIR/rename.rs:59:9
-   |
-LL | #![warn(clippy::cmp_nan)]
-   |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
-
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
+error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
+  --> $DIR/rename.rs:83:9
+   |
+LL | #![warn(clippy::cmp_nan)]
+   |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
+
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> $DIR/rename.rs:97:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:98:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:99:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:100:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:101:9
+  --> $DIR/rename.rs:99:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:102:9
+  --> $DIR/rename.rs:100:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> $DIR/rename.rs:103:9
+  --> $DIR/rename.rs:101:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:104:9
+  --> $DIR/rename.rs:102:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:105:9
+  --> $DIR/rename.rs:103:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
diff --git a/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs b/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs
index 08916398cbb..a207e422135 100644
--- a/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs
+++ b/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs
@@ -37,33 +37,33 @@ fn ifs_same_cond_fn() {
 
     if function() {
     } else if function() {
-        //~ ERROR ifs same condition
+        //~^ ERROR: `if` has the same function call as a previous `if`
     }
 
     if fn_arg(a) {
     } else if fn_arg(a) {
-        //~ ERROR ifs same condition
+        //~^ ERROR: `if` has the same function call as a previous `if`
     }
 
     if obj.method() {
     } else if obj.method() {
-        //~ ERROR ifs same condition
+        //~^ ERROR: `if` has the same function call as a previous `if`
     }
 
     if obj.method_arg(a) {
     } else if obj.method_arg(a) {
-        //~ ERROR ifs same condition
+        //~^ ERROR: `if` has the same function call as a previous `if`
     }
 
     let mut v = vec![1];
     if v.pop().is_none() {
-        //~ ERROR ifs same condition
     } else if v.pop().is_none() {
+        //~^ ERROR: `if` has the same function call as a previous `if`
     }
 
     if v.len() == 42 {
-        //~ ERROR ifs same condition
     } else if v.len() == 42 {
+        //~^ ERROR: `if` has the same function call as a previous `if`
     }
 
     if v.len() == 1 {
diff --git a/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr b/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr
index 6aacc73b90d..199e6769ff7 100644
--- a/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr
+++ b/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr
@@ -52,7 +52,7 @@ LL |     if obj.method_arg(a) {
    |        ^^^^^^^^^^^^^^^^^
 
 error: this `if` has the same function call as a previous `if`
-  --> $DIR/same_functions_in_if_condition.rs:61:15
+  --> $DIR/same_functions_in_if_condition.rs:60:15
    |
 LL |     } else if v.pop().is_none() {
    |               ^^^^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     if v.pop().is_none() {
    |        ^^^^^^^^^^^^^^^^^
 
 error: this `if` has the same function call as a previous `if`
-  --> $DIR/same_functions_in_if_condition.rs:66:15
+  --> $DIR/same_functions_in_if_condition.rs:65:15
    |
 LL |     } else if v.len() == 42 {
    |               ^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs
index 670599b0dcf..3cdbfaa1626 100644
--- a/src/tools/clippy/tests/ui/search_is_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some.rs
@@ -1,5 +1,6 @@
 //@aux-build:option_helpers.rs
 #![warn(clippy::search_is_some)]
+#![allow(clippy::useless_vec)]
 #![allow(dead_code)]
 extern crate option_helpers;
 use option_helpers::IteratorFalsePositives;
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
index 6bea8c67477..7eff614d17c 100644
--- a/src/tools/clippy/tests/ui/search_is_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some.stderr
@@ -1,5 +1,5 @@
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some.rs:14:13
+  --> $DIR/search_is_some.rs:15:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -12,7 +12,7 @@ LL | |                    ).is_some();
    = note: `-D clippy::search-is-some` implied by `-D warnings`
 
 error: called `is_some()` after searching an `Iterator` with `position`
-  --> $DIR/search_is_some.rs:20:13
+  --> $DIR/search_is_some.rs:21:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -24,7 +24,7 @@ LL | |                    ).is_some();
    = help: this is more succinctly expressed by calling `any()`
 
 error: called `is_some()` after searching an `Iterator` with `rposition`
-  --> $DIR/search_is_some.rs:26:13
+  --> $DIR/search_is_some.rs:27:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -36,13 +36,13 @@ LL | |                    ).is_some();
    = help: this is more succinctly expressed by calling `any()`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some.rs:41:20
+  --> $DIR/search_is_some.rs:42:20
    |
 LL |     let _ = (0..1).find(some_closure).is_some();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(some_closure)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some.rs:51:13
+  --> $DIR/search_is_some.rs:52:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -54,7 +54,7 @@ LL | |                    ).is_none();
    = help: this is more succinctly expressed by calling `any()` with negation
 
 error: called `is_none()` after searching an `Iterator` with `position`
-  --> $DIR/search_is_some.rs:57:13
+  --> $DIR/search_is_some.rs:58:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -66,7 +66,7 @@ LL | |                    ).is_none();
    = help: this is more succinctly expressed by calling `any()` with negation
 
 error: called `is_none()` after searching an `Iterator` with `rposition`
-  --> $DIR/search_is_some.rs:63:13
+  --> $DIR/search_is_some.rs:64:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -78,7 +78,7 @@ LL | |                    ).is_none();
    = help: this is more succinctly expressed by calling `any()` with negation
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some.rs:78:13
+  --> $DIR/search_is_some.rs:79:13
    |
 LL |     let _ = (0..1).find(some_closure).is_none();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(some_closure)`
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
index 9386618c123..08fb87cb306 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(dead_code, clippy::explicit_auto_deref)]
+#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)]
 #![warn(clippy::search_is_some)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
index 6b2537a96c2..ec3386933a6 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(dead_code, clippy::explicit_auto_deref)]
+#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)]
 #![warn(clippy::search_is_some)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
index e9116fc59f1..aa16f9da037 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(dead_code, clippy::explicit_auto_deref)]
+#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)]
 #![warn(clippy::search_is_some)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
index b1528399457..aeb6f118bed 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(dead_code, clippy::explicit_auto_deref)]
+#![allow(dead_code, clippy::explicit_auto_deref, clippy::useless_vec)]
 #![warn(clippy::search_is_some)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/self_assignment.rs b/src/tools/clippy/tests/ui/self_assignment.rs
index ef647622910..ec3ae120942 100644
--- a/src/tools/clippy/tests/ui/self_assignment.rs
+++ b/src/tools/clippy/tests/ui/self_assignment.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::self_assignment)]
+#![allow(clippy::useless_vec)]
 
 pub struct S<'a> {
     a: i32,
diff --git a/src/tools/clippy/tests/ui/self_assignment.stderr b/src/tools/clippy/tests/ui/self_assignment.stderr
index 826e0d0ba88..bed88244eea 100644
--- a/src/tools/clippy/tests/ui/self_assignment.stderr
+++ b/src/tools/clippy/tests/ui/self_assignment.stderr
@@ -1,5 +1,5 @@
 error: self-assignment of `a` to `a`
-  --> $DIR/self_assignment.rs:12:5
+  --> $DIR/self_assignment.rs:13:5
    |
 LL |     a = a;
    |     ^^^^^
@@ -7,61 +7,61 @@ LL |     a = a;
    = note: `-D clippy::self-assignment` implied by `-D warnings`
 
 error: self-assignment of `*b` to `*b`
-  --> $DIR/self_assignment.rs:13:5
+  --> $DIR/self_assignment.rs:14:5
    |
 LL |     *b = *b;
    |     ^^^^^^^
 
 error: self-assignment of `s` to `s`
-  --> $DIR/self_assignment.rs:14:5
+  --> $DIR/self_assignment.rs:15:5
    |
 LL |     s = s;
    |     ^^^^^
 
 error: self-assignment of `s.a` to `s.a`
-  --> $DIR/self_assignment.rs:15:5
+  --> $DIR/self_assignment.rs:16:5
    |
 LL |     s.a = s.a;
    |     ^^^^^^^^^
 
 error: self-assignment of `s.b[5 + 5]` to `s.b[10]`
-  --> $DIR/self_assignment.rs:16:5
+  --> $DIR/self_assignment.rs:17:5
    |
 LL |     s.b[10] = s.b[5 + 5];
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: self-assignment of `s.c[0][1]` to `s.c[0][1]`
-  --> $DIR/self_assignment.rs:17:5
+  --> $DIR/self_assignment.rs:18:5
    |
 LL |     s.c[0][1] = s.c[0][1];
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: self-assignment of `s.b[a]` to `s.b[a]`
-  --> $DIR/self_assignment.rs:18:5
+  --> $DIR/self_assignment.rs:19:5
    |
 LL |     s.b[a] = s.b[a];
    |     ^^^^^^^^^^^^^^^
 
 error: self-assignment of `*s.e` to `*s.e`
-  --> $DIR/self_assignment.rs:19:5
+  --> $DIR/self_assignment.rs:20:5
    |
 LL |     *s.e = *s.e;
    |     ^^^^^^^^^^^
 
 error: self-assignment of `s.b[10 + a]` to `s.b[a + 10]`
-  --> $DIR/self_assignment.rs:20:5
+  --> $DIR/self_assignment.rs:21:5
    |
 LL |     s.b[a + 10] = s.b[10 + a];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: self-assignment of `t.1` to `t.1`
-  --> $DIR/self_assignment.rs:23:5
+  --> $DIR/self_assignment.rs:24:5
    |
 LL |     t.1 = t.1;
    |     ^^^^^^^^^
 
 error: self-assignment of `(t.0)` to `t.0`
-  --> $DIR/self_assignment.rs:24:5
+  --> $DIR/self_assignment.rs:25:5
    |
 LL |     t.0 = (t.0);
    |     ^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/shadow.rs b/src/tools/clippy/tests/ui/shadow.rs
index 2c0fc3e3fd8..9be8c5e59d0 100644
--- a/src/tools/clippy/tests/ui/shadow.rs
+++ b/src/tools/clippy/tests/ui/shadow.rs
@@ -1,7 +1,7 @@
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)]
-#![allow(clippy::let_unit_value)]
+#![allow(clippy::let_unit_value, clippy::needless_if)]
 
 extern crate proc_macro_derive;
 
diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.fixed b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.fixed
new file mode 100644
index 00000000000..acc78d6bb04
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.fixed
@@ -0,0 +1,627 @@
+// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
+// //@run-rustfix
+#![warn(clippy::significant_drop_in_scrutinee)]
+#![allow(dead_code, unused_assignments)]
+#![allow(clippy::match_single_binding, clippy::single_match, clippy::uninlined_format_args)]
+
+use std::num::ParseIntError;
+use std::ops::Deref;
+use std::sync::atomic::{AtomicU64, Ordering};
+use std::sync::RwLock;
+use std::sync::{Mutex, MutexGuard};
+
+struct State {}
+
+impl State {
+    fn foo(&self) -> bool {
+        true
+    }
+
+    fn bar(&self) {}
+}
+
+fn should_not_trigger_lint_with_mutex_guard_outside_match() {
+    let mutex = Mutex::new(State {});
+
+    // Should not trigger lint because the temporary should drop at the `;` on line before the match
+    let is_foo = mutex.lock().unwrap().foo();
+    match is_foo {
+        true => {
+            mutex.lock().unwrap().bar();
+        },
+        false => {},
+    };
+}
+
+fn should_not_trigger_lint_with_mutex_guard_when_taking_ownership_in_match() {
+    let mutex = Mutex::new(State {});
+
+    // Should not trigger lint because the scrutinee is explicitly returning the MutexGuard,
+    // so its lifetime should not be surprising.
+    match mutex.lock() {
+        Ok(guard) => {
+            guard.foo();
+            mutex.lock().unwrap().bar();
+        },
+        _ => {},
+    };
+}
+
+fn should_trigger_lint_with_mutex_guard_in_match_scrutinee() {
+    let mutex = Mutex::new(State {});
+
+    // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it
+    // is preserved until the end of the match, but there is no clear indication that this is the
+    // case.
+    match mutex.lock().unwrap().foo() {
+        true => {
+            mutex.lock().unwrap().bar();
+        },
+        false => {},
+    };
+}
+
+fn should_not_trigger_lint_with_mutex_guard_in_match_scrutinee_when_lint_allowed() {
+    let mutex = Mutex::new(State {});
+
+    // Lint should not be triggered because it is "allowed" below.
+    #[allow(clippy::significant_drop_in_scrutinee)]
+    match mutex.lock().unwrap().foo() {
+        true => {
+            mutex.lock().unwrap().bar();
+        },
+        false => {},
+    };
+}
+
+fn should_not_trigger_lint_for_insignificant_drop() {
+    // Should not trigger lint because there are no temporaries whose drops have a significant
+    // side effect.
+    match 1u64.to_string().is_empty() {
+        true => {
+            println!("It was empty")
+        },
+        false => {
+            println!("It was not empty")
+        },
+    }
+}
+
+struct StateWithMutex {
+    m: Mutex<u64>,
+}
+
+struct MutexGuardWrapper<'a> {
+    mg: MutexGuard<'a, u64>,
+}
+
+impl<'a> MutexGuardWrapper<'a> {
+    fn get_the_value(&self) -> u64 {
+        *self.mg.deref()
+    }
+}
+
+struct MutexGuardWrapperWrapper<'a> {
+    mg: MutexGuardWrapper<'a>,
+}
+
+impl<'a> MutexGuardWrapperWrapper<'a> {
+    fn get_the_value(&self) -> u64 {
+        *self.mg.mg.deref()
+    }
+}
+
+impl StateWithMutex {
+    fn lock_m(&self) -> MutexGuardWrapper<'_> {
+        MutexGuardWrapper {
+            mg: self.m.lock().unwrap(),
+        }
+    }
+
+    fn lock_m_m(&self) -> MutexGuardWrapperWrapper<'_> {
+        MutexGuardWrapperWrapper {
+            mg: MutexGuardWrapper {
+                mg: self.m.lock().unwrap(),
+            },
+        }
+    }
+
+    fn foo(&self) -> bool {
+        true
+    }
+
+    fn bar(&self) {}
+}
+
+fn should_trigger_lint_with_wrapped_mutex() {
+    let s = StateWithMutex { m: Mutex::new(1) };
+
+    // Should trigger lint because a temporary contains a type with a significant drop and its
+    // lifetime is not obvious. Additionally, it is not obvious from looking at the scrutinee that
+    // the temporary contains such a type, making it potentially even more surprising.
+    match s.lock_m().get_the_value() {
+        1 => {
+            println!("Got 1. Is it still 1?");
+            println!("{}", s.lock_m().get_the_value());
+        },
+        2 => {
+            println!("Got 2. Is it still 2?");
+            println!("{}", s.lock_m().get_the_value());
+        },
+        _ => {},
+    }
+    println!("All done!");
+}
+
+fn should_trigger_lint_with_double_wrapped_mutex() {
+    let s = StateWithMutex { m: Mutex::new(1) };
+
+    // Should trigger lint because a temporary contains a type which further contains a type with a
+    // significant drop and its lifetime is not obvious. Additionally, it is not obvious from
+    // looking at the scrutinee that the temporary contains such a type, making it potentially even
+    // more surprising.
+    match s.lock_m_m().get_the_value() {
+        1 => {
+            println!("Got 1. Is it still 1?");
+            println!("{}", s.lock_m().get_the_value());
+        },
+        2 => {
+            println!("Got 2. Is it still 2?");
+            println!("{}", s.lock_m().get_the_value());
+        },
+        _ => {},
+    }
+    println!("All done!");
+}
+
+struct Counter {
+    i: AtomicU64,
+}
+
+#[clippy::has_significant_drop]
+struct CounterWrapper<'a> {
+    counter: &'a Counter,
+}
+
+impl<'a> CounterWrapper<'a> {
+    fn new(counter: &Counter) -> CounterWrapper {
+        counter.i.fetch_add(1, Ordering::Relaxed);
+        CounterWrapper { counter }
+    }
+}
+
+impl<'a> Drop for CounterWrapper<'a> {
+    fn drop(&mut self) {
+        self.counter.i.fetch_sub(1, Ordering::Relaxed);
+    }
+}
+
+impl Counter {
+    fn temp_increment(&self) -> Vec<CounterWrapper> {
+        vec![CounterWrapper::new(self), CounterWrapper::new(self)]
+    }
+}
+
+fn should_trigger_lint_for_vec() {
+    let counter = Counter { i: AtomicU64::new(0) };
+
+    // Should trigger lint because the temporary in the scrutinee returns a collection of types
+    // which have significant drops. The types with significant drops are also non-obvious when
+    // reading the expression in the scrutinee.
+    match counter.temp_increment().len() {
+        2 => {
+            let current_count = counter.i.load(Ordering::Relaxed);
+            println!("Current count {}", current_count);
+            assert_eq!(current_count, 0);
+        },
+        1 => {},
+        3 => {},
+        _ => {},
+    };
+}
+
+struct StateWithField {
+    s: String,
+}
+
+// Should trigger lint only on the type in the tuple which is created using a temporary
+// with a significant drop. Additionally, this test ensures that the format of the tuple
+// is preserved correctly in the suggestion.
+fn should_trigger_lint_for_tuple_in_scrutinee() {
+    let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() });
+
+    {
+        match (mutex1.lock().unwrap().s.len(), true) {
+            (3, _) => {
+                println!("started");
+                mutex1.lock().unwrap().s.len();
+                println!("done");
+            },
+            (_, _) => {},
+        };
+
+        match (true, mutex1.lock().unwrap().s.len(), true) {
+            (_, 3, _) => {
+                println!("started");
+                mutex1.lock().unwrap().s.len();
+                println!("done");
+            },
+            (_, _, _) => {},
+        };
+
+        let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() });
+        match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) {
+            (3, _, 3) => {
+                println!("started");
+                mutex1.lock().unwrap().s.len();
+                mutex2.lock().unwrap().s.len();
+                println!("done");
+            },
+            (_, _, _) => {},
+        };
+
+        let mutex3 = Mutex::new(StateWithField { s: "three".to_owned() });
+        match mutex3.lock().unwrap().s.as_str() {
+            "three" => {
+                println!("started");
+                mutex1.lock().unwrap().s.len();
+                mutex2.lock().unwrap().s.len();
+                println!("done");
+            },
+            _ => {},
+        };
+
+        match (true, mutex3.lock().unwrap().s.as_str()) {
+            (_, "three") => {
+                println!("started");
+                mutex1.lock().unwrap().s.len();
+                mutex2.lock().unwrap().s.len();
+                println!("done");
+            },
+            (_, _) => {},
+        };
+    }
+}
+
+// Should trigger lint when either side of a binary operation creates a temporary with a
+// significant drop.
+// To avoid potential unnecessary copies or creating references that would trigger the significant
+// drop problem, the lint recommends moving the entire binary operation.
+fn should_trigger_lint_for_accessing_field_in_mutex_in_one_side_of_binary_op() {
+    let mutex = Mutex::new(StateWithField { s: "state".to_owned() });
+
+    match mutex.lock().unwrap().s.len() > 1 {
+        true => {
+            mutex.lock().unwrap().s.len();
+        },
+        false => {},
+    };
+
+    match 1 < mutex.lock().unwrap().s.len() {
+        true => {
+            mutex.lock().unwrap().s.len();
+        },
+        false => {},
+    };
+}
+
+// Should trigger lint when both sides of a binary operation creates a temporary with a
+// significant drop.
+// To avoid potential unnecessary copies or creating references that would trigger the significant
+// drop problem, the lint recommends moving the entire binary operation.
+fn should_trigger_lint_for_accessing_fields_in_mutex_in_both_sides_of_binary_op() {
+    let mutex1 = Mutex::new(StateWithField { s: "state".to_owned() });
+    let mutex2 = Mutex::new(StateWithField {
+        s: "statewithfield".to_owned(),
+    });
+
+    match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() {
+        true => {
+            println!(
+                "{} < {}",
+                mutex1.lock().unwrap().s.len(),
+                mutex2.lock().unwrap().s.len()
+            );
+        },
+        false => {},
+    };
+
+    match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() {
+        true => {
+            println!(
+                "{} >= {}",
+                mutex1.lock().unwrap().s.len(),
+                mutex2.lock().unwrap().s.len()
+            );
+        },
+        false => {},
+    };
+}
+
+fn should_not_trigger_lint_for_closure_in_scrutinee() {
+    let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() });
+
+    let get_mutex_guard = || mutex1.lock().unwrap().s.len();
+
+    // Should not trigger lint because the temporary with a significant drop will be dropped
+    // at the end of the closure, so the MutexGuard will be unlocked and not have a potentially
+    // surprising lifetime.
+    match get_mutex_guard() > 1 {
+        true => {
+            mutex1.lock().unwrap().s.len();
+        },
+        false => {},
+    };
+}
+
+fn should_trigger_lint_for_return_from_closure_in_scrutinee() {
+    let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() });
+
+    let get_mutex_guard = || mutex1.lock().unwrap();
+
+    // Should trigger lint because the temporary with a significant drop is returned from the
+    // closure but not used directly in any match arms, so it has a potentially surprising lifetime.
+    match get_mutex_guard().s.len() > 1 {
+        true => {
+            mutex1.lock().unwrap().s.len();
+        },
+        false => {},
+    };
+}
+
+fn should_trigger_lint_for_return_from_match_in_scrutinee() {
+    let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() });
+    let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() });
+
+    let i = 100;
+
+    // Should trigger lint because the nested match within the scrutinee returns a temporary with a
+    // significant drop is but not used directly in any match arms, so it has a potentially
+    // surprising lifetime.
+    match match i {
+        100 => mutex1.lock().unwrap(),
+        _ => mutex2.lock().unwrap(),
+    }
+    .s
+    .len()
+        > 1
+    {
+        true => {
+            mutex1.lock().unwrap().s.len();
+        },
+        false => {
+            println!("nothing to do here");
+        },
+    };
+}
+
+fn should_trigger_lint_for_return_from_if_in_scrutinee() {
+    let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() });
+    let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() });
+
+    let i = 100;
+
+    // Should trigger lint because the nested if-expression within the scrutinee returns a temporary
+    // with a significant drop is but not used directly in any match arms, so it has a potentially
+    // surprising lifetime.
+    match if i > 1 {
+        mutex1.lock().unwrap()
+    } else {
+        mutex2.lock().unwrap()
+    }
+    .s
+    .len()
+        > 1
+    {
+        true => {
+            mutex1.lock().unwrap().s.len();
+        },
+        false => {},
+    };
+}
+
+fn should_not_trigger_lint_for_if_in_scrutinee() {
+    let mutex = Mutex::new(StateWithField { s: "state".to_owned() });
+
+    let i = 100;
+
+    // Should not trigger the lint because the temporary with a significant drop *is* dropped within
+    // the body of the if-expression nested within the match scrutinee, and therefore does not have
+    // a potentially surprising lifetime.
+    match if i > 1 {
+        mutex.lock().unwrap().s.len() > 1
+    } else {
+        false
+    } {
+        true => {
+            mutex.lock().unwrap().s.len();
+        },
+        false => {},
+    };
+}
+
+struct StateWithBoxedMutexGuard {
+    u: Mutex<u64>,
+}
+
+impl StateWithBoxedMutexGuard {
+    fn new() -> StateWithBoxedMutexGuard {
+        StateWithBoxedMutexGuard { u: Mutex::new(42) }
+    }
+    fn lock(&self) -> Box<MutexGuard<u64>> {
+        Box::new(self.u.lock().unwrap())
+    }
+}
+
+fn should_trigger_lint_for_boxed_mutex_guard() {
+    let s = StateWithBoxedMutexGuard::new();
+
+    // Should trigger lint because a temporary Box holding a type with a significant drop in a match
+    // scrutinee may have a potentially surprising lifetime.
+    match s.lock().deref().deref() {
+        0 | 1 => println!("Value was less than 2"),
+        _ => println!("Value is {}", s.lock().deref()),
+    };
+}
+
+struct StateStringWithBoxedMutexGuard {
+    s: Mutex<String>,
+}
+
+impl StateStringWithBoxedMutexGuard {
+    fn new() -> StateStringWithBoxedMutexGuard {
+        StateStringWithBoxedMutexGuard {
+            s: Mutex::new("A String".to_owned()),
+        }
+    }
+    fn lock(&self) -> Box<MutexGuard<String>> {
+        Box::new(self.s.lock().unwrap())
+    }
+}
+
+fn should_trigger_lint_for_boxed_mutex_guard_holding_string() {
+    let s = StateStringWithBoxedMutexGuard::new();
+
+    let matcher = String::from("A String");
+
+    // Should trigger lint because a temporary Box holding a type with a significant drop in a match
+    // scrutinee may have a potentially surprising lifetime.
+    match s.lock().deref().deref() {
+        matcher => println!("Value is {}", s.lock().deref()),
+        _ => println!("Value was not a match"),
+    };
+}
+
+struct StateWithIntField {
+    i: u64,
+}
+
+// Should trigger lint when either side of an assign expression contains a temporary with a
+// significant drop, because the temporary's lifetime will be extended to the end of the match.
+// To avoid potential unnecessary copies or creating references that would trigger the significant
+// drop problem, the lint recommends moving the entire binary operation.
+fn should_trigger_lint_in_assign_expr() {
+    let mutex = Mutex::new(StateWithIntField { i: 10 });
+
+    let mut i = 100;
+
+    match mutex.lock().unwrap().i = i {
+        _ => {
+            println!("{}", mutex.lock().unwrap().i);
+        },
+    };
+
+    match i = mutex.lock().unwrap().i {
+        _ => {
+            println!("{}", mutex.lock().unwrap().i);
+        },
+    };
+
+    match mutex.lock().unwrap().i += 1 {
+        _ => {
+            println!("{}", mutex.lock().unwrap().i);
+        },
+    };
+
+    match i += mutex.lock().unwrap().i {
+        _ => {
+            println!("{}", mutex.lock().unwrap().i);
+        },
+    };
+}
+
+#[derive(Debug)]
+enum RecursiveEnum {
+    Foo(Option<Box<RecursiveEnum>>),
+}
+
+#[derive(Debug)]
+enum GenericRecursiveEnum<T> {
+    Foo(T, Option<Box<GenericRecursiveEnum<T>>>),
+}
+
+fn should_not_cause_stack_overflow() {
+    // Test that when a type recursively contains itself, a stack overflow does not occur when
+    // checking sub-types for significant drops.
+    let f = RecursiveEnum::Foo(Some(Box::new(RecursiveEnum::Foo(None))));
+    match f {
+        RecursiveEnum::Foo(Some(f)) => {
+            println!("{:?}", f)
+        },
+        RecursiveEnum::Foo(f) => {
+            println!("{:?}", f)
+        },
+    }
+
+    let f = GenericRecursiveEnum::Foo(1u64, Some(Box::new(GenericRecursiveEnum::Foo(2u64, None))));
+    match f {
+        GenericRecursiveEnum::Foo(i, Some(f)) => {
+            println!("{} {:?}", i, f)
+        },
+        GenericRecursiveEnum::Foo(i, f) => {
+            println!("{} {:?}", i, f)
+        },
+    }
+}
+
+fn should_not_produce_lint_for_try_desugar() -> Result<u64, ParseIntError> {
+    // TryDesugar (i.e. using `?` for a Result type) will turn into a match but is out of scope
+    // for this lint
+    let rwlock = RwLock::new("1".to_string());
+    let result = rwlock.read().unwrap().parse::<u64>()?;
+    println!("{}", result);
+    rwlock.write().unwrap().push('2');
+    Ok(result)
+}
+
+struct ResultReturner {
+    s: String,
+}
+
+impl ResultReturner {
+    fn to_number(&self) -> Result<i64, ParseIntError> {
+        self.s.parse::<i64>()
+    }
+}
+
+fn should_trigger_lint_for_non_ref_move_and_clone_suggestion() {
+    let rwlock = RwLock::<ResultReturner>::new(ResultReturner { s: "1".to_string() });
+    match rwlock.read().unwrap().to_number() {
+        Ok(n) => println!("Converted to number: {}", n),
+        Err(e) => println!("Could not convert {} to number", e),
+    };
+}
+
+fn should_trigger_lint_for_read_write_lock_for_loop() {
+    // For-in loops desugar to match expressions and are prone to the type of deadlock this lint is
+    // designed to look for.
+    let rwlock = RwLock::<Vec<String>>::new(vec!["1".to_string()]);
+    for s in rwlock.read().unwrap().iter() {
+        println!("{}", s);
+    }
+}
+
+fn do_bar(mutex: &Mutex<State>) {
+    mutex.lock().unwrap().bar();
+}
+
+fn should_trigger_lint_without_significant_drop_in_arm() {
+    let mutex = Mutex::new(State {});
+
+    // Should trigger lint because the lifetime of the temporary MutexGuard is surprising because it
+    // is preserved until the end of the match, but there is no clear indication that this is the
+    // case.
+    match mutex.lock().unwrap().foo() {
+        true => do_bar(&mutex),
+        false => {},
+    };
+}
+
+fn should_not_trigger_on_significant_iterator_drop() {
+    let lines = std::io::stdin().lines();
+    for line in lines {
+        println!("foo: {}", line.unwrap());
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
index ee7f2b0631a..7b848ead784 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
@@ -16,6 +16,18 @@ pub fn complex_return_triggers_the_lint() -> i32 {
     foo()
 }
 
+pub fn issue_10413() {
+    let mutex = Mutex::new(Some(1));
+    let opt = Some(1);
+    if opt.is_some() {
+        let lock = mutex.lock().unwrap();
+        let _ = *lock;
+        if opt.is_some() {
+            let _ = *lock;
+        }
+    }
+}
+
 pub fn path_return_can_be_ignored() -> i32 {
     let mutex = Mutex::new(1);
     let lock = mutex.lock().unwrap();
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.rs b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
index 9c139deb95f..36f77cf1bdb 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.rs
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
@@ -15,6 +15,18 @@ pub fn complex_return_triggers_the_lint() -> i32 {
     foo()
 }
 
+pub fn issue_10413() {
+    let mutex = Mutex::new(Some(1));
+    let opt = Some(1);
+    if opt.is_some() {
+        let lock = mutex.lock().unwrap();
+        let _ = *lock;
+        if opt.is_some() {
+            let _ = *lock;
+        }
+    }
+}
+
 pub fn path_return_can_be_ignored() -> i32 {
     let mutex = Mutex::new(1);
     let lock = mutex.lock().unwrap();
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
index ab8ce356ec7..3bdac0b0a6b 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
@@ -23,7 +23,7 @@ LL +     drop(lock);
    |
 
 error: temporary with significant `Drop` can be early dropped
-  --> $DIR/significant_drop_tightening.rs:44:13
+  --> $DIR/significant_drop_tightening.rs:56:13
    |
 LL | /     {
 LL | |         let mutex = Mutex::new(1i32);
@@ -43,7 +43,7 @@ LL +         drop(lock);
    |
 
 error: temporary with significant `Drop` can be early dropped
-  --> $DIR/significant_drop_tightening.rs:65:13
+  --> $DIR/significant_drop_tightening.rs:77:13
    |
 LL | /     {
 LL | |         let mutex = Mutex::new(1i32);
@@ -67,7 +67,7 @@ LL +
    |
 
 error: temporary with significant `Drop` can be early dropped
-  --> $DIR/significant_drop_tightening.rs:71:17
+  --> $DIR/significant_drop_tightening.rs:83:17
    |
 LL | /     {
 LL | |         let mutex = Mutex::new(vec![1i32]);
diff --git a/src/tools/clippy/tests/ui/single_call_fn.rs b/src/tools/clippy/tests/ui/single_call_fn.rs
new file mode 100644
index 00000000000..76e175014b8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/single_call_fn.rs
@@ -0,0 +1,74 @@
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(clippy::redundant_closure_call, unused)]
+#![warn(clippy::single_call_fn)]
+#![no_main]
+
+#[macro_use]
+extern crate proc_macros;
+
+// Do not lint since it's public
+pub fn f() {}
+
+fn i() {}
+fn j() {}
+
+fn h() {
+    // Linted
+    let a = i;
+    // Do not lint closures
+    let a = (|| {
+        // Not linted
+        a();
+        // Imo, it's reasonable to lint this as the function is still only being used once. Just in
+        // a closure.
+        j();
+    });
+    a();
+}
+
+fn g() {
+    f();
+}
+
+fn c() {
+    println!("really");
+    println!("long");
+    println!("function...");
+}
+
+fn d() {
+    c();
+}
+
+fn a() {}
+
+fn b() {
+    a();
+
+    external! {
+        fn lol() {
+            lol_inner();
+        }
+        fn lol_inner() {}
+    }
+    with_span! {
+        span
+        fn lol2() {
+            lol2_inner();
+        }
+        fn lol2_inner() {}
+    }
+}
+
+fn e() {
+    b();
+    b();
+}
+
+#[test]
+fn k() {}
+
+#[test]
+fn l() {
+    k();
+}
diff --git a/src/tools/clippy/tests/ui/single_call_fn.stderr b/src/tools/clippy/tests/ui/single_call_fn.stderr
new file mode 100644
index 00000000000..9ef8c487844
--- /dev/null
+++ b/src/tools/clippy/tests/ui/single_call_fn.stderr
@@ -0,0 +1,55 @@
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:33:1
+   |
+LL | / fn c() {
+LL | |     println!("really");
+LL | |     println!("long");
+LL | |     println!("function...");
+LL | | }
+   | |_^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:40:5
+   |
+LL |     c();
+   |     ^
+   = note: `-D clippy::single-call-fn` implied by `-D warnings`
+
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:12:1
+   |
+LL | fn i() {}
+   | ^^^^^^^^^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:17:13
+   |
+LL |     let a = i;
+   |             ^
+
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:43:1
+   |
+LL | fn a() {}
+   | ^^^^^^^^^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:46:5
+   |
+LL |     a();
+   |     ^
+
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:13:1
+   |
+LL | fn j() {}
+   | ^^^^^^^^^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:24:9
+   |
+LL |         j();
+   |         ^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.fixed b/src/tools/clippy/tests/ui/single_char_add_str.fixed
index cbcf1ab21c9..cb301c8bc15 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.fixed
+++ b/src/tools/clippy/tests/ui/single_char_add_str.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::single_char_add_str)]
+#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes)]
 
 macro_rules! get_string {
     () => {
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.rs b/src/tools/clippy/tests/ui/single_char_add_str.rs
index a1f005cc833..99baf35ac29 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.rs
+++ b/src/tools/clippy/tests/ui/single_char_add_str.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::single_char_add_str)]
+#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes)]
 
 macro_rules! get_string {
     () => {
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.stderr b/src/tools/clippy/tests/ui/single_char_add_str.stderr
index 55d91583ad0..3f93c18470e 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.stderr
+++ b/src/tools/clippy/tests/ui/single_char_add_str.stderr
@@ -1,5 +1,5 @@
 error: calling `push_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:14:5
+  --> $DIR/single_char_add_str.rs:15:5
    |
 LL |     string.push_str("R");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('R')`
@@ -7,85 +7,85 @@ LL |     string.push_str("R");
    = note: `-D clippy::single-char-add-str` implied by `-D warnings`
 
 error: calling `push_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:15:5
+  --> $DIR/single_char_add_str.rs:16:5
    |
 LL |     string.push_str("'");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/'')`
 
 error: calling `push_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:20:5
+  --> $DIR/single_char_add_str.rs:21:5
    |
 LL |     string.push_str("/x52");
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/x52')`
 
 error: calling `push_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:21:5
+  --> $DIR/single_char_add_str.rs:22:5
    |
 LL |     string.push_str("/u{0052}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('/u{0052}')`
 
 error: calling `push_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:22:5
+  --> $DIR/single_char_add_str.rs:23:5
    |
 LL |     string.push_str(r##"a"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('a')`
 
 error: calling `push_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:24:5
+  --> $DIR/single_char_add_str.rs:25:5
    |
 LL |     get_string!().push_str("ö");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `get_string!().push('ö')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:29:5
+  --> $DIR/single_char_add_str.rs:30:5
    |
 LL |     string.insert_str(0, "R");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, 'R')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:30:5
+  --> $DIR/single_char_add_str.rs:31:5
    |
 LL |     string.insert_str(1, "'");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(1, '/'')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:35:5
+  --> $DIR/single_char_add_str.rs:36:5
    |
 LL |     string.insert_str(0, "/x52");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '/x52')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:36:5
+  --> $DIR/single_char_add_str.rs:37:5
    |
 LL |     string.insert_str(0, "/u{0052}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '/u{0052}')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:38:5
+  --> $DIR/single_char_add_str.rs:39:5
    |
 LL |     string.insert_str(x, r##"a"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(x, 'a')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:40:5
+  --> $DIR/single_char_add_str.rs:41:5
    |
 LL |     string.insert_str(Y, r##"a"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, 'a')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:41:5
+  --> $DIR/single_char_add_str.rs:42:5
    |
 LL |     string.insert_str(Y, r##"""##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '"')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:42:5
+  --> $DIR/single_char_add_str.rs:43:5
    |
 LL |     string.insert_str(Y, r##"'"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '/'')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> $DIR/single_char_add_str.rs:44:5
+  --> $DIR/single_char_add_str.rs:45:5
    |
 LL |     get_string!().insert_str(1, "?");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `get_string!().insert(1, '?')`
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.fixed b/src/tools/clippy/tests/ui/single_char_pattern.fixed
index dba89872070..7ae62231acc 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.fixed
+++ b/src/tools/clippy/tests/ui/single_char_pattern.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused_must_use)]
+#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)]
 
 use std::collections::HashSet;
 
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.rs b/src/tools/clippy/tests/ui/single_char_pattern.rs
index 6a145a14bfd..0604624e767 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.rs
+++ b/src/tools/clippy/tests/ui/single_char_pattern.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused_must_use)]
+#![allow(clippy::needless_raw_strings, clippy::needless_raw_string_hashes, unused_must_use)]
 
 use std::collections::HashSet;
 
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.stderr b/src/tools/clippy/tests/ui/single_char_pattern.stderr
index 5564aac674d..5ae2450c226 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.stderr
+++ b/src/tools/clippy/tests/ui/single_char_pattern.stderr
@@ -226,13 +226,13 @@ error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:65:13
    |
 LL |     x.split(r#"/"#);
-   |             ^^^^^^ help: try using a `char` instead: `'/'`
+   |             ^^^^^^ help: try using a `char` instead: `'//'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:66:13
    |
 LL |     x.split(r"/");
-   |             ^^^^ help: try using a `char` instead: `'/'`
+   |             ^^^^ help: try using a `char` instead: `'//'`
 
 error: aborting due to 39 previous errors
 
diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed
index 1697a0cf29b..598f259415d 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.fixed
+++ b/src/tools/clippy/tests/ui/single_element_loop.fixed
@@ -1,6 +1,8 @@
 //@run-rustfix
 // Tests from for_loop.rs that don't have suggestions
 
+#![allow(clippy::single_range_in_vec_init)]
+
 #[warn(clippy::single_element_loop)]
 fn main() {
     let item1 = 2;
diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs
index 860424f42dd..3fc461735a4 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.rs
+++ b/src/tools/clippy/tests/ui/single_element_loop.rs
@@ -1,6 +1,8 @@
 //@run-rustfix
 // Tests from for_loop.rs that don't have suggestions
 
+#![allow(clippy::single_range_in_vec_init)]
+
 #[warn(clippy::single_element_loop)]
 fn main() {
     let item1 = 2;
diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr
index 14437a59745..c40c6198945 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.stderr
+++ b/src/tools/clippy/tests/ui/single_element_loop.stderr
@@ -1,5 +1,5 @@
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:7:5
+  --> $DIR/single_element_loop.rs:9:5
    |
 LL | /     for item in &[item1] {
 LL | |         dbg!(item);
@@ -16,7 +16,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:11:5
+  --> $DIR/single_element_loop.rs:13:5
    |
 LL | /     for item in [item1].iter() {
 LL | |         dbg!(item);
@@ -32,7 +32,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:15:5
+  --> $DIR/single_element_loop.rs:17:5
    |
 LL | /     for item in &[0..5] {
 LL | |         dbg!(item);
@@ -48,7 +48,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:19:5
+  --> $DIR/single_element_loop.rs:21:5
    |
 LL | /     for item in [0..5].iter_mut() {
 LL | |         dbg!(item);
@@ -64,7 +64,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:23:5
+  --> $DIR/single_element_loop.rs:25:5
    |
 LL | /     for item in [0..5] {
 LL | |         dbg!(item);
@@ -80,7 +80,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:27:5
+  --> $DIR/single_element_loop.rs:29:5
    |
 LL | /     for item in [0..5].into_iter() {
 LL | |         dbg!(item);
@@ -96,7 +96,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:46:5
+  --> $DIR/single_element_loop.rs:48:5
    |
 LL | /     for _ in [42] {
 LL | |         let _f = |n: u32| {
diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed
index 77a2cf3b991..e7b1fd6a85f 100644
--- a/src/tools/clippy/tests/ui/single_match.fixed
+++ b/src/tools/clippy/tests/ui/single_match.fixed
@@ -1,6 +1,11 @@
 //@run-rustfix
 #![warn(clippy::single_match)]
-#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)]
+#![allow(
+    unused,
+    clippy::uninlined_format_args,
+    clippy::needless_if,
+    clippy::redundant_pattern_matching
+)]
 fn dummy() {}
 
 fn single_match() {
@@ -207,3 +212,43 @@ fn issue_10808(bar: Option<i32>) {
         }
     }
 }
+
+mod issue8634 {
+    struct SomeError(i32, i32);
+
+    fn foo(x: Result<i32, ()>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(()) => {
+                // Ignore this error because blah blah blah.
+            },
+        }
+    }
+
+    fn bar(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                // TODO: Process the error properly.
+            },
+        }
+    }
+
+    fn block_comment(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                /*
+                let's make sure that this also
+                does not lint block comments.
+                */
+            },
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index 8d0ab5b99ad..1515a7053e5 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -1,6 +1,11 @@
 //@run-rustfix
 #![warn(clippy::single_match)]
-#![allow(unused, clippy::uninlined_format_args, clippy::redundant_pattern_matching)]
+#![allow(
+    unused,
+    clippy::uninlined_format_args,
+    clippy::needless_if,
+    clippy::redundant_pattern_matching
+)]
 fn dummy() {}
 
 fn single_match() {
@@ -265,3 +270,43 @@ fn issue_10808(bar: Option<i32>) {
         _ => {},
     }
 }
+
+mod issue8634 {
+    struct SomeError(i32, i32);
+
+    fn foo(x: Result<i32, ()>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(()) => {
+                // Ignore this error because blah blah blah.
+            },
+        }
+    }
+
+    fn bar(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                // TODO: Process the error properly.
+            },
+        }
+    }
+
+    fn block_comment(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                /*
+                let's make sure that this also
+                does not lint block comments.
+                */
+            },
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index dad66e2ab2e..ef901513240 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:9:5
+  --> $DIR/single_match.rs:14:5
    |
 LL | /     match x {
 LL | |         Some(y) => {
@@ -18,7 +18,7 @@ LL ~     };
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:17:5
+  --> $DIR/single_match.rs:22:5
    |
 LL | /     match x {
 LL | |         // Note the missing block braces.
@@ -30,7 +30,7 @@ LL | |     }
    | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:26:5
+  --> $DIR/single_match.rs:31:5
    |
 LL | /     match z {
 LL | |         (2..=3, 7..=9) => dummy(),
@@ -39,7 +39,7 @@ LL | |     };
    | |_____^ help: try this: `if let (2..=3, 7..=9) = z { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:55:5
+  --> $DIR/single_match.rs:60:5
    |
 LL | /     match x {
 LL | |         Some(y) => dummy(),
@@ -48,7 +48,7 @@ LL | |     };
    | |_____^ help: try this: `if let Some(y) = x { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:60:5
+  --> $DIR/single_match.rs:65:5
    |
 LL | /     match y {
 LL | |         Ok(y) => dummy(),
@@ -57,7 +57,7 @@ LL | |     };
    | |_____^ help: try this: `if let Ok(y) = y { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:67:5
+  --> $DIR/single_match.rs:72:5
    |
 LL | /     match c {
 LL | |         Cow::Borrowed(..) => dummy(),
@@ -66,7 +66,7 @@ LL | |     };
    | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> $DIR/single_match.rs:88:5
+  --> $DIR/single_match.rs:93:5
    |
 LL | /     match x {
 LL | |         "test" => println!(),
@@ -75,7 +75,7 @@ LL | |     }
    | |_____^ help: try this: `if x == "test" { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> $DIR/single_match.rs:101:5
+  --> $DIR/single_match.rs:106:5
    |
 LL | /     match x {
 LL | |         Foo::A => println!(),
@@ -84,7 +84,7 @@ LL | |     }
    | |_____^ help: try this: `if x == Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> $DIR/single_match.rs:107:5
+  --> $DIR/single_match.rs:112:5
    |
 LL | /     match x {
 LL | |         FOO_C => println!(),
@@ -93,7 +93,7 @@ LL | |     }
    | |_____^ help: try this: `if x == FOO_C { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> $DIR/single_match.rs:112:5
+  --> $DIR/single_match.rs:117:5
    |
 LL | /     match &&x {
 LL | |         Foo::A => println!(),
@@ -102,7 +102,7 @@ LL | |     }
    | |_____^ help: try this: `if x == Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> $DIR/single_match.rs:118:5
+  --> $DIR/single_match.rs:123:5
    |
 LL | /     match &x {
 LL | |         Foo::A => println!(),
@@ -111,7 +111,7 @@ LL | |     }
    | |_____^ help: try this: `if x == &Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:135:5
+  --> $DIR/single_match.rs:140:5
    |
 LL | /     match x {
 LL | |         Bar::A => println!(),
@@ -120,7 +120,7 @@ LL | |     }
    | |_____^ help: try this: `if let Bar::A = x { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:143:5
+  --> $DIR/single_match.rs:148:5
    |
 LL | /     match x {
 LL | |         None => println!(),
@@ -129,7 +129,7 @@ LL | |     };
    | |_____^ help: try this: `if let None = x { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:165:5
+  --> $DIR/single_match.rs:170:5
    |
 LL | /     match x {
 LL | |         (Some(_), _) => {},
@@ -138,7 +138,7 @@ LL | |     }
    | |_____^ help: try this: `if let (Some(_), _) = x {}`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:171:5
+  --> $DIR/single_match.rs:176:5
    |
 LL | /     match x {
 LL | |         (Some(E::V), _) => todo!(),
@@ -147,7 +147,7 @@ LL | |     }
    | |_____^ help: try this: `if let (Some(E::V), _) = x { todo!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:177:5
+  --> $DIR/single_match.rs:182:5
    |
 LL | /     match (Some(42), Some(E::V), Some(42)) {
 LL | |         (.., Some(E::V), _) => {},
@@ -156,7 +156,7 @@ LL | |     }
    | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:249:5
+  --> $DIR/single_match.rs:254:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -176,7 +176,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:257:5
+  --> $DIR/single_match.rs:262:5
    |
 LL | /     match bar {
 LL | |         #[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed
index f88498655a4..fcc8f14803d 100644
--- a/src/tools/clippy/tests/ui/single_match_else.fixed
+++ b/src/tools/clippy/tests/ui/single_match_else.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index b34b9553919..77afd58a08d 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/single_range_in_vec_init.rs b/src/tools/clippy/tests/ui/single_range_in_vec_init.rs
new file mode 100644
index 00000000000..833e1c43bfc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/single_range_in_vec_init.rs
@@ -0,0 +1,58 @@
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(clippy::no_effect, clippy::useless_vec, unused)]
+#![warn(clippy::single_range_in_vec_init)]
+#![feature(generic_arg_infer)]
+
+#[macro_use]
+extern crate proc_macros;
+
+macro_rules! a {
+    () => {
+        vec![0..200];
+    };
+}
+
+fn awa<T: PartialOrd>(start: T, end: T) {
+    [start..end];
+}
+
+fn awa_vec<T: PartialOrd>(start: T, end: T) {
+    vec![start..end];
+}
+
+fn main() {
+    // Lint
+    [0..200];
+    vec![0..200];
+    [0u8..200];
+    [0usize..200];
+    [0..200usize];
+    vec![0u8..200];
+    vec![0usize..200];
+    vec![0..200usize];
+    // Only suggest collect
+    [0..200isize];
+    vec![0..200isize];
+    // Do not lint
+    [0..200, 0..100];
+    vec![0..200, 0..100];
+    [0.0..200.0];
+    vec![0.0..200.0];
+    // `Copy` is not implemented for `Range`, so this doesn't matter
+    // FIXME: [0..200; 2];
+    // FIXME: [vec!0..200; 2];
+
+    // Unfortunately skips any macros
+    a!();
+
+    // Skip external macros and procedural macros
+    external! {
+        [0..200];
+        vec![0..200];
+    }
+    with_span! {
+        span
+        [0..200];
+        vec![0..200];
+    }
+}
diff --git a/src/tools/clippy/tests/ui/single_range_in_vec_init.stderr b/src/tools/clippy/tests/ui/single_range_in_vec_init.stderr
new file mode 100644
index 00000000000..3e3d521f4a5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/single_range_in_vec_init.stderr
@@ -0,0 +1,145 @@
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:25:5
+   |
+LL |     [0..200];
+   |     ^^^^^^^^
+   |
+   = note: `-D clippy::single-range-in-vec-init` implied by `-D warnings`
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200).collect::<std::vec::Vec<i32>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200, try
+   |
+LL |     [0; 200];
+   |      ~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:26:5
+   |
+LL |     vec![0..200];
+   |     ^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200).collect::<std::vec::Vec<i32>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200, try
+   |
+LL |     vec![0; 200];
+   |          ~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:27:5
+   |
+LL |     [0u8..200];
+   |     ^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0u8..200).collect::<std::vec::Vec<u8>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200, try
+   |
+LL |     [0u8; 200];
+   |      ~~~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:28:5
+   |
+LL |     [0usize..200];
+   |     ^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0usize..200).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200, try
+   |
+LL |     [0usize; 200];
+   |      ~~~~~~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:29:5
+   |
+LL |     [0..200usize];
+   |     ^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200usize).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200usize, try
+   |
+LL |     [0; 200usize];
+   |      ~~~~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:30:5
+   |
+LL |     vec![0u8..200];
+   |     ^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0u8..200).collect::<std::vec::Vec<u8>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200, try
+   |
+LL |     vec![0u8; 200];
+   |          ~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:31:5
+   |
+LL |     vec![0usize..200];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0usize..200).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200, try
+   |
+LL |     vec![0usize; 200];
+   |          ~~~~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:32:5
+   |
+LL |     vec![0..200usize];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200usize).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200usize, try
+   |
+LL |     vec![0; 200usize];
+   |          ~~~~~~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:34:5
+   |
+LL |     [0..200isize];
+   |     ^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200isize).collect::<std::vec::Vec<isize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:35:5
+   |
+LL |     vec![0..200isize];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200isize).collect::<std::vec::Vec<isize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/skip_while_next.rs b/src/tools/clippy/tests/ui/skip_while_next.rs
index 62574e2c8ce..8e4cd82cec3 100644
--- a/src/tools/clippy/tests/ui/skip_while_next.rs
+++ b/src/tools/clippy/tests/ui/skip_while_next.rs
@@ -1,7 +1,7 @@
 //@aux-build:option_helpers.rs
 
 #![warn(clippy::skip_while_next)]
-#![allow(clippy::disallowed_names)]
+#![allow(clippy::disallowed_names, clippy::useless_vec)]
 
 extern crate option_helpers;
 use option_helpers::IteratorFalsePositives;
diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.fixed b/src/tools/clippy/tests/ui/stable_sort_primitive.fixed
index 1370dd2df4d..50c1fc71a3f 100644
--- a/src/tools/clippy/tests/ui/stable_sort_primitive.fixed
+++ b/src/tools/clippy/tests/ui/stable_sort_primitive.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::stable_sort_primitive)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // positive examples
diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.rs b/src/tools/clippy/tests/ui/stable_sort_primitive.rs
index cd344dd1238..bd1bb428f2b 100644
--- a/src/tools/clippy/tests/ui/stable_sort_primitive.rs
+++ b/src/tools/clippy/tests/ui/stable_sort_primitive.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::stable_sort_primitive)]
+#![allow(clippy::useless_vec)]
 
 fn main() {
     // positive examples
diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.stderr b/src/tools/clippy/tests/ui/stable_sort_primitive.stderr
index 1432fdcff77..aa5d7b7e491 100644
--- a/src/tools/clippy/tests/ui/stable_sort_primitive.stderr
+++ b/src/tools/clippy/tests/ui/stable_sort_primitive.stderr
@@ -1,5 +1,5 @@
 error: used `sort` on primitive type `i32`
-  --> $DIR/stable_sort_primitive.rs:7:5
+  --> $DIR/stable_sort_primitive.rs:8:5
    |
 LL |     vec.sort();
    |     ^^^^^^^^^^ help: try: `vec.sort_unstable()`
@@ -8,7 +8,7 @@ LL |     vec.sort();
    = note: `-D clippy::stable-sort-primitive` implied by `-D warnings`
 
 error: used `sort` on primitive type `bool`
-  --> $DIR/stable_sort_primitive.rs:9:5
+  --> $DIR/stable_sort_primitive.rs:10:5
    |
 LL |     vec.sort();
    |     ^^^^^^^^^^ help: try: `vec.sort_unstable()`
@@ -16,7 +16,7 @@ LL |     vec.sort();
    = note: an unstable sort typically performs faster without any observable difference for this data type
 
 error: used `sort` on primitive type `char`
-  --> $DIR/stable_sort_primitive.rs:11:5
+  --> $DIR/stable_sort_primitive.rs:12:5
    |
 LL |     vec.sort();
    |     ^^^^^^^^^^ help: try: `vec.sort_unstable()`
@@ -24,7 +24,7 @@ LL |     vec.sort();
    = note: an unstable sort typically performs faster without any observable difference for this data type
 
 error: used `sort` on primitive type `str`
-  --> $DIR/stable_sort_primitive.rs:13:5
+  --> $DIR/stable_sort_primitive.rs:14:5
    |
 LL |     vec.sort();
    |     ^^^^^^^^^^ help: try: `vec.sort_unstable()`
@@ -32,7 +32,7 @@ LL |     vec.sort();
    = note: an unstable sort typically performs faster without any observable difference for this data type
 
 error: used `sort` on primitive type `tuple`
-  --> $DIR/stable_sort_primitive.rs:15:5
+  --> $DIR/stable_sort_primitive.rs:16:5
    |
 LL |     vec.sort();
    |     ^^^^^^^^^^ help: try: `vec.sort_unstable()`
@@ -40,7 +40,7 @@ LL |     vec.sort();
    = note: an unstable sort typically performs faster without any observable difference for this data type
 
 error: used `sort` on primitive type `array`
-  --> $DIR/stable_sort_primitive.rs:17:5
+  --> $DIR/stable_sort_primitive.rs:18:5
    |
 LL |     vec.sort();
    |     ^^^^^^^^^^ help: try: `vec.sort_unstable()`
@@ -48,7 +48,7 @@ LL |     vec.sort();
    = note: an unstable sort typically performs faster without any observable difference for this data type
 
 error: used `sort` on primitive type `i32`
-  --> $DIR/stable_sort_primitive.rs:19:5
+  --> $DIR/stable_sort_primitive.rs:20:5
    |
 LL |     arr.sort();
    |     ^^^^^^^^^^ help: try: `arr.sort_unstable()`
diff --git a/src/tools/clippy/tests/ui/starts_ends_with.fixed b/src/tools/clippy/tests/ui/starts_ends_with.fixed
index 29d56f852ed..b7237069dc5 100644
--- a/src/tools/clippy/tests/ui/starts_ends_with.fixed
+++ b/src/tools/clippy/tests/ui/starts_ends_with.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(dead_code, unused_must_use)]
+#![allow(clippy::needless_if, dead_code, unused_must_use)]
 
 fn main() {}
 
diff --git a/src/tools/clippy/tests/ui/starts_ends_with.rs b/src/tools/clippy/tests/ui/starts_ends_with.rs
index 56bbe2574d4..658312e87e4 100644
--- a/src/tools/clippy/tests/ui/starts_ends_with.rs
+++ b/src/tools/clippy/tests/ui/starts_ends_with.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-#![allow(dead_code, unused_must_use)]
+#![allow(clippy::needless_if, dead_code, unused_must_use)]
 
 fn main() {}
 
diff --git a/src/tools/clippy/tests/ui/string_add.rs b/src/tools/clippy/tests/ui/string_add.rs
index de78dfe4d69..6980242ae72 100644
--- a/src/tools/clippy/tests/ui/string_add.rs
+++ b/src/tools/clippy/tests/ui/string_add.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 extern crate proc_macros;
 use proc_macros::external;
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
index 3fc11b8b088..0edd81acc7a 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 //@aux-build:macro_rules.rs
 
-#![allow(dead_code, unused_variables)]
+#![allow(clippy::needless_raw_string_hashes, dead_code, unused_variables)]
 #![warn(clippy::string_lit_as_bytes)]
 
 #[macro_use]
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
index 7d54acf630e..2647f02f0e9 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 //@aux-build:macro_rules.rs
 
-#![allow(dead_code, unused_variables)]
+#![allow(clippy::needless_raw_string_hashes, dead_code, unused_variables)]
 #![warn(clippy::string_lit_as_bytes)]
 
 #[macro_use]
diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
index 4823d909208..0473ccdc3f6 100644
--- a/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
+++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.rs
@@ -1,7 +1,12 @@
-//@aux-build:proc_macro_suspicious_else_formatting.rs
+//@aux-build:proc_macro_suspicious_else_formatting.rs:proc-macro
 
 #![warn(clippy::suspicious_else_formatting)]
-#![allow(clippy::if_same_then_else, clippy::let_unit_value, clippy::needless_else)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::let_unit_value,
+    clippy::needless_if,
+    clippy::needless_else
+)]
 
 extern crate proc_macro_suspicious_else_formatting;
 use proc_macro_suspicious_else_formatting::DeriveBadSpan;
@@ -108,6 +113,13 @@ fn main() {
     else
     {
     }
+
+    //#10273 This is fine. Don't warn
+    if foo() {
+    } else
+    /* whelp */
+    {
+    }
 }
 
 // #7650 - Don't lint. Proc-macro using bad spans for `if` expressions.
diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
index 2e512b47f12..723fdd7e93e 100644
--- a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
@@ -1,5 +1,5 @@
 error: this looks like an `else {..}` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:17:6
+  --> $DIR/suspicious_else_formatting.rs:22:6
    |
 LL |     } {
    |      ^
@@ -8,7 +8,7 @@ LL |     } {
    = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:21:6
+  --> $DIR/suspicious_else_formatting.rs:26:6
    |
 LL |     } if foo() {
    |      ^
@@ -16,7 +16,7 @@ LL |     } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:28:10
+  --> $DIR/suspicious_else_formatting.rs:33:10
    |
 LL |         } if foo() {
    |          ^
@@ -24,7 +24,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:36:10
+  --> $DIR/suspicious_else_formatting.rs:41:10
    |
 LL |         } if foo() {
    |          ^
@@ -32,7 +32,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:45:6
+  --> $DIR/suspicious_else_formatting.rs:50:6
    |
 LL |       } else
    |  ______^
@@ -42,7 +42,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:57:6
+  --> $DIR/suspicious_else_formatting.rs:62:6
    |
 LL |       } else
    |  ______^
@@ -52,7 +52,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:62:6
+  --> $DIR/suspicious_else_formatting.rs:67:6
    |
 LL |       }
    |  ______^
@@ -63,7 +63,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:89:6
+  --> $DIR/suspicious_else_formatting.rs:94:6
    |
 LL |       }
    |  ______^
@@ -75,7 +75,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:97:6
+  --> $DIR/suspicious_else_formatting.rs:102:6
    |
 LL |       }
    |  ______^
diff --git a/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.rs b/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.rs
index 9564e373c24..3c5ca1762fe 100644
--- a/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.rs
+++ b/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::suspicious_unary_op_formatting)]
+#![allow(clippy::needless_if)]
 
 #[rustfmt::skip]
 fn main() {
diff --git a/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr
index 9f1289ccba0..52b0e99a1d3 100644
--- a/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr
@@ -1,5 +1,5 @@
 error: by not having a space between `>` and `-` it looks like `>-` is a single operator
-  --> $DIR/suspicious_unary_op_formatting.rs:8:9
+  --> $DIR/suspicious_unary_op_formatting.rs:9:9
    |
 LL |     if a >- 30 {}
    |         ^^^^
@@ -8,7 +8,7 @@ LL |     if a >- 30 {}
    = note: `-D clippy::suspicious-unary-op-formatting` implied by `-D warnings`
 
 error: by not having a space between `>=` and `-` it looks like `>=-` is a single operator
-  --> $DIR/suspicious_unary_op_formatting.rs:9:9
+  --> $DIR/suspicious_unary_op_formatting.rs:10:9
    |
 LL |     if a >=- 30 {}
    |         ^^^^^
@@ -16,7 +16,7 @@ LL |     if a >=- 30 {}
    = help: put a space between `>=` and `-` and remove the space after `-`
 
 error: by not having a space between `&&` and `!` it looks like `&&!` is a single operator
-  --> $DIR/suspicious_unary_op_formatting.rs:14:9
+  --> $DIR/suspicious_unary_op_formatting.rs:15:9
    |
 LL |     if b &&! c {}
    |         ^^^^^
@@ -24,7 +24,7 @@ LL |     if b &&! c {}
    = help: put a space between `&&` and `!` and remove the space after `!`
 
 error: by not having a space between `>` and `-` it looks like `>-` is a single operator
-  --> $DIR/suspicious_unary_op_formatting.rs:16:9
+  --> $DIR/suspicious_unary_op_formatting.rs:17:9
    |
 LL |     if a >-   30 {}
    |         ^^^^^^
diff --git a/src/tools/clippy/tests/ui/swap.fixed b/src/tools/clippy/tests/ui/swap.fixed
index fd3569cf362..22f904e3fd9 100644
--- a/src/tools/clippy/tests/ui/swap.fixed
+++ b/src/tools/clippy/tests/ui/swap.fixed
@@ -10,7 +10,8 @@
     dead_code,
     unused_assignments,
     unused_variables,
-    clippy::let_and_return
+    clippy::let_and_return,
+    clippy::useless_vec
 )]
 
 struct Foo(u32);
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs
index 34fbce0524b..ada64f89e6d 100644
--- a/src/tools/clippy/tests/ui/swap.rs
+++ b/src/tools/clippy/tests/ui/swap.rs
@@ -10,7 +10,8 @@
     dead_code,
     unused_assignments,
     unused_variables,
-    clippy::let_and_return
+    clippy::let_and_return,
+    clippy::useless_vec
 )]
 
 struct Foo(u32);
diff --git a/src/tools/clippy/tests/ui/swap.stderr b/src/tools/clippy/tests/ui/swap.stderr
index 0c246268499..a3b9c2b744c 100644
--- a/src/tools/clippy/tests/ui/swap.stderr
+++ b/src/tools/clippy/tests/ui/swap.stderr
@@ -1,5 +1,5 @@
 error: this looks like you are swapping `bar.a` and `bar.b` manually
-  --> $DIR/swap.rs:27:5
+  --> $DIR/swap.rs:28:5
    |
 LL | /     let temp = bar.a;
 LL | |     bar.a = bar.b;
@@ -10,7 +10,7 @@ LL | |     bar.b = temp;
    = note: `-D clippy::manual-swap` implied by `-D warnings`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:39:5
+  --> $DIR/swap.rs:40:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -18,7 +18,7 @@ LL | |     foo[1] = temp;
    | |__________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:48:5
+  --> $DIR/swap.rs:49:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -26,7 +26,7 @@ LL | |     foo[1] = temp;
    | |__________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:67:5
+  --> $DIR/swap.rs:68:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -34,7 +34,7 @@ LL | |     foo[1] = temp;
    | |__________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping `a` and `b` manually
-  --> $DIR/swap.rs:78:5
+  --> $DIR/swap.rs:79:5
    |
 LL | /     a ^= b;
 LL | |     b ^= a;
@@ -42,7 +42,7 @@ LL | |     a ^= b;
    | |___________^ help: try: `std::mem::swap(&mut a, &mut b);`
 
 error: this looks like you are swapping `bar.a` and `bar.b` manually
-  --> $DIR/swap.rs:86:5
+  --> $DIR/swap.rs:87:5
    |
 LL | /     bar.a ^= bar.b;
 LL | |     bar.b ^= bar.a;
@@ -50,7 +50,7 @@ LL | |     bar.a ^= bar.b;
    | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:94:5
+  --> $DIR/swap.rs:95:5
    |
 LL | /     foo[0] ^= foo[1];
 LL | |     foo[1] ^= foo[0];
@@ -58,7 +58,7 @@ LL | |     foo[0] ^= foo[1];
    | |_____________________^ help: try: `foo.swap(0, 1);`
 
 error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
-  --> $DIR/swap.rs:123:5
+  --> $DIR/swap.rs:124:5
    |
 LL | /     let temp = foo[0][1];
 LL | |     foo[0][1] = bar[1][0];
@@ -68,7 +68,7 @@ LL | |     bar[1][0] = temp;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `a` and `b` manually
-  --> $DIR/swap.rs:137:7
+  --> $DIR/swap.rs:138:7
    |
 LL |       ; let t = a;
    |  _______^
@@ -79,7 +79,7 @@ LL | |     b = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `c.0` and `a` manually
-  --> $DIR/swap.rs:146:7
+  --> $DIR/swap.rs:147:7
    |
 LL |       ; let t = c.0;
    |  _______^
@@ -90,7 +90,7 @@ LL | |     a = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `b` and `a` manually
-  --> $DIR/swap.rs:172:5
+  --> $DIR/swap.rs:173:5
    |
 LL | /     let t = b;
 LL | |     b = a;
@@ -100,7 +100,7 @@ LL | |     a = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> $DIR/swap.rs:134:5
+  --> $DIR/swap.rs:135:5
    |
 LL | /     a = b;
 LL | |     b = a;
@@ -110,7 +110,7 @@ LL | |     b = a;
    = note: `-D clippy::almost-swapped` implied by `-D warnings`
 
 error: this looks like you are trying to swap `c.0` and `a`
-  --> $DIR/swap.rs:143:5
+  --> $DIR/swap.rs:144:5
    |
 LL | /     c.0 = a;
 LL | |     a = c.0;
@@ -119,7 +119,7 @@ LL | |     a = c.0;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> $DIR/swap.rs:150:5
+  --> $DIR/swap.rs:151:5
    |
 LL | /     let a = b;
 LL | |     let b = a;
@@ -128,7 +128,7 @@ LL | |     let b = a;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `d` and `c`
-  --> $DIR/swap.rs:155:5
+  --> $DIR/swap.rs:156:5
    |
 LL | /     d = c;
 LL | |     c = d;
@@ -137,7 +137,7 @@ LL | |     c = d;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> $DIR/swap.rs:159:5
+  --> $DIR/swap.rs:160:5
    |
 LL | /     let a = b;
 LL | |     b = a;
@@ -146,7 +146,7 @@ LL | |     b = a;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `s.0.x` and `s.0.y` manually
-  --> $DIR/swap.rs:207:5
+  --> $DIR/swap.rs:208:5
    |
 LL | /     let t = s.0.x;
 LL | |     s.0.x = s.0.y;
diff --git a/src/tools/clippy/tests/ui/tests_outside_test_module.rs b/src/tools/clippy/tests/ui/tests_outside_test_module.rs
index 21fdfdf9005..d53c692b78e 100644
--- a/src/tools/clippy/tests/ui/tests_outside_test_module.rs
+++ b/src/tools/clippy/tests/ui/tests_outside_test_module.rs
@@ -1,4 +1,3 @@
-//@compile-flags: --test
 #![allow(unused)]
 #![warn(clippy::tests_outside_test_module)]
 
diff --git a/src/tools/clippy/tests/ui/tests_outside_test_module.stderr b/src/tools/clippy/tests/ui/tests_outside_test_module.stderr
index 125a79d6edf..71c649c5d27 100644
--- a/src/tools/clippy/tests/ui/tests_outside_test_module.stderr
+++ b/src/tools/clippy/tests/ui/tests_outside_test_module.stderr
@@ -1,5 +1,5 @@
 error: this function marked with #[test] is outside a #[cfg(test)] module
-  --> $DIR/tests_outside_test_module.rs:11:1
+  --> $DIR/tests_outside_test_module.rs:10:1
    |
 LL | fn my_test() {}
    | ^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.fixed b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.fixed
new file mode 100644
index 00000000000..9f75ad895cd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.fixed
@@ -0,0 +1,9 @@
+//@run-rustfix
+//@compile-flags: -C incremental=target/debug/test/incr
+
+// see https://github.com/rust-lang/rust-clippy/issues/10969
+
+fn main() {
+    let s = "Hello, world!";
+    println!("{}", s);
+}
diff --git a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs
new file mode 100644
index 00000000000..67115f7c5a7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.rs
@@ -0,0 +1,9 @@
+//@run-rustfix
+//@compile-flags: -C incremental=target/debug/test/incr
+
+// see https://github.com/rust-lang/rust-clippy/issues/10969
+
+fn main() {
+    let s = "Hello, world!";
+    println!("{}", s.to_string());
+}
diff --git a/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr
new file mode 100644
index 00000000000..a992c542914
--- /dev/null
+++ b/src/tools/clippy/tests/ui/to_string_in_format_args_incremental.stderr
@@ -0,0 +1,10 @@
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/to_string_in_format_args_incremental.rs:8:21
+   |
+LL |     println!("{}", s.to_string());
+   |                     ^^^^^^^^^^^^ help: remove this
+   |
+   = note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
index ea30c1fda6f..9ad45c7a817 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::toplevel_ref_arg)]
-#![allow(clippy::uninlined_format_args, unused)]
+#![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)]
 
 extern crate proc_macros;
 use proc_macros::{external, inline_macros};
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
index 7a3d33e5be5..45ccc024cbd 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::toplevel_ref_arg)]
-#![allow(clippy::uninlined_format_args, unused)]
+#![allow(clippy::uninlined_format_args, unused, clippy::useless_vec)]
 
 extern crate proc_macros;
 use proc_macros::{external, inline_macros};
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs b/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs
index 8aaf47b1bd0..464762af825 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![warn(clippy::toplevel_ref_arg)]
 #![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
index f06ffab5d9b..61a6c98ed5a 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs
@@ -32,7 +32,7 @@ fn transmute_ptr_to_ptr() {
         // ref-ref transmutes; bad
         let _: &f32 = std::mem::transmute(&1u32);
         let _: &f64 = std::mem::transmute(&1f32);
-        // ^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
+        //:^ this test is here because both f32 and f64 are the same TypeVariant, but they are not
         // the same type
         let _: &mut f32 = std::mem::transmute(&mut 1u32);
         let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
index ac55ab5a8e2..215f0ac1842 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
@@ -1,8 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::transmute_ptr_to_ref)]
-#![allow(clippy::match_single_binding)]
-#![allow(unused_must_use)]
+#![allow(clippy::match_single_binding, clippy::unnecessary_cast)]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
     let _: &T = &*p;
@@ -39,7 +38,7 @@ fn _issue1231() {
 
     type Bar<'a> = &'a u8;
     let raw = 42 as *const i32;
-    let _ = unsafe { &*(raw as *const u8) };
+    unsafe { &*(raw as *const u8) };
 }
 
 unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
index 901a3e90dbe..3528e137903 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
@@ -1,8 +1,7 @@
 //@run-rustfix
 
 #![warn(clippy::transmute_ptr_to_ref)]
-#![allow(clippy::match_single_binding)]
-#![allow(unused_must_use)]
+#![allow(clippy::match_single_binding, clippy::unnecessary_cast)]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
     let _: &T = std::mem::transmute(p);
@@ -39,7 +38,7 @@ fn _issue1231() {
 
     type Bar<'a> = &'a u8;
     let raw = 42 as *const i32;
-    let _ = unsafe { std::mem::transmute::<_, Bar>(raw) };
+    unsafe { std::mem::transmute::<_, Bar>(raw) };
 }
 
 unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
index 68007edc410..b3e6c09d2d7 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
@@ -1,5 +1,5 @@
 error: transmute from a pointer type (`*const T`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:8:17
+  --> $DIR/transmute_ptr_to_ref.rs:7:17
    |
 LL |     let _: &T = std::mem::transmute(p);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p`
@@ -7,127 +7,127 @@ LL |     let _: &T = std::mem::transmute(p);
    = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> $DIR/transmute_ptr_to_ref.rs:11:21
+  --> $DIR/transmute_ptr_to_ref.rs:10:21
    |
 LL |     let _: &mut T = std::mem::transmute(m);
    |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:14:17
+  --> $DIR/transmute_ptr_to_ref.rs:13:17
    |
 LL |     let _: &T = std::mem::transmute(m);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> $DIR/transmute_ptr_to_ref.rs:17:21
+  --> $DIR/transmute_ptr_to_ref.rs:16:21
    |
 LL |     let _: &mut T = std::mem::transmute(p as *mut T);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)`
 
 error: transmute from a pointer type (`*const U`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:20:17
+  --> $DIR/transmute_ptr_to_ref.rs:19:17
    |
 LL |     let _: &T = std::mem::transmute(o);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`)
-  --> $DIR/transmute_ptr_to_ref.rs:23:21
+  --> $DIR/transmute_ptr_to_ref.rs:22:21
    |
 LL |     let _: &mut T = std::mem::transmute(om);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:26:17
+  --> $DIR/transmute_ptr_to_ref.rs:25:17
    |
 LL |     let _: &T = std::mem::transmute(om);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`)
-  --> $DIR/transmute_ptr_to_ref.rs:36:32
+  --> $DIR/transmute_ptr_to_ref.rs:35:32
    |
 LL |     let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`)
-  --> $DIR/transmute_ptr_to_ref.rs:38:33
+  --> $DIR/transmute_ptr_to_ref.rs:37:33
    |
 LL |     let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
-  --> $DIR/transmute_ptr_to_ref.rs:42:22
+  --> $DIR/transmute_ptr_to_ref.rs:41:14
    |
-LL |     let _ = unsafe { std::mem::transmute::<_, Bar>(raw) };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
+LL |     unsafe { std::mem::transmute::<_, Bar>(raw) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:47:14
+  --> $DIR/transmute_ptr_to_ref.rs:46:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:48:14
+  --> $DIR/transmute_ptr_to_ref.rs:47:14
    |
 LL |         1 => std::mem::transmute(y),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:49:14
+  --> $DIR/transmute_ptr_to_ref.rs:48:14
    |
 LL |         2 => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:50:14
+  --> $DIR/transmute_ptr_to_ref.rs:49:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(y),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:58:19
+  --> $DIR/transmute_ptr_to_ref.rs:57:19
    |
 LL |     let _: &u32 = std::mem::transmute(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:59:19
+  --> $DIR/transmute_ptr_to_ref.rs:58:19
    |
 LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:61:14
+  --> $DIR/transmute_ptr_to_ref.rs:60:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:62:14
+  --> $DIR/transmute_ptr_to_ref.rs:61:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:70:19
+  --> $DIR/transmute_ptr_to_ref.rs:69:19
    |
 LL |     let _: &u32 = std::mem::transmute(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:71:19
+  --> $DIR/transmute_ptr_to_ref.rs:70:19
    |
 LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:73:14
+  --> $DIR/transmute_ptr_to_ref.rs:72:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:74:14
+  --> $DIR/transmute_ptr_to_ref.rs:73:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)`
diff --git a/src/tools/clippy/tests/ui/try_err.fixed b/src/tools/clippy/tests/ui/try_err.fixed
index dc773ad4bad..1816740870a 100644
--- a/src/tools/clippy/tests/ui/try_err.fixed
+++ b/src/tools/clippy/tests/ui/try_err.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![deny(clippy::try_err)]
 #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
diff --git a/src/tools/clippy/tests/ui/try_err.rs b/src/tools/clippy/tests/ui/try_err.rs
index 7a7433a7ec2..0e47c4d023e 100644
--- a/src/tools/clippy/tests/ui/try_err.rs
+++ b/src/tools/clippy/tests/ui/try_err.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![deny(clippy::try_err)]
 #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
diff --git a/src/tools/clippy/tests/ui/tuple_array_conversions.rs b/src/tools/clippy/tests/ui/tuple_array_conversions.rs
new file mode 100644
index 00000000000..f96a7c97f1a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/tuple_array_conversions.rs
@@ -0,0 +1,73 @@
+//@aux-build:proc_macros.rs:proc-macro
+#![allow(clippy::no_effect, clippy::useless_vec, unused)]
+#![warn(clippy::tuple_array_conversions)]
+
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+    let x = [1, 2];
+    let x = (x[0], x[1]);
+    let x = [x.0, x.1];
+    let x = &[1, 2];
+    let x = (x[0], x[1]);
+
+    let t1: &[(u32, u32)] = &[(1, 2), (3, 4)];
+    let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect();
+    t1.iter().for_each(|&(a, b)| _ = [a, b]);
+    let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect();
+    t1.iter().for_each(|&(a, b)| _ = [a, b]);
+    // Do not lint
+    let v2: Vec<[u32; 2]> = t1.iter().map(|&t| t.into()).collect();
+    let t3: Vec<(u32, u32)> = v2.iter().map(|&v| v.into()).collect();
+    let x = [1; 13];
+    let x = (
+        x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12],
+    );
+    let x = [x.0, x.1, x.2, x.3, x.4, x.5, x.6, x.7, x.8, x.9, x.10, x.11, x.12];
+    let x = (1, 2);
+    let x = (x.0, x.1);
+    let x = [1, 2];
+    let x = [x[0], x[1]];
+    let x = vec![1, 2];
+    let x = (x[0], x[1]);
+    let x = [1; 3];
+    let x = (x[0],);
+    let x = (1, 2, 3);
+    let x = [x.0];
+    let x = (1, 2);
+    let y = (1, 2);
+    [x.0, y.0];
+    [x.0, y.1];
+    let x = [x.0, x.0];
+    let x = (x[0], x[0]);
+    external! {
+        let t1: &[(u32, u32)] = &[(1, 2), (3, 4)];
+        let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect();
+        let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect();
+    }
+    with_span! {
+        span
+        let t1: &[(u32, u32)] = &[(1, 2), (3, 4)];
+        let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect();
+        let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect();
+    }
+}
+
+#[clippy::msrv = "1.70.0"]
+fn msrv_too_low() {
+    let x = [1, 2];
+    let x = (x[0], x[1]);
+    let x = [x.0, x.1];
+    let x = &[1, 2];
+    let x = (x[0], x[1]);
+}
+
+#[clippy::msrv = "1.71.0"]
+fn msrv_juust_right() {
+    let x = [1, 2];
+    let x = (x[0], x[1]);
+    let x = [x.0, x.1];
+    let x = &[1, 2];
+    let x = (x[0], x[1]);
+}
diff --git a/src/tools/clippy/tests/ui/tuple_array_conversions.stderr b/src/tools/clippy/tests/ui/tuple_array_conversions.stderr
new file mode 100644
index 00000000000..be653e8efb7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/tuple_array_conversions.stderr
@@ -0,0 +1,83 @@
+error: it looks like you're trying to convert an array to a tuple
+  --> $DIR/tuple_array_conversions.rs:10:13
+   |
+LL |     let x = (x[0], x[1]);
+   |             ^^^^^^^^^^^^
+   |
+   = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed
+   = note: `-D clippy::tuple-array-conversions` implied by `-D warnings`
+
+error: it looks like you're trying to convert a tuple to an array
+  --> $DIR/tuple_array_conversions.rs:11:13
+   |
+LL |     let x = [x.0, x.1];
+   |             ^^^^^^^^^^
+   |
+   = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed
+
+error: it looks like you're trying to convert an array to a tuple
+  --> $DIR/tuple_array_conversions.rs:13:13
+   |
+LL |     let x = (x[0], x[1]);
+   |             ^^^^^^^^^^^^
+   |
+   = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed
+
+error: it looks like you're trying to convert a tuple to an array
+  --> $DIR/tuple_array_conversions.rs:16:53
+   |
+LL |     let v1: Vec<[u32; 2]> = t1.iter().map(|&(a, b)| [a, b]).collect();
+   |                                                     ^^^^^^
+   |
+   = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed
+
+error: it looks like you're trying to convert a tuple to an array
+  --> $DIR/tuple_array_conversions.rs:17:38
+   |
+LL |     t1.iter().for_each(|&(a, b)| _ = [a, b]);
+   |                                      ^^^^^^
+   |
+   = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed
+
+error: it looks like you're trying to convert an array to a tuple
+  --> $DIR/tuple_array_conversions.rs:18:55
+   |
+LL |     let t2: Vec<(u32, u32)> = v1.iter().map(|&[a, b]| (a, b)).collect();
+   |                                                       ^^^^^^
+   |
+   = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed
+
+error: it looks like you're trying to convert a tuple to an array
+  --> $DIR/tuple_array_conversions.rs:19:38
+   |
+LL |     t1.iter().for_each(|&(a, b)| _ = [a, b]);
+   |                                      ^^^^^^
+   |
+   = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed
+
+error: it looks like you're trying to convert an array to a tuple
+  --> $DIR/tuple_array_conversions.rs:69:13
+   |
+LL |     let x = (x[0], x[1]);
+   |             ^^^^^^^^^^^^
+   |
+   = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed
+
+error: it looks like you're trying to convert a tuple to an array
+  --> $DIR/tuple_array_conversions.rs:70:13
+   |
+LL |     let x = [x.0, x.1];
+   |             ^^^^^^^^^^
+   |
+   = help: use `.into()` instead, or `<[T; N]>::from` if type annotations are needed
+
+error: it looks like you're trying to convert an array to a tuple
+  --> $DIR/tuple_array_conversions.rs:72:13
+   |
+LL |     let x = (x[0], x[1]);
+   |             ^^^^^^^^^^^^
+   |
+   = help: use `.into()` instead, or `<(T0, T1, ..., Tn)>::from` if type annotations are needed
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/type_complexity.rs b/src/tools/clippy/tests/ui/type_complexity.rs
index 86a7bd7b627..816950110b2 100644
--- a/src/tools/clippy/tests/ui/type_complexity.rs
+++ b/src/tools/clippy/tests/ui/type_complexity.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::all)]
-#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box)]
+#![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)]
 #![feature(associated_type_defaults)]
 
 type Alias = Vec<Vec<Box<(u32, u32, u32, u32)>>>; // no warning here
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
index 8b4613b3f6e..874d97f7a46 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
@@ -1,6 +1,7 @@
 #![deny(clippy::type_repetition_in_bounds)]
 #![allow(clippy::extra_unused_type_parameters)]
 
+use serde::Deserialize;
 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
 
 pub fn foo<T>(_t: T)
@@ -70,6 +71,20 @@ mod issue4326 {
     }
 }
 
+// Extern macros shouldn't lint, again (see #10504)
+mod issue10504 {
+    use serde::{Deserialize, Serialize};
+    use std::fmt::Debug;
+    use std::hash::Hash;
+
+    #[derive(Debug, Serialize, Deserialize)]
+    #[serde(bound(
+        serialize = "T: Serialize + Hash + Eq",
+        deserialize = "Box<T>: serde::de::DeserializeOwned + Hash + Eq"
+    ))]
+    struct OpaqueParams<T: ?Sized + Debug>(std::marker::PhantomData<T>);
+}
+
 // Issue #7360
 struct Foo<T, U>
 where
@@ -95,4 +110,28 @@ where
 // This should not lint
 fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
 
+#[clippy::msrv = "1.14.0"]
+mod issue8772_fail {
+    pub trait Trait<X, Y, Z> {}
+
+    pub fn f<T: ?Sized, U>(arg: usize)
+    where
+        T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
+        U: Clone + Sync + 'static,
+    {
+    }
+}
+
+#[clippy::msrv = "1.15.0"]
+mod issue8772_pass {
+    pub trait Trait<X, Y, Z> {}
+
+    pub fn f<T: ?Sized, U>(arg: usize)
+    where
+        T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
+        U: Clone + Sync + 'static,
+    {
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
index a90df03c04f..54973c5bda5 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:9:5
+  --> $DIR/type_repetition_in_bounds.rs:10:5
    |
 LL |     T: Clone,
    |     ^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:26:5
+  --> $DIR/type_repetition_in_bounds.rs:27:5
    |
 LL |     Self: Copy + Default + Ord,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |     Self: Copy + Default + Ord,
    = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
 
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:86:5
+  --> $DIR/type_repetition_in_bounds.rs:101:5
    |
 LL |     T: Clone,
    |     ^^^^^^^^
@@ -28,12 +28,20 @@ LL |     T: Clone,
    = help: consider combining the bounds: `T: ?Sized + Clone`
 
 error: this type has already been used as a bound predicate
-  --> $DIR/type_repetition_in_bounds.rs:91:5
+  --> $DIR/type_repetition_in_bounds.rs:106:5
    |
 LL |     T: ?Sized,
    |     ^^^^^^^^^
    |
    = help: consider combining the bounds: `T: Clone + ?Sized`
 
-error: aborting due to 4 previous errors
+error: this type has already been used as a bound predicate
+  --> $DIR/type_repetition_in_bounds.rs:131:9
+   |
+LL |         T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider combining the bounds: `T: ?Sized + Trait<Option<usize>, Box<[String]>, bool>`
+
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
index 229d150851a..a9cc4295435 100644
--- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_unsafe.rs
+//@aux-build:proc_macro_unsafe.rs:proc-macro
 
 #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
 #![allow(clippy::let_unit_value, clippy::missing_safety_doc)]
@@ -509,4 +509,26 @@ fn issue_9142() {
     };
 }
 
+pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    1
+}
+
+pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    2
+}
+
+fn issue_10832() {
+    // Safety: A safety comment. But it will warn anyways
+    let _some_variable_with_a_very_long_name_to_break_the_line =
+        unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Another safety comment. But it will warn anyways
+    const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Yet another safety comment. But it will warn anyways
+    static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
index d1c1bb5ffea..ee1d3aa285a 100644
--- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
+++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
@@ -318,5 +318,29 @@ LL |             let bar = unsafe {};
    |
    = help: consider adding a safety comment on the preceding line
 
-error: aborting due to 36 previous errors
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:523:9
+   |
+LL |         unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:527:9
+   |
+LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:531:9
+   |
+LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: aborting due to 39 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unicode.fixed b/src/tools/clippy/tests/ui/unicode.fixed
index 910968afa7f..032040c4805 100644
--- a/src/tools/clippy/tests/ui/unicode.fixed
+++ b/src/tools/clippy/tests/ui/unicode.fixed
@@ -1,5 +1,4 @@
 //@run-rustfix
-//@compile-flags: --test
 #![allow(dead_code)]
 
 #[warn(clippy::invisible_characters)]
diff --git a/src/tools/clippy/tests/ui/unicode.rs b/src/tools/clippy/tests/ui/unicode.rs
index bc4b84d3435..dd215bc6048 100644
--- a/src/tools/clippy/tests/ui/unicode.rs
+++ b/src/tools/clippy/tests/ui/unicode.rs
@@ -1,5 +1,4 @@
 //@run-rustfix
-//@compile-flags: --test
 #![allow(dead_code)]
 
 #[warn(clippy::invisible_characters)]
diff --git a/src/tools/clippy/tests/ui/unicode.stderr b/src/tools/clippy/tests/ui/unicode.stderr
index ea74a81451e..21cc22a778b 100644
--- a/src/tools/clippy/tests/ui/unicode.stderr
+++ b/src/tools/clippy/tests/ui/unicode.stderr
@@ -1,5 +1,5 @@
 error: invisible character detected
-  --> $DIR/unicode.rs:7:12
+  --> $DIR/unicode.rs:6:12
    |
 LL |     print!("Here >​< is a ZWS, and ​another");
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{200B}< is a ZWS, and /u{200B}another"`
@@ -7,19 +7,19 @@ LL |     print!("Here >​< is a ZWS, and ​another");
    = note: `-D clippy::invisible-characters` implied by `-D warnings`
 
 error: invisible character detected
-  --> $DIR/unicode.rs:9:12
+  --> $DIR/unicode.rs:8:12
    |
 LL |     print!("Here >­< is a SHY, and ­another");
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{AD}< is a SHY, and /u{AD}another"`
 
 error: invisible character detected
-  --> $DIR/unicode.rs:11:12
+  --> $DIR/unicode.rs:10:12
    |
 LL |     print!("Here >⁠< is a WJ, and ⁠another");
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >/u{2060}< is a WJ, and /u{2060}another"`
 
 error: non-NFC Unicode sequence detected
-  --> $DIR/unicode.rs:17:12
+  --> $DIR/unicode.rs:16:12
    |
 LL |     print!("̀àh?");
    |            ^^^^^ help: consider replacing the string with: `"̀àh?"`
@@ -27,37 +27,37 @@ LL |     print!("̀àh?");
    = note: `-D clippy::unicode-not-nfc` implied by `-D warnings`
 
 error: literal non-ASCII character detected
-  --> $DIR/unicode.rs:25:16
+  --> $DIR/unicode.rs:24:16
    |
 LL |         print!("Üben!");
    |                ^^^^^^^ help: consider replacing the string with: `"/u{dc}ben!"`
    |
 note: the lint level is defined here
-  --> $DIR/unicode.rs:22:13
+  --> $DIR/unicode.rs:21:13
    |
 LL |     #![deny(clippy::non_ascii_literal)]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: literal non-ASCII character detected
-  --> $DIR/unicode.rs:31:36
+  --> $DIR/unicode.rs:30:36
    |
 LL |         const _EMPTY_BLOCK: char = '▱';
    |                                    ^^^ help: consider replacing the string with: `'/u{25b1}'`
 
 error: literal non-ASCII character detected
-  --> $DIR/unicode.rs:32:35
+  --> $DIR/unicode.rs:31:35
    |
 LL |         const _FULL_BLOCK: char = '▰';
    |                                   ^^^ help: consider replacing the string with: `'/u{25b0}'`
 
 error: literal non-ASCII character detected
-  --> $DIR/unicode.rs:52:21
+  --> $DIR/unicode.rs:51:21
    |
 LL |             let _ = "悲しいかな、ここに日本語を書くことはできない。";
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"/u{60b2}/u{3057}/u{3044}/u{304b}/u{306a}/u{3001}/u{3053}/u{3053}/u{306b}/u{65e5}/u{672c}/u{8a9e}/u{3092}/u{66f8}/u{304f}/u{3053}/u{3068}/u{306f}/u{3067}/u{304d}/u{306a}/u{3044}/u{3002}"`
    |
 note: the lint level is defined here
-  --> $DIR/unicode.rs:41:17
+  --> $DIR/unicode.rs:40:17
    |
 LL |         #![deny(clippy::non_ascii_literal)]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
index e25d123dd51..a042731a9bf 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -1,8 +1,13 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 //@run-rustfix
 #![warn(clippy::uninlined_format_args)]
 #![allow(named_arguments_used_positionally, unused)]
-#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
+#![allow(
+    clippy::eq_op,
+    clippy::format_in_format_args,
+    clippy::print_literal,
+    clippy::unnecessary_literal_unwrap
+)]
 
 extern crate proc_macros;
 use proc_macros::with_span;
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
index 6793ec24441..d830b74d607 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -1,8 +1,13 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 //@run-rustfix
 #![warn(clippy::uninlined_format_args)]
 #![allow(named_arguments_used_positionally, unused)]
-#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
+#![allow(
+    clippy::eq_op,
+    clippy::format_in_format_args,
+    clippy::print_literal,
+    clippy::unnecessary_literal_unwrap
+)]
 
 extern crate proc_macros;
 use proc_macros::with_span;
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.stderr b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
index dc4af6ef42e..44ca61f008c 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.stderr
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
@@ -1,5 +1,5 @@
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:40:5
+  --> $DIR/uninlined_format_args.rs:45:5
    |
 LL |     println!("val='{}'", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL +     println!("val='{local_i32}'");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:41:5
+  --> $DIR/uninlined_format_args.rs:46:5
    |
 LL |     println!("val='{   }'", local_i32); // 3 spaces
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL +     println!("val='{local_i32}'"); // 3 spaces
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:42:5
+  --> $DIR/uninlined_format_args.rs:47:5
    |
 LL |     println!("val='{    }'", local_i32); // tab
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL +     println!("val='{local_i32}'"); // tab
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:43:5
+  --> $DIR/uninlined_format_args.rs:48:5
    |
 LL |     println!("val='{     }'", local_i32); // space+tab
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL +     println!("val='{local_i32}'"); // space+tab
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:44:5
+  --> $DIR/uninlined_format_args.rs:49:5
    |
 LL |     println!("val='{     }'", local_i32); // tab+space
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL +     println!("val='{local_i32}'"); // tab+space
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:45:5
+  --> $DIR/uninlined_format_args.rs:50:5
    |
 LL | /     println!(
 LL | |         "val='{
@@ -70,7 +70,7 @@ LL | |     );
    | |_____^
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:50:5
+  --> $DIR/uninlined_format_args.rs:55:5
    |
 LL |     println!("{}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +82,7 @@ LL +     println!("{local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:51:5
+  --> $DIR/uninlined_format_args.rs:56:5
    |
 LL |     println!("{}", fn_arg);
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -94,7 +94,7 @@ LL +     println!("{fn_arg}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:52:5
+  --> $DIR/uninlined_format_args.rs:57:5
    |
 LL |     println!("{:?}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL +     println!("{local_i32:?}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:53:5
+  --> $DIR/uninlined_format_args.rs:58:5
    |
 LL |     println!("{:#?}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,7 +118,7 @@ LL +     println!("{local_i32:#?}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:54:5
+  --> $DIR/uninlined_format_args.rs:59:5
    |
 LL |     println!("{:4}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +130,7 @@ LL +     println!("{local_i32:4}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:55:5
+  --> $DIR/uninlined_format_args.rs:60:5
    |
 LL |     println!("{:04}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -142,7 +142,7 @@ LL +     println!("{local_i32:04}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:56:5
+  --> $DIR/uninlined_format_args.rs:61:5
    |
 LL |     println!("{:<3}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL +     println!("{local_i32:<3}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:57:5
+  --> $DIR/uninlined_format_args.rs:62:5
    |
 LL |     println!("{:#010x}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +166,7 @@ LL +     println!("{local_i32:#010x}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:58:5
+  --> $DIR/uninlined_format_args.rs:63:5
    |
 LL |     println!("{:.1}", local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -178,7 +178,7 @@ LL +     println!("{local_f64:.1}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:62:5
+  --> $DIR/uninlined_format_args.rs:67:5
    |
 LL |     println!("{} {}", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -190,7 +190,7 @@ LL +     println!("{local_i32} {local_f64}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:64:5
+  --> $DIR/uninlined_format_args.rs:69:5
    |
 LL |     println!("{}", val);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -202,7 +202,7 @@ LL +     println!("{val}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:65:5
+  --> $DIR/uninlined_format_args.rs:70:5
    |
 LL |     println!("{}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -214,7 +214,7 @@ LL +     println!("{val}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:67:5
+  --> $DIR/uninlined_format_args.rs:72:5
    |
 LL |     println!("val='{/t }'", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -226,7 +226,7 @@ LL +     println!("val='{local_i32}'");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:68:5
+  --> $DIR/uninlined_format_args.rs:73:5
    |
 LL |     println!("val='{/n }'", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +238,7 @@ LL +     println!("val='{local_i32}'");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:69:5
+  --> $DIR/uninlined_format_args.rs:74:5
    |
 LL |     println!("val='{local_i32}'", local_i32 = local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -250,7 +250,7 @@ LL +     println!("val='{local_i32}'");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:70:5
+  --> $DIR/uninlined_format_args.rs:75:5
    |
 LL |     println!("val='{local_i32}'", local_i32 = fn_arg);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -262,7 +262,7 @@ LL +     println!("val='{fn_arg}'");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:71:5
+  --> $DIR/uninlined_format_args.rs:76:5
    |
 LL |     println!("{0}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -274,7 +274,7 @@ LL +     println!("{local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:72:5
+  --> $DIR/uninlined_format_args.rs:77:5
    |
 LL |     println!("{0:?}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -286,7 +286,7 @@ LL +     println!("{local_i32:?}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:73:5
+  --> $DIR/uninlined_format_args.rs:78:5
    |
 LL |     println!("{0:#?}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -298,7 +298,7 @@ LL +     println!("{local_i32:#?}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:74:5
+  --> $DIR/uninlined_format_args.rs:79:5
    |
 LL |     println!("{0:04}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -310,7 +310,7 @@ LL +     println!("{local_i32:04}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:75:5
+  --> $DIR/uninlined_format_args.rs:80:5
    |
 LL |     println!("{0:<3}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -322,7 +322,7 @@ LL +     println!("{local_i32:<3}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:76:5
+  --> $DIR/uninlined_format_args.rs:81:5
    |
 LL |     println!("{0:#010x}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -334,7 +334,7 @@ LL +     println!("{local_i32:#010x}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:77:5
+  --> $DIR/uninlined_format_args.rs:82:5
    |
 LL |     println!("{0:.1}", local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -346,7 +346,7 @@ LL +     println!("{local_f64:.1}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:78:5
+  --> $DIR/uninlined_format_args.rs:83:5
    |
 LL |     println!("{0} {0}", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -358,7 +358,7 @@ LL +     println!("{local_i32} {local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:79:5
+  --> $DIR/uninlined_format_args.rs:84:5
    |
 LL |     println!("{1} {} {0} {}", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -370,7 +370,7 @@ LL +     println!("{local_f64} {local_i32} {local_i32} {local_f64}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:80:5
+  --> $DIR/uninlined_format_args.rs:85:5
    |
 LL |     println!("{0} {1}", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -382,7 +382,7 @@ LL +     println!("{local_i32} {local_f64}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:81:5
+  --> $DIR/uninlined_format_args.rs:86:5
    |
 LL |     println!("{1} {0}", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -394,7 +394,7 @@ LL +     println!("{local_f64} {local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:82:5
+  --> $DIR/uninlined_format_args.rs:87:5
    |
 LL |     println!("{1} {0} {1} {0}", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -406,7 +406,7 @@ LL +     println!("{local_f64} {local_i32} {local_f64} {local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:84:5
+  --> $DIR/uninlined_format_args.rs:89:5
    |
 LL |     println!("{v}", v = local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -418,7 +418,7 @@ LL +     println!("{local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:85:5
+  --> $DIR/uninlined_format_args.rs:90:5
    |
 LL |     println!("{local_i32:0$}", width);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -430,7 +430,7 @@ LL +     println!("{local_i32:width$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:86:5
+  --> $DIR/uninlined_format_args.rs:91:5
    |
 LL |     println!("{local_i32:w$}", w = width);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -442,7 +442,7 @@ LL +     println!("{local_i32:width$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:87:5
+  --> $DIR/uninlined_format_args.rs:92:5
    |
 LL |     println!("{local_i32:.0$}", prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -454,7 +454,7 @@ LL +     println!("{local_i32:.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:88:5
+  --> $DIR/uninlined_format_args.rs:93:5
    |
 LL |     println!("{local_i32:.p$}", p = prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -466,7 +466,7 @@ LL +     println!("{local_i32:.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:89:5
+  --> $DIR/uninlined_format_args.rs:94:5
    |
 LL |     println!("{:0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -478,7 +478,7 @@ LL +     println!("{val:val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:90:5
+  --> $DIR/uninlined_format_args.rs:95:5
    |
 LL |     println!("{0:0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -490,7 +490,7 @@ LL +     println!("{val:val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:91:5
+  --> $DIR/uninlined_format_args.rs:96:5
    |
 LL |     println!("{:0$.0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -502,7 +502,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:92:5
+  --> $DIR/uninlined_format_args.rs:97:5
    |
 LL |     println!("{0:0$.0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -514,7 +514,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:93:5
+  --> $DIR/uninlined_format_args.rs:98:5
    |
 LL |     println!("{0:0$.v$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -526,7 +526,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:94:5
+  --> $DIR/uninlined_format_args.rs:99:5
    |
 LL |     println!("{0:v$.0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -538,7 +538,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:95:5
+  --> $DIR/uninlined_format_args.rs:100:5
    |
 LL |     println!("{v:0$.0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -550,7 +550,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:96:5
+  --> $DIR/uninlined_format_args.rs:101:5
    |
 LL |     println!("{v:v$.0$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -562,7 +562,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:97:5
+  --> $DIR/uninlined_format_args.rs:102:5
    |
 LL |     println!("{v:0$.v$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -574,7 +574,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:98:5
+  --> $DIR/uninlined_format_args.rs:103:5
    |
 LL |     println!("{v:v$.v$}", v = val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -586,7 +586,7 @@ LL +     println!("{val:val$.val$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:99:5
+  --> $DIR/uninlined_format_args.rs:104:5
    |
 LL |     println!("{:0$}", width);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -598,7 +598,7 @@ LL +     println!("{width:width$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:100:5
+  --> $DIR/uninlined_format_args.rs:105:5
    |
 LL |     println!("{:1$}", local_i32, width);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -610,7 +610,7 @@ LL +     println!("{local_i32:width$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:101:5
+  --> $DIR/uninlined_format_args.rs:106:5
    |
 LL |     println!("{:w$}", w = width);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -622,7 +622,7 @@ LL +     println!("{width:width$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:102:5
+  --> $DIR/uninlined_format_args.rs:107:5
    |
 LL |     println!("{:w$}", local_i32, w = width);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -634,7 +634,7 @@ LL +     println!("{local_i32:width$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:103:5
+  --> $DIR/uninlined_format_args.rs:108:5
    |
 LL |     println!("{:.0$}", prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -646,7 +646,7 @@ LL +     println!("{prec:.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:104:5
+  --> $DIR/uninlined_format_args.rs:109:5
    |
 LL |     println!("{:.1$}", local_i32, prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -658,7 +658,7 @@ LL +     println!("{local_i32:.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:105:5
+  --> $DIR/uninlined_format_args.rs:110:5
    |
 LL |     println!("{:.p$}", p = prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -670,7 +670,7 @@ LL +     println!("{prec:.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:106:5
+  --> $DIR/uninlined_format_args.rs:111:5
    |
 LL |     println!("{:.p$}", local_i32, p = prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -682,7 +682,7 @@ LL +     println!("{local_i32:.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:107:5
+  --> $DIR/uninlined_format_args.rs:112:5
    |
 LL |     println!("{:0$.1$}", width, prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -694,7 +694,7 @@ LL +     println!("{width:width$.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:108:5
+  --> $DIR/uninlined_format_args.rs:113:5
    |
 LL |     println!("{:0$.w$}", width, w = prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -706,7 +706,7 @@ LL +     println!("{width:width$.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:109:5
+  --> $DIR/uninlined_format_args.rs:114:5
    |
 LL |     println!("{:1$.2$}", local_f64, width, prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -718,7 +718,7 @@ LL +     println!("{local_f64:width$.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:110:5
+  --> $DIR/uninlined_format_args.rs:115:5
    |
 LL |     println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -730,7 +730,7 @@ LL +     println!("{local_f64:width$.prec$} {local_f64} {width} {prec}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:111:5
+  --> $DIR/uninlined_format_args.rs:116:5
    |
 LL | /     println!(
 LL | |         "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}",
@@ -739,7 +739,7 @@ LL | |     );
    | |_____^
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:122:5
+  --> $DIR/uninlined_format_args.rs:127:5
    |
 LL |     println!("Width = {}, value with width = {:0$}", local_i32, local_f64);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -751,7 +751,7 @@ LL +     println!("Width = {local_i32}, value with width = {local_f64:local_i32$
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:123:5
+  --> $DIR/uninlined_format_args.rs:128:5
    |
 LL |     println!("{:w$.p$}", local_i32, w = width, p = prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -763,7 +763,7 @@ LL +     println!("{local_i32:width$.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:124:5
+  --> $DIR/uninlined_format_args.rs:129:5
    |
 LL |     println!("{:w$.p$}", w = width, p = prec);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -775,7 +775,7 @@ LL +     println!("{width:width$.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:143:5
+  --> $DIR/uninlined_format_args.rs:148:5
    |
 LL | /     println!(
 LL | |         "{}",
@@ -785,7 +785,7 @@ LL | |     );
    | |_____^
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:148:5
+  --> $DIR/uninlined_format_args.rs:153:5
    |
 LL |     println!("{}", /* comment with a comma , in it */ val);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -797,7 +797,7 @@ LL +     println!("{val}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:154:9
+  --> $DIR/uninlined_format_args.rs:159:9
    |
 LL |         panic!("p1 {}", local_i32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -809,7 +809,7 @@ LL +         panic!("p1 {local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:157:9
+  --> $DIR/uninlined_format_args.rs:162:9
    |
 LL |         panic!("p2 {0}", local_i32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -821,7 +821,7 @@ LL +         panic!("p2 {local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:160:9
+  --> $DIR/uninlined_format_args.rs:165:9
    |
 LL |         panic!("p3 {local_i32}", local_i32 = local_i32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -833,7 +833,7 @@ LL +         panic!("p3 {local_i32}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:180:5
+  --> $DIR/uninlined_format_args.rs:185:5
    |
 LL |     println!("expand='{}'", local_i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unit_arg.rs b/src/tools/clippy/tests/ui/unit_arg.rs
index d082063c8e8..fded8db5daf 100644
--- a/src/tools/clippy/tests/ui/unit_arg.rs
+++ b/src/tools/clippy/tests/ui/unit_arg.rs
@@ -1,4 +1,4 @@
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![warn(clippy::unit_arg)]
 #![allow(unused_must_use, unused_variables)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/unit_cmp.rs b/src/tools/clippy/tests/ui/unit_cmp.rs
index 3d271104361..fc75f548a1b 100644
--- a/src/tools/clippy/tests/ui/unit_cmp.rs
+++ b/src/tools/clippy/tests/ui/unit_cmp.rs
@@ -2,7 +2,8 @@
 #![allow(
     clippy::no_effect,
     clippy::unnecessary_operation,
-    clippy::derive_partial_eq_without_eq
+    clippy::derive_partial_eq_without_eq,
+    clippy::needless_if
 )]
 
 #[derive(PartialEq)]
diff --git a/src/tools/clippy/tests/ui/unit_cmp.stderr b/src/tools/clippy/tests/ui/unit_cmp.stderr
index 41cf19ae685..79c890d644c 100644
--- a/src/tools/clippy/tests/ui/unit_cmp.stderr
+++ b/src/tools/clippy/tests/ui/unit_cmp.stderr
@@ -1,5 +1,5 @@
 error: ==-comparison of unit values detected. This will always be true
-  --> $DIR/unit_cmp.rs:16:8
+  --> $DIR/unit_cmp.rs:17:8
    |
 LL |       if {
    |  ________^
@@ -12,7 +12,7 @@ LL | |     } {}
    = note: `-D clippy::unit-cmp` implied by `-D warnings`
 
 error: >-comparison of unit values detected. This will always be false
-  --> $DIR/unit_cmp.rs:22:8
+  --> $DIR/unit_cmp.rs:23:8
    |
 LL |       if {
    |  ________^
@@ -23,7 +23,7 @@ LL | |     } {}
    | |_____^
 
 error: `assert_eq` of unit values detected. This will always succeed
-  --> $DIR/unit_cmp.rs:28:5
+  --> $DIR/unit_cmp.rs:29:5
    |
 LL | /     assert_eq!(
 LL | |         {
@@ -35,7 +35,7 @@ LL | |     );
    | |_____^
 
 error: `debug_assert_eq` of unit values detected. This will always succeed
-  --> $DIR/unit_cmp.rs:36:5
+  --> $DIR/unit_cmp.rs:37:5
    |
 LL | /     debug_assert_eq!(
 LL | |         {
@@ -47,7 +47,7 @@ LL | |     );
    | |_____^
 
 error: `assert_ne` of unit values detected. This will always fail
-  --> $DIR/unit_cmp.rs:45:5
+  --> $DIR/unit_cmp.rs:46:5
    |
 LL | /     assert_ne!(
 LL | |         {
@@ -59,7 +59,7 @@ LL | |     );
    | |_____^
 
 error: `debug_assert_ne` of unit values detected. This will always fail
-  --> $DIR/unit_cmp.rs:53:5
+  --> $DIR/unit_cmp.rs:54:5
    |
 LL | /     debug_assert_ne!(
 LL | |         {
diff --git a/src/tools/clippy/tests/ui/unit_return_expecting_ord.rs b/src/tools/clippy/tests/ui/unit_return_expecting_ord.rs
index bdb4710cc69..f2a9694f99e 100644
--- a/src/tools/clippy/tests/ui/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/tests/ui/unit_return_expecting_ord.rs
@@ -1,6 +1,7 @@
 #![warn(clippy::unit_return_expecting_ord)]
 #![allow(clippy::needless_return)]
 #![allow(clippy::unused_unit)]
+#![allow(clippy::useless_vec)]
 #![feature(is_sorted)]
 
 struct Struct {
diff --git a/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr b/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
index 1d9564ce225..3a295af55ea 100644
--- a/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
+++ b/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
@@ -1,36 +1,36 @@
 error: this closure returns the unit type which also implements Ord
-  --> $DIR/unit_return_expecting_ord.rs:18:25
+  --> $DIR/unit_return_expecting_ord.rs:19:25
    |
 LL |     structs.sort_by_key(|s| {
    |                         ^^^
    |
 help: probably caused by this trailing semicolon
-  --> $DIR/unit_return_expecting_ord.rs:19:24
+  --> $DIR/unit_return_expecting_ord.rs:20:24
    |
 LL |         double(s.field);
    |                        ^
    = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings`
 
 error: this closure returns the unit type which also implements PartialOrd
-  --> $DIR/unit_return_expecting_ord.rs:22:30
+  --> $DIR/unit_return_expecting_ord.rs:23:30
    |
 LL |     structs.is_sorted_by_key(|s| {
    |                              ^^^
    |
 help: probably caused by this trailing semicolon
-  --> $DIR/unit_return_expecting_ord.rs:23:24
+  --> $DIR/unit_return_expecting_ord.rs:24:24
    |
 LL |         double(s.field);
    |                        ^
 
 error: this closure returns the unit type which also implements PartialOrd
-  --> $DIR/unit_return_expecting_ord.rs:25:30
+  --> $DIR/unit_return_expecting_ord.rs:26:30
    |
 LL |     structs.is_sorted_by_key(|s| {
    |                              ^^^
 
 error: this closure returns the unit type which also implements Ord
-  --> $DIR/unit_return_expecting_ord.rs:35:25
+  --> $DIR/unit_return_expecting_ord.rs:36:25
    |
 LL |     structs.sort_by_key(|s| unit(s.field));
    |                         ^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
index bcc231ea7bc..8efd44baf59 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
@@ -1,13 +1,43 @@
 //@run-rustfix
+//@aux-build:extern_fake_libc.rs
 #![warn(clippy::unnecessary_cast)]
 #![allow(
-    unused_must_use,
     clippy::borrow_as_ptr,
     clippy::no_effect,
     clippy::nonstandard_macro_braces,
-    clippy::unnecessary_operation
+    clippy::unnecessary_operation,
+    nonstandard_style,
+    unused
 )]
 
+extern crate extern_fake_libc;
+
+type PtrConstU8 = *const u8;
+type PtrMutU8 = *mut u8;
+
+fn owo<T>(ptr: *const T) -> *const T {
+    ptr
+}
+
+fn uwu<T, U>(ptr: *const T) -> *const U {
+    ptr as *const U
+}
+
+mod fake_libc {
+    type pid_t = i32;
+    pub unsafe fn getpid() -> pid_t {
+        pid_t::from(0)
+    }
+    // Make sure a where clause does not break it
+    pub fn getpid_SAFE_TRUTH<T: Clone>(t: &T) -> pid_t
+    where
+        T: Clone,
+    {
+        t;
+        unsafe { getpid() }
+    }
+}
+
 #[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
@@ -22,6 +52,26 @@ fn main() {
     1_i32;
     1_f32;
 
+    let _: *mut u8 = [1u8, 2].as_ptr() as *mut u8;
+
+    [1u8, 2].as_ptr();
+    [1u8, 2].as_ptr() as *mut u8;
+    [1u8, 2].as_mut_ptr();
+    [1u8, 2].as_mut_ptr() as *const u8;
+    [1u8, 2].as_ptr() as PtrConstU8;
+    [1u8, 2].as_ptr() as PtrMutU8;
+    [1u8, 2].as_mut_ptr() as PtrMutU8;
+    [1u8, 2].as_mut_ptr() as PtrConstU8;
+    let _: *const u8 = [1u8, 2].as_ptr() as _;
+    let _: *mut u8 = [1u8, 2].as_mut_ptr() as _;
+    let _: *const u8 = [1u8, 2].as_ptr() as *const _;
+    let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _;
+
+    owo::<u32>([1u32].as_ptr());
+    uwu::<u32, u8>([1u32].as_ptr());
+    // this will not lint in the function body even though they have the same type, instead here
+    uwu::<u32, u32>([1u32].as_ptr());
+
     // macro version
     macro_rules! foo {
         ($a:ident, $b:ident) => {
@@ -35,12 +85,37 @@ fn main() {
     foo!(b, f32);
     foo!(c, f64);
 
+    // do not lint cast from cfg-dependant type
+    let x = 0 as std::ffi::c_ulong;
+    let y = x as u64;
+    let x: std::ffi::c_ulong = 0;
+    let y = x as u64;
+
     // do not lint cast to cfg-dependant type
-    1 as std::os::raw::c_char;
+    let x = 1 as std::os::raw::c_char;
+    let y = x as u64;
 
     // do not lint cast to alias type
     1 as I32Alias;
     &1 as &I32Alias;
+    // or from
+    let x: I32Alias = 1;
+    let y = x as u64;
+    fake_libc::getpid_SAFE_TRUTH(&0u32) as i32;
+    extern_fake_libc::getpid_SAFE_TRUTH() as i32;
+    let pid = unsafe { fake_libc::getpid() };
+    pid as i32;
+
+    let i8_ptr: *const i8 = &1;
+    let u8_ptr: *const u8 = &1;
+
+    // cfg dependant pointees
+    i8_ptr as *const std::os::raw::c_char;
+    u8_ptr as *const std::os::raw::c_char;
+
+    // type aliased pointees
+    i8_ptr as *const std::ffi::c_char;
+    u8_ptr as *const std::ffi::c_char;
 
     // issue #9960
     macro_rules! bind_var {
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs
index 282b2f1283e..c7723ef51f9 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs
@@ -1,13 +1,43 @@
 //@run-rustfix
+//@aux-build:extern_fake_libc.rs
 #![warn(clippy::unnecessary_cast)]
 #![allow(
-    unused_must_use,
     clippy::borrow_as_ptr,
     clippy::no_effect,
     clippy::nonstandard_macro_braces,
-    clippy::unnecessary_operation
+    clippy::unnecessary_operation,
+    nonstandard_style,
+    unused
 )]
 
+extern crate extern_fake_libc;
+
+type PtrConstU8 = *const u8;
+type PtrMutU8 = *mut u8;
+
+fn owo<T>(ptr: *const T) -> *const T {
+    ptr as *const T
+}
+
+fn uwu<T, U>(ptr: *const T) -> *const U {
+    ptr as *const U
+}
+
+mod fake_libc {
+    type pid_t = i32;
+    pub unsafe fn getpid() -> pid_t {
+        pid_t::from(0)
+    }
+    // Make sure a where clause does not break it
+    pub fn getpid_SAFE_TRUTH<T: Clone>(t: &T) -> pid_t
+    where
+        T: Clone,
+    {
+        t;
+        unsafe { getpid() }
+    }
+}
+
 #[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
@@ -22,6 +52,26 @@ fn main() {
     1_i32 as i32;
     1_f32 as f32;
 
+    let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8;
+
+    [1u8, 2].as_ptr() as *const u8;
+    [1u8, 2].as_ptr() as *mut u8;
+    [1u8, 2].as_mut_ptr() as *mut u8;
+    [1u8, 2].as_mut_ptr() as *const u8;
+    [1u8, 2].as_ptr() as PtrConstU8;
+    [1u8, 2].as_ptr() as PtrMutU8;
+    [1u8, 2].as_mut_ptr() as PtrMutU8;
+    [1u8, 2].as_mut_ptr() as PtrConstU8;
+    let _: *const u8 = [1u8, 2].as_ptr() as _;
+    let _: *mut u8 = [1u8, 2].as_mut_ptr() as _;
+    let _: *const u8 = [1u8, 2].as_ptr() as *const _;
+    let _: *mut u8 = [1u8, 2].as_mut_ptr() as *mut _;
+
+    owo::<u32>([1u32].as_ptr()) as *const u32;
+    uwu::<u32, u8>([1u32].as_ptr()) as *const u8;
+    // this will not lint in the function body even though they have the same type, instead here
+    uwu::<u32, u32>([1u32].as_ptr()) as *const u32;
+
     // macro version
     macro_rules! foo {
         ($a:ident, $b:ident) => {
@@ -35,12 +85,37 @@ fn main() {
     foo!(b, f32);
     foo!(c, f64);
 
+    // do not lint cast from cfg-dependant type
+    let x = 0 as std::ffi::c_ulong;
+    let y = x as u64;
+    let x: std::ffi::c_ulong = 0;
+    let y = x as u64;
+
     // do not lint cast to cfg-dependant type
-    1 as std::os::raw::c_char;
+    let x = 1 as std::os::raw::c_char;
+    let y = x as u64;
 
     // do not lint cast to alias type
     1 as I32Alias;
     &1 as &I32Alias;
+    // or from
+    let x: I32Alias = 1;
+    let y = x as u64;
+    fake_libc::getpid_SAFE_TRUTH(&0u32) as i32;
+    extern_fake_libc::getpid_SAFE_TRUTH() as i32;
+    let pid = unsafe { fake_libc::getpid() };
+    pid as i32;
+
+    let i8_ptr: *const i8 = &1;
+    let u8_ptr: *const u8 = &1;
+
+    // cfg dependant pointees
+    i8_ptr as *const std::os::raw::c_char;
+    u8_ptr as *const std::os::raw::c_char;
+
+    // type aliased pointees
+    i8_ptr as *const std::ffi::c_char;
+    u8_ptr as *const std::ffi::c_char;
 
     // issue #9960
     macro_rules! bind_var {
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
index fcee4ee2a65..f0443556fb4 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
@@ -1,190 +1,232 @@
+error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`)
+  --> $DIR/unnecessary_cast.rs:19:5
+   |
+LL |     ptr as *const T
+   |     ^^^^^^^^^^^^^^^ help: try: `ptr`
+   |
+   = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
+
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:14:5
+  --> $DIR/unnecessary_cast.rs:44:5
    |
 LL |     1i32 as i32;
    |     ^^^^^^^^^^^ help: try: `1_i32`
-   |
-   = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:15:5
+  --> $DIR/unnecessary_cast.rs:45:5
    |
 LL |     1f32 as f32;
    |     ^^^^^^^^^^^ help: try: `1_f32`
 
 error: casting to the same type is unnecessary (`bool` -> `bool`)
-  --> $DIR/unnecessary_cast.rs:16:5
+  --> $DIR/unnecessary_cast.rs:46:5
    |
 LL |     false as bool;
    |     ^^^^^^^^^^^^^ help: try: `false`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:19:5
+  --> $DIR/unnecessary_cast.rs:49:5
    |
 LL |     -1_i32 as i32;
    |     ^^^^^^^^^^^^^ help: try: `-1_i32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:20:5
+  --> $DIR/unnecessary_cast.rs:50:5
    |
 LL |     - 1_i32 as i32;
    |     ^^^^^^^^^^^^^^ help: try: `- 1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:21:5
+  --> $DIR/unnecessary_cast.rs:51:5
    |
 LL |     -1f32 as f32;
    |     ^^^^^^^^^^^^ help: try: `-1_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:22:5
+  --> $DIR/unnecessary_cast.rs:52:5
    |
 LL |     1_i32 as i32;
    |     ^^^^^^^^^^^^ help: try: `1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:23:5
+  --> $DIR/unnecessary_cast.rs:53:5
    |
 LL |     1_f32 as f32;
    |     ^^^^^^^^^^^^ help: try: `1_f32`
 
+error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
+  --> $DIR/unnecessary_cast.rs:55:22
+   |
+LL |     let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()`
+
+error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
+  --> $DIR/unnecessary_cast.rs:57:5
+   |
+LL |     [1u8, 2].as_ptr() as *const u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()`
+
+error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`)
+  --> $DIR/unnecessary_cast.rs:59:5
+   |
+LL |     [1u8, 2].as_mut_ptr() as *mut u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()`
+
+error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
+  --> $DIR/unnecessary_cast.rs:70:5
+   |
+LL |     owo::<u32>([1u32].as_ptr()) as *const u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::<u32>([1u32].as_ptr())`
+
+error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
+  --> $DIR/unnecessary_cast.rs:71:5
+   |
+LL |     uwu::<u32, u8>([1u32].as_ptr()) as *const u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u8>([1u32].as_ptr())`
+
+error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
+  --> $DIR/unnecessary_cast.rs:73:5
+   |
+LL |     uwu::<u32, u32>([1u32].as_ptr()) as *const u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u32>([1u32].as_ptr())`
+
 error: casting integer literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:64:9
+  --> $DIR/unnecessary_cast.rs:139:9
    |
 LL |         100 as f32;
    |         ^^^^^^^^^^ help: try: `100_f32`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:65:9
+  --> $DIR/unnecessary_cast.rs:140:9
    |
 LL |         100 as f64;
    |         ^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:66:9
+  --> $DIR/unnecessary_cast.rs:141:9
    |
 LL |         100_i32 as f64;
    |         ^^^^^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:67:17
+  --> $DIR/unnecessary_cast.rs:142:17
    |
 LL |         let _ = -100 as f32;
    |                 ^^^^^^^^^^^ help: try: `-100_f32`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:68:17
+  --> $DIR/unnecessary_cast.rs:143:17
    |
 LL |         let _ = -100 as f64;
    |                 ^^^^^^^^^^^ help: try: `-100_f64`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:69:17
+  --> $DIR/unnecessary_cast.rs:144:17
    |
 LL |         let _ = -100_i32 as f64;
    |                 ^^^^^^^^^^^^^^^ help: try: `-100_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:70:9
+  --> $DIR/unnecessary_cast.rs:145:9
    |
 LL |         100. as f32;
    |         ^^^^^^^^^^^ help: try: `100_f32`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:71:9
+  --> $DIR/unnecessary_cast.rs:146:9
    |
 LL |         100. as f64;
    |         ^^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:83:9
+  --> $DIR/unnecessary_cast.rs:158:9
    |
 LL |         1 as u32;
    |         ^^^^^^^^ help: try: `1_u32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:84:9
+  --> $DIR/unnecessary_cast.rs:159:9
    |
 LL |         0x10 as i32;
    |         ^^^^^^^^^^^ help: try: `0x10_i32`
 
 error: casting integer literal to `usize` is unnecessary
-  --> $DIR/unnecessary_cast.rs:85:9
+  --> $DIR/unnecessary_cast.rs:160:9
    |
 LL |         0b10 as usize;
    |         ^^^^^^^^^^^^^ help: try: `0b10_usize`
 
 error: casting integer literal to `u16` is unnecessary
-  --> $DIR/unnecessary_cast.rs:86:9
+  --> $DIR/unnecessary_cast.rs:161:9
    |
 LL |         0o73 as u16;
    |         ^^^^^^^^^^^ help: try: `0o73_u16`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:87:9
+  --> $DIR/unnecessary_cast.rs:162:9
    |
 LL |         1_000_000_000 as u32;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:89:9
+  --> $DIR/unnecessary_cast.rs:164:9
    |
 LL |         1.0 as f64;
    |         ^^^^^^^^^^ help: try: `1.0_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:90:9
+  --> $DIR/unnecessary_cast.rs:165:9
    |
 LL |         0.5 as f32;
    |         ^^^^^^^^^^ help: try: `0.5_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:94:17
+  --> $DIR/unnecessary_cast.rs:169:17
    |
 LL |         let _ = -1 as i32;
    |                 ^^^^^^^^^ help: try: `-1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:95:17
+  --> $DIR/unnecessary_cast.rs:170:17
    |
 LL |         let _ = -1.0 as f32;
    |                 ^^^^^^^^^^^ help: try: `-1.0_f32`
 
 error: casting to the same type is unnecessary (`i32` -> `i32`)
-  --> $DIR/unnecessary_cast.rs:101:18
+  --> $DIR/unnecessary_cast.rs:176:18
    |
 LL |         let _ = &(x as i32);
    |                  ^^^^^^^^^^ help: try: `{ x }`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:107:22
+  --> $DIR/unnecessary_cast.rs:182:22
    |
 LL |         let _: i32 = -(1) as i32;
    |                      ^^^^^^^^^^^ help: try: `-1_i32`
 
 error: casting integer literal to `i64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:109:22
+  --> $DIR/unnecessary_cast.rs:184:22
    |
 LL |         let _: i64 = -(1) as i64;
    |                      ^^^^^^^^^^^ help: try: `-1_i64`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:116:22
+  --> $DIR/unnecessary_cast.rs:191:22
    |
 LL |         let _: f64 = (-8.0 as f64).exp();
    |                      ^^^^^^^^^^^^^ help: try: `(-8.0_f64)`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:118:23
+  --> $DIR/unnecessary_cast.rs:193:23
    |
 LL |         let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
    |                       ^^^^^^^^^^^^ help: try: `8.0_f64`
 
 error: casting to the same type is unnecessary (`f32` -> `f32`)
-  --> $DIR/unnecessary_cast.rs:126:20
+  --> $DIR/unnecessary_cast.rs:201:20
    |
 LL |         let _num = foo() as f32;
    |                    ^^^^^^^^^^^^ help: try: `foo()`
 
-error: aborting due to 31 previous errors
+error: aborting due to 38 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.fixed b/src/tools/clippy/tests/ui/unnecessary_fold.fixed
index 2bed14973ca..bd1d4a152ae 100644
--- a/src/tools/clippy/tests/ui/unnecessary_fold.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_fold.fixed
@@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() {
         .any(|x| x > 2);
 }
 
+fn issue10000() {
+    use std::collections::HashMap;
+    use std::hash::BuildHasher;
+
+    fn anything<T>(_: T) {}
+    fn num(_: i32) {}
+    fn smoketest_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
+        map.insert(0, 0);
+        assert_eq!(map.values().sum::<i32>(), 0);
+
+        // more cases:
+        let _ = map.values().sum::<i32>();
+        let _ = map.values().product::<i32>();
+        let _: i32 = map.values().sum();
+        let _: i32 = map.values().product();
+        anything(map.values().sum::<i32>());
+        anything(map.values().product::<i32>());
+        num(map.values().sum());
+        num(map.values().product());
+    }
+
+    smoketest_map(HashMap::new());
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.rs b/src/tools/clippy/tests/ui/unnecessary_fold.rs
index a3cec8ea3d5..d27cc460c44 100644
--- a/src/tools/clippy/tests/ui/unnecessary_fold.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_fold.rs
@@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() {
         .fold(false, |acc, x| acc || x > 2);
 }
 
+fn issue10000() {
+    use std::collections::HashMap;
+    use std::hash::BuildHasher;
+
+    fn anything<T>(_: T) {}
+    fn num(_: i32) {}
+    fn smoketest_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
+        map.insert(0, 0);
+        assert_eq!(map.values().fold(0, |x, y| x + y), 0);
+
+        // more cases:
+        let _ = map.values().fold(0, |x, y| x + y);
+        let _ = map.values().fold(1, |x, y| x * y);
+        let _: i32 = map.values().fold(0, |x, y| x + y);
+        let _: i32 = map.values().fold(1, |x, y| x * y);
+        anything(map.values().fold(0, |x, y| x + y));
+        anything(map.values().fold(1, |x, y| x * y));
+        num(map.values().fold(0, |x, y| x + y));
+        num(map.values().fold(1, |x, y| x * y));
+    }
+
+    smoketest_map(HashMap::new());
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.stderr b/src/tools/clippy/tests/ui/unnecessary_fold.stderr
index 22c44588ab7..98979f7477f 100644
--- a/src/tools/clippy/tests/ui/unnecessary_fold.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_fold.stderr
@@ -36,5 +36,59 @@ error: this `.fold` can be written more succinctly using another method
 LL |         .fold(false, |acc, x| acc || x > 2);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)`
 
-error: aborting due to 6 previous errors
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:60:33
+   |
+LL |         assert_eq!(map.values().fold(0, |x, y| x + y), 0);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:63:30
+   |
+LL |         let _ = map.values().fold(0, |x, y| x + y);
+   |                              ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:64:30
+   |
+LL |         let _ = map.values().fold(1, |x, y| x * y);
+   |                              ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:65:35
+   |
+LL |         let _: i32 = map.values().fold(0, |x, y| x + y);
+   |                                   ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:66:35
+   |
+LL |         let _: i32 = map.values().fold(1, |x, y| x * y);
+   |                                   ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:67:31
+   |
+LL |         anything(map.values().fold(0, |x, y| x + y));
+   |                               ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:68:31
+   |
+LL |         anything(map.values().fold(1, |x, y| x * y));
+   |                               ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:69:26
+   |
+LL |         num(map.values().fold(0, |x, y| x + y));
+   |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:70:26
+   |
+LL |         num(map.values().fold(1, |x, y| x * y));
+   |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()`
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.fixed b/src/tools/clippy/tests/ui/unnecessary_join.fixed
index e102df62599..f13a5275e31 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_join.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::unnecessary_join)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::useless_vec)]
 
 fn main() {
     // should be linted
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.rs b/src/tools/clippy/tests/ui/unnecessary_join.rs
index b87c15bc126..6014d723a2f 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_join.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 #![warn(clippy::unnecessary_join)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::useless_vec)]
 
 fn main() {
     // should be linted
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
index c3728886ec9..dca38034177 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
@@ -1,9 +1,13 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![warn(clippy::unnecessary_lazy_evaluations)]
 #![allow(clippy::redundant_closure)]
 #![allow(clippy::bind_instead_of_map)]
 #![allow(clippy::map_identity)]
+#![allow(clippy::needless_borrow)]
+#![allow(clippy::unnecessary_literal_unwrap)]
+
+use std::ops::Deref;
 
 extern crate proc_macros;
 use proc_macros::with_span;
@@ -41,6 +45,15 @@ impl Drop for Issue9427FollowUp {
     }
 }
 
+struct Issue10437;
+impl Deref for Issue10437 {
+    type Target = u32;
+    fn deref(&self) -> &Self::Target {
+        println!("side effect deref");
+        &0
+    }
+}
+
 fn main() {
     let astronomers_pi = 10;
     let ext_arr: [usize; 1] = [2];
@@ -65,6 +78,15 @@ fn main() {
     let _ = nested_tuple_opt.unwrap_or(Some((1, 2)));
     let _ = cond.then_some(astronomers_pi);
 
+    // Should lint - Builtin deref
+    let r = &1;
+    let _ = Some(1).unwrap_or(*r);
+    let b = Box::new(1);
+    let _ = Some(1).unwrap_or(*b);
+    // Should lint - Builtin deref through autoderef
+    let _ = Some(1).as_ref().unwrap_or(&r);
+    let _ = Some(1).as_ref().unwrap_or(&b);
+
     // Cases when unwrap is not called on a simple variable
     let _ = Some(10).unwrap_or(2);
     let _ = Some(10).and(ext_opt);
@@ -93,6 +115,12 @@ fn main() {
     let _ = deep.0.or_else(|| some_call());
     let _ = opt.ok_or_else(|| ext_arr[0]);
 
+    let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl
+    let _ = Some(1).unwrap_or(*Issue10437);
+
+    let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437);
+    let _ = Some(1).as_ref().unwrap_or(&Issue10437);
+
     // Should not lint - bool
     let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
     let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
index 76e50fa5b03..7fda719edc1 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
@@ -1,9 +1,13 @@
 //@run-rustfix
-//@aux-build: proc_macros.rs
+//@aux-build: proc_macros.rs:proc-macro
 #![warn(clippy::unnecessary_lazy_evaluations)]
 #![allow(clippy::redundant_closure)]
 #![allow(clippy::bind_instead_of_map)]
 #![allow(clippy::map_identity)]
+#![allow(clippy::needless_borrow)]
+#![allow(clippy::unnecessary_literal_unwrap)]
+
+use std::ops::Deref;
 
 extern crate proc_macros;
 use proc_macros::with_span;
@@ -41,6 +45,15 @@ impl Drop for Issue9427FollowUp {
     }
 }
 
+struct Issue10437;
+impl Deref for Issue10437 {
+    type Target = u32;
+    fn deref(&self) -> &Self::Target {
+        println!("side effect deref");
+        &0
+    }
+}
+
 fn main() {
     let astronomers_pi = 10;
     let ext_arr: [usize; 1] = [2];
@@ -65,6 +78,15 @@ fn main() {
     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
     let _ = cond.then(|| astronomers_pi);
 
+    // Should lint - Builtin deref
+    let r = &1;
+    let _ = Some(1).unwrap_or_else(|| *r);
+    let b = Box::new(1);
+    let _ = Some(1).unwrap_or_else(|| *b);
+    // Should lint - Builtin deref through autoderef
+    let _ = Some(1).as_ref().unwrap_or_else(|| &r);
+    let _ = Some(1).as_ref().unwrap_or_else(|| &b);
+
     // Cases when unwrap is not called on a simple variable
     let _ = Some(10).unwrap_or_else(|| 2);
     let _ = Some(10).and_then(|_| ext_opt);
@@ -93,6 +115,12 @@ fn main() {
     let _ = deep.0.or_else(|| some_call());
     let _ = opt.ok_or_else(|| ext_arr[0]);
 
+    let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl
+    let _ = Some(1).unwrap_or(*Issue10437);
+
+    let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437);
+    let _ = Some(1).as_ref().unwrap_or(&Issue10437);
+
     // Should not lint - bool
     let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
     let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
index 0339755442c..458eed1f359 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
@@ -1,5 +1,5 @@
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:56:13
+  --> $DIR/unnecessary_lazy_eval.rs:69:13
    |
 LL |     let _ = opt.unwrap_or_else(|| 2);
    |             ^^^^--------------------
@@ -9,7 +9,7 @@ LL |     let _ = opt.unwrap_or_else(|| 2);
    = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:57:13
+  --> $DIR/unnecessary_lazy_eval.rs:70:13
    |
 LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |             ^^^^---------------------------------
@@ -17,7 +17,7 @@ LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:58:13
+  --> $DIR/unnecessary_lazy_eval.rs:71:13
    |
 LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |             ^^^^-------------------------------------
@@ -25,7 +25,7 @@ LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:60:13
+  --> $DIR/unnecessary_lazy_eval.rs:73:13
    |
 LL |     let _ = opt.and_then(|_| ext_opt);
    |             ^^^^---------------------
@@ -33,7 +33,7 @@ LL |     let _ = opt.and_then(|_| ext_opt);
    |                 help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:61:13
+  --> $DIR/unnecessary_lazy_eval.rs:74:13
    |
 LL |     let _ = opt.or_else(|| ext_opt);
    |             ^^^^-------------------
@@ -41,7 +41,7 @@ LL |     let _ = opt.or_else(|| ext_opt);
    |                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:62:13
+  --> $DIR/unnecessary_lazy_eval.rs:75:13
    |
 LL |     let _ = opt.or_else(|| None);
    |             ^^^^----------------
@@ -49,7 +49,7 @@ LL |     let _ = opt.or_else(|| None);
    |                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:63:13
+  --> $DIR/unnecessary_lazy_eval.rs:76:13
    |
 LL |     let _ = opt.get_or_insert_with(|| 2);
    |             ^^^^------------------------
@@ -57,7 +57,7 @@ LL |     let _ = opt.get_or_insert_with(|| 2);
    |                 help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:64:13
+  --> $DIR/unnecessary_lazy_eval.rs:77:13
    |
 LL |     let _ = opt.ok_or_else(|| 2);
    |             ^^^^----------------
@@ -65,7 +65,7 @@ LL |     let _ = opt.ok_or_else(|| 2);
    |                 help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:65:13
+  --> $DIR/unnecessary_lazy_eval.rs:78:13
    |
 LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |             ^^^^^^^^^^^^^^^^^-------------------------------
@@ -73,7 +73,7 @@ LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:66:13
+  --> $DIR/unnecessary_lazy_eval.rs:79:13
    |
 LL |     let _ = cond.then(|| astronomers_pi);
    |             ^^^^^-----------------------
@@ -81,7 +81,39 @@ LL |     let _ = cond.then(|| astronomers_pi);
    |                  help: use `then_some(..)` instead: `then_some(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:69:13
+  --> $DIR/unnecessary_lazy_eval.rs:83:13
+   |
+LL |     let _ = Some(1).unwrap_or_else(|| *r);
+   |             ^^^^^^^^---------------------
+   |                     |
+   |                     help: use `unwrap_or(..)` instead: `unwrap_or(*r)`
+
+error: unnecessary closure used to substitute value for `Option::None`
+  --> $DIR/unnecessary_lazy_eval.rs:85:13
+   |
+LL |     let _ = Some(1).unwrap_or_else(|| *b);
+   |             ^^^^^^^^---------------------
+   |                     |
+   |                     help: use `unwrap_or(..)` instead: `unwrap_or(*b)`
+
+error: unnecessary closure used to substitute value for `Option::None`
+  --> $DIR/unnecessary_lazy_eval.rs:87:13
+   |
+LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &r);
+   |             ^^^^^^^^^^^^^^^^^---------------------
+   |                              |
+   |                              help: use `unwrap_or(..)` instead: `unwrap_or(&r)`
+
+error: unnecessary closure used to substitute value for `Option::None`
+  --> $DIR/unnecessary_lazy_eval.rs:88:13
+   |
+LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &b);
+   |             ^^^^^^^^^^^^^^^^^---------------------
+   |                              |
+   |                              help: use `unwrap_or(..)` instead: `unwrap_or(&b)`
+
+error: unnecessary closure used to substitute value for `Option::None`
+  --> $DIR/unnecessary_lazy_eval.rs:91:13
    |
 LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |             ^^^^^^^^^--------------------
@@ -89,7 +121,7 @@ LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |                      help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:70:13
+  --> $DIR/unnecessary_lazy_eval.rs:92:13
    |
 LL |     let _ = Some(10).and_then(|_| ext_opt);
    |             ^^^^^^^^^---------------------
@@ -97,7 +129,7 @@ LL |     let _ = Some(10).and_then(|_| ext_opt);
    |                      help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:71:28
+  --> $DIR/unnecessary_lazy_eval.rs:93:28
    |
 LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                            ^^^^^-------------------
@@ -105,7 +137,7 @@ LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:72:13
+  --> $DIR/unnecessary_lazy_eval.rs:94:13
    |
 LL |     let _ = None.get_or_insert_with(|| 2);
    |             ^^^^^------------------------
@@ -113,7 +145,7 @@ LL |     let _ = None.get_or_insert_with(|| 2);
    |                  help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:73:35
+  --> $DIR/unnecessary_lazy_eval.rs:95:35
    |
 LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                   ^^^^^----------------
@@ -121,7 +153,7 @@ LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                        help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:74:28
+  --> $DIR/unnecessary_lazy_eval.rs:96:28
    |
 LL |     let _: Option<usize> = None.or_else(|| None);
    |                            ^^^^^----------------
@@ -129,7 +161,7 @@ LL |     let _: Option<usize> = None.or_else(|| None);
    |                                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:77:13
+  --> $DIR/unnecessary_lazy_eval.rs:99:13
    |
 LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |             ^^^^^^^--------------------
@@ -137,7 +169,7 @@ LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |                    help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:78:13
+  --> $DIR/unnecessary_lazy_eval.rs:100:13
    |
 LL |     let _ = deep.0.and_then(|_| ext_opt);
    |             ^^^^^^^---------------------
@@ -145,7 +177,7 @@ LL |     let _ = deep.0.and_then(|_| ext_opt);
    |                    help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:79:13
+  --> $DIR/unnecessary_lazy_eval.rs:101:13
    |
 LL |     let _ = deep.0.or_else(|| None);
    |             ^^^^^^^----------------
@@ -153,7 +185,7 @@ LL |     let _ = deep.0.or_else(|| None);
    |                    help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:80:13
+  --> $DIR/unnecessary_lazy_eval.rs:102:13
    |
 LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |             ^^^^^^^------------------------
@@ -161,7 +193,7 @@ LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |                    help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:81:13
+  --> $DIR/unnecessary_lazy_eval.rs:103:13
    |
 LL |     let _ = deep.0.ok_or_else(|| 2);
    |             ^^^^^^^----------------
@@ -169,7 +201,7 @@ LL |     let _ = deep.0.ok_or_else(|| 2);
    |                    help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:105:28
+  --> $DIR/unnecessary_lazy_eval.rs:133:28
    |
 LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                            ^^^^^-------------------
@@ -177,7 +209,7 @@ LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:106:13
+  --> $DIR/unnecessary_lazy_eval.rs:134:13
    |
 LL |     let _ = deep.0.or_else(|| Some(3));
    |             ^^^^^^^-------------------
@@ -185,7 +217,7 @@ LL |     let _ = deep.0.or_else(|| Some(3));
    |                    help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:107:13
+  --> $DIR/unnecessary_lazy_eval.rs:135:13
    |
 LL |     let _ = opt.or_else(|| Some(3));
    |             ^^^^-------------------
@@ -193,7 +225,7 @@ LL |     let _ = opt.or_else(|| Some(3));
    |                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:113:13
+  --> $DIR/unnecessary_lazy_eval.rs:141:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| 2);
    |             ^^^^^---------------------
@@ -201,7 +233,7 @@ LL |     let _ = res2.unwrap_or_else(|_| 2);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:114:13
+  --> $DIR/unnecessary_lazy_eval.rs:142:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |             ^^^^^----------------------------------
@@ -209,7 +241,7 @@ LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:115:13
+  --> $DIR/unnecessary_lazy_eval.rs:143:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |             ^^^^^--------------------------------------
@@ -217,7 +249,7 @@ LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:137:35
+  --> $DIR/unnecessary_lazy_eval.rs:165:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                   ^^^^--------------------
@@ -225,7 +257,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                       help: use `and(..)` instead: `and(Err(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:138:35
+  --> $DIR/unnecessary_lazy_eval.rs:166:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                   ^^^^---------------------------------
@@ -233,7 +265,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                       help: use `and(..)` instead: `and(Err(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:139:35
+  --> $DIR/unnecessary_lazy_eval.rs:167:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
    |                                   ^^^^-------------------------------------
@@ -241,7 +273,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
    |                                       help: use `and(..)` instead: `and(Err(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:141:35
+  --> $DIR/unnecessary_lazy_eval.rs:169:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                   ^^^^------------------
@@ -249,7 +281,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                       help: use `or(..)` instead: `or(Ok(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:142:35
+  --> $DIR/unnecessary_lazy_eval.rs:170:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                   ^^^^-------------------------------
@@ -257,7 +289,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                       help: use `or(..)` instead: `or(Ok(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:143:35
+  --> $DIR/unnecessary_lazy_eval.rs:171:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                   ^^^^-----------------------------------
@@ -265,7 +297,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:144:35
+  --> $DIR/unnecessary_lazy_eval.rs:172:35
    |
 LL |       let _: Result<usize, usize> = res.
    |  ___________________________________^
@@ -279,5 +311,5 @@ LL | |     or_else(|_| Ok(ext_str.some_field));
    |       |
    |       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
-error: aborting due to 34 previous errors
+error: aborting due to 38 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
index b05dd143bfd..b4a1f81679a 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::unnecessary_lazy_evaluations)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 struct Deep(Option<usize>);
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
index 20acab6e844..7f353ba0698 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr
@@ -1,5 +1,5 @@
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval_unfixable.rs:12:13
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:13:13
    |
 LL |     let _ = Ok(1).unwrap_or_else(|()| 2);
    |             ^^^^^^----------------------
@@ -9,7 +9,7 @@ LL |     let _ = Ok(1).unwrap_or_else(|()| 2);
    = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval_unfixable.rs:16:13
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13
    |
 LL |     let _ = Ok(1).unwrap_or_else(|e::E| 2);
    |             ^^^^^^------------------------
@@ -17,7 +17,7 @@ LL |     let _ = Ok(1).unwrap_or_else(|e::E| 2);
    |                   help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval_unfixable.rs:17:13
+  --> $DIR/unnecessary_lazy_eval_unfixable.rs:18:13
    |
 LL |     let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2);
    |             ^^^^^^-------------------------------------
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed
new file mode 100644
index 00000000000..630a1bea3c8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed
@@ -0,0 +1,78 @@
+//@run-rustfix
+#![warn(clippy::unnecessary_literal_unwrap)]
+#![allow(unreachable_code)]
+#![allow(
+    clippy::unnecessary_lazy_evaluations,
+    clippy::diverging_sub_expression,
+    clippy::let_unit_value,
+    clippy::no_effect
+)]
+
+fn unwrap_option_some() {
+    let _val = 1;
+    let _val = 1;
+
+    1;
+    1;
+}
+
+fn unwrap_option_none() {
+    let _val = panic!();
+    let _val = panic!("this always happens");
+
+    panic!();
+    panic!("this always happens");
+}
+
+fn unwrap_result_ok() {
+    let _val = 1;
+    let _val = 1;
+    let _val = panic!("{:?}", 1);
+    let _val = panic!("{1}: {:?}", 1, "this always happens");
+
+    1;
+    1;
+    panic!("{:?}", 1);
+    panic!("{1}: {:?}", 1, "this always happens");
+}
+
+fn unwrap_result_err() {
+    let _val = 1;
+    let _val = 1;
+    let _val = panic!("{:?}", 1);
+    let _val = panic!("{1}: {:?}", 1, "this always happens");
+
+    1;
+    1;
+    panic!("{:?}", 1);
+    panic!("{1}: {:?}", 1, "this always happens");
+}
+
+fn unwrap_methods_option() {
+    let _val = 1;
+    let _val = 1;
+    let _val = 1;
+
+    1;
+    1;
+    1;
+}
+
+fn unwrap_methods_result() {
+    let _val = 1;
+    let _val = 1;
+    let _val = 1;
+
+    1;
+    1;
+    1;
+}
+
+fn main() {
+    unwrap_option_some();
+    unwrap_option_none();
+    unwrap_result_ok();
+    unwrap_result_err();
+    unwrap_methods_option();
+    unwrap_methods_result();
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.rs b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.rs
new file mode 100644
index 00000000000..14f92cb370f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.rs
@@ -0,0 +1,78 @@
+//@run-rustfix
+#![warn(clippy::unnecessary_literal_unwrap)]
+#![allow(unreachable_code)]
+#![allow(
+    clippy::unnecessary_lazy_evaluations,
+    clippy::diverging_sub_expression,
+    clippy::let_unit_value,
+    clippy::no_effect
+)]
+
+fn unwrap_option_some() {
+    let _val = Some(1).unwrap();
+    let _val = Some(1).expect("this never happens");
+
+    Some(1).unwrap();
+    Some(1).expect("this never happens");
+}
+
+fn unwrap_option_none() {
+    let _val = None::<()>.unwrap();
+    let _val = None::<()>.expect("this always happens");
+
+    None::<()>.unwrap();
+    None::<()>.expect("this always happens");
+}
+
+fn unwrap_result_ok() {
+    let _val = Ok::<_, ()>(1).unwrap();
+    let _val = Ok::<_, ()>(1).expect("this never happens");
+    let _val = Ok::<_, ()>(1).unwrap_err();
+    let _val = Ok::<_, ()>(1).expect_err("this always happens");
+
+    Ok::<_, ()>(1).unwrap();
+    Ok::<_, ()>(1).expect("this never happens");
+    Ok::<_, ()>(1).unwrap_err();
+    Ok::<_, ()>(1).expect_err("this always happens");
+}
+
+fn unwrap_result_err() {
+    let _val = Err::<(), _>(1).unwrap_err();
+    let _val = Err::<(), _>(1).expect_err("this never happens");
+    let _val = Err::<(), _>(1).unwrap();
+    let _val = Err::<(), _>(1).expect("this always happens");
+
+    Err::<(), _>(1).unwrap_err();
+    Err::<(), _>(1).expect_err("this never happens");
+    Err::<(), _>(1).unwrap();
+    Err::<(), _>(1).expect("this always happens");
+}
+
+fn unwrap_methods_option() {
+    let _val = Some(1).unwrap_or(2);
+    let _val = Some(1).unwrap_or_default();
+    let _val = Some(1).unwrap_or_else(|| 2);
+
+    Some(1).unwrap_or(2);
+    Some(1).unwrap_or_default();
+    Some(1).unwrap_or_else(|| 2);
+}
+
+fn unwrap_methods_result() {
+    let _val = Ok::<_, ()>(1).unwrap_or(2);
+    let _val = Ok::<_, ()>(1).unwrap_or_default();
+    let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2);
+
+    Ok::<_, ()>(1).unwrap_or(2);
+    Ok::<_, ()>(1).unwrap_or_default();
+    Ok::<_, ()>(1).unwrap_or_else(|_| 2);
+}
+
+fn main() {
+    unwrap_option_some();
+    unwrap_option_none();
+    unwrap_result_ok();
+    unwrap_result_err();
+    unwrap_methods_option();
+    unwrap_methods_result();
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
new file mode 100644
index 00000000000..0c71ee05323
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
@@ -0,0 +1,413 @@
+error: used `unwrap()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:12:16
+   |
+LL |     let _val = Some(1).unwrap();
+   |                ^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings`
+help: remove the `Some` and `unwrap()`
+   |
+LL -     let _val = Some(1).unwrap();
+LL +     let _val = 1;
+   |
+
+error: used `expect()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:13:16
+   |
+LL |     let _val = Some(1).expect("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `expect()`
+   |
+LL -     let _val = Some(1).expect("this never happens");
+LL +     let _val = 1;
+   |
+
+error: used `unwrap()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:15:5
+   |
+LL |     Some(1).unwrap();
+   |     ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap()`
+   |
+LL -     Some(1).unwrap();
+LL +     1;
+   |
+
+error: used `expect()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:16:5
+   |
+LL |     Some(1).expect("this never happens");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `expect()`
+   |
+LL -     Some(1).expect("this never happens");
+LL +     1;
+   |
+
+error: used `unwrap()` on `None` value
+  --> $DIR/unnecessary_literal_unwrap.rs:20:16
+   |
+LL |     let _val = None::<()>.unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()`
+
+error: used `expect()` on `None` value
+  --> $DIR/unnecessary_literal_unwrap.rs:21:16
+   |
+LL |     let _val = None::<()>.expect("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `None` and `expect()`
+   |
+LL |     let _val = panic!("this always happens");
+   |                ~~~~~~~                     ~
+
+error: used `unwrap()` on `None` value
+  --> $DIR/unnecessary_literal_unwrap.rs:23:5
+   |
+LL |     None::<()>.unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^ help: remove the `None` and `unwrap()`: `panic!()`
+
+error: used `expect()` on `None` value
+  --> $DIR/unnecessary_literal_unwrap.rs:24:5
+   |
+LL |     None::<()>.expect("this always happens");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `None` and `expect()`
+   |
+LL |     panic!("this always happens");
+   |     ~~~~~~~                     ~
+
+error: used `unwrap()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:28:16
+   |
+LL |     let _val = Ok::<_, ()>(1).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap()`
+   |
+LL -     let _val = Ok::<_, ()>(1).unwrap();
+LL +     let _val = 1;
+   |
+
+error: used `expect()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:29:16
+   |
+LL |     let _val = Ok::<_, ()>(1).expect("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect()`
+   |
+LL -     let _val = Ok::<_, ()>(1).expect("this never happens");
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:30:16
+   |
+LL |     let _val = Ok::<_, ()>(1).unwrap_err();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_err()`
+   |
+LL |     let _val = panic!("{:?}", 1);
+   |                ~~~~~~~~~~~~~~  ~
+
+error: used `expect_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:31:16
+   |
+LL |     let _val = Ok::<_, ()>(1).expect_err("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect_err()`
+   |
+LL |     let _val = panic!("{1}: {:?}", 1, "this always happens");
+   |                ~~~~~~~~~~~~~~~~~~~  ~
+
+error: used `unwrap()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:33:5
+   |
+LL |     Ok::<_, ()>(1).unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap()`
+   |
+LL -     Ok::<_, ()>(1).unwrap();
+LL +     1;
+   |
+
+error: used `expect()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:34:5
+   |
+LL |     Ok::<_, ()>(1).expect("this never happens");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect()`
+   |
+LL -     Ok::<_, ()>(1).expect("this never happens");
+LL +     1;
+   |
+
+error: used `unwrap_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:35:5
+   |
+LL |     Ok::<_, ()>(1).unwrap_err();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_err()`
+   |
+LL |     panic!("{:?}", 1);
+   |     ~~~~~~~~~~~~~~  ~
+
+error: used `expect_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:36:5
+   |
+LL |     Ok::<_, ()>(1).expect_err("this always happens");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect_err()`
+   |
+LL |     panic!("{1}: {:?}", 1, "this always happens");
+   |     ~~~~~~~~~~~~~~~~~~~  ~
+
+error: used `unwrap_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:40:16
+   |
+LL |     let _val = Err::<(), _>(1).unwrap_err();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap_err()`
+   |
+LL -     let _val = Err::<(), _>(1).unwrap_err();
+LL +     let _val = 1;
+   |
+
+error: used `expect_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:41:16
+   |
+LL |     let _val = Err::<(), _>(1).expect_err("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect_err()`
+   |
+LL -     let _val = Err::<(), _>(1).expect_err("this never happens");
+LL +     let _val = 1;
+   |
+
+error: used `unwrap()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:42:16
+   |
+LL |     let _val = Err::<(), _>(1).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap()`
+   |
+LL |     let _val = panic!("{:?}", 1);
+   |                ~~~~~~~~~~~~~~  ~
+
+error: used `expect()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:43:16
+   |
+LL |     let _val = Err::<(), _>(1).expect("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect()`
+   |
+LL |     let _val = panic!("{1}: {:?}", 1, "this always happens");
+   |                ~~~~~~~~~~~~~~~~~~~  ~
+
+error: used `unwrap_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:45:5
+   |
+LL |     Err::<(), _>(1).unwrap_err();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap_err()`
+   |
+LL -     Err::<(), _>(1).unwrap_err();
+LL +     1;
+   |
+
+error: used `expect_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:46:5
+   |
+LL |     Err::<(), _>(1).expect_err("this never happens");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect_err()`
+   |
+LL -     Err::<(), _>(1).expect_err("this never happens");
+LL +     1;
+   |
+
+error: used `unwrap()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:47:5
+   |
+LL |     Err::<(), _>(1).unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap()`
+   |
+LL |     panic!("{:?}", 1);
+   |     ~~~~~~~~~~~~~~  ~
+
+error: used `expect()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap.rs:48:5
+   |
+LL |     Err::<(), _>(1).expect("this always happens");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect()`
+   |
+LL |     panic!("{1}: {:?}", 1, "this always happens");
+   |     ~~~~~~~~~~~~~~~~~~~  ~
+
+error: used `unwrap_or()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:52:16
+   |
+LL |     let _val = Some(1).unwrap_or(2);
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or()`
+   |
+LL -     let _val = Some(1).unwrap_or(2);
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_or_default()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:53:16
+   |
+LL |     let _val = Some(1).unwrap_or_default();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_default()`
+   |
+LL -     let _val = Some(1).unwrap_or_default();
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_or_else()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:54:16
+   |
+LL |     let _val = Some(1).unwrap_or_else(|| 2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_else()`
+   |
+LL -     let _val = Some(1).unwrap_or_else(|| 2);
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_or()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:56:5
+   |
+LL |     Some(1).unwrap_or(2);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or()`
+   |
+LL -     Some(1).unwrap_or(2);
+LL +     1;
+   |
+
+error: used `unwrap_or_default()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:57:5
+   |
+LL |     Some(1).unwrap_or_default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_default()`
+   |
+LL -     Some(1).unwrap_or_default();
+LL +     1;
+   |
+
+error: used `unwrap_or_else()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap.rs:58:5
+   |
+LL |     Some(1).unwrap_or_else(|| 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_else()`
+   |
+LL -     Some(1).unwrap_or_else(|| 2);
+LL +     1;
+   |
+
+error: used `unwrap_or()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:62:16
+   |
+LL |     let _val = Ok::<_, ()>(1).unwrap_or(2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or()`
+   |
+LL -     let _val = Ok::<_, ()>(1).unwrap_or(2);
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_or_default()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:63:16
+   |
+LL |     let _val = Ok::<_, ()>(1).unwrap_or_default();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_default()`
+   |
+LL -     let _val = Ok::<_, ()>(1).unwrap_or_default();
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_or_else()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:64:16
+   |
+LL |     let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_else()`
+   |
+LL -     let _val = Ok::<_, ()>(1).unwrap_or_else(|_| 2);
+LL +     let _val = 1;
+   |
+
+error: used `unwrap_or()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:66:5
+   |
+LL |     Ok::<_, ()>(1).unwrap_or(2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or()`
+   |
+LL -     Ok::<_, ()>(1).unwrap_or(2);
+LL +     1;
+   |
+
+error: used `unwrap_or_default()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:67:5
+   |
+LL |     Ok::<_, ()>(1).unwrap_or_default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_default()`
+   |
+LL -     Ok::<_, ()>(1).unwrap_or_default();
+LL +     1;
+   |
+
+error: used `unwrap_or_else()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap.rs:68:5
+   |
+LL |     Ok::<_, ()>(1).unwrap_or_else(|_| 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_else()`
+   |
+LL -     Ok::<_, ()>(1).unwrap_or_else(|_| 2);
+LL +     1;
+   |
+
+error: aborting due to 36 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.rs
new file mode 100644
index 00000000000..711fdce3962
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.rs
@@ -0,0 +1,116 @@
+#![warn(clippy::unnecessary_literal_unwrap)]
+#![allow(unreachable_code)]
+#![allow(clippy::unnecessary_lazy_evaluations, clippy::let_unit_value)]
+
+fn unwrap_option_some() {
+    let val = Some(1);
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this never happens");
+}
+
+fn unwrap_option_some_context() {
+    let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap();
+    let _val = Some::<usize>([1, 2, 3].iter().sum()).expect("this never happens");
+
+    let val = Some::<usize>([1, 2, 3].iter().sum());
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this never happens");
+}
+
+fn unwrap_option_none() {
+    let val = None::<()>;
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this always happens");
+}
+
+fn unwrap_result_ok() {
+    let val = Ok::<_, ()>(1);
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this never happens");
+    let _val2 = val.unwrap_err();
+    let _val2 = val.expect_err("this always happens");
+}
+
+fn unwrap_result_ok_context() {
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap();
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).expect("this never happens");
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_err();
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).expect_err("this always happens");
+
+    let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this never happens");
+    let _val2 = val.unwrap_err();
+    let _val2 = val.expect_err("this always happens");
+}
+
+fn unwrap_result_err() {
+    let val = Err::<(), _>(1);
+    let _val2 = val.unwrap_err();
+    let _val2 = val.expect_err("this never happens");
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this always happens");
+}
+
+fn unwrap_result_err_context() {
+    let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err();
+    let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens");
+    let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap();
+    let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens");
+
+    let val = Err::<(), usize>([1, 2, 3].iter().sum());
+    let _val2 = val.unwrap_err();
+    let _val2 = val.expect_err("this never happens");
+    let _val2 = val.unwrap();
+    let _val2 = val.expect("this always happens");
+}
+
+fn unwrap_methods_option() {
+    let val = Some(1);
+    let _val2 = val.unwrap_or(2);
+    let _val2 = val.unwrap_or_default();
+    let _val2 = val.unwrap_or_else(|| 2);
+}
+
+fn unwrap_methods_option_context() {
+    let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or(2);
+    let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or_default();
+    let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or_else(|| 2);
+
+    let val = Some::<usize>([1, 2, 3].iter().sum());
+    let _val2 = val.unwrap_or(2);
+    let _val2 = val.unwrap_or_default();
+    let _val2 = val.unwrap_or_else(|| 2);
+}
+
+fn unwrap_methods_result() {
+    let val = Ok::<_, ()>(1);
+    let _val2 = val.unwrap_or(2);
+    let _val2 = val.unwrap_or_default();
+    let _val2 = val.unwrap_or_else(|_| 2);
+}
+
+fn unwrap_methods_result_context() {
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or(2);
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or_default();
+    let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2);
+
+    let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+    let _val2 = val.unwrap_or(2);
+    let _val2 = val.unwrap_or_default();
+    let _val2 = val.unwrap_or_else(|_| 2);
+}
+
+fn main() {
+    unwrap_option_some();
+    unwrap_option_some_context();
+    unwrap_option_none();
+    unwrap_result_ok();
+    unwrap_result_ok_context();
+    unwrap_result_err();
+    unwrap_result_err_context();
+    unwrap_methods_option();
+    unwrap_methods_option_context();
+    unwrap_methods_result();
+    unwrap_methods_result_context();
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.stderr
new file mode 100644
index 00000000000..feb9325b77a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap_unfixable.stderr
@@ -0,0 +1,603 @@
+error: used `unwrap()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:7:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:6:15
+   |
+LL |     let val = Some(1);
+   |               ^^^^^^^
+   = note: `-D clippy::unnecessary-literal-unwrap` implied by `-D warnings`
+
+error: used `expect()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:8:17
+   |
+LL |     let _val2 = val.expect("this never happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:6:15
+   |
+LL |     let val = Some(1);
+   |               ^^^^^^^
+
+error: used `unwrap()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:12:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).expect("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:13:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).expect("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:16:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:15:15
+   |
+LL |     let val = Some::<usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:17:17
+   |
+LL |     let _val2 = val.expect("this never happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:15:15
+   |
+LL |     let val = Some::<usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `None` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:22:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `None` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:15
+   |
+LL |     let val = None::<()>;
+   |               ^^^^^^^^^^
+
+error: used `expect()` on `None` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:23:17
+   |
+LL |     let _val2 = val.expect("this always happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `None` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:21:15
+   |
+LL |     let val = None::<()>;
+   |               ^^^^^^^^^^
+
+error: used `unwrap()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:28:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `expect()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:29:17
+   |
+LL |     let _val2 = val.expect("this never happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `unwrap_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:30:17
+   |
+LL |     let _val2 = val.unwrap_err();
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `expect_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:31:17
+   |
+LL |     let _val2 = val.expect_err("this always happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:27:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:35:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).expect("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:36:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).expect("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_err();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:37:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_err();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:38:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).expect_err("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:38:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).expect_err("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:41:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:42:17
+   |
+LL |     let _val2 = val.expect("this never happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:43:17
+   |
+LL |     let _val2 = val.unwrap_err();
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect_err()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:44:17
+   |
+LL |     let _val2 = val.expect_err("this always happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `expect_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:40:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:49:17
+   |
+LL |     let _val2 = val.unwrap_err();
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15
+   |
+LL |     let val = Err::<(), _>(1);
+   |               ^^^^^^^^^^^^^^^
+
+error: used `expect_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:50:17
+   |
+LL |     let _val2 = val.expect_err("this never happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15
+   |
+LL |     let val = Err::<(), _>(1);
+   |               ^^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:51:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15
+   |
+LL |     let val = Err::<(), _>(1);
+   |               ^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:52:17
+   |
+LL |     let _val2 = val.expect("this always happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:48:15
+   |
+LL |     let val = Err::<(), _>(1);
+   |               ^^^^^^^^^^^^^^^
+
+error: used `unwrap_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:56:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:56:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap_err();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:57:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:57:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect_err("this never happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:58:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:58:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:59:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:59:16
+   |
+LL |     let _val = Err::<(), usize>([1, 2, 3].iter().sum()).expect("this always happens");
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:62:17
+   |
+LL |     let _val2 = val.unwrap_err();
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15
+   |
+LL |     let val = Err::<(), usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect_err()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:63:17
+   |
+LL |     let _val2 = val.expect_err("this never happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect_err()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15
+   |
+LL |     let val = Err::<(), usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:64:17
+   |
+LL |     let _val2 = val.unwrap();
+   |                 ^^^^^^^^^^^^
+   |
+help: remove the `Err` and `unwrap()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15
+   |
+LL |     let val = Err::<(), usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `expect()` on `Err` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:65:17
+   |
+LL |     let _val2 = val.expect("this always happens");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Err` and `expect()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:61:15
+   |
+LL |     let val = Err::<(), usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:70:17
+   |
+LL |     let _val2 = val.unwrap_or(2);
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15
+   |
+LL |     let val = Some(1);
+   |               ^^^^^^^
+
+error: used `unwrap_or_default()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:71:17
+   |
+LL |     let _val2 = val.unwrap_or_default();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_default()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15
+   |
+LL |     let val = Some(1);
+   |               ^^^^^^^
+
+error: used `unwrap_or_else()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:72:17
+   |
+LL |     let _val2 = val.unwrap_or_else(|| 2);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_else()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:69:15
+   |
+LL |     let val = Some(1);
+   |               ^^^^^^^
+
+error: used `unwrap_or()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:76:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or(2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:76:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or(2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_default()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:77:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or_default();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_default()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:77:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or_default();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_else()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:78:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or_else(|| 2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_else()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:78:16
+   |
+LL |     let _val = Some::<usize>([1, 2, 3].iter().sum()).unwrap_or_else(|| 2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:81:17
+   |
+LL |     let _val2 = val.unwrap_or(2);
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15
+   |
+LL |     let val = Some::<usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_default()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:82:17
+   |
+LL |     let _val2 = val.unwrap_or_default();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_default()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15
+   |
+LL |     let val = Some::<usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_else()` on `Some` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:83:17
+   |
+LL |     let _val2 = val.unwrap_or_else(|| 2);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Some` and `unwrap_or_else()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:80:15
+   |
+LL |     let val = Some::<usize>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:88:17
+   |
+LL |     let _val2 = val.unwrap_or(2);
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `unwrap_or_default()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:89:17
+   |
+LL |     let _val2 = val.unwrap_or_default();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_default()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `unwrap_or_else()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:90:17
+   |
+LL |     let _val2 = val.unwrap_or_else(|_| 2);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_else()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:87:15
+   |
+LL |     let val = Ok::<_, ()>(1);
+   |               ^^^^^^^^^^^^^^
+
+error: used `unwrap_or()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:94:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or(2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:94:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or(2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_default()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:95:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or_default();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_default()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:95:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or_default();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_else()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:96:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_else()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:96:16
+   |
+LL |     let _val = Ok::<usize, ()>([1, 2, 3].iter().sum()).unwrap_or_else(|_| 2);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:99:17
+   |
+LL |     let _val2 = val.unwrap_or(2);
+   |                 ^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_default()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:100:17
+   |
+LL |     let _val2 = val.unwrap_or_default();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_default()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: used `unwrap_or_else()` on `Ok` value
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:101:17
+   |
+LL |     let _val2 = val.unwrap_or_else(|_| 2);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the `Ok` and `unwrap_or_else()`
+  --> $DIR/unnecessary_literal_unwrap_unfixable.rs:98:15
+   |
+LL |     let val = Ok::<usize, ()>([1, 2, 3].iter().sum());
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 50 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
index 89fedb145f8..d858701ae8a 100644
--- a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
-#![allow(clippy::let_unit_value, clippy::missing_safety_doc)]
+#![allow(clippy::let_unit_value, clippy::missing_safety_doc, clippy::needless_if)]
 
 mod unsafe_items_invalid_comment {
     // SAFETY:
diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed
index 165cabd8298..19380ad00dc 100644
--- a/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(clippy::stable_sort_primitive)]
+#![allow(clippy::stable_sort_primitive, clippy::useless_vec)]
 
 use std::cell::Ref;
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs
index 8a2158d5a84..cea1b65b520 100644
--- a/src/tools/clippy/tests/ui/unnecessary_sort_by.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(clippy::stable_sort_primitive)]
+#![allow(clippy::stable_sort_primitive, clippy::useless_vec)]
 
 use std::cell::Ref;
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
index bdf746cf2c4..eae1271d1aa 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused)]
+#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)]
 #![warn(clippy::unnecessary_struct_initialization)]
 
 struct S {
diff --git a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
index 7271e2f957a..4abd560f84b 100644
--- a/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_struct_initialization.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused)]
+#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)]
 #![warn(clippy::unnecessary_struct_initialization)]
 
 struct S {
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
index c879fdc3b6a..592a53f3a81 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![allow(clippy::needless_borrow, clippy::ptr_arg)]
-#![warn(clippy::unnecessary_to_owned)]
+#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
 
 use std::borrow::Cow;
 use std::ffi::{CStr, CString, OsStr, OsString};
@@ -474,3 +474,36 @@ mod issue_10021 {
         Ok(())
     }
 }
+
+mod issue_10033 {
+    #![allow(dead_code)]
+    use std::{fmt::Display, ops::Deref};
+
+    fn _main() {
+        let f = Foo;
+
+        // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
+        // deref to `str`)
+        foo(&f.to_string());
+    }
+
+    fn foo(s: &str) {
+        println!("{}", s);
+    }
+
+    struct Foo;
+
+    impl Deref for Foo {
+        type Target = str;
+
+        fn deref(&self) -> &Self::Target {
+            "str"
+        }
+    }
+
+    impl Display for Foo {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "Foo")
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
index 10588beb263..f2e48b1c4a6 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![allow(clippy::needless_borrow, clippy::ptr_arg)]
-#![warn(clippy::unnecessary_to_owned)]
+#![warn(clippy::unnecessary_to_owned, clippy::redundant_clone)]
 
 use std::borrow::Cow;
 use std::ffi::{CStr, CString, OsStr, OsString};
@@ -474,3 +474,36 @@ mod issue_10021 {
         Ok(())
     }
 }
+
+mod issue_10033 {
+    #![allow(dead_code)]
+    use std::{fmt::Display, ops::Deref};
+
+    fn _main() {
+        let f = Foo;
+
+        // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
+        // deref to `str`)
+        foo(&f.to_string());
+    }
+
+    fn foo(s: &str) {
+        println!("{}", s);
+    }
+
+    struct Foo;
+
+    impl Deref for Foo {
+        type Target = str;
+
+        fn deref(&self) -> &Self::Target {
+            "str"
+        }
+    }
+
+    impl Display for Foo {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "Foo")
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs
index 373b18470f6..2d55dc664a3 100644
--- a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macros.rs
+//@aux-build:proc_macros.rs:proc-macro
 
 #![allow(clippy::let_unit_value)]
 #![warn(clippy::unnecessary_safety_doc)]
diff --git a/src/tools/clippy/tests/ui/unneeded_field_pattern.rs b/src/tools/clippy/tests/ui/unneeded_field_pattern.rs
index fa639aa70d6..48ae1cf6640 100644
--- a/src/tools/clippy/tests/ui/unneeded_field_pattern.rs
+++ b/src/tools/clippy/tests/ui/unneeded_field_pattern.rs
@@ -1,5 +1,9 @@
+//@aux-build:proc_macros.rs:proc-macro
 #![warn(clippy::unneeded_field_pattern)]
-#[allow(dead_code, unused)]
+#![allow(dead_code, unused)]
+
+#[macro_use]
+extern crate proc_macros;
 
 struct Foo {
     a: i32,
@@ -19,4 +23,12 @@ fn main() {
         Foo { b: 0, .. } => {}, // should be OK
         Foo { .. } => {},       // and the Force might be with this one
     }
+    external! {
+        let f = Foo { a: 0, b: 0, c: 0 };
+        match f {
+            Foo { a: _, b: 0, .. } => {},
+
+            Foo { a: _, b: _, c: _ } => {},
+        }
+    }
 }
diff --git a/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr b/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr
index 6f7c3154569..3f15684986f 100644
--- a/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr
+++ b/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr
@@ -1,5 +1,5 @@
 error: you matched a field with a wildcard pattern, consider using `..` instead
-  --> $DIR/unneeded_field_pattern.rs:14:15
+  --> $DIR/unneeded_field_pattern.rs:18:15
    |
 LL |         Foo { a: _, b: 0, .. } => {},
    |               ^^^^
@@ -8,7 +8,7 @@ LL |         Foo { a: _, b: 0, .. } => {},
    = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings`
 
 error: all the struct fields are matched to a wildcard pattern, consider using `..`
-  --> $DIR/unneeded_field_pattern.rs:16:9
+  --> $DIR/unneeded_field_pattern.rs:20:9
    |
 LL |         Foo { a: _, b: _, c: _ } => {},
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed
index 16c2de760e5..2eeba509e83 100644
--- a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed
+++ b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.fixed
@@ -1,6 +1,11 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 #![feature(stmt_expr_attributes)]
 #![deny(clippy::unneeded_wildcard_pattern)]
+#![allow(clippy::needless_if)]
+
+#[macro_use]
+extern crate proc_macros;
 
 fn main() {
     let t = (0, 1, 2, 3);
@@ -42,4 +47,8 @@ fn main() {
     {
         if let S(0, ..,) = s {};
     }
+    external! {
+        let t = (0, 1, 2, 3);
+        if let (0, _, ..) = t {};
+    }
 }
diff --git a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs
index 9d9eae1d903..5416cfaa542 100644
--- a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs
+++ b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.rs
@@ -1,6 +1,11 @@
 //@run-rustfix
+//@aux-build:proc_macros.rs:proc-macro
 #![feature(stmt_expr_attributes)]
 #![deny(clippy::unneeded_wildcard_pattern)]
+#![allow(clippy::needless_if)]
+
+#[macro_use]
+extern crate proc_macros;
 
 fn main() {
     let t = (0, 1, 2, 3);
@@ -42,4 +47,8 @@ fn main() {
     {
         if let S(0, .., _, _,) = s {};
     }
+    external! {
+        let t = (0, 1, 2, 3);
+        if let (0, _, ..) = t {};
+    }
 }
diff --git a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.stderr b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.stderr
index 716d9ecff89..ffbdc049506 100644
--- a/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.stderr
+++ b/src/tools/clippy/tests/ui/unneeded_wildcard_pattern.stderr
@@ -1,89 +1,89 @@
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:8:18
+  --> $DIR/unneeded_wildcard_pattern.rs:13:18
    |
 LL |     if let (0, .., _) = t {};
    |                  ^^^ help: remove it
    |
 note: the lint level is defined here
-  --> $DIR/unneeded_wildcard_pattern.rs:3:9
+  --> $DIR/unneeded_wildcard_pattern.rs:4:9
    |
 LL | #![deny(clippy::unneeded_wildcard_pattern)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:9:16
+  --> $DIR/unneeded_wildcard_pattern.rs:14:16
    |
 LL |     if let (0, _, ..) = t {};
    |                ^^^ help: remove it
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:10:13
+  --> $DIR/unneeded_wildcard_pattern.rs:15:13
    |
 LL |     if let (_, .., 0) = t {};
    |             ^^^ help: remove it
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:11:15
+  --> $DIR/unneeded_wildcard_pattern.rs:16:15
    |
 LL |     if let (.., _, 0) = t {};
    |               ^^^ help: remove it
 
 error: these patterns are unneeded as the `..` pattern can match those elements
-  --> $DIR/unneeded_wildcard_pattern.rs:12:16
+  --> $DIR/unneeded_wildcard_pattern.rs:17:16
    |
 LL |     if let (0, _, _, ..) = t {};
    |                ^^^^^^ help: remove them
 
 error: these patterns are unneeded as the `..` pattern can match those elements
-  --> $DIR/unneeded_wildcard_pattern.rs:13:18
+  --> $DIR/unneeded_wildcard_pattern.rs:18:18
    |
 LL |     if let (0, .., _, _) = t {};
    |                  ^^^^^^ help: remove them
 
 error: these patterns are unneeded as the `..` pattern can match those elements
-  --> $DIR/unneeded_wildcard_pattern.rs:22:22
+  --> $DIR/unneeded_wildcard_pattern.rs:27:22
    |
 LL |         if let (0, .., _, _,) = t {};
    |                      ^^^^^^ help: remove them
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:29:19
+  --> $DIR/unneeded_wildcard_pattern.rs:34:19
    |
 LL |     if let S(0, .., _) = s {};
    |                   ^^^ help: remove it
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:30:17
+  --> $DIR/unneeded_wildcard_pattern.rs:35:17
    |
 LL |     if let S(0, _, ..) = s {};
    |                 ^^^ help: remove it
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:31:14
+  --> $DIR/unneeded_wildcard_pattern.rs:36:14
    |
 LL |     if let S(_, .., 0) = s {};
    |              ^^^ help: remove it
 
 error: this pattern is unneeded as the `..` pattern can match that element
-  --> $DIR/unneeded_wildcard_pattern.rs:32:16
+  --> $DIR/unneeded_wildcard_pattern.rs:37:16
    |
 LL |     if let S(.., _, 0) = s {};
    |                ^^^ help: remove it
 
 error: these patterns are unneeded as the `..` pattern can match those elements
-  --> $DIR/unneeded_wildcard_pattern.rs:33:17
+  --> $DIR/unneeded_wildcard_pattern.rs:38:17
    |
 LL |     if let S(0, _, _, ..) = s {};
    |                 ^^^^^^ help: remove them
 
 error: these patterns are unneeded as the `..` pattern can match those elements
-  --> $DIR/unneeded_wildcard_pattern.rs:34:19
+  --> $DIR/unneeded_wildcard_pattern.rs:39:19
    |
 LL |     if let S(0, .., _, _) = s {};
    |                   ^^^^^^ help: remove them
 
 error: these patterns are unneeded as the `..` pattern can match those elements
-  --> $DIR/unneeded_wildcard_pattern.rs:43:23
+  --> $DIR/unneeded_wildcard_pattern.rs:48:23
    |
 LL |         if let S(0, .., _, _,) = s {};
    |                       ^^^^^^ help: remove them
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
index 8ec35ba4eea..738045595c0 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
@@ -2,7 +2,13 @@
 
 #![feature(box_patterns)]
 #![warn(clippy::unnested_or_patterns)]
-#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)]
+#![allow(
+    clippy::cognitive_complexity,
+    clippy::match_ref_pats,
+    clippy::upper_case_acronyms,
+    clippy::needless_if,
+    clippy::manual_range_patterns
+)]
 #![allow(unreachable_patterns, irrefutable_let_patterns, unused)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.rs b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
index efdb91b2402..9e0e7b5def9 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.rs
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
@@ -2,7 +2,13 @@
 
 #![feature(box_patterns)]
 #![warn(clippy::unnested_or_patterns)]
-#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)]
+#![allow(
+    clippy::cognitive_complexity,
+    clippy::match_ref_pats,
+    clippy::upper_case_acronyms,
+    clippy::needless_if,
+    clippy::manual_range_patterns
+)]
 #![allow(unreachable_patterns, irrefutable_let_patterns, unused)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
index a1f193db555..b997e4ce85f 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
@@ -1,5 +1,5 @@
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:12:12
+  --> $DIR/unnested_or_patterns.rs:18:12
    |
 LL |     if let box 0 | box 2 = Box::new(0) {}
    |            ^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL |     if let box (0 | 2) = Box::new(0) {}
    |            ~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:13:12
+  --> $DIR/unnested_or_patterns.rs:19:12
    |
 LL |     if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {}
    |            ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:15:12
+  --> $DIR/unnested_or_patterns.rs:21:12
    |
 LL |     if let Some(1) | C0 | Some(2) = None {}
    |            ^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     if let Some(1 | 2) | C0 = None {}
    |            ~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:16:12
+  --> $DIR/unnested_or_patterns.rs:22:12
    |
 LL |     if let &mut 0 | &mut 2 = &mut 0 {}
    |            ^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     if let &mut (0 | 2) = &mut 0 {}
    |            ~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:17:12
+  --> $DIR/unnested_or_patterns.rs:23:12
    |
 LL |     if let x @ 0 | x @ 2 = 0 {}
    |            ^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     if let x @ (0 | 2) = 0 {}
    |            ~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:18:12
+  --> $DIR/unnested_or_patterns.rs:24:12
    |
 LL |     if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     if let (0, 1 | 2 | 3) = (0, 0) {}
    |            ~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:19:12
+  --> $DIR/unnested_or_patterns.rs:25:12
    |
 LL |     if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     if let (1 | 2 | 3, 0) = (0, 0) {}
    |            ~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:20:12
+  --> $DIR/unnested_or_patterns.rs:26:12
    |
 LL |     if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     if let (x, ..) | (x, 1 | 2) = (0, 1) {}
    |            ~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:21:12
+  --> $DIR/unnested_or_patterns.rs:27:12
    |
 LL |     if let [0] | [1] = [0] {}
    |            ^^^^^^^^^
@@ -99,7 +99,7 @@ LL |     if let [0 | 1] = [0] {}
    |            ~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:22:12
+  --> $DIR/unnested_or_patterns.rs:28:12
    |
 LL |     if let [x, 0] | [x, 1] = [0, 1] {}
    |            ^^^^^^^^^^^^^^^
@@ -110,7 +110,7 @@ LL |     if let [x, 0 | 1] = [0, 1] {}
    |            ~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:23:12
+  --> $DIR/unnested_or_patterns.rs:29:12
    |
 LL |     if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -121,7 +121,7 @@ LL |     if let [x, 0 | 1 | 2] = [0, 1] {}
    |            ~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:24:12
+  --> $DIR/unnested_or_patterns.rs:30:12
    |
 LL |     if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL |     if let [x, ..] | [x, 1 | 2] = [0, 1] {}
    |            ~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:26:12
+  --> $DIR/unnested_or_patterns.rs:32:12
    |
 LL |     if let TS(0, x) | TS(1, x) = TS(0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -143,7 +143,7 @@ LL |     if let TS(0 | 1, x) = TS(0, 0) {}
    |            ~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:27:12
+  --> $DIR/unnested_or_patterns.rs:33:12
    |
 LL |     if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL |     if let TS(1 | 2 | 3, 0) = TS(0, 0) {}
    |            ~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:28:12
+  --> $DIR/unnested_or_patterns.rs:34:12
    |
 LL |     if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -165,7 +165,7 @@ LL |     if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {}
    |            ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:33:12
+  --> $DIR/unnested_or_patterns.rs:39:12
    |
 LL |     if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL |     if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {}
    |            ~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns.rs:44:12
+  --> $DIR/unnested_or_patterns.rs:50:12
    |
 LL |     if let [1] | [53] = [0] {}
    |            ^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
index de40e936747..11dc3437875 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
@@ -2,7 +2,12 @@
 
 #![feature(box_patterns)]
 #![warn(clippy::unnested_or_patterns)]
-#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)]
+#![allow(
+    clippy::cognitive_complexity,
+    clippy::match_ref_pats,
+    clippy::needless_if,
+    clippy::manual_range_patterns
+)]
 #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs
index 87f66d26c46..b2556082741 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs
@@ -2,7 +2,12 @@
 
 #![feature(box_patterns)]
 #![warn(clippy::unnested_or_patterns)]
-#![allow(clippy::cognitive_complexity, clippy::match_ref_pats)]
+#![allow(
+    clippy::cognitive_complexity,
+    clippy::match_ref_pats,
+    clippy::needless_if,
+    clippy::manual_range_patterns
+)]
 #![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr
index 41e8d3fc709..76e890b3a2e 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr
@@ -1,5 +1,5 @@
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:9:12
+  --> $DIR/unnested_or_patterns2.rs:14:12
    |
 LL |     if let Some(Some(0)) | Some(Some(1)) = None {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL |     if let Some(Some(0 | 1)) = None {}
    |            ~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:10:12
+  --> $DIR/unnested_or_patterns2.rs:15:12
    |
 LL |     if let Some(Some(0)) | Some(Some(1) | Some(2)) = None {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     if let Some(Some(0 | 1 | 2)) = None {}
    |            ~~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:11:12
+  --> $DIR/unnested_or_patterns2.rs:16:12
    |
 LL |     if let Some(Some(0 | 1) | Some(2)) | Some(Some(3) | Some(4)) = None {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     if let Some(Some(0 | 1 | 2 | 3 | 4)) = None {}
    |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:12:12
+  --> $DIR/unnested_or_patterns2.rs:17:12
    |
 LL |     if let Some(Some(0) | Some(1 | 2)) = None {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     if let Some(Some(0 | 1 | 2)) = None {}
    |            ~~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:13:12
+  --> $DIR/unnested_or_patterns2.rs:18:12
    |
 LL |     if let ((0,),) | ((1,) | (2,),) = ((0,),) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     if let ((0 | 1 | 2,),) = ((0,),) {}
    |            ~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:14:12
+  --> $DIR/unnested_or_patterns2.rs:19:12
    |
 LL |     if let 0 | (1 | 2) = 0 {}
    |            ^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     if let 0 | 1 | 2 = 0 {}
    |            ~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:15:12
+  --> $DIR/unnested_or_patterns2.rs:20:12
    |
 LL |     if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {}
    |            ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnested or-patterns
-  --> $DIR/unnested_or_patterns2.rs:16:12
+  --> $DIR/unnested_or_patterns2.rs:21:12
    |
 LL |     if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
index b6241612d9d..12512087267 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![warn(clippy::unseparated_literal_suffix)]
 #![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
index ae583f4bde3..0a3ffc4784b 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![warn(clippy::unseparated_literal_suffix)]
 #![allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/unused_async.rs b/src/tools/clippy/tests/ui/unused_async.rs
index bfaa5dadfa5..69e46ab4736 100644
--- a/src/tools/clippy/tests/ui/unused_async.rs
+++ b/src/tools/clippy/tests/ui/unused_async.rs
@@ -1,4 +1,6 @@
 #![warn(clippy::unused_async)]
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
 
 use std::future::Future;
 use std::pin::Pin;
@@ -23,6 +25,18 @@ mod issue10800 {
     }
 }
 
+mod issue10459 {
+    trait HasAsyncMethod {
+        async fn do_something() -> u32;
+    }
+
+    impl HasAsyncMethod for () {
+        async fn do_something() -> u32 {
+            1
+        }
+    }
+}
+
 async fn foo() -> i32 {
     4
 }
diff --git a/src/tools/clippy/tests/ui/unused_async.stderr b/src/tools/clippy/tests/ui/unused_async.stderr
index 8ac2066a6b2..ffae8366b88 100644
--- a/src/tools/clippy/tests/ui/unused_async.stderr
+++ b/src/tools/clippy/tests/ui/unused_async.stderr
@@ -1,5 +1,5 @@
 error: unused `async` for function with no await statements
-  --> $DIR/unused_async.rs:11:5
+  --> $DIR/unused_async.rs:13:5
    |
 LL | /     async fn async_block_await() {
 LL | |         async {
@@ -10,14 +10,14 @@ LL | |     }
    |
    = help: consider removing the `async` from this function
 note: `await` used in an async block, which does not require the enclosing function to be `async`
-  --> $DIR/unused_async.rs:13:23
+  --> $DIR/unused_async.rs:15:23
    |
 LL |             ready(()).await;
    |                       ^^^^^
    = note: `-D clippy::unused-async` implied by `-D warnings`
 
 error: unused `async` for function with no await statements
-  --> $DIR/unused_async.rs:26:1
+  --> $DIR/unused_async.rs:40:1
    |
 LL | / async fn foo() -> i32 {
 LL | |     4
@@ -27,7 +27,7 @@ LL | | }
    = help: consider removing the `async` from this function
 
 error: unused `async` for function with no await statements
-  --> $DIR/unused_async.rs:37:5
+  --> $DIR/unused_async.rs:51:5
    |
 LL | /     async fn unused(&self) -> i32 {
 LL | |         1
diff --git a/src/tools/clippy/tests/ui/unwrap.rs b/src/tools/clippy/tests/ui/unwrap.rs
index d9fd402e7cf..64d6437834e 100644
--- a/src/tools/clippy/tests/ui/unwrap.rs
+++ b/src/tools/clippy/tests/ui/unwrap.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::unwrap_used)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn unwrap_option() {
     let opt = Some(0);
diff --git a/src/tools/clippy/tests/ui/unwrap.stderr b/src/tools/clippy/tests/ui/unwrap.stderr
index d49bf2b3228..3796d942ff9 100644
--- a/src/tools/clippy/tests/ui/unwrap.stderr
+++ b/src/tools/clippy/tests/ui/unwrap.stderr
@@ -1,5 +1,5 @@
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap.rs:5:13
+  --> $DIR/unwrap.rs:6:13
    |
 LL |     let _ = opt.unwrap();
    |             ^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let _ = opt.unwrap();
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: used `unwrap()` on a `Result` value
-  --> $DIR/unwrap.rs:10:13
+  --> $DIR/unwrap.rs:11:13
    |
 LL |     let _ = res.unwrap();
    |             ^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     let _ = res.unwrap();
    = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message
 
 error: used `unwrap_err()` on a `Result` value
-  --> $DIR/unwrap.rs:11:13
+  --> $DIR/unwrap.rs:12:13
    |
 LL |     let _ = res.unwrap_err();
    |             ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.rs b/src/tools/clippy/tests/ui/unwrap_expect_used.rs
index 9f27fef8249..7f57efc53c9 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.rs
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::unwrap_used, clippy::expect_used)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 trait OptionExt {
     type Item;
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
index fe4ecef1145..1a551ab5ab8 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
@@ -1,5 +1,5 @@
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_expect_used.rs:23:5
+  --> $DIR/unwrap_expect_used.rs:24:5
    |
 LL |     Some(3).unwrap();
    |     ^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     Some(3).unwrap();
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: used `expect()` on an `Option` value
-  --> $DIR/unwrap_expect_used.rs:24:5
+  --> $DIR/unwrap_expect_used.rs:25:5
    |
 LL |     Some(3).expect("Hello world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     Some(3).expect("Hello world!");
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `unwrap()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:31:5
+  --> $DIR/unwrap_expect_used.rs:32:5
    |
 LL |     a.unwrap();
    |     ^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     a.unwrap();
    = help: if this value is an `Err`, it will panic
 
 error: used `expect()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:32:5
+  --> $DIR/unwrap_expect_used.rs:33:5
    |
 LL |     a.expect("Hello world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     a.expect("Hello world!");
    = help: if this value is an `Err`, it will panic
 
 error: used `unwrap_err()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:33:5
+  --> $DIR/unwrap_expect_used.rs:34:5
    |
 LL |     a.unwrap_err();
    |     ^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL |     a.unwrap_err();
    = help: if this value is an `Ok`, it will panic
 
 error: used `expect_err()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:34:5
+  --> $DIR/unwrap_expect_used.rs:35:5
    |
 LL |     a.expect_err("Hello error!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unwrap_or.rs b/src/tools/clippy/tests/ui/unwrap_or.rs
index a0c003f5b1e..5bea85e6692 100644
--- a/src/tools/clippy/tests/ui/unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/unwrap_or.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::all, clippy::or_fun_call)]
+#![allow(clippy::unnecessary_literal_unwrap)]
 
 fn main() {
     let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len();
diff --git a/src/tools/clippy/tests/ui/unwrap_or.stderr b/src/tools/clippy/tests/ui/unwrap_or.stderr
index c3a7464fd47..cf720eaaf05 100644
--- a/src/tools/clippy/tests/ui/unwrap_or.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_or.stderr
@@ -1,5 +1,5 @@
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/unwrap_or.rs:4:47
+  --> $DIR/unwrap_or.rs:5:47
    |
 LL |     let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())`
@@ -7,7 +7,7 @@ LL |     let s = Some(String::from("test string")).unwrap_or("Fail".to_string())
    = note: `-D clippy::or-fun-call` implied by `-D warnings`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/unwrap_or.rs:8:47
+  --> $DIR/unwrap_or.rs:9:47
    |
 LL |     let s = Some(String::from("test string")).unwrap_or("Fail".to_string()).len();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "Fail".to_string())`
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed b/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
index 59a0ca3f192..08b89a18bbb 100644
--- a/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
+++ b/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
@@ -2,7 +2,7 @@
 
 #![warn(clippy::unwrap_or_else_default)]
 #![allow(dead_code)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)]
 
 /// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint.
 fn unwrap_or_else_default() {
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.rs b/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
index 97cafa336ed..ad2a744908f 100644
--- a/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
+++ b/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
@@ -2,7 +2,7 @@
 
 #![warn(clippy::unwrap_or_else_default)]
 #![allow(dead_code)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)]
 
 /// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint.
 fn unwrap_or_else_default() {
diff --git a/src/tools/clippy/tests/ui/update-all-references.sh b/src/tools/clippy/tests/ui/update-all-references.sh
index 4391499a1e1..d4204307026 100755
--- a/src/tools/clippy/tests/ui/update-all-references.sh
+++ b/src/tools/clippy/tests/ui/update-all-references.sh
@@ -1,3 +1,3 @@
 #!/bin/bash
 
-echo "Please use 'cargo dev bless' instead."
+echo "Please use 'cargo bless' instead."
diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed
index 89ea14759b7..4179f21c510 100644
--- a/src/tools/clippy/tests/ui/use_self.fixed
+++ b/src/tools/clippy/tests/ui/use_self.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![warn(clippy::use_self)]
 #![allow(dead_code, unreachable_code)]
diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs
index 49e5bcb7ed9..01a36def9e9 100644
--- a/src/tools/clippy/tests/ui/use_self.rs
+++ b/src/tools/clippy/tests/ui/use_self.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![warn(clippy::use_self)]
 #![allow(dead_code, unreachable_code)]
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs
index c672eff1c27..879e2e24ab3 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.rs
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs
@@ -1,4 +1,4 @@
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 #![feature(rustc_private)]
 #![warn(clippy::all)]
 #![warn(clippy::used_underscore_binding)]
diff --git a/src/tools/clippy/tests/ui/useless_attribute.fixed b/src/tools/clippy/tests/ui/useless_attribute.fixed
index de6660c95e6..8e77ec444b5 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.fixed
+++ b/src/tools/clippy/tests/ui/useless_attribute.fixed
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![allow(unused)]
 #![warn(clippy::useless_attribute)]
diff --git a/src/tools/clippy/tests/ui/useless_attribute.rs b/src/tools/clippy/tests/ui/useless_attribute.rs
index 8de4331e8a6..27498d9bc13 100644
--- a/src/tools/clippy/tests/ui/useless_attribute.rs
+++ b/src/tools/clippy/tests/ui/useless_attribute.rs
@@ -1,5 +1,5 @@
 //@run-rustfix
-//@aux-build:proc_macro_derive.rs
+//@aux-build:proc_macro_derive.rs:proc-macro
 
 #![allow(unused)]
 #![warn(clippy::useless_attribute)]
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index c16caa38fe9..5d2c5b11658 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![deny(clippy::useless_conversion)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::needless_if, clippy::unnecessary_wraps)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = val;
@@ -155,6 +155,35 @@ fn main() {
     let _ = vec![s4, s4, s4].into_iter();
 }
 
+#[allow(dead_code)]
+fn explicit_into_iter_fn_arg() {
+    fn a<T>(_: T) {}
+    fn b<T: IntoIterator<Item = i32>>(_: T) {}
+    fn c(_: impl IntoIterator<Item = i32>) {}
+    fn d<T>(_: T)
+    where
+        T: IntoIterator<Item = i32>,
+    {
+    }
+    fn f(_: std::vec::IntoIter<i32>) {}
+
+    a(vec![1, 2].into_iter());
+    b(vec![1, 2]);
+    c(vec![1, 2]);
+    d(vec![1, 2]);
+    b([&1, &2, &3].into_iter().cloned());
+
+    b(vec![1, 2]);
+    b(vec![1, 2]);
+
+    macro_rules! macro_generated {
+        () => {
+            vec![1, 2].into_iter()
+        };
+    }
+    b(macro_generated!());
+}
+
 #[derive(Copy, Clone)]
 struct Foo<const C: char>;
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index c75a2bce4ca..03a3e3f95ba 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -1,7 +1,7 @@
 //@run-rustfix
 
 #![deny(clippy::useless_conversion)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::needless_if, clippy::unnecessary_wraps)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = T::from(val);
@@ -155,6 +155,35 @@ fn main() {
     let _ = vec![s4, s4, s4].into_iter().into_iter();
 }
 
+#[allow(dead_code)]
+fn explicit_into_iter_fn_arg() {
+    fn a<T>(_: T) {}
+    fn b<T: IntoIterator<Item = i32>>(_: T) {}
+    fn c(_: impl IntoIterator<Item = i32>) {}
+    fn d<T>(_: T)
+    where
+        T: IntoIterator<Item = i32>,
+    {
+    }
+    fn f(_: std::vec::IntoIter<i32>) {}
+
+    a(vec![1, 2].into_iter());
+    b(vec![1, 2].into_iter());
+    c(vec![1, 2].into_iter());
+    d(vec![1, 2].into_iter());
+    b([&1, &2, &3].into_iter().cloned());
+
+    b(vec![1, 2].into_iter().into_iter());
+    b(vec![1, 2].into_iter().into_iter().into_iter());
+
+    macro_rules! macro_generated {
+        () => {
+            vec![1, 2].into_iter()
+        };
+    }
+    b(macro_generated!());
+}
+
 #[derive(Copy, Clone)]
 struct Foo<const C: char>;
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index 4dca3aac533..4957f73a469 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -118,5 +118,65 @@ error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
 LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
 
-error: aborting due to 19 previous errors
+error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
+  --> $DIR/useless_conversion.rs:171:7
+   |
+LL |     b(vec![1, 2].into_iter());
+   |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
+   |
+note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
+  --> $DIR/useless_conversion.rs:161:13
+   |
+LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
+  --> $DIR/useless_conversion.rs:172:7
+   |
+LL |     c(vec![1, 2].into_iter());
+   |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
+   |
+note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
+  --> $DIR/useless_conversion.rs:162:18
+   |
+LL |     fn c(_: impl IntoIterator<Item = i32>) {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
+  --> $DIR/useless_conversion.rs:173:7
+   |
+LL |     d(vec![1, 2].into_iter());
+   |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
+   |
+note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
+  --> $DIR/useless_conversion.rs:165:12
+   |
+LL |         T: IntoIterator<Item = i32>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
+  --> $DIR/useless_conversion.rs:176:7
+   |
+LL |     b(vec![1, 2].into_iter().into_iter());
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
+   |
+note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
+  --> $DIR/useless_conversion.rs:161:13
+   |
+LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
+  --> $DIR/useless_conversion.rs:177:7
+   |
+LL |     b(vec![1, 2].into_iter().into_iter().into_iter());
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
+   |
+note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
+  --> $DIR/useless_conversion.rs:161:13
+   |
+LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.rs b/src/tools/clippy/tests/ui/useless_conversion_try.rs
index 4acf5b5fa2d..ec0512ce210 100644
--- a/src/tools/clippy/tests/ui/useless_conversion_try.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion_try.rs
@@ -1,4 +1,5 @@
 #![deny(clippy::useless_conversion)]
+#![allow(clippy::needless_if)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = T::try_from(val).unwrap();
diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.stderr b/src/tools/clippy/tests/ui/useless_conversion_try.stderr
index 9aef9dda6f6..54189f8d286 100644
--- a/src/tools/clippy/tests/ui/useless_conversion_try.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion_try.stderr
@@ -1,5 +1,5 @@
 error: useless conversion to the same type: `T`
-  --> $DIR/useless_conversion_try.rs:4:13
+  --> $DIR/useless_conversion_try.rs:5:13
    |
 LL |     let _ = T::try_from(val).unwrap();
    |             ^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::useless_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: useless conversion to the same type: `T`
-  --> $DIR/useless_conversion_try.rs:5:5
+  --> $DIR/useless_conversion_try.rs:6:5
    |
 LL |     val.try_into().unwrap()
    |     ^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |     val.try_into().unwrap()
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:27:21
+  --> $DIR/useless_conversion_try.rs:28:21
    |
 LL |     let _: String = "foo".to_string().try_into().unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL |     let _: String = "foo".to_string().try_into().unwrap();
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:28:21
+  --> $DIR/useless_conversion_try.rs:29:21
    |
 LL |     let _: String = TryFrom::try_from("foo".to_string()).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL |     let _: String = TryFrom::try_from("foo".to_string()).unwrap();
    = help: consider removing `TryFrom::try_from()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:29:13
+  --> $DIR/useless_conversion_try.rs:30:13
    |
 LL |     let _ = String::try_from("foo".to_string()).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     let _ = String::try_from("foo".to_string()).unwrap();
    = help: consider removing `String::try_from()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:30:13
+  --> $DIR/useless_conversion_try.rs:31:13
    |
 LL |     let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,7 +52,7 @@ LL |     let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
    = help: consider removing `String::try_from()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:31:21
+  --> $DIR/useless_conversion_try.rs:32:21
    |
 LL |     let _: String = format!("Hello {}", "world").try_into().unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL |     let _: String = format!("Hello {}", "world").try_into().unwrap();
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:32:21
+  --> $DIR/useless_conversion_try.rs:33:21
    |
 LL |     let _: String = String::new().try_into().unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@ LL |     let _: String = String::new().try_into().unwrap();
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion_try.rs:33:27
+  --> $DIR/useless_conversion_try.rs:34:27
    |
 LL |     let _: String = match String::from("_").try_into() {
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/vec.fixed b/src/tools/clippy/tests/ui/vec.fixed
index d77a4dd8e0b..fcdc917c1b1 100644
--- a/src/tools/clippy/tests/ui/vec.fixed
+++ b/src/tools/clippy/tests/ui/vec.fixed
@@ -1,9 +1,12 @@
 //@run-rustfix
 #![warn(clippy::useless_vec)]
-#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)]
+#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)]
 
-#[derive(Debug)]
-struct NonCopy;
+use std::rc::Rc;
+
+struct StructWithVec {
+    _x: Vec<i32>,
+}
 
 fn on_slice(_: &[u8]) {}
 
@@ -60,14 +63,6 @@ fn main() {
     on_mut_slice(&mut vec![2; line.length]);
     on_mut_slice(&mut vec![2; line.length()]);
 
-    for a in &[1, 2, 3] {
-        println!("{:?}", a);
-    }
-
-    for a in vec![NonCopy, NonCopy] {
-        println!("{:?}", a);
-    }
-
     on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
     on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
 
@@ -75,4 +70,69 @@ fn main() {
     for a in vec![1; 201] {
         println!("{:?}", a);
     }
+
+    // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246
+    let _x: i32 = [1, 2, 3].iter().sum();
+
+    // Do lint
+    let mut x = [1, 2, 3];
+    x.fill(123);
+    dbg!(x[0]);
+    dbg!(x.len());
+    dbg!(x.iter().sum::<i32>());
+
+    let _x: &[i32] = &[1, 2, 3];
+
+    for _ in [1, 2, 3] {}
+
+    // Don't lint
+    let x = vec![1, 2, 3];
+    let _v: Vec<i32> = x;
+
+    let x = vec![1, 2, 3];
+    let _s = StructWithVec { _x: x };
+
+    // Explicit type annotation would make the change to [1, 2, 3]
+    // a compile error.
+    let _x: Vec<i32> = vec![1, 2, 3];
+
+    // Calling a Vec method through a mutable reference
+    let mut x = vec![1, 2, 3];
+    let re = &mut x;
+    re.push(4);
+
+    // Comparing arrays whose length is not equal is a compile error
+    let x = vec![1, 2, 3];
+    let y = vec![1, 2, 3, 4];
+    dbg!(x == y);
+
+    // Non-copy types
+    let _x = vec![String::new(); 10];
+    #[allow(clippy::rc_clone_in_vec_init)]
+    let _x = vec![Rc::new(1); 10];
+
+    // Too large
+    let _x = vec![1; 201];
+}
+
+#[clippy::msrv = "1.53"]
+fn above() {
+    for a in [1, 2, 3] {
+        let _: usize = a;
+    }
+
+    for a in [String::new(), String::new()] {
+        let _: String = a;
+    }
+}
+
+#[clippy::msrv = "1.52"]
+fn below() {
+    for a in vec![1, 2, 3] {
+        let _: usize = a;
+    }
+
+    for a in vec![String::new(), String::new()] {
+        let _: String = a;
+    }
 }
diff --git a/src/tools/clippy/tests/ui/vec.rs b/src/tools/clippy/tests/ui/vec.rs
index dfed3a29a03..0404d8cdb84 100644
--- a/src/tools/clippy/tests/ui/vec.rs
+++ b/src/tools/clippy/tests/ui/vec.rs
@@ -1,9 +1,12 @@
 //@run-rustfix
 #![warn(clippy::useless_vec)]
-#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)]
+#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args, unused)]
 
-#[derive(Debug)]
-struct NonCopy;
+use std::rc::Rc;
+
+struct StructWithVec {
+    _x: Vec<i32>,
+}
 
 fn on_slice(_: &[u8]) {}
 
@@ -60,14 +63,6 @@ fn main() {
     on_mut_slice(&mut vec![2; line.length]);
     on_mut_slice(&mut vec![2; line.length()]);
 
-    for a in vec![1, 2, 3] {
-        println!("{:?}", a);
-    }
-
-    for a in vec![NonCopy, NonCopy] {
-        println!("{:?}", a);
-    }
-
     on_vec(&vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
     on_mut_vec(&mut vec![1; 201]); // Ok, size of `vec` higher than `too_large_for_stack`
 
@@ -75,4 +70,69 @@ fn main() {
     for a in vec![1; 201] {
         println!("{:?}", a);
     }
+
+    // https://github.com/rust-lang/rust-clippy/issues/2262#issuecomment-783979246
+    let _x: i32 = vec![1, 2, 3].iter().sum();
+
+    // Do lint
+    let mut x = vec![1, 2, 3];
+    x.fill(123);
+    dbg!(x[0]);
+    dbg!(x.len());
+    dbg!(x.iter().sum::<i32>());
+
+    let _x: &[i32] = &vec![1, 2, 3];
+
+    for _ in vec![1, 2, 3] {}
+
+    // Don't lint
+    let x = vec![1, 2, 3];
+    let _v: Vec<i32> = x;
+
+    let x = vec![1, 2, 3];
+    let _s = StructWithVec { _x: x };
+
+    // Explicit type annotation would make the change to [1, 2, 3]
+    // a compile error.
+    let _x: Vec<i32> = vec![1, 2, 3];
+
+    // Calling a Vec method through a mutable reference
+    let mut x = vec![1, 2, 3];
+    let re = &mut x;
+    re.push(4);
+
+    // Comparing arrays whose length is not equal is a compile error
+    let x = vec![1, 2, 3];
+    let y = vec![1, 2, 3, 4];
+    dbg!(x == y);
+
+    // Non-copy types
+    let _x = vec![String::new(); 10];
+    #[allow(clippy::rc_clone_in_vec_init)]
+    let _x = vec![Rc::new(1); 10];
+
+    // Too large
+    let _x = vec![1; 201];
+}
+
+#[clippy::msrv = "1.53"]
+fn above() {
+    for a in vec![1, 2, 3] {
+        let _: usize = a;
+    }
+
+    for a in vec![String::new(), String::new()] {
+        let _: String = a;
+    }
+}
+
+#[clippy::msrv = "1.52"]
+fn below() {
+    for a in vec![1, 2, 3] {
+        let _: usize = a;
+    }
+
+    for a in vec![String::new(), String::new()] {
+        let _: String = a;
+    }
 }
diff --git a/src/tools/clippy/tests/ui/vec.stderr b/src/tools/clippy/tests/ui/vec.stderr
index 7d1de05a5c8..33d565b2d52 100644
--- a/src/tools/clippy/tests/ui/vec.stderr
+++ b/src/tools/clippy/tests/ui/vec.stderr
@@ -1,5 +1,5 @@
 error: useless use of `vec!`
-  --> $DIR/vec.rs:28:14
+  --> $DIR/vec.rs:31:14
    |
 LL |     on_slice(&vec![]);
    |              ^^^^^^^ help: you can use a slice directly: `&[]`
@@ -7,64 +7,94 @@ LL |     on_slice(&vec![]);
    = note: `-D clippy::useless-vec` implied by `-D warnings`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:30:18
+  --> $DIR/vec.rs:33:18
    |
 LL |     on_mut_slice(&mut vec![]);
    |                  ^^^^^^^^^^^ help: you can use a slice directly: `&mut []`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:32:14
+  --> $DIR/vec.rs:35:14
    |
 LL |     on_slice(&vec![1, 2]);
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:34:18
+  --> $DIR/vec.rs:37:18
    |
 LL |     on_mut_slice(&mut vec![1, 2]);
    |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:36:14
+  --> $DIR/vec.rs:39:14
    |
 LL |     on_slice(&vec![1, 2]);
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:38:18
+  --> $DIR/vec.rs:41:18
    |
 LL |     on_mut_slice(&mut vec![1, 2]);
    |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:40:14
+  --> $DIR/vec.rs:43:14
    |
 LL |     on_slice(&vec!(1, 2));
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:42:18
+  --> $DIR/vec.rs:45:18
    |
 LL |     on_mut_slice(&mut vec![1, 2]);
    |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1, 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:44:14
+  --> $DIR/vec.rs:47:14
    |
 LL |     on_slice(&vec![1; 2]);
    |              ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:46:18
+  --> $DIR/vec.rs:49:18
    |
 LL |     on_mut_slice(&mut vec![1; 2]);
    |                  ^^^^^^^^^^^^^^^ help: you can use a slice directly: `&mut [1; 2]`
 
 error: useless use of `vec!`
-  --> $DIR/vec.rs:63:14
+  --> $DIR/vec.rs:75:19
+   |
+LL |     let _x: i32 = vec![1, 2, 3].iter().sum();
+   |                   ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:78:17
+   |
+LL |     let mut x = vec![1, 2, 3];
+   |                 ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:84:22
+   |
+LL |     let _x: &[i32] = &vec![1, 2, 3];
+   |                      ^^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:86:14
+   |
+LL |     for _ in vec![1, 2, 3] {}
+   |              ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:120:14
    |
 LL |     for a in vec![1, 2, 3] {
-   |              ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]`
+   |              ^^^^^^^^^^^^^ help: you can use an array directly: `[1, 2, 3]`
+
+error: useless use of `vec!`
+  --> $DIR/vec.rs:124:14
+   |
+LL |     for a in vec![String::new(), String::new()] {
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[String::new(), String::new()]`
 
-error: aborting due to 11 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
index c2f216a8911..41a380ab8f6 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
@@ -6,7 +6,9 @@
     clippy::manual_find,
     clippy::never_loop,
     clippy::redundant_closure_call,
-    clippy::uninlined_format_args
+    clippy::single_range_in_vec_init,
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 fn base() {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
index 971bd5f0c4a..4c6433880b6 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
@@ -6,7 +6,9 @@
     clippy::manual_find,
     clippy::never_loop,
     clippy::redundant_closure_call,
-    clippy::uninlined_format_args
+    clippy::single_range_in_vec_init,
+    clippy::uninlined_format_args,
+    clippy::useless_vec
 )]
 
 fn base() {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
index 4d98666190d..3236765e1db 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
@@ -1,5 +1,5 @@
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:14:5
+  --> $DIR/while_let_on_iterator.rs:16:5
    |
 LL |     while let Option::Some(x) = iter.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
@@ -7,151 +7,151 @@ LL |     while let Option::Some(x) = iter.next() {
    = note: `-D clippy::while-let-on-iterator` implied by `-D warnings`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:19:5
+  --> $DIR/while_let_on_iterator.rs:21:5
    |
 LL |     while let Some(x) = iter.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:24:5
+  --> $DIR/while_let_on_iterator.rs:26:5
    |
 LL |     while let Some(_) = iter.next() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:100:9
+  --> $DIR/while_let_on_iterator.rs:102:9
    |
 LL |         while let Some([..]) = it.next() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:107:9
+  --> $DIR/while_let_on_iterator.rs:109:9
    |
 LL |         while let Some([_x]) = it.next() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:120:9
+  --> $DIR/while_let_on_iterator.rs:122:9
    |
 LL |         while let Some(x @ [_]) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:140:9
+  --> $DIR/while_let_on_iterator.rs:142:9
    |
 LL |         while let Some(_) = y.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:197:9
+  --> $DIR/while_let_on_iterator.rs:199:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:208:5
+  --> $DIR/while_let_on_iterator.rs:210:5
    |
 LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:210:9
+  --> $DIR/while_let_on_iterator.rs:212:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:219:9
+  --> $DIR/while_let_on_iterator.rs:221:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:228:9
+  --> $DIR/while_let_on_iterator.rs:230:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:245:9
+  --> $DIR/while_let_on_iterator.rs:247:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:260:13
+  --> $DIR/while_let_on_iterator.rs:262:13
    |
 LL |             while let Some(i) = self.0.next() {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:292:13
+  --> $DIR/while_let_on_iterator.rs:294:13
    |
 LL |             while let Some(i) = self.0.0.0.next() {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:321:5
+  --> $DIR/while_let_on_iterator.rs:323:5
    |
 LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:333:9
+  --> $DIR/while_let_on_iterator.rs:335:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:347:5
+  --> $DIR/while_let_on_iterator.rs:349:5
    |
 LL |     while let Some(x) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:358:5
+  --> $DIR/while_let_on_iterator.rs:360:5
    |
 LL |     while let Some(x) = it.0.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:393:5
+  --> $DIR/while_let_on_iterator.rs:395:5
    |
 LL |     while let Some(x) = s.x.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:400:5
+  --> $DIR/while_let_on_iterator.rs:402:5
    |
 LL |     while let Some(x) = x[0].next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:408:9
+  --> $DIR/while_let_on_iterator.rs:410:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:418:9
+  --> $DIR/while_let_on_iterator.rs:420:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:428:9
+  --> $DIR/while_let_on_iterator.rs:430:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:438:9
+  --> $DIR/while_let_on_iterator.rs:440:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:448:5
+  --> $DIR/while_let_on_iterator.rs:450:5
    |
 LL |     while let Some(..) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed
index 733bbcfbcef..2961b062ec3 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed
@@ -211,7 +211,7 @@ mod super_imports {
     }
 
     mod use_explicit_should_be_replaced {
-        use super_imports::foofoo;
+        use crate::super_imports::foofoo;
 
         fn with_explicit() {
             let _ = foofoo();
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs
index 4acdd374bde..28508a2538b 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports.rs
@@ -212,7 +212,7 @@ mod super_imports {
     }
 
     mod use_explicit_should_be_replaced {
-        use super_imports::*;
+        use crate::super_imports::*;
 
         fn with_explicit() {
             let _ = foofoo();
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr
index 235be2d5708..c96b3041a00 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr
@@ -107,8 +107,8 @@ LL |             use super::*;
 error: usage of wildcard import
   --> $DIR/wildcard_imports.rs:215:13
    |
-LL |         use super_imports::*;
-   |             ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
+LL |         use crate::super_imports::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
 
 error: usage of wildcard import
   --> $DIR/wildcard_imports.rs:224:17
diff --git a/src/tools/clippy/tests/ui/write_literal_2.rs b/src/tools/clippy/tests/ui/write_literal_2.rs
index 55a11daa1d3..805127e2750 100644
--- a/src/tools/clippy/tests/ui/write_literal_2.rs
+++ b/src/tools/clippy/tests/ui/write_literal_2.rs
@@ -1,5 +1,5 @@
 #![allow(unused_must_use)]
-#![warn(clippy::write_literal)]
+#![warn(clippy::needless_raw_strings, clippy::write_literal)]
 
 use std::io::Write;
 
diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr
index d5956db9ff0..18591250aad 100644
--- a/src/tools/clippy/tests/ui/write_literal_2.stderr
+++ b/src/tools/clippy/tests/ui/write_literal_2.stderr
@@ -1,3 +1,11 @@
+error: unnecessary raw string literal
+  --> $DIR/write_literal_2.rs:10:24
+   |
+LL |     writeln!(v, r"{}", r"{hello}");
+   |                        ^^^^^^^^^^ help: try: `"{hello}"`
+   |
+   = note: `-D clippy::needless-raw-strings` implied by `-D warnings`
+
 error: literal with an empty format string
   --> $DIR/write_literal_2.rs:9:23
    |
@@ -87,7 +95,7 @@ LL |         "1", "2", "3",
 help: try this
    |
 LL ~         "some 1/
-LL ~         {} / {}", "2", "3",
+LL ~         {} // {}", "2", "3",
    |
 
 error: literal with an empty format string
@@ -98,7 +106,7 @@ LL |         "1", "2", "3",
    |
 help: try this
    |
-LL ~         2 / {}",
+LL ~         2 // {}",
 LL ~         "1", "3",
    |
 
@@ -110,43 +118,43 @@ LL |         "1", "2", "3",
    |
 help: try this
    |
-LL ~         {} / 3",
+LL ~         {} // 3",
 LL ~         "1", "2",
    |
 
 error: literal with an empty format string
   --> $DIR/write_literal_2.rs:27:23
    |
-LL |     writeln!(v, "{}", "/");
+LL |     writeln!(v, "{}", "//");
    |                       ^^^^
    |
 help: try this
    |
-LL -     writeln!(v, "{}", "/");
-LL +     writeln!(v, "/");
+LL -     writeln!(v, "{}", "//");
+LL +     writeln!(v, "//");
    |
 
 error: literal with an empty format string
   --> $DIR/write_literal_2.rs:28:24
    |
-LL |     writeln!(v, r"{}", "/");
+LL |     writeln!(v, r"{}", "//");
    |                        ^^^^
    |
 help: try this
    |
-LL -     writeln!(v, r"{}", "/");
+LL -     writeln!(v, r"{}", "//");
 LL +     writeln!(v, r"/");
    |
 
 error: literal with an empty format string
   --> $DIR/write_literal_2.rs:29:26
    |
-LL |     writeln!(v, r#"{}"#, "/");
+LL |     writeln!(v, r#"{}"#, "//");
    |                          ^^^^
    |
 help: try this
    |
-LL -     writeln!(v, r#"{}"#, "/");
+LL -     writeln!(v, r#"{}"#, "//");
 LL +     writeln!(v, r#"/"#);
    |
 
@@ -159,7 +167,7 @@ LL |     writeln!(v, "{}", r"/");
 help: try this
    |
 LL -     writeln!(v, "{}", r"/");
-LL +     writeln!(v, "/");
+LL +     writeln!(v, "//");
    |
 
 error: literal with an empty format string
@@ -186,5 +194,5 @@ error: literal with an empty format string
 LL |     writeln!(v, r#"{}{}"#, '#', '"'); // hard mode
    |                                 ^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/write_with_newline.fixed b/src/tools/clippy/tests/ui/write_with_newline.fixed
new file mode 100644
index 00000000000..0a10e526a2f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/write_with_newline.fixed
@@ -0,0 +1,63 @@
+// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
+// //@run-rustfix
+
+#![allow(clippy::write_literal)]
+#![warn(clippy::write_with_newline)]
+
+use std::io::Write;
+
+fn main() {
+    let mut v = Vec::new();
+
+    // These should fail
+    writeln!(v, "Hello");
+    writeln!(v, "Hello {}", "world");
+    writeln!(v, "Hello {} {}", "world", "#2");
+    writeln!(v, "{}", 1265);
+    writeln!(v);
+
+    // These should be fine
+    write!(v, "");
+    write!(v, "Hello");
+    writeln!(v, "Hello");
+    writeln!(v, "Hello\n");
+    writeln!(v, "Hello {}\n", "world");
+    write!(v, "Issue\n{}", 1265);
+    write!(v, "{}", 1265);
+    write!(v, "\n{}", 1275);
+    write!(v, "\n\n");
+    write!(v, "like eof\n\n");
+    write!(v, "Hello {} {}\n\n", "world", "#2");
+    writeln!(v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126
+    writeln!(v, "\nbla\n\n"); // #3126
+
+    // Escaping
+    write!(v, "\\n"); // #3514
+    writeln!(v, "\\"); // should fail
+    write!(v, "\\\\n");
+
+    // Raw strings
+    write!(v, r"\n"); // #3778
+
+    // Literal newlines should also fail
+    writeln!(
+        v
+    );
+    writeln!(
+        v
+    );
+
+    // Don't warn on CRLF (#4208)
+    write!(v, "\r\n");
+    write!(v, "foo\r\n");
+    writeln!(v, "\\r"); // warns
+    write!(v, "foo\rbar\n");
+
+    // Ignore expanded format strings
+    macro_rules! newline {
+        () => {
+            "\n"
+        };
+    }
+    write!(v, newline!());
+}
diff --git a/src/tools/clippy/tests/ui/write_with_newline.stderr b/src/tools/clippy/tests/ui/write_with_newline.stderr
index 9035275b29d..03a18a4dc3f 100644
--- a/src/tools/clippy/tests/ui/write_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/write_with_newline.stderr
@@ -62,13 +62,13 @@ LL +     writeln!(v);
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:36:5
    |
-LL |     write!(v, "//n"); // should fail
+LL |     write!(v, "///n"); // should fail
    |     ^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!` instead
    |
-LL -     write!(v, "//n"); // should fail
-LL +     writeln!(v, "/"); // should fail
+LL -     write!(v, "///n"); // should fail
+LL +     writeln!(v, "//"); // should fail
    |
 
 error: using `write!()` with a format string that ends in a single newline
@@ -106,13 +106,13 @@ LL ~         v
 error: using `write!()` with a format string that ends in a single newline
   --> $DIR/write_with_newline.rs:57:5
    |
-LL |     write!(v, "/r/n");
+LL |     write!(v, "//r/n");
    |     ^^^^^^^^^^^^^^^^^^
    |
 help: use `writeln!` instead
    |
-LL -     write!(v, "/r/n");
-LL +     writeln!(v, "/r");
+LL -     write!(v, "//r/n");
+LL +     writeln!(v, "//r");
    |
 
 error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/workspace.rs b/src/tools/clippy/tests/workspace.rs
index c9cbc50546c..699ab2be199 100644
--- a/src/tools/clippy/tests/workspace.rs
+++ b/src/tools/clippy/tests/workspace.rs
@@ -7,6 +7,46 @@ use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE};
 mod test_utils;
 
 #[test]
+fn test_module_style_with_dep_in_subdir() {
+    if IS_RUSTC_TEST_SUITE {
+        return;
+    }
+    let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    let target_dir = root.join("target").join("workspace_test");
+    let cwd = root.join("tests/workspace_test");
+
+    // Make sure we start with a clean state
+    Command::new("cargo")
+        .current_dir(&cwd)
+        .env("CARGO_TARGET_DIR", &target_dir)
+        .arg("clean")
+        .args(["-p", "pass-no-mod-with-dep-in-subdir"])
+        .args(["-p", "pass-mod-with-dep-in-subdir"])
+        .output()
+        .unwrap();
+
+    // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887)
+    // `mod.rs` checks should not be applied to crate dependencies
+    // located in the subdirectory of workspace
+    let output = Command::new(&*CARGO_CLIPPY_PATH)
+        .current_dir(&cwd)
+        .env("CARGO_INCREMENTAL", "0")
+        .env("CARGO_TARGET_DIR", &target_dir)
+        .arg("clippy")
+        .args(["-p", "pass-no-mod-with-dep-in-subdir"])
+        .args(["-p", "pass-mod-with-dep-in-subdir"])
+        .arg("--")
+        .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
+        .output()
+        .unwrap();
+
+    println!("status: {}", output.status);
+    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
+    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
+    assert!(output.status.success());
+}
+
+#[test]
 fn test_no_deps_ignores_path_deps_in_workspaces() {
     if IS_RUSTC_TEST_SUITE {
         return;
diff --git a/src/tools/clippy/tests/workspace_test/Cargo.toml b/src/tools/clippy/tests/workspace_test/Cargo.toml
index bf5b4ca5288..d24b278ccc2 100644
--- a/src/tools/clippy/tests/workspace_test/Cargo.toml
+++ b/src/tools/clippy/tests/workspace_test/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
 edition = "2018"
 
 [workspace]
-members = ["subcrate"]
+members = ["subcrate", "module_style/pass_no_mod_with_dep_in_subdir", "module_style/pass_mod_with_dep_in_subdir"]
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml
new file mode 100644
index 00000000000..15dcde4e30a
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "pass-mod-with-dep-in-subdir"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+dep-no-mod = { path = "dep_no_mod"}
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml
new file mode 100644
index 00000000000..55569bc25ed
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "dep-no-mod"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs
new file mode 100644
index 00000000000..7b0966a4586
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs
@@ -0,0 +1,2 @@
+pub mod hello;
+pub struct Thing;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs
new file mode 100644
index 00000000000..99940dce528
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs
@@ -0,0 +1 @@
+pub struct Hello;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs
new file mode 100644
index 00000000000..c62f9acbf2c
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs
@@ -0,0 +1,5 @@
+pub mod foo;
+
+pub fn foo() {
+    let _ = foo::Thing;
+}
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs
new file mode 100644
index 00000000000..5cb4795e945
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs
@@ -0,0 +1,13 @@
+#![deny(clippy::self_named_module_files)]
+
+mod bad;
+mod more;
+extern crate dep_no_mod;
+
+fn main() {
+    let _ = bad::Thing;
+    let _ = more::foo::Foo;
+    let _ = more::inner::Inner;
+    let _ = dep_no_mod::foo::Thing;
+    let _ = dep_no_mod::foo::hello::Hello;
+}
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs
new file mode 100644
index 00000000000..4a835673a59
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs
new file mode 100644
index 00000000000..aa84f78cc2c
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs
@@ -0,0 +1 @@
+pub struct Inner;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs
new file mode 100644
index 00000000000..d79569f78ff
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs
@@ -0,0 +1,2 @@
+pub mod foo;
+pub mod inner;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml
new file mode 100644
index 00000000000..060cb18dc9f
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "pass-no-mod-with-dep-in-subdir"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+dep-with-mod = { path = "dep_with_mod"}
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml
new file mode 100644
index 00000000000..b25725cd561
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "dep-with-mod"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs
new file mode 100644
index 00000000000..4647424f2c2
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs
@@ -0,0 +1,7 @@
+pub mod with_mod;
+
+pub fn foo() {
+    let _ = with_mod::Thing;
+    let _ = with_mod::inner::stuff::Inner;
+    let _ = with_mod::inner::stuff::most::Snarks;
+}
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs
new file mode 100644
index 00000000000..91cd540a28f
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs
@@ -0,0 +1 @@
+pub mod stuff;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs
new file mode 100644
index 00000000000..7713fa9d35c
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs
@@ -0,0 +1,3 @@
+pub mod most;
+
+pub struct Inner;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs
new file mode 100644
index 00000000000..5a5eaf9670f
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs
@@ -0,0 +1 @@
+pub struct Snarks;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs
new file mode 100644
index 00000000000..a12734db7cb
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs
@@ -0,0 +1,3 @@
+pub mod inner;
+
+pub struct Thing;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs
new file mode 100644
index 00000000000..42eb99cd7a3
--- /dev/null
+++ b/src/tools/clippy/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs
@@ -0,0 +1,9 @@
+#![deny(clippy::mod_module_files)]
+
+mod good;
+pub use dep_with_mod::with_mod::Thing;
+
+fn main() {
+    let _ = good::Thing;
+    let _ = dep_with_mod::with_mod::Thing;
+}
diff --git a/src/tools/clippy/util/etc/vscode-tasks.json b/src/tools/clippy/util/etc/vscode-tasks.json
index ab98f9b4154..38e31b337a0 100644
--- a/src/tools/clippy/util/etc/vscode-tasks.json
+++ b/src/tools/clippy/util/etc/vscode-tasks.json
@@ -47,9 +47,9 @@
             "group": "test"
         },
         {
-            "label": "cargo dev bless",
+            "label": "bless ui tests",
             "type": "shell",
-            "command": "cargo dev bless",
+            "command": "cargo bless",
             "problemMatcher": [],
             "group": "none"
         }
diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html
index 8791debad72..99e211654d1 100644
--- a/src/tools/clippy/util/gh-pages/index.html
+++ b/src/tools/clippy/util/gh-pages/index.html
@@ -501,9 +501,11 @@ Otherwise, have a great day =^.^=
                     <div class="col-12 col-md-7 search-control">
                         <div class="input-group">
                             <label class="input-group-addon" id="filter-label" for="search-input">Filter:</label>
-                            <input type="text" class="form-control filter-input" placeholder="Keywords or search string" id="search-input" ng-model="search" ng-model-options="{debounce: 50}"/>
+                            <input type="text" class="form-control filter-input" placeholder="Keywords or search string" id="search-input"
+                                ng-model="search" ng-blur="updatePath()" ng-keyup="$event.keyCode == 13 && updatePath()"
+                                ng-model-options="{debounce: 50}" />
                             <span class="input-group-btn">
-                                <button class="filter-clear btn" type="button" ng-click="search = ''">
+                                <button class="filter-clear btn" type="button" ng-click="search = ''; updatePath();">
                                     Clear
                                 </button>
                             </span>
@@ -517,7 +519,8 @@ Otherwise, have a great day =^.^=
                     <h2 class="panel-title">
                         <div class="panel-title-name">
                             <span>{{lint.id}}</span>
-                            <a href="#{{lint.id}}" class="anchor label label-default" ng-click="open[lint.id] = true; $event.stopPropagation()">&para;</a>
+                            <a href="#{{lint.id}}" class="anchor label label-default"
+                                ng-click="openLint(lint); $event.preventDefault(); $event.stopPropagation()">&para;</a>
                             <a href="" id="clipboard-{{lint.id}}" class="anchor label label-default" ng-click="copyToClipboard(lint); $event.stopPropagation()">
                                 &#128203;
                             </a>
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index 1c16ecd6b0b..f59245e556c 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -24,9 +24,9 @@
         target.scrollIntoView();
     }
 
-    function scrollToLintByURL($scope) {
-        var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
-            scrollToLint(window.location.hash.slice(1));
+    function scrollToLintByURL($scope, $location) {
+        var removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
+            scrollToLint($location.path().substring(1));
             removeListener();
         });
     }
@@ -106,10 +106,10 @@
                 }
             };
         })
-        .controller("lintList", function ($scope, $http, $timeout) {
+        .controller("lintList", function ($scope, $http, $location, $timeout) {
             // Level filter
             var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
-            $scope.levels = LEVEL_FILTERS_DEFAULT;
+            $scope.levels = { ...LEVEL_FILTERS_DEFAULT };
             $scope.byLevels = function (lint) {
                 return $scope.levels[lint.level];
             };
@@ -146,6 +146,165 @@
                 "=": {enabled: false, minorVersion: null },
             };
 
+            // Map the versionFilters to the query parameters in a way that is easier to work with in a URL
+            const versionFilterKeyMap = {
+                "≥": "gte",
+                "≤": "lte",
+                "=": "eq"
+            };
+            const reverseVersionFilterKeyMap = Object.fromEntries(
+                Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key])
+            );
+
+            // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them
+            // to corresponding $scope variables.
+            function loadFromURLParameters() {
+                // Extract parameters from URL
+                const urlParameters = $location.search();
+
+                // Define a helper function that assigns URL parameters to a provided scope variable
+                const handleParameter = (parameter, scopeVariable, defaultValues) => {
+                    if (urlParameters[parameter]) {
+                        const items = urlParameters[parameter].split(',');
+                        for (const key in scopeVariable) {
+                            if (scopeVariable.hasOwnProperty(key)) {
+                                scopeVariable[key] = items.includes(key);
+                            }
+                        }
+                    } else if (defaultValues) {
+                        for (const key in defaultValues) {
+                            if (scopeVariable.hasOwnProperty(key)) {
+                                scopeVariable[key] = defaultValues[key];
+                            }
+                        }
+                    }
+                };
+
+                handleParameter('levels', $scope.levels, LEVEL_FILTERS_DEFAULT);
+                handleParameter('groups', $scope.groups, GROUPS_FILTER_DEFAULT);
+
+                // Handle 'versions' parameter separately because it needs additional processing
+                if (urlParameters.versions) {
+                    const versionFilters = urlParameters.versions.split(',');
+                    for (const versionFilter of versionFilters) {
+                        const [key, minorVersion] = versionFilter.split(':');
+                        const parsedMinorVersion = parseInt(minorVersion);
+
+                        // Map the key from the URL parameter to its original form
+                        const originalKey = reverseVersionFilterKeyMap[key];
+
+                        if (originalKey in $scope.versionFilters && !isNaN(parsedMinorVersion)) {
+                            $scope.versionFilters[originalKey].enabled = true;
+                            $scope.versionFilters[originalKey].minorVersion = parsedMinorVersion;
+                        }
+                    }
+                }
+
+                // Load the search parameter from the URL path
+                const searchParameter = $location.path().substring(1); // Remove the leading slash
+                if (searchParameter) {
+                    $scope.search = searchParameter;
+                    $scope.open[searchParameter] = true;
+                    scrollToLintByURL($scope, $location);
+                }
+            }
+
+            // updateURLParameter updates the URL parameter with the given key to the given value
+            function updateURLParameter(filterObj, urlKey, defaultValue = {}, processFilter = filter => filter) {
+                const parameter = Object.keys(filterObj)
+                    .filter(filter => filterObj[filter])
+                    .sort()
+                    .map(processFilter)
+                    .filter(Boolean) // Filters out any falsy values, including null
+                    .join(',');
+
+                const defaultParameter = Object.keys(defaultValue)
+                    .filter(filter => defaultValue[filter])
+                    .sort()
+                    .map(processFilter)
+                    .filter(Boolean) // Filters out any falsy values, including null
+                    .join(',');
+
+                // if we ended up back at the defaults, just remove it from the URL
+                if (parameter === defaultParameter) {
+                    $location.search(urlKey, null);
+                } else {
+                    $location.search(urlKey, parameter || null);
+                }
+            }
+
+            // updateVersionURLParameter updates the version URL parameter with the given version filters
+            function updateVersionURLParameter(versionFilters) {
+                updateURLParameter(
+                    versionFilters,
+                    'versions', {},
+                    versionFilter => versionFilters[versionFilter].enabled && versionFilters[versionFilter].minorVersion != null
+                        ? `${versionFilterKeyMap[versionFilter]}:${versionFilters[versionFilter].minorVersion}`
+                        : null
+                );
+            }
+
+            // updateAllURLParameters updates all the URL parameters with the current filter settings
+            function updateAllURLParameters() {
+                updateURLParameter($scope.levels, 'levels', LEVEL_FILTERS_DEFAULT);
+                updateURLParameter($scope.groups, 'groups', GROUPS_FILTER_DEFAULT);
+                updateVersionURLParameter($scope.versionFilters);
+            }
+
+            // Add $watches to automatically update URL parameters when the data changes
+            $scope.$watch('levels', function (newVal, oldVal) {
+                if (newVal !== oldVal) {
+                    updateURLParameter(newVal, 'levels', LEVEL_FILTERS_DEFAULT);
+                }
+            }, true);
+
+            $scope.$watch('groups', function (newVal, oldVal) {
+                if (newVal !== oldVal) {
+                    updateURLParameter(newVal, 'groups', GROUPS_FILTER_DEFAULT);
+                }
+            }, true);
+
+            $scope.$watch('versionFilters', function (newVal, oldVal) {
+                if (newVal !== oldVal) {
+                    updateVersionURLParameter(newVal);
+                }
+            }, true);
+
+            // Watch for changes in the URL path and update the search and lint display
+            $scope.$watch(function () { return $location.path(); }, function (newPath) {
+                const searchParameter = newPath.substring(1);
+                if ($scope.search !== searchParameter) {
+                    $scope.search = searchParameter;
+                    $scope.open[searchParameter] = true;
+                    scrollToLintByURL($scope, $location);
+                }
+            });
+
+            let debounceTimeout;
+            $scope.$watch('search', function (newVal, oldVal) {
+                if (newVal !== oldVal) {
+                    if (debounceTimeout) {
+                        $timeout.cancel(debounceTimeout);
+                    }
+
+                    debounceTimeout = $timeout(function () {
+                        $location.path(newVal);
+                    }, 1000);
+                }
+            });
+
+            $scope.$watch(function () { return $location.search(); }, function (newParameters) {
+                loadFromURLParameters();
+            }, true);
+
+            $scope.updatePath = function () {
+                if (debounceTimeout) {
+                    $timeout.cancel(debounceTimeout);
+                }
+
+                $location.path($scope.search);
+            }
+
             $scope.selectTheme = function (theme) {
                 setTheme(theme, true);
             }
@@ -169,10 +328,9 @@
             };
 
             $scope.resetGroupsToDefault = function () {
-                const groups = $scope.groups;
-                for (const [key, value] of Object.entries(GROUPS_FILTER_DEFAULT)) {
-                    groups[key] = value;
-                }
+                $scope.groups = {
+                    ...GROUPS_FILTER_DEFAULT
+                };
             };
 
             $scope.selectedValuesCount = function (obj) {
@@ -272,6 +430,12 @@
                 return true;
             }
 
+            // Show details for one lint
+            $scope.openLint = function (lint) {
+                $scope.open[lint.id] = true;
+                $location.path(lint.id);
+            };
+
             $scope.copyToClipboard = function (lint) {
                 const clipboard = document.getElementById("clipboard-" + lint.id);
                 if (clipboard) {
@@ -296,14 +460,12 @@
             // Get data
             $scope.open = {};
             $scope.loading = true;
+
             // This will be used to jump into the source code of the version that this documentation is for.
             $scope.docVersion = window.location.pathname.split('/')[2] || "master";
 
-            if (window.location.hash.length > 1) {
-                $scope.search = window.location.hash.slice(1);
-                $scope.open[window.location.hash.slice(1)] = true;
-                scrollToLintByURL($scope);
-            }
+            // Set up the filters from the URL parameters before we start loading the data
+            loadFromURLParameters();
 
             $http.get('./lints.json')
                 .success(function (data) {
@@ -315,7 +477,7 @@
                         selectGroup($scope, selectedGroup.toLowerCase());
                     }
 
-                    scrollToLintByURL($scope);
+                    scrollToLintByURL($scope, $location);
 
                     setTimeout(function () {
                         var el = document.getElementById('filter-input');
@@ -326,18 +488,6 @@
                     $scope.error = data;
                     $scope.loading = false;
                 });
-
-            window.addEventListener('hashchange', function () {
-                // trigger re-render
-                $timeout(function () {
-                    $scope.levels = LEVEL_FILTERS_DEFAULT;
-                    $scope.search = window.location.hash.slice(1);
-                    $scope.open[window.location.hash.slice(1)] = true;
-
-                    scrollToLintByURL($scope);
-                });
-                return true;
-            }, false);
         });
 })();
 
diff --git a/src/tools/clippy/util/gh-pages/versions.html b/src/tools/clippy/util/gh-pages/versions.html
index 6e810a349bf..31ce8819329 100644
--- a/src/tools/clippy/util/gh-pages/versions.html
+++ b/src/tools/clippy/util/gh-pages/versions.html
@@ -36,7 +36,7 @@
                 <ul class="list-group">
                     <a class="list-group-item" ng-repeat="version in data | orderBy:versionOrder:true"
                        href="./{{version}}/index.html">
-                        {{normalizeVersionDisplay(version)}}
+                        {{version}}
                     </a>
                 </ul>
             </article>
@@ -54,18 +54,15 @@
         .controller('docVersions', function ($scope, $http) {
             $scope.loading = true;
 
-            $scope.normalizeVersionDisplay = function(v) {
-                return v.replace(/^v/, '');
-            };
-
             $scope.normalizeVersion = function(v) {
-                return v.replace(/^v/, '').replace(/^rust-/, '');
+                return v.replace(/^rust-/, '');
             };
 
             $scope.versionOrder = function(v) {
                 if (v === 'master') { return Infinity; }
                 if (v === 'stable') { return Number.MAX_VALUE; }
                 if (v === 'beta') { return Number.MAX_VALUE - 1; }
+                if (v === 'pre-1.29.0') { return Number.MIN_VALUE; }
 
                 return $scope.normalizeVersion(v)
                     .split('.')
diff --git a/src/tools/clippy/util/versions.py b/src/tools/clippy/util/versions.py
index 0cfa007d1b2..c041fc606a8 100755
--- a/src/tools/clippy/util/versions.py
+++ b/src/tools/clippy/util/versions.py
@@ -1,24 +1,27 @@
 #!/usr/bin/env python
 
 import json
+import logging as log
 import os
 import sys
-import logging as log
-log.basicConfig(level=log.INFO, format='%(levelname)s: %(message)s')
+
+log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
 
 
 def key(v):
-    if v == 'master':
-        return float('inf')
-    if v == 'stable':
+    if v == "master":
+        return float("inf")
+    if v == "stable":
         return sys.maxsize
-    if v == 'beta':
+    if v == "beta":
         return sys.maxsize - 1
+    if v == "pre-1.29.0":
+        return -1
 
-    v = v.replace('v', '').replace('rust-', '')
+    v = v.replace("rust-", "")
 
     s = 0
-    for i, val in enumerate(v.split('.')[::-1]):
+    for i, val in enumerate(v.split(".")[::-1]):
         s += int(val) * 100**i
 
     return s
@@ -31,7 +34,11 @@ def main():
 
     outdir = sys.argv[1]
     versions = [
-        dir for dir in os.listdir(outdir) if not dir.startswith(".") and os.path.isdir(os.path.join(outdir, dir))
+        dir
+        for dir in os.listdir(outdir)
+        if not dir.startswith(".")
+        and not dir.startswith("v")
+        and os.path.isdir(os.path.join(outdir, dir))
     ]
     versions.sort(key=key)
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 85a8fbcffbe..c95a125c737 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -66,6 +66,7 @@ string_enum! {
         JsDocTest => "js-doc-test",
         MirOpt => "mir-opt",
         Assembly => "assembly",
+        RunCoverage => "run-coverage",
     }
 }
 
@@ -438,7 +439,7 @@ pub struct TargetCfgs {
 
 impl TargetCfgs {
     fn new(config: &Config) -> TargetCfgs {
-        let targets: HashMap<String, TargetCfg> = serde_json::from_str(&rustc_output(
+        let mut targets: HashMap<String, TargetCfg> = serde_json::from_str(&rustc_output(
             config,
             &["--print=all-target-specs-json", "-Zunstable-options"],
         ))
@@ -453,6 +454,18 @@ impl TargetCfgs {
         let mut all_families = HashSet::new();
         let mut all_pointer_widths = HashSet::new();
 
+        // Handle custom target specs, which are not included in `--print=all-target-specs-json`.
+        if config.target.ends_with(".json") {
+            targets.insert(
+                config.target.clone(),
+                serde_json::from_str(&rustc_output(
+                    config,
+                    &["--print=target-spec-json", "-Zunstable-options", "--target", &config.target],
+                ))
+                .unwrap(),
+            );
+        }
+
         for (target, cfg) in targets.iter() {
             all_archs.insert(cfg.arch.clone());
             all_oses.insert(cfg.os.clone());
@@ -626,6 +639,7 @@ pub const UI_EXTENSIONS: &[&str] = &[
     UI_STDERR_64,
     UI_STDERR_32,
     UI_STDERR_16,
+    UI_COVERAGE,
 ];
 pub const UI_STDERR: &str = "stderr";
 pub const UI_STDOUT: &str = "stdout";
@@ -635,6 +649,7 @@ pub const UI_RUN_STDOUT: &str = "run.stdout";
 pub const UI_STDERR_64: &str = "64bit.stderr";
 pub const UI_STDERR_32: &str = "32bit.stderr";
 pub const UI_STDERR_16: &str = "16bit.stderr";
+pub const UI_COVERAGE: &str = "coverage";
 
 /// Absolute path to the directory where all output for all tests in the given
 /// `relative_dir` group should reside. Example:
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 8cc935e54d1..c835962ad12 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -161,7 +161,7 @@ pub struct TestProps {
     // customized normalization rules
     pub normalize_stdout: Vec<(String, String)>,
     pub normalize_stderr: Vec<(String, String)>,
-    pub failure_status: i32,
+    pub failure_status: Option<i32>,
     // For UI tests, allows compiler to exit with arbitrary failure status
     pub dont_check_failure_status: bool,
     // Whether or not `rustfix` should apply the `CodeSuggestion`s of this test and compile the
@@ -257,7 +257,7 @@ impl TestProps {
             check_test_line_numbers_match: false,
             normalize_stdout: vec![],
             normalize_stderr: vec![],
-            failure_status: -1,
+            failure_status: None,
             dont_check_failure_status: false,
             run_rustfix: false,
             rustfix_only_machine_applicable: false,
@@ -428,7 +428,7 @@ impl TestProps {
                     .parse_name_value_directive(ln, FAILURE_STATUS)
                     .and_then(|code| code.trim().parse::<i32>().ok())
                 {
-                    self.failure_status = code;
+                    self.failure_status = Some(code);
                 }
 
                 config.set_name_directive(
@@ -491,11 +491,8 @@ impl TestProps {
             });
         }
 
-        if self.failure_status == -1 {
-            self.failure_status = 1;
-        }
         if self.should_ice {
-            self.failure_status = 101;
+            self.failure_status = Some(101);
         }
 
         if config.mode == Mode::Incremental {
@@ -615,10 +612,25 @@ pub fn line_directive<'line>(
 }
 
 fn iter_header<R: Read>(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str, usize)) {
+    iter_header_extra(testfile, rdr, &[], it)
+}
+
+fn iter_header_extra(
+    testfile: &Path,
+    rdr: impl Read,
+    extra_directives: &[&str],
+    it: &mut dyn FnMut(Option<&str>, &str, usize),
+) {
     if testfile.is_dir() {
         return;
     }
 
+    // Process any extra directives supplied by the caller (e.g. because they
+    // are implied by the test mode), with a dummy line number of 0.
+    for directive in extra_directives {
+        it(None, directive, 0);
+    }
+
     let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" };
 
     let mut rdr = BufReader::new(rdr);
@@ -897,7 +909,27 @@ pub fn make_test_description<R: Read>(
     let mut ignore_message = None;
     let mut should_fail = false;
 
-    iter_header(path, src, &mut |revision, ln, line_number| {
+    let extra_directives: &[&str] = match config.mode {
+        // The run-coverage tests are treated as having these extra directives,
+        // without needing to specify them manually in every test file.
+        // (Some of the comments below have been copied over from
+        // `tests/run-make/coverage-reports/Makefile`, which no longer exists.)
+        Mode::RunCoverage => {
+            &[
+                "needs-profiler-support",
+                // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
+                // properly. Since we only have GCC on the CI ignore the test for now.
+                "ignore-windows-gnu",
+                // FIXME(pietroalbini): this test currently does not work on cross-compiled
+                // targets because remote-test is not capable of sending back the *.profraw
+                // files generated by the LLVM instrumentation.
+                "ignore-cross-compile",
+            ]
+        }
+        _ => &[],
+    };
+
+    iter_header_extra(path, src, extra_directives, &mut |revision, ln, line_number| {
         if revision.is_some() && revision != cfg {
             return;
         }
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 0e306696a90..62364ede47b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -87,7 +87,7 @@ pub(super) fn handle_needs(
         },
         Need {
             name: "needs-profiler-support",
-            condition: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
+            condition: cache.profiler_support,
             ignore_reason: "ignored when profiler support is disabled",
         },
         Need {
@@ -195,6 +195,7 @@ pub(super) struct CachedNeedsConditions {
     sanitizer_memtag: bool,
     sanitizer_shadow_call_stack: bool,
     sanitizer_safestack: bool,
+    profiler_support: bool,
     xray: bool,
     rust_lld: bool,
     i686_dlltool: bool,
@@ -232,6 +233,7 @@ impl CachedNeedsConditions {
             sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target),
             sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target),
             sanitizer_safestack: util::SAFESTACK_SUPPORTED_TARGETS.contains(target),
+            profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
             xray: util::XRAY_SUPPORTED_TARGETS.contains(target),
 
             // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 5c8ee7895d3..fddfbac78d5 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -6,8 +6,8 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs
 use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
 use crate::common::{CompareMode, FailMode, PassMode};
 use crate::common::{Config, TestPaths};
-use crate::common::{Pretty, RunPassValgrind};
-use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
+use crate::common::{Pretty, RunCoverage, RunPassValgrind};
+use crate::common::{UI_COVERAGE, UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::compute_diff::{write_diff, write_filtered_diff};
 use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
@@ -253,6 +253,7 @@ impl<'test> TestCx<'test> {
             MirOpt => self.run_mir_opt_test(),
             Assembly => self.run_assembly_test(),
             JsDocTest => self.run_js_doc_test(),
+            RunCoverage => self.run_coverage_test(),
         }
     }
 
@@ -384,7 +385,7 @@ impl<'test> TestCx<'test> {
     }
 
     fn check_correct_failure_status(&self, proc_res: &ProcRes) {
-        let expected_status = Some(self.props.failure_status);
+        let expected_status = Some(self.props.failure_status.unwrap_or(1));
         let received_status = proc_res.status.code();
 
         if expected_status != received_status {
@@ -465,6 +466,296 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn run_coverage_test(&self) {
+        let should_run = self.run_if_enabled();
+        let proc_res = self.compile_test(should_run, Emit::None);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+        drop(proc_res);
+
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let profraw_path = self.output_base_dir().join("default.profraw");
+        let profdata_path = self.output_base_dir().join("default.profdata");
+
+        // Delete any existing profraw/profdata files to rule out unintended
+        // interference between repeated test runs.
+        if profraw_path.exists() {
+            std::fs::remove_file(&profraw_path).unwrap();
+        }
+        if profdata_path.exists() {
+            std::fs::remove_file(&profdata_path).unwrap();
+        }
+
+        let proc_res = self.exec_compiled_test_general(
+            &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())],
+            false,
+        );
+        if self.props.failure_status.is_some() {
+            self.check_correct_failure_status(&proc_res);
+        } else if !proc_res.status.success() {
+            self.fatal_proc_rec("test run failed!", &proc_res);
+        }
+        drop(proc_res);
+
+        let mut profraw_paths = vec![profraw_path];
+        let mut bin_paths = vec![self.make_exe_name()];
+
+        if self.config.suite == "run-coverage-rustdoc" {
+            self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths);
+        }
+
+        // Run `llvm-profdata merge` to index the raw coverage output.
+        let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| {
+            cmd.args(["merge", "--sparse", "--output"]);
+            cmd.arg(&profdata_path);
+            cmd.args(&profraw_paths);
+        });
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res);
+        }
+        drop(proc_res);
+
+        // Run `llvm-cov show` to produce a coverage report in text format.
+        let proc_res = self.run_llvm_tool("llvm-cov", |cmd| {
+            cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]);
+
+            cmd.arg("--Xdemangler");
+            cmd.arg(self.config.rust_demangler_path.as_ref().unwrap());
+
+            cmd.arg("--instr-profile");
+            cmd.arg(&profdata_path);
+
+            for bin in &bin_paths {
+                cmd.arg("--object");
+                cmd.arg(bin);
+            }
+        });
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("llvm-cov show failed!", &proc_res);
+        }
+
+        let kind = UI_COVERAGE;
+
+        let expected_coverage = self.load_expected_output(kind);
+        let normalized_actual_coverage =
+            self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| {
+                self.fatal_proc_rec(&err, &proc_res);
+            });
+
+        let coverage_errors = self.compare_output(
+            kind,
+            &normalized_actual_coverage,
+            &expected_coverage,
+            self.props.compare_output_lines_by_subset,
+        );
+
+        if coverage_errors > 0 {
+            self.fatal_proc_rec(
+                &format!("{} errors occurred comparing coverage output.", coverage_errors),
+                &proc_res,
+            );
+        }
+    }
+
+    /// Run any doctests embedded in this test file, and add any resulting
+    /// `.profraw` files and doctest executables to the given vectors.
+    fn run_doctests_for_coverage(
+        &self,
+        profraw_paths: &mut Vec<PathBuf>,
+        bin_paths: &mut Vec<PathBuf>,
+    ) {
+        // Put .profraw files and doctest executables in dedicated directories,
+        // to make it easier to glob them all later.
+        let profraws_dir = self.output_base_dir().join("doc_profraws");
+        let bins_dir = self.output_base_dir().join("doc_bins");
+
+        // Remove existing directories to prevent cross-run interference.
+        if profraws_dir.try_exists().unwrap() {
+            std::fs::remove_dir_all(&profraws_dir).unwrap();
+        }
+        if bins_dir.try_exists().unwrap() {
+            std::fs::remove_dir_all(&bins_dir).unwrap();
+        }
+
+        let mut rustdoc_cmd =
+            Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed"));
+
+        // In general there will be multiple doctest binaries running, so we
+        // tell the profiler runtime to write their coverage data into separate
+        // profraw files.
+        rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw"));
+
+        rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]);
+
+        // Without this, the doctests complain about not being able to find
+        // their enclosing file's crate for some reason.
+        rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]);
+
+        // Persist the doctest binaries so that `llvm-cov show` can read their
+        // embedded coverage mappings later.
+        rustdoc_cmd.arg("-Zunstable-options");
+        rustdoc_cmd.arg("--persist-doctests");
+        rustdoc_cmd.arg(&bins_dir);
+
+        rustdoc_cmd.arg("-L");
+        rustdoc_cmd.arg(self.aux_output_dir_name());
+
+        rustdoc_cmd.arg(&self.testpaths.file);
+
+        let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
+        }
+
+        fn glob_iter(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> {
+            let path_str = path.as_ref().to_str().unwrap();
+            let iter = glob(path_str).unwrap();
+            iter.map(Result::unwrap)
+        }
+
+        // Find all profraw files in the profraw directory.
+        for p in glob_iter(profraws_dir.join("*.profraw")) {
+            profraw_paths.push(p);
+        }
+        // Find all executables in the `--persist-doctests` directory, while
+        // avoiding other file types (e.g. `.pdb` on Windows). This doesn't
+        // need to be perfect, as long as it can handle the files actually
+        // produced by `rustdoc --test`.
+        for p in glob_iter(bins_dir.join("**/*")) {
+            let is_bin = p.is_file()
+                && match p.extension() {
+                    None => true,
+                    Some(ext) => ext == OsStr::new("exe"),
+                };
+            if is_bin {
+                bin_paths.push(p);
+            }
+        }
+    }
+
+    fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes {
+        let tool_path = self
+            .config
+            .llvm_bin_dir
+            .as_ref()
+            .expect("this test expects the LLVM bin dir to be available")
+            .join(name);
+
+        let mut cmd = Command::new(tool_path);
+        configure_cmd_fn(&mut cmd);
+
+        let output = cmd.output().unwrap_or_else(|_| panic!("failed to exec `{cmd:?}`"));
+
+        let proc_res = ProcRes {
+            status: output.status,
+            stdout: String::from_utf8(output.stdout).unwrap(),
+            stderr: String::from_utf8(output.stderr).unwrap(),
+            cmdline: format!("{cmd:?}"),
+        };
+        self.dump_output(&proc_res.stdout, &proc_res.stderr);
+
+        proc_res
+    }
+
+    fn normalize_coverage_output(&self, coverage: &str) -> Result<String, String> {
+        let normalized = self.normalize_output(coverage, &[]);
+
+        let mut lines = normalized.lines().collect::<Vec<_>>();
+
+        Self::sort_coverage_file_sections(&mut lines)?;
+        Self::sort_coverage_subviews(&mut lines)?;
+
+        let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::<String>();
+        Ok(joined_lines)
+    }
+
+    /// Coverage reports can describe multiple source files, separated by
+    /// blank lines. The order of these files is unpredictable (since it
+    /// depends on implementation details), so we need to sort the file
+    /// sections into a consistent order before comparing against a snapshot.
+    fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> {
+        // Group the lines into file sections, separated by blank lines.
+        let mut sections = coverage_lines.split(|line| line.is_empty()).collect::<Vec<_>>();
+
+        // The last section should be empty, representing an extra trailing blank line.
+        if !sections.last().is_some_and(|last| last.is_empty()) {
+            return Err("coverage report should end with an extra blank line".to_owned());
+        }
+
+        // Sort the file sections (not including the final empty "section").
+        let except_last = sections.len() - 1;
+        (&mut sections[..except_last]).sort();
+
+        // Join the file sections back into a flat list of lines, with
+        // sections separated by blank lines.
+        let joined = sections.join(&[""] as &[_]);
+        assert_eq!(joined.len(), coverage_lines.len());
+        *coverage_lines = joined;
+
+        Ok(())
+    }
+
+    fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> {
+        let mut output_lines = Vec::new();
+
+        // We accumulate a list of zero or more "subviews", where each
+        // subview is a list of one or more lines.
+        let mut subviews: Vec<Vec<&str>> = Vec::new();
+
+        fn flush<'a>(subviews: &mut Vec<Vec<&'a str>>, output_lines: &mut Vec<&'a str>) {
+            if subviews.is_empty() {
+                return;
+            }
+
+            // Take and clear the list of accumulated subviews.
+            let mut subviews = std::mem::take(subviews);
+
+            // The last "subview" should be just a boundary line on its own,
+            // so exclude it when sorting the other subviews.
+            let except_last = subviews.len() - 1;
+            (&mut subviews[..except_last]).sort();
+
+            for view in subviews {
+                for line in view {
+                    output_lines.push(line);
+                }
+            }
+        }
+
+        for (line, line_num) in coverage_lines.iter().zip(1..) {
+            if line.starts_with("  ------------------") {
+                // This is a subview boundary line, so start a new subview.
+                subviews.push(vec![line]);
+            } else if line.starts_with("  |") {
+                // Add this line to the current subview.
+                subviews
+                    .last_mut()
+                    .ok_or(format!(
+                        "unexpected subview line outside of a subview on line {line_num}"
+                    ))?
+                    .push(line);
+            } else {
+                // This line is not part of a subview, so sort and print any
+                // accumulated subviews, and then print the line as-is.
+                flush(&mut subviews, &mut output_lines);
+                output_lines.push(line);
+            }
+        }
+
+        flush(&mut subviews, &mut output_lines);
+        assert!(subviews.is_empty());
+
+        assert_eq!(output_lines.len(), coverage_lines.len());
+        *coverage_lines = output_lines;
+
+        Ok(())
+    }
+
     fn run_pretty_test(&self) {
         if self.props.pp_exact.is_some() {
             logv(self.config, "testing for exact pretty-printing".to_owned());
@@ -1598,7 +1889,26 @@ impl<'test> TestCx<'test> {
     }
 
     fn exec_compiled_test(&self) -> ProcRes {
-        let env = &self.props.exec_env;
+        self.exec_compiled_test_general(&[], true)
+    }
+
+    fn exec_compiled_test_general(
+        &self,
+        env_extra: &[(&str, &str)],
+        delete_after_success: bool,
+    ) -> ProcRes {
+        let prepare_env = |cmd: &mut Command| {
+            for key in &self.props.unset_exec_env {
+                cmd.env_remove(key);
+            }
+
+            for (key, val) in &self.props.exec_env {
+                cmd.env(key, val);
+            }
+            for (key, val) in env_extra {
+                cmd.env(key, val);
+            }
+        };
 
         let proc_res = match &*self.config.target {
             // This is pretty similar to below, we're transforming:
@@ -1635,10 +1945,7 @@ impl<'test> TestCx<'test> {
                     .args(support_libs)
                     .args(args);
 
-                for key in &self.props.unset_exec_env {
-                    test_client.env_remove(key);
-                }
-                test_client.envs(env.clone());
+                prepare_env(&mut test_client);
 
                 self.compose_and_run(
                     test_client,
@@ -1653,10 +1960,7 @@ impl<'test> TestCx<'test> {
                 let mut wr_run = Command::new("wr-run");
                 wr_run.args(&[&prog]).args(args);
 
-                for key in &self.props.unset_exec_env {
-                    wr_run.env_remove(key);
-                }
-                wr_run.envs(env.clone());
+                prepare_env(&mut wr_run);
 
                 self.compose_and_run(
                     wr_run,
@@ -1671,10 +1975,7 @@ impl<'test> TestCx<'test> {
                 let mut program = Command::new(&prog);
                 program.args(args).current_dir(&self.output_base_dir());
 
-                for key in &self.props.unset_exec_env {
-                    program.env_remove(key);
-                }
-                program.envs(env.clone());
+                prepare_env(&mut program);
 
                 self.compose_and_run(
                     program,
@@ -1685,7 +1986,7 @@ impl<'test> TestCx<'test> {
             }
         };
 
-        if proc_res.status.success() {
+        if delete_after_success && proc_res.status.success() {
             // delete the executable after running it to save space.
             // it is ok if the deletion failed.
             let _ = fs::remove_file(self.make_exe_name());
@@ -1812,6 +2113,7 @@ impl<'test> TestCx<'test> {
             || self.is_vxworks_pure_static()
             || self.config.target.contains("bpf")
             || !self.config.target_cfg().dynamic_linking
+            || self.config.mode == RunCoverage
         {
             // We primarily compile all auxiliary libraries as dynamic libraries
             // to avoid code size bloat and large binaries as much as possible
@@ -1822,6 +2124,10 @@ impl<'test> TestCx<'test> {
             // dynamic libraries so we just go back to building a normal library. Note,
             // however, that for MUSL if the library is built with `force_host` then
             // it's ok to be a dylib as the host should always support dylibs.
+            //
+            // Coverage tests want static linking by default so that coverage
+            // mappings in auxiliary libraries can be merged into the final
+            // executable.
             (false, Some("lib"))
         } else {
             (true, Some("dylib"))
@@ -1999,6 +2305,10 @@ impl<'test> TestCx<'test> {
                     }
                 }
                 DebugInfo => { /* debuginfo tests must be unoptimized */ }
+                RunCoverage => {
+                    // Coverage reports are affected by optimization level, and
+                    // the current snapshots assume no optimization by default.
+                }
                 _ => {
                     rustc.arg("-O");
                 }
@@ -2065,6 +2375,9 @@ impl<'test> TestCx<'test> {
 
                 rustc.arg(dir_opt);
             }
+            RunCoverage => {
+                rustc.arg("-Cinstrument-coverage");
+            }
             RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake
             | CodegenUnits | JsDocTest | Assembly => {
                 // do not use JSON output
@@ -4061,7 +4374,7 @@ impl ProcRes {
     pub fn print_info(&self) {
         fn render(name: &str, contents: &str) -> String {
             let contents = json::extract_rendered(contents);
-            let contents = contents.trim();
+            let contents = contents.trim_end();
             if contents.is_empty() {
                 format!("{name}: none")
             } else {
diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs
index 60f39cb36ab..4c19ed97fb8 100644
--- a/src/tools/miri/cargo-miri/src/util.rs
+++ b/src/tools/miri/cargo-miri/src/util.rs
@@ -82,7 +82,7 @@ pub enum MiriCommand {
 pub fn escape_for_toml(s: &str) -> String {
     // We want to surround this string in quotes `"`. So we first escape all quotes,
     // and also all backslashes (that are used to escape quotes).
-    let s = s.replace('\\', r#"\\"#).replace('"', r#"\""#);
+    let s = s.replace('\\', r"\\").replace('"', r#"\""#);
     format!("\"{s}\"")
 }
 
@@ -130,7 +130,7 @@ pub fn exec(mut cmd: Command) -> ! {
     {
         use std::os::unix::process::CommandExt;
         let error = cmd.exec();
-        Err(error).expect("failed to run command")
+        panic!("failed to run command: {error}")
     }
 }
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 6790454bdb7..a58471f31b4 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-75726cae37317c7262b69d3e9fd11a3496a88d04
+d5a74249c843e06b502fb097ebea2383b9a5d9b8
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index c9674e0a2fe..de307a3c5f5 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -221,7 +221,10 @@ impl AllocHistory {
 impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
     pub fn start_grant(&mut self, perm: Permission) {
         let Operation::Retag(op) = &mut self.operation else {
-            unreachable!("start_grant must only be called during a retag, this is: {:?}", self.operation)
+            unreachable!(
+                "start_grant must only be called during a retag, this is: {:?}",
+                self.operation
+            )
         };
         op.permission = Some(perm);
 
@@ -286,7 +289,8 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
         tag: BorTag,
         protector_tag: Option<BorTag>,
     ) -> Option<TagHistory> {
-        let Some(created) = self.history
+        let Some(created) = self
+            .history
             .creations
             .iter()
             .rev()
@@ -315,22 +319,27 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
                         None
                     }
                 })
-            }).or_else(|| {
+            })
+            .or_else(|| {
                 // If we didn't find a retag that created this tag, it might be the base tag of
                 // this allocation.
                 if self.history.base.0.tag() == tag {
                     Some((
-                        format!("{tag:?} was created here, as the base tag for {:?}", self.history.id),
-                        self.history.base.1.data()
+                        format!(
+                            "{tag:?} was created here, as the base tag for {:?}",
+                            self.history.id
+                        ),
+                        self.history.base.1.data(),
                     ))
                 } else {
                     None
                 }
-            }) else {
-                // But if we don't have a creation event, this is related to a wildcard, and there
-                // is really nothing we can do to help.
-                return None;
-            };
+            })
+        else {
+            // But if we don't have a creation event, this is related to a wildcard, and there
+            // is really nothing we can do to help.
+            return None;
+        };
 
         let invalidated = self.history.invalidations.iter().rev().find_map(|event| {
             if event.tag == tag { Some(event.generate_diagnostic()) } else { None }
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 29881bbcfca..6288ff9beef 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -430,12 +430,15 @@ impl<'tcx> Stack {
                 .find_granting(AccessKind::Write, derived_from, exposed_tags)
                 .map_err(|()| dcx.grant_error(self))?;
 
-            let (Some(granting_idx), ProvenanceExtra::Concrete(_)) = (granting_idx, derived_from) else {
+            let (Some(granting_idx), ProvenanceExtra::Concrete(_)) = (granting_idx, derived_from)
+            else {
                 // The parent is a wildcard pointer or matched the unknown bottom.
                 // This is approximate. Nobody knows what happened, so forget everything.
                 // The new thing is SRW anyway, so we cannot push it "on top of the unknown part"
                 // (for all we know, it might join an SRW group inside the unknown).
-                trace!("reborrow: forgetting stack entirely due to SharedReadWrite reborrow from wildcard or unknown");
+                trace!(
+                    "reborrow: forgetting stack entirely due to SharedReadWrite reborrow from wildcard or unknown"
+                );
                 self.set_unknown_bottom(global.next_ptr_tag);
                 return Ok(());
             };
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
index a1e949183ad..291807c25ee 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
@@ -196,19 +196,19 @@ impl<'tcx> Stack {
         let ProvenanceExtra::Concrete(tag) = tag else {
             // Handle the wildcard case.
             // Go search the stack for an exposed tag.
-            if let Some(idx) =
-                self.borrows
-                    .iter()
-                    .enumerate() // we also need to know *where* in the stack
-                    .rev() // search top-to-bottom
-                    .find_map(|(idx, item)| {
-                        // If the item fits and *might* be this wildcard, use it.
-                        if item.perm().grants(access) && exposed_tags.contains(&item.tag()) {
-                            Some(idx)
-                        } else {
-                            None
-                        }
-                    })
+            if let Some(idx) = self
+                .borrows
+                .iter()
+                .enumerate() // we also need to know *where* in the stack
+                .rev() // search top-to-bottom
+                .find_map(|(idx, item)| {
+                    // If the item fits and *might* be this wildcard, use it.
+                    if item.perm().grants(access) && exposed_tags.contains(&item.tag()) {
+                        Some(idx)
+                    } else {
+                        None
+                    }
+                })
             {
                 return Ok(Some(idx));
             }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
index a87a4bbddad..3b2d6f9608e 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
@@ -570,9 +570,13 @@ impl DisplayRepr {
         extraction_aux(tree, tree.root, show_unnamed, &mut v);
         let Some(root) = v.pop() else {
             if show_unnamed {
-                unreachable!("This allocation contains no tags, not even a root. This should not happen.");
+                unreachable!(
+                    "This allocation contains no tags, not even a root. This should not happen."
+                );
             }
-            eprintln!("This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags.");
+            eprintln!(
+                "This allocation does not contain named tags. Use `miri_print_borrow_state(_, true)` to also print unnamed tags."
+            );
             return None;
         };
         assert!(v.is_empty());
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index c4fc2fea74c..cf0fb42fd1b 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -256,7 +256,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             ptr_size.bytes()
         );
 
-        let Some(new_perm) = new_perm else { return Ok(Some((alloc_id, orig_tag))); };
+        let Some(new_perm) = new_perm else {
+            return Ok(Some((alloc_id, orig_tag)));
+        };
 
         if let Some(protect) = new_perm.protector {
             // We register the protection in two different places.
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index e79bb47c78b..7e92dc7a0c7 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(local_key_cell_methods)]
 #![feature(round_ties_even)]
 #![feature(os_str_bytes)]
+#![feature(lint_reasons)]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index f88ad040e05..bbe5bbee719 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -311,7 +311,7 @@ pub struct PrimitiveLayouts<'tcx> {
 }
 
 impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
-    fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx>> {
+    fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, &'tcx LayoutError<'tcx>> {
         let tcx = layout_cx.tcx;
         let mut_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Mut });
         let const_raw_ptr = tcx.mk_ptr(TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not });
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index 1995db715e8..94f8cfbfb1c 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -483,7 +483,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 // `index` is an array, not a SIMD type
                 let ty::Array(_, index_len) = index.layout.ty.kind() else {
-                    span_bug!(this.cur_span(), "simd_shuffle index argument has non-array type {}", index.layout.ty)
+                    span_bug!(
+                        this.cur_span(),
+                        "simd_shuffle index argument has non-array type {}",
+                        index.layout.ty
+                    )
                 };
                 let index_len = index_len.eval_target_usize(*this.tcx, this.param_env());
 
@@ -622,9 +626,7 @@ fn fmax_op<'tcx>(
     right: &ImmTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, Scalar<Provenance>> {
     assert_eq!(left.layout.ty, right.layout.ty);
-    let ty::Float(float_ty) = left.layout.ty.kind() else {
-        bug!("fmax operand is not a float")
-    };
+    let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmax operand is not a float") };
     let left = left.to_scalar();
     let right = right.to_scalar();
     Ok(match float_ty {
@@ -638,9 +640,7 @@ fn fmin_op<'tcx>(
     right: &ImmTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, Scalar<Provenance>> {
     assert_eq!(left.layout.ty, right.layout.ty);
-    let ty::Float(float_ty) = left.layout.ty.kind() else {
-        bug!("fmin operand is not a float")
-    };
+    let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmin operand is not a float") };
     let left = left.to_scalar();
     let right = right.to_scalar();
     Ok(match float_ty {
diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs
index dc395d39ce1..87e887000c5 100644
--- a/src/tools/miri/src/shims/unix/linux/fd.rs
+++ b/src/tools/miri/src/shims/unix/linux/fd.rs
@@ -181,6 +181,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics.
     ///
     /// <https://linux.die.net/man/2/eventfd>
+    #[expect(clippy::needless_if)]
     fn eventfd(
         &mut self,
         val: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index d43dc6b92a3..73671e716ef 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -88,6 +88,7 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
         mode,
         program,
         output_conflict_handling,
+        out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"),
         edition: Some("2021".into()),
         ..Config::rustc(path.into())
     };
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index 0d4e057223d..fbcd0a57f4e 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -2,6 +2,17 @@
 
 ## [Unreleased]
 
+
+## [1.6.0] 2023-07-02
+
+### Added
+
+- Support for formatting let-else statements [#5690]
+- New config option, `single_line_let_else_max_width`, that allows users to configure the maximum length of single line `let-else` statements. `let-else` statements that otherwise meet the requirements to be formatted on a single line will have their divergent`else` block formatted over multiple lines if they exceed this length [#5684]
+
+[#5690]: (https://github.com/rust-lang/rustfmt/pulls/5690)
+[#5684]: https://github.com/rust-lang/rustfmt/issues/5684
+
 ## [1.5.3] 2023-06-20
 
 ### Fixed
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index 999125118f8..bd28df7a757 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -481,9 +481,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
 dependencies = [
  "unicode-ident",
 ]
@@ -545,7 +545,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.5.3"
+version = "1.6.0"
 dependencies = [
  "annotate-snippets",
  "anyhow",
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index a8928bfcd50..8c312f47a28 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "rustfmt-nightly"
-version = "1.5.3"
+version = "1.6.0"
 description = "Tool to find and fix Rust formatting issues"
 repository = "https://github.com/rust-lang/rustfmt"
 readme = "README.md"
diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md
index ac638ff91e6..ac5747800b2 100644
--- a/src/tools/rustfmt/Configurations.md
+++ b/src/tools/rustfmt/Configurations.md
@@ -2392,6 +2392,78 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
+## `single_line_let_else_max_width`
+
+Maximum line length for single line let-else statements.
+See the [let-else statement section of the Rust Style Guide](https://github.com/rust-lang/rust/blob/master/src/doc/style-guide/src/statements.md#else-blocks-let-else-statements) for more details on when a let-else statement may be written on a single line.
+A value of `0` (zero) means the divergent `else` block will always be formatted over multiple lines.
+Note this occurs when `use_small_heuristics` is set to `Off`.
+
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_let_else_max_width` will take precedence.
+
+- **Default value**: `50`
+- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
+- **Stable**: Yes
+
+#### `50` (default):
+
+```rust
+fn main() {
+    let Some(w) = opt else { return Ok(()) };
+
+    let Some(x) = opt else { return };
+
+    let Some(y) = opt else {
+        return;
+    };
+
+    let Some(z) = some_very_very_very_very_long_name else {
+        return;
+    };
+}
+```
+
+#### `0`:
+
+```rust
+fn main() {
+    let Some(w) = opt else {
+        return Ok(());
+    };
+
+    let Some(x) = opt else {
+        return;
+    };
+
+    let Some(y) = opt else {
+        return;
+    };
+
+    let Some(z) = some_very_very_very_very_long_name else {
+        return;
+    };
+}
+```
+
+#### `100`:
+
+```rust
+fn main() {
+    let Some(w) = opt else { return Ok(()) };
+
+    let Some(x) = opt else { return };
+
+    let Some(y) = opt else {
+        return;
+    };
+
+    let Some(z) = some_very_very_very_very_long_name else { return };
+}
+```
+
+See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
+
+
 ## `space_after_colon`
 
 Leave a space after the colon.
@@ -2804,6 +2876,7 @@ The ratios are:
 * [`array_width`](#array_width) - `60%`
 * [`chain_width`](#chain_width) - `60%`
 * [`single_line_if_else_max_width`](#single_line_if_else_max_width) - `50%`
+* [`single_line_let_else_max_width`](#single_line_let_else_max_width) - `50%`
 
 For example when `max_width` is set to `100`, the width settings are:
 * `fn_call_width=60`
@@ -2813,6 +2886,7 @@ For example when `max_width` is set to `100`, the width settings are:
 * `array_width=60`
 * `chain_width=60`
 * `single_line_if_else_max_width=50`
+* `single_line_let_else_max_width=50`
 
 and when `max_width` is set to `200`:
 * `fn_call_width=120`
@@ -2822,6 +2896,7 @@ and when `max_width` is set to `200`:
 * `array_width=120`
 * `chain_width=120`
 * `single_line_if_else_max_width=100`
+* `single_line_let_else_max_width=100`
 
 ```rust
 enum Lorem {
@@ -2891,6 +2966,7 @@ So if `max_width` is set to `200`, then all the width settings are also set to `
 * `array_width=200`
 * `chain_width=200`
 * `single_line_if_else_max_width=200`
+* `single_line_let_else_max_width=200`
 
 ```rust
 enum Lorem {
@@ -2918,6 +2994,7 @@ See also:
 * [`array_width`](#array_width)
 * [`chain_width`](#chain_width)
 * [`single_line_if_else_max_width`](#single_line_if_else_max_width)
+* [`single_line_let_else_max_width`](#single_line_let_else_max_width)
 
 ## `use_try_shorthand`
 
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.lock b/src/tools/rustfmt/config_proc_macro/Cargo.lock
index 7af746f0c96..6267958646b 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.lock
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
 dependencies = [
  "unicode-ident",
 ]
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 03b909cd80c..33ff8b03da2 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-06-19"
+channel = "nightly-2023-07-01"
 components = ["llvm-tools", "rustc-dev"]
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index 54ca7676dfc..c836b4bbb78 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -121,6 +121,7 @@ macro_rules! create_config {
                     | "use_small_heuristics"
                     | "fn_call_width"
                     | "single_line_if_else_max_width"
+                    | "single_line_let_else_max_width"
                     | "attr_fn_like_width"
                     | "struct_lit_width"
                     | "struct_variant_width"
@@ -269,6 +270,7 @@ macro_rules! create_config {
                     | "use_small_heuristics"
                     | "fn_call_width"
                     | "single_line_if_else_max_width"
+                    | "single_line_let_else_max_width"
                     | "attr_fn_like_width"
                     | "struct_lit_width"
                     | "struct_variant_width"
@@ -407,6 +409,14 @@ macro_rules! create_config {
                     "single_line_if_else_max_width",
                 );
                 self.single_line_if_else_max_width.2 = single_line_if_else_max_width;
+
+                let single_line_let_else_max_width = get_width_value(
+                    self.was_set().single_line_let_else_max_width(),
+                    self.single_line_let_else_max_width.2,
+                    heuristics.single_line_let_else_max_width,
+                    "single_line_let_else_max_width",
+                );
+                self.single_line_let_else_max_width.2 = single_line_let_else_max_width;
             }
 
             fn set_heuristics(&mut self) {
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index 14f27f3f8b6..6f41b299e87 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -58,6 +58,9 @@ create_config! {
     chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line.";
     single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \
         expressions. A value of zero means always break if-else expressions.";
+    single_line_let_else_max_width: usize, 50, true, "Maximum line length for single line \
+        let-else statements. A value of zero means always format the divergent `else` block \
+        over multiple lines.";
 
     // Comments. macros, and strings
     wrap_comments: bool, false, false, "Break comments to fit on the line";
@@ -473,6 +476,9 @@ mod test {
             chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line.";
             single_line_if_else_max_width: usize, 50, true, "Maximum line length for single \
                 line if-else expressions. A value of zero means always break if-else expressions.";
+            single_line_let_else_max_width: usize, 50, false, "Maximum line length for single \
+                line let-else statements. A value of zero means always format the divergent \
+                `else` block over multiple lines.";
 
             // Options that are used by the tests
             stable_option: bool, false, true, "A stable option";
@@ -619,6 +625,7 @@ struct_variant_width = 35
 array_width = 60
 chain_width = 60
 single_line_if_else_max_width = 50
+single_line_let_else_max_width = 50
 wrap_comments = false
 format_code_in_doc_comments = false
 doc_comment_code_block_width = 100
diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs
index 408017d2432..3aa1a4de99d 100644
--- a/src/tools/rustfmt/src/config/options.rs
+++ b/src/tools/rustfmt/src/config/options.rs
@@ -236,6 +236,9 @@ pub struct WidthHeuristics {
     // Maximum line length for single line if-else expressions. A value
     // of zero means always break if-else expressions.
     pub(crate) single_line_if_else_max_width: usize,
+    // Maximum line length for single line let-else statements. A value of zero means
+    // always format the divergent `else` block over multiple lines.
+    pub(crate) single_line_let_else_max_width: usize,
 }
 
 impl fmt::Display for WidthHeuristics {
@@ -255,6 +258,7 @@ impl WidthHeuristics {
             array_width: usize::max_value(),
             chain_width: usize::max_value(),
             single_line_if_else_max_width: 0,
+            single_line_let_else_max_width: 0,
         }
     }
 
@@ -267,6 +271,7 @@ impl WidthHeuristics {
             array_width: max_width,
             chain_width: max_width,
             single_line_if_else_max_width: max_width,
+            single_line_let_else_max_width: max_width,
         }
     }
 
@@ -288,6 +293,7 @@ impl WidthHeuristics {
             array_width: (60.0 * max_width_ratio).round() as usize,
             chain_width: (60.0 * max_width_ratio).round() as usize,
             single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize,
+            single_line_let_else_max_width: (50.0 * max_width_ratio).round() as usize,
         }
     }
 }
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 5600f7778f2..5b1b4fbd491 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -577,6 +577,17 @@ fn rewrite_block(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<String> {
+    rewrite_block_inner(block, attrs, label, true, context, shape)
+}
+
+fn rewrite_block_inner(
+    block: &ast::Block,
+    attrs: Option<&[ast::Attribute]>,
+    label: Option<ast::Label>,
+    allow_single_line: bool,
+    context: &RewriteContext<'_>,
+    shape: Shape,
+) -> Option<String> {
     let prefix = block_prefix(context, block, shape)?;
 
     // shape.width is used only for the single line case: either the empty block `{}`,
@@ -587,7 +598,7 @@ fn rewrite_block(
 
     let result = rewrite_block_with_visitor(context, &prefix, block, attrs, label, shape, true);
     if let Some(ref result_str) = result {
-        if result_str.lines().count() <= 3 {
+        if allow_single_line && result_str.lines().count() <= 3 {
             if let rw @ Some(_) =
                 rewrite_single_line_block(context, &prefix, block, attrs, label, shape)
             {
@@ -599,6 +610,16 @@ fn rewrite_block(
     result
 }
 
+/// Rewrite the divergent block of a `let-else` statement.
+pub(crate) fn rewrite_let_else_block(
+    block: &ast::Block,
+    allow_single_line: bool,
+    context: &RewriteContext<'_>,
+    shape: Shape,
+) -> Option<String> {
+    rewrite_block_inner(block, None, None, allow_single_line, context, shape)
+}
+
 // Rewrite condition if the given expression has one.
 pub(crate) fn rewrite_cond(
     context: &RewriteContext<'_>,
@@ -1005,6 +1026,49 @@ impl<'a> ControlFlow<'a> {
     }
 }
 
+/// Rewrite the `else` keyword with surrounding comments.
+///
+/// force_newline_else: whether or not to rewrite the `else` keyword on a newline.
+/// is_last: true if this is an `else` and `false` if this is an `else if` block.
+/// context: rewrite context
+/// span: Span between the end of the last expression and the start of the else block,
+///       which contains the `else` keyword
+/// shape: Shape
+pub(crate) fn rewrite_else_kw_with_comments(
+    force_newline_else: bool,
+    is_last: bool,
+    context: &RewriteContext<'_>,
+    span: Span,
+    shape: Shape,
+) -> String {
+    let else_kw_lo = context.snippet_provider.span_before(span, "else");
+    let before_else_kw = mk_sp(span.lo(), else_kw_lo);
+    let before_else_kw_comment = extract_comment(before_else_kw, context, shape);
+
+    let else_kw_hi = context.snippet_provider.span_after(span, "else");
+    let after_else_kw = mk_sp(else_kw_hi, span.hi());
+    let after_else_kw_comment = extract_comment(after_else_kw, context, shape);
+
+    let newline_sep = &shape.indent.to_string_with_newline(context.config);
+    let before_sep = match context.config.control_brace_style() {
+        _ if force_newline_else => newline_sep.as_ref(),
+        ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => {
+            newline_sep.as_ref()
+        }
+        ControlBraceStyle::AlwaysSameLine => " ",
+    };
+    let after_sep = match context.config.control_brace_style() {
+        ControlBraceStyle::AlwaysNextLine if is_last => newline_sep.as_ref(),
+        _ => " ",
+    };
+
+    format!(
+        "{}else{}",
+        before_else_kw_comment.as_ref().map_or(before_sep, |s| &**s),
+        after_else_kw_comment.as_ref().map_or(after_sep, |s| &**s),
+    )
+}
+
 impl<'a> Rewrite for ControlFlow<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         debug!("ControlFlow::rewrite {:?} {:?}", self, shape);
@@ -1071,41 +1135,14 @@ impl<'a> Rewrite for ControlFlow<'a> {
                 }
             };
 
-            let between_kwd_else_block = mk_sp(
-                self.block.span.hi(),
-                context
-                    .snippet_provider
-                    .span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"),
-            );
-            let between_kwd_else_block_comment =
-                extract_comment(between_kwd_else_block, context, shape);
-
-            let after_else = mk_sp(
-                context
-                    .snippet_provider
-                    .span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"),
-                else_block.span.lo(),
+            let else_kw = rewrite_else_kw_with_comments(
+                false,
+                last_in_chain,
+                context,
+                self.block.span.between(else_block.span),
+                shape,
             );
-            let after_else_comment = extract_comment(after_else, context, shape);
-
-            let between_sep = match context.config.control_brace_style() {
-                ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => {
-                    &*alt_block_sep
-                }
-                ControlBraceStyle::AlwaysSameLine => " ",
-            };
-            let after_sep = match context.config.control_brace_style() {
-                ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep,
-                _ => " ",
-            };
-
-            result.push_str(&format!(
-                "{}else{}",
-                between_kwd_else_block_comment
-                    .as_ref()
-                    .map_or(between_sep, |s| &**s),
-                after_else_comment.as_ref().map_or(after_sep, |s| &**s),
-            ));
+            result.push_str(&else_kw);
             result.push_str(&rewrite?);
         }
 
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 3ecdb5b4c60..d5bc38303e0 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -18,7 +18,8 @@ use crate::config::lists::*;
 use crate::config::{BraceStyle, Config, IndentStyle, Version};
 use crate::expr::{
     is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
-    rewrite_assign_rhs_with_comments, RhsAssignKind, RhsTactics,
+    rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, rewrite_let_else_block,
+    RhsAssignKind, RhsTactics,
 };
 use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
 use crate::macros::{rewrite_macro, MacroPosition};
@@ -44,7 +45,7 @@ fn type_annotation_separator(config: &Config) -> &str {
 }
 
 // Statements of the form
-// let pat: ty = init;
+// let pat: ty = init; or let pat: ty = init else { .. };
 impl Rewrite for ast::Local {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         debug!(
@@ -54,7 +55,7 @@ impl Rewrite for ast::Local {
 
         skip_out_of_file_lines_range!(context, self.span);
 
-        if contains_skip(&self.attrs) || matches!(self.kind, ast::LocalKind::InitElse(..)) {
+        if contains_skip(&self.attrs) {
             return None;
         }
 
@@ -112,7 +113,7 @@ impl Rewrite for ast::Local {
 
         result.push_str(&infix);
 
-        if let Some((init, _els)) = self.kind.init_else_opt() {
+        if let Some((init, else_block)) = self.kind.init_else_opt() {
             // 1 = trailing semicolon;
             let nested_shape = shape.sub_width(1)?;
 
@@ -123,7 +124,49 @@ impl Rewrite for ast::Local {
                 &RhsAssignKind::Expr(&init.kind, init.span),
                 nested_shape,
             )?;
-            // todo else
+
+            if let Some(block) = else_block {
+                let else_kw_span = init.span.between(block.span);
+                let force_newline_else = pat_str.contains('\n')
+                    || !same_line_else_kw_and_brace(&result, context, else_kw_span, nested_shape);
+                let else_kw = rewrite_else_kw_with_comments(
+                    force_newline_else,
+                    true,
+                    context,
+                    else_kw_span,
+                    shape,
+                );
+                result.push_str(&else_kw);
+
+                // At this point we've written `let {pat} = {expr} else' into the buffer, and we
+                // want to calculate up front if there's room to write the divergent block on the
+                // same line. The available space varies based on indentation so we clamp the width
+                // on the smaller of `shape.width` and `single_line_let_else_max_width`.
+                let max_width =
+                    std::cmp::min(shape.width, context.config.single_line_let_else_max_width());
+
+                // If available_space hits zero we know for sure this will be a multi-lined block
+                let available_space = max_width.saturating_sub(result.len());
+
+                let allow_single_line = !force_newline_else
+                    && available_space > 0
+                    && allow_single_line_let_else_block(&result, block);
+
+                let mut rw_else_block =
+                    rewrite_let_else_block(block, allow_single_line, context, shape)?;
+
+                let single_line_else = !rw_else_block.contains('\n');
+                // +1 for the trailing `;`
+                let else_block_exceeds_width = rw_else_block.len() + 1 > available_space;
+
+                if allow_single_line && single_line_else && else_block_exceeds_width {
+                    // writing this on one line would exceed the available width
+                    // so rewrite the else block over multiple lines.
+                    rw_else_block = rewrite_let_else_block(block, false, context, shape)?;
+                }
+
+                result.push_str(&rw_else_block);
+            };
         }
 
         result.push(';');
@@ -131,6 +174,61 @@ impl Rewrite for ast::Local {
     }
 }
 
+/// When the initializer expression is multi-lined, then the else keyword and opening brace of the
+/// block ( i.e. "else {") should be put on the same line as the end of the initializer expression
+/// if all the following are true:
+///
+/// 1. The initializer expression ends with one or more closing parentheses, square brackets,
+///    or braces
+/// 2. There is nothing else on that line
+/// 3. That line is not indented beyond the indent on the first line of the let keyword
+fn same_line_else_kw_and_brace(
+    init_str: &str,
+    context: &RewriteContext<'_>,
+    else_kw_span: Span,
+    init_shape: Shape,
+) -> bool {
+    if !init_str.contains('\n') {
+        // initializer expression is single lined. The "else {" can only be placed on the same line
+        // as the initializer expression if there is enough room for it.
+        // 7 = ` else {`
+        return init_shape.width.saturating_sub(init_str.len()) >= 7;
+    }
+
+    // 1. The initializer expression ends with one or more `)`, `]`, `}`.
+    if !init_str.ends_with([')', ']', '}']) {
+        return false;
+    }
+
+    // 2. There is nothing else on that line
+    // For example, there are no comments
+    let else_kw_snippet = context.snippet(else_kw_span).trim();
+    if else_kw_snippet != "else" {
+        return false;
+    }
+
+    // 3. The last line of the initializer expression is not indented beyond the `let` keyword
+    let indent = init_shape.indent.to_string(context.config);
+    init_str
+        .lines()
+        .last()
+        .expect("initializer expression is multi-lined")
+        .strip_prefix(indent.as_ref())
+        .map_or(false, |l| !l.starts_with(char::is_whitespace))
+}
+
+fn allow_single_line_let_else_block(result: &str, block: &ast::Block) -> bool {
+    if result.contains('\n') {
+        return false;
+    }
+
+    if block.stmts.len() <= 1 {
+        return true;
+    }
+
+    false
+}
+
 // FIXME convert to using rewrite style rather than visitor
 // FIXME format modules in this style
 #[allow(dead_code)]
diff --git a/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs
new file mode 100644
index 00000000000..a73c9084bf2
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs
@@ -0,0 +1,40 @@
+// rustfmt-single_line_let_else_max_width: 100
+
+fn main() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else {
+        return
+    };
+
+    let Some(c) = opt else {
+        // a comment should always force the block to be multi-lined
+        return
+    };
+
+    let Some(c) = opt else { /* a comment should always force the block to be multi-lined */ return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+
+    let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else {
+        return
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
+        return Ok(None)
+    };
+
+    let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else {
+        return Err(Error::new(variant.span(), r#"expected a doc comment"#))
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else {
+        return Ok(None)
+    };
+
+    let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else {
+        return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`"))
+    };
+}
diff --git a/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs
new file mode 100644
index 00000000000..87d0583c552
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs
@@ -0,0 +1,40 @@
+// rustfmt-single_line_let_else_max_width: 50
+
+fn main() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else {
+        return
+    };
+
+    let Some(c) = opt else {
+        // a comment should always force the block to be multi-lined
+        return
+    };
+
+    let Some(c) = opt else { /* a comment should always force the block to be multi-lined */ return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+
+    let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else {
+        return
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
+        return Ok(None)
+    };
+
+    let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else {
+        return Err(Error::new(variant.span(), r#"expected a doc comment"#))
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else {
+        return Ok(None)
+    };
+
+    let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else {
+        return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`"))
+    };
+}
diff --git a/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs
new file mode 100644
index 00000000000..afb9e503307
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs
@@ -0,0 +1,40 @@
+// rustfmt-single_line_let_else_max_width: 0
+
+fn main() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else {
+        return
+    };
+
+    let Some(c) = opt else {
+        // a comment should always force the block to be multi-lined
+        return
+    };
+
+    let Some(c) = opt else { /* a comment should always force the block to be multi-lined */ return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+
+    let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else {
+        return
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
+        return Ok(None)
+    };
+
+    let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else {
+        return Err(Error::new(variant.span(), r#"expected a doc comment"#))
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else {
+        return Ok(None)
+    };
+
+    let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else {
+        return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`"))
+    };
+}
diff --git a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs
index 68bc40271a1..95238c54844 100644
--- a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs
+++ b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs
@@ -23,3 +23,13 @@ fn main() {
         sit
     };
 }
+
+fn format_let_else() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+}
diff --git a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs
index 8d30932e2c2..b79302e22ab 100644
--- a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs
+++ b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs
@@ -23,3 +23,13 @@ fn main() {
         sit
     };
 }
+
+fn format_let_else() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+}
diff --git a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs
index f76392d2404..80bcdd89896 100644
--- a/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs
+++ b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs
@@ -23,3 +23,13 @@ fn main() {
         sit
     };
 }
+
+fn format_let_else() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+}
diff --git a/src/tools/rustfmt/tests/source/let_else.rs b/src/tools/rustfmt/tests/source/let_else.rs
index a6e816fb524..85b3604ad3c 100644
--- a/src/tools/rustfmt/tests/source/let_else.rs
+++ b/src/tools/rustfmt/tests/source/let_else.rs
@@ -1,3 +1,162 @@
+// rustfmt-single_line_let_else_max_width: 100
+
 fn main() {
-    let Some(1) = Some(1) else { return };
+    // Although this won't compile it still parses so make sure we can format empty else blocks
+    let Some(x) = opt else {};
+
+    // let-else may be formatted on a single line if they are "short"
+    // and only contain a single expression
+    let Some(x) = opt else { return };
+
+    let Some(x) = opt else {
+        return
+    };
+
+    let Some(x) = opt else { return; };
+
+    let Some(x) = opt else {
+        // nope
+        return;
+    };
+
+    let Some(x) = opt else { let y = 1; return y };
+
+    let Some(x) = y.foo("abc", fairly_long_identifier, "def", "123456", "string", "cheese") else { bar() };
+
+    let Some(x) = abcdef().foo("abc", some_really_really_really_long_ident, "ident", "123456").bar().baz().qux("fffffffffffffffff") else { foo_bar() };
+}
+
+fn with_comments_around_else_keyword() {
+    let Some(x) = opt /* pre else keyword block-comment */ else { return };
+
+    let Some(x) = opt else /* post else keyword block-comment */ { return };
+
+    let Some(x) = opt /* pre else keyword block-comment */ else /* post else keyword block-comment */ { return };
+
+    let Some(x) = opt // pre else keyword line-comment
+    else { return };
+
+    let Some(x) = opt else
+     // post else keyword line-comment
+    { return };
+
+    let Some(x) = opt // pre else keyword line-comment
+    else
+    // post else keyword line-comment
+    { return };
+
+}
+
+fn unbreakable_initializer_expr_pre_formatting_let_else_length_near_max_width() {
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 100 (max_width)
+    // Post Formatting:
+    // The formatting is left unchanged!
+    let Some(x) = some_really_really_really_really_really_really_really_long_name_A else { return };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 100 (max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_really_really_really_long_name___B else {return};
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 100 (max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_long_name_____C else {some_divergent_function()};
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 101 (> max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_really_really_really_long_name__D else { return };
+}
+
+fn unbreakable_initializer_expr_pre_formatting_length_up_to_opening_brace_near_max_width() {
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else {` is 99 (< max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_really_really_really_really_long_name___E else {return};
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else {` is 101 (> max_width)
+    // Post Formatting:
+    // The else keyword and opening brace cannot fit on the same line as the initializer expr.
+    // They are formatted on the next line.
+    let Some(x) = some_really_really_really_really_really_really_really_really_long_name_____F else {return};
+}
+
+fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_near_max_width() {
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 99 (< max_width)
+    // Post Formatting:
+    // The else keyword and opening brace cannot fit on the same line as the initializer expr.
+    // They are formatted on the next line.
+    let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name___G else {return};
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 100 (max_width)
+    // Post Formatting:
+    // Break after the `=` and put the initializer expr on it's own line.
+    // Because the initializer expr is multi-lined the else is placed on it's own line.
+    let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name____H else {return};
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 109 (> max_width)
+    // Post Formatting:
+    // Break after the `=` and put the initializer expr on it's own line.
+    // Because the initializer expr is multi-lined the else is placed on it's own line.
+    // The initializer expr has a length of 91, which when indented on the next line
+    // The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be
+    // before we start running into max_width issues. I suspect this is becuase the shape is
+    // accounting for the `;` at the end of the `let-else` statement.
+    let Some(x) = some_really_really_really_really_really_really_really_really_really_really_long_name______I else {return};
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 110 (> max_width)
+    // Post Formatting:
+    // Max length issues prevent us from formatting.
+    // The initializer expr has a length of 92, which if it would be indented on the next line
+    // the `(indent)init` line has a lengh of 100 which == max_width of 100.
+    // One might expect formatting to succeed, but I suspect the reason we hit max_width issues is
+    // because the Shape is accounting for the `;` at the end of the `let-else` statement.
+    let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return};
+}
+
+fn long_patterns() {
+    let Foo {x: Bar(..), y: FooBar(..), z: Baz(..)} = opt else {
+        return;
+    };
+
+    // with version=One we don't wrap long array patterns
+    let [aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd] = opt else {
+        return;
+    };
+
+    let ("aaaaaaaaaaaaaaaaaaa" | "bbbbbbbbbbbbbbbbb" | "cccccccccccccccccccccccc" | "dddddddddddddddd" | "eeeeeeeeeeeeeeee") = opt else {
+        return;
+    };
+
+    let Some(Ok((Message::ChangeColor(super::color::Color::Rgb(r, g, b)), Point { x, y, z }))) = opt else {
+        return;
+    };
+}
+
+fn with_trailing_try_operator() {
+    // Currently the trailing ? forces the else on the next line
+    // This may be revisited in style edition 2024
+    let Some(next_bucket) = ranking_rules[cur_ranking_rule_index].next_bucket(ctx, logger, &ranking_rule_universes[cur_ranking_rule_index])? else { return };
+
+    // Maybe this is a workaround?
+    let Ok(Some(next_bucket)) = ranking_rules[cur_ranking_rule_index].next_bucket(ctx, logger, &ranking_rule_universes[cur_ranking_rule_index]) else { return };
 }
diff --git a/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs
new file mode 100644
index 00000000000..0409124a5b0
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs
@@ -0,0 +1,60 @@
+// rustfmt-single_line_let_else_max_width: 100
+
+fn main() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(c) = opt else {
+        // a comment should always force the block to be multi-lined
+        return;
+    };
+
+    let Some(c) = opt else {
+        /* a comment should always force the block to be multi-lined */
+        return;
+    };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+
+    let Expr::Slice(ast::ExprSlice {
+        lower,
+        upper,
+        step,
+        range: _,
+    }) = slice.as_ref()
+    else {
+        return;
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
+        return Ok(None);
+    };
+
+    let Some(doc_attr) = variant
+        .attrs
+        .iter()
+        .find(|attr| attr.path().is_ident("doc"))
+    else {
+        return Err(Error::new(variant.span(), r#"expected a doc comment"#));
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else {
+        return Ok(None);
+    };
+
+    let Stmt::Expr(
+        Expr::Call(ExprCall {
+            args: some_args, ..
+        }),
+        _,
+    ) = last_stmt
+    else {
+        return Err(Error::new(
+            last_stmt.span(),
+            "expected last expression to be `Some(match (..) { .. })`",
+        ));
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs
new file mode 100644
index 00000000000..6afc2b6f2b0
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs
@@ -0,0 +1,62 @@
+// rustfmt-single_line_let_else_max_width: 50
+
+fn main() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(c) = opt else {
+        // a comment should always force the block to be multi-lined
+        return;
+    };
+
+    let Some(c) = opt else {
+        /* a comment should always force the block to be multi-lined */
+        return;
+    };
+
+    let Some(d) = some_very_very_very_very_long_name else {
+        return;
+    };
+
+    let Expr::Slice(ast::ExprSlice {
+        lower,
+        upper,
+        step,
+        range: _,
+    }) = slice.as_ref()
+    else {
+        return;
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
+        return Ok(None);
+    };
+
+    let Some(doc_attr) = variant
+        .attrs
+        .iter()
+        .find(|attr| attr.path().is_ident("doc"))
+    else {
+        return Err(Error::new(variant.span(), r#"expected a doc comment"#));
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else {
+        return Ok(None);
+    };
+
+    let Stmt::Expr(
+        Expr::Call(ExprCall {
+            args: some_args, ..
+        }),
+        _,
+    ) = last_stmt
+    else {
+        return Err(Error::new(
+            last_stmt.span(),
+            "expected last expression to be `Some(match (..) { .. })`",
+        ));
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs
new file mode 100644
index 00000000000..b5fd0b9edaf
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs
@@ -0,0 +1,66 @@
+// rustfmt-single_line_let_else_max_width: 0
+
+fn main() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else {
+        return;
+    };
+
+    let Some(c) = opt else {
+        return;
+    };
+
+    let Some(c) = opt else {
+        // a comment should always force the block to be multi-lined
+        return;
+    };
+
+    let Some(c) = opt else {
+        /* a comment should always force the block to be multi-lined */
+        return;
+    };
+
+    let Some(d) = some_very_very_very_very_long_name else {
+        return;
+    };
+
+    let Expr::Slice(ast::ExprSlice {
+        lower,
+        upper,
+        step,
+        range: _,
+    }) = slice.as_ref()
+    else {
+        return;
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true)? else {
+        return Ok(None);
+    };
+
+    let Some(doc_attr) = variant
+        .attrs
+        .iter()
+        .find(|attr| attr.path().is_ident("doc"))
+    else {
+        return Err(Error::new(variant.span(), r#"expected a doc comment"#));
+    };
+
+    let Some((base_place, current)) = self.lower_expr_as_place(current, *base, true) else {
+        return Ok(None);
+    };
+
+    let Stmt::Expr(
+        Expr::Call(ExprCall {
+            args: some_args, ..
+        }),
+        _,
+    ) = last_stmt
+    else {
+        return Err(Error::new(
+            last_stmt.span(),
+            "expected last expression to be `Some(match (..) { .. })`",
+        ));
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs
index d67bd9aafaf..ad40739233e 100644
--- a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs
+++ b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs
@@ -24,3 +24,15 @@ fn main() {
 
     let lorem = if ipsum { dolor } else { sit };
 }
+
+fn format_let_else() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(d) = some_very_very_very_very_long_name else {
+        return;
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs
index 785dfbea014..fe57f853d9d 100644
--- a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs
+++ b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs
@@ -13,3 +13,13 @@ fn main() {
 
     let lorem = if ipsum { dolor } else { sit };
 }
+
+fn format_let_else() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else { return };
+
+    let Some(c) = opt else { return };
+
+    let Some(d) = some_very_very_very_very_long_name else { return };
+}
diff --git a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs
index f76392d2404..b0b4e4ee49f 100644
--- a/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs
+++ b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs
@@ -23,3 +23,19 @@ fn main() {
         sit
     };
 }
+
+fn format_let_else() {
+    let Some(a) = opt else {};
+
+    let Some(b) = opt else {
+        return;
+    };
+
+    let Some(c) = opt else {
+        return;
+    };
+
+    let Some(d) = some_very_very_very_very_long_name else {
+        return;
+    };
+}
diff --git a/src/tools/rustfmt/tests/target/let_else.rs b/src/tools/rustfmt/tests/target/let_else.rs
index a6e816fb524..6554a0961c0 100644
--- a/src/tools/rustfmt/tests/target/let_else.rs
+++ b/src/tools/rustfmt/tests/target/let_else.rs
@@ -1,3 +1,254 @@
+// rustfmt-single_line_let_else_max_width: 100
+
 fn main() {
-    let Some(1) = Some(1) else { return };
+    // Although this won't compile it still parses so make sure we can format empty else blocks
+    let Some(x) = opt else {};
+
+    // let-else may be formatted on a single line if they are "short"
+    // and only contain a single expression
+    let Some(x) = opt else { return };
+
+    let Some(x) = opt else { return };
+
+    let Some(x) = opt else {
+        return;
+    };
+
+    let Some(x) = opt else {
+        // nope
+        return;
+    };
+
+    let Some(x) = opt else {
+        let y = 1;
+        return y;
+    };
+
+    let Some(x) = y.foo(
+        "abc",
+        fairly_long_identifier,
+        "def",
+        "123456",
+        "string",
+        "cheese",
+    ) else {
+        bar()
+    };
+
+    let Some(x) = abcdef()
+        .foo(
+            "abc",
+            some_really_really_really_long_ident,
+            "ident",
+            "123456",
+        )
+        .bar()
+        .baz()
+        .qux("fffffffffffffffff")
+    else {
+        foo_bar()
+    };
+}
+
+fn with_comments_around_else_keyword() {
+    let Some(x) = opt
+    /* pre else keyword block-comment */
+    else {
+        return;
+    };
+
+    let Some(x) = opt else
+    /* post else keyword block-comment */
+    {
+        return;
+    };
+
+    let Some(x) = opt
+    /* pre else keyword block-comment */
+    else
+    /* post else keyword block-comment */
+    {
+        return;
+    };
+
+    let Some(x) = opt
+    // pre else keyword line-comment
+    else {
+        return;
+    };
+
+    let Some(x) = opt else
+    // post else keyword line-comment
+    {
+        return;
+    };
+
+    let Some(x) = opt
+    // pre else keyword line-comment
+    else
+    // post else keyword line-comment
+    {
+        return;
+    };
+}
+
+fn unbreakable_initializer_expr_pre_formatting_let_else_length_near_max_width() {
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 100 (max_width)
+    // Post Formatting:
+    // The formatting is left unchanged!
+    let Some(x) = some_really_really_really_really_really_really_really_long_name_A else { return };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 100 (max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_really_really_really_long_name___B else {
+        return;
+    };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 100 (max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_long_name_____C else {
+        some_divergent_function()
+    };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else block;` is 101 (> max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_really_really_really_long_name__D else {
+        return;
+    };
+}
+
+fn unbreakable_initializer_expr_pre_formatting_length_up_to_opening_brace_near_max_width() {
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else {` is 99 (< max_width)
+    // Post Formatting:
+    // The else keyword and opening brace remain on the same line as the initializer expr,
+    // and the else block is formatted over multiple lines because we can't fit the
+    // else block on the same line as the initializer expr.
+    let Some(x) = some_really_really_really_really_really_really_really_really_long_name___E else {
+        return;
+    };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init else {` is 101 (> max_width)
+    // Post Formatting:
+    // The else keyword and opening brace cannot fit on the same line as the initializer expr.
+    // They are formatted on the next line.
+    let Some(x) = some_really_really_really_really_really_really_really_really_long_name_____F
+    else {
+        return;
+    };
+}
+
+fn unbreakable_initializer_expr_pre_formatting_length_through_initializer_expr_near_max_width() {
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 99 (< max_width)
+    // Post Formatting:
+    // The else keyword and opening brace cannot fit on the same line as the initializer expr.
+    // They are formatted on the next line.
+    let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name___G
+    else {
+        return;
+    };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 100 (max_width)
+    // Post Formatting:
+    // Break after the `=` and put the initializer expr on it's own line.
+    // Because the initializer expr is multi-lined the else is placed on it's own line.
+    let Some(x) =
+        some_really_really_really_really_really_really_really_really_really_long_name____H
+    else {
+        return;
+    };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 109 (> max_width)
+    // Post Formatting:
+    // Break after the `=` and put the initializer expr on it's own line.
+    // Because the initializer expr is multi-lined the else is placed on it's own line.
+    // The initializer expr has a length of 91, which when indented on the next line
+    // The `(indent)init` line has a lengh of 99. This is the max length that the `init` can be
+    // before we start running into max_width issues. I suspect this is becuase the shape is
+    // accounting for the `;` at the end of the `let-else` statement.
+    let Some(x) =
+        some_really_really_really_really_really_really_really_really_really_really_long_name______I
+    else {
+        return;
+    };
+
+    // Pre Formatting:
+    // The length of `(indent)let pat = init` is 110 (> max_width)
+    // Post Formatting:
+    // Max length issues prevent us from formatting.
+    // The initializer expr has a length of 92, which if it would be indented on the next line
+    // the `(indent)init` line has a lengh of 100 which == max_width of 100.
+    // One might expect formatting to succeed, but I suspect the reason we hit max_width issues is
+    // because the Shape is accounting for the `;` at the end of the `let-else` statement.
+    let Some(x) = some_really_really_really_really_really_really_really_really_really_really_really_long_nameJ else {return};
+}
+
+fn long_patterns() {
+    let Foo {
+        x: Bar(..),
+        y: FooBar(..),
+        z: Baz(..),
+    } = opt
+    else {
+        return;
+    };
+
+    // with version=One we don't wrap long array patterns
+    let [aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd] = opt else {
+        return;
+    };
+
+    let ("aaaaaaaaaaaaaaaaaaa"
+    | "bbbbbbbbbbbbbbbbb"
+    | "cccccccccccccccccccccccc"
+    | "dddddddddddddddd"
+    | "eeeeeeeeeeeeeeee") = opt
+    else {
+        return;
+    };
+
+    let Some(Ok((Message::ChangeColor(super::color::Color::Rgb(r, g, b)), Point { x, y, z }))) =
+        opt
+    else {
+        return;
+    };
+}
+
+fn with_trailing_try_operator() {
+    // Currently the trailing ? forces the else on the next line
+    // This may be revisited in style edition 2024
+    let Some(next_bucket) = ranking_rules[cur_ranking_rule_index].next_bucket(
+        ctx,
+        logger,
+        &ranking_rule_universes[cur_ranking_rule_index],
+    )?
+    else {
+        return;
+    };
+
+    // Maybe this is a workaround?
+    let Ok(Some(next_bucket)) = ranking_rules[cur_ranking_rule_index].next_bucket(
+        ctx,
+        logger,
+        &ranking_rule_universes[cur_ranking_rule_index],
+    ) else {
+        return;
+    };
 }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 8db479af286..b6c57342a05 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -111,7 +111,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "aho-corasick",
     "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801
     "annotate-snippets",
-    "ansi_term",
     "ar_archive_writer",
     "arrayvec",
     "atty",
@@ -143,6 +142,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "either",
     "elsa",
     "ena",
+    "equivalent",
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",
@@ -187,10 +187,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "memmap2",
     "memoffset",
     "miniz_oxide",
+    "nu-ansi-term",
     "num_cpus",
     "object",
     "odht",
     "once_cell",
+    "overload",
     "parking_lot",
     "parking_lot_core",
     "pathdiff",
diff --git a/tests/run-make/coverage/lib/doctest_crate.rs b/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs
index c3210146d69..c3210146d69 100644
--- a/tests/run-make/coverage/lib/doctest_crate.rs
+++ b/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt b/tests/run-coverage-rustdoc/doctest.coverage
index 732de652627..0fce73a6048 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt
+++ b/tests/run-coverage-rustdoc/doctest.coverage
@@ -1,4 +1,15 @@
-../coverage/doctest.rs:
+$DIR/auxiliary/doctest_crate.rs:
+    1|       |/// A function run only from within doctests
+    2|      3|pub fn fn_run_in_doctests(conditional: usize) {
+    3|      3|    match conditional {
+    4|      1|        1 => assert_eq!(1, 1), // this is run,
+    5|      1|        2 => assert_eq!(1, 1), // this,
+    6|      1|        3 => assert_eq!(1, 1), // and this too
+    7|      0|        _ => assert_eq!(1, 2), // however this is not
+    8|       |    }
+    9|      3|}
+
+$DIR/doctest.rs:
     1|       |//! This test ensures that code from doctests is properly re-mapped.
     2|       |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
     3|       |//!
@@ -67,7 +78,7 @@
    63|       |//!     doctest_main()
    64|       |//! }
    65|       |//! ```
-   66|       |
+   66|       |// aux-build:doctest_crate.rs
    67|       |/// doctest attached to fn testing external code:
    68|       |/// ```
    69|      1|/// extern crate doctest_crate;
@@ -102,14 +113,3 @@
    98|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
    99|       |// if the indentation changed. I don't know if there is a more viable solution.
 
-../coverage/lib/doctest_crate.rs:
-    1|       |/// A function run only from within doctests
-    2|      3|pub fn fn_run_in_doctests(conditional: usize) {
-    3|      3|    match conditional {
-    4|      1|        1 => assert_eq!(1, 1), // this is run,
-    5|      1|        2 => assert_eq!(1, 1), // this,
-    6|      1|        3 => assert_eq!(1, 1), // and this too
-    7|      0|        _ => assert_eq!(1, 2), // however this is not
-    8|       |    }
-    9|      3|}
-
diff --git a/tests/run-make/coverage/doctest.rs b/tests/run-coverage-rustdoc/doctest.rs
index ec04ea57063..251b0c291e9 100644
--- a/tests/run-make/coverage/doctest.rs
+++ b/tests/run-coverage-rustdoc/doctest.rs
@@ -63,7 +63,7 @@
 //!     doctest_main()
 //! }
 //! ```
-
+// aux-build:doctest_crate.rs
 /// doctest attached to fn testing external code:
 /// ```
 /// extern crate doctest_crate;
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-coverage/abort.coverage
index a71c58d618d..a71c58d618d 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
+++ b/tests/run-coverage/abort.coverage
diff --git a/tests/run-make/coverage/abort.rs b/tests/run-coverage/abort.rs
index 98264bdc1af..98264bdc1af 100644
--- a/tests/run-make/coverage/abort.rs
+++ b/tests/run-coverage/abort.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt b/tests/run-coverage/assert.coverage
index 405688806ea..a7134a149e2 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt
+++ b/tests/run-coverage/assert.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-101
+    2|       |// failure-status: 101
     3|       |
     4|      4|fn might_fail_assert(one_plus_one: u32) {
     5|      4|    println!("does 1 + 1 = {}?", one_plus_one);
diff --git a/tests/run-make/coverage/assert.rs b/tests/run-coverage/assert.rs
index c85f2748eb9..d32a37e078e 100644
--- a/tests/run-make/coverage/assert.rs
+++ b/tests/run-coverage/assert.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-101
+// failure-status: 101
 
 fn might_fail_assert(one_plus_one: u32) {
     println!("does 1 + 1 = {}?", one_plus_one);
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async.txt b/tests/run-coverage/async.coverage
index 93c1535b06b..93c1535b06b 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.async.txt
+++ b/tests/run-coverage/async.coverage
diff --git a/tests/run-make/coverage/async.rs b/tests/run-coverage/async.rs
index efd9e62d64e..efd9e62d64e 100644
--- a/tests/run-make/coverage/async.rs
+++ b/tests/run-coverage/async.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async2.txt b/tests/run-coverage/async2.coverage
index 500dde1f269..500dde1f269 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.async2.txt
+++ b/tests/run-coverage/async2.coverage
diff --git a/tests/run-make/coverage/async2.rs b/tests/run-coverage/async2.rs
index 959d48ce9db..959d48ce9db 100644
--- a/tests/run-make/coverage/async2.rs
+++ b/tests/run-coverage/async2.rs
diff --git a/tests/run-make/coverage/lib/inline_always_with_dead_code.rs b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
index 2b21dee6ccf..2b21dee6ccf 100644
--- a/tests/run-make/coverage/lib/inline_always_with_dead_code.rs
+++ b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs
diff --git a/tests/run-make/coverage/lib/unused_mod_helper.rs b/tests/run-coverage/auxiliary/unused_mod_helper.rs
index ae1cc1531ed..ae1cc1531ed 100644
--- a/tests/run-make/coverage/lib/unused_mod_helper.rs
+++ b/tests/run-coverage/auxiliary/unused_mod_helper.rs
diff --git a/tests/run-make/coverage/lib/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs
index 8b8b1f7f351..16592d48dda 100644
--- a/tests/run-make/coverage/lib/used_crate.rs
+++ b/tests/run-coverage/auxiliary/used_crate.rs
@@ -1,6 +1,6 @@
 #![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-use std::fmt::Debug;
+// compile-flags: -C opt-level=3
+use std::fmt::Debug; // ^^ validates coverage now works with optimizations
 
 pub fn used_function() {
     // Initialize test constants in a way that cannot be determined at compile time, to ensure
diff --git a/tests/run-make/coverage/lib/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs
index 4a052756d4e..8b8e9d5483f 100644
--- a/tests/run-make/coverage/lib/used_inline_crate.rs
+++ b/tests/run-coverage/auxiliary/used_inline_crate.rs
@@ -1,7 +1,7 @@
 #![allow(unused_assignments, unused_variables)]
 
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-
+// compile-flags: -C opt-level=3
+// ^^ validates coverage now works with optimizations
 use std::fmt::Debug;
 
 pub fn used_function() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt b/tests/run-coverage/closure.coverage
index 002ecec3b91..45d36b72e3a 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
+++ b/tests/run-coverage/closure.coverage
@@ -1,6 +1,6 @@
     1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
-    3|      1|fn main() {
+    2|       |// compile-flags: -C opt-level=2
+    3|      1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
     4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
     5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
     6|      1|    // dependent conditions.
diff --git a/tests/run-make/coverage/closure.rs b/tests/run-coverage/closure.rs
index 32ec0bcdf8c..eb3a1ebff88 100644
--- a/tests/run-make/coverage/closure.rs
+++ b/tests/run-coverage/closure.rs
@@ -1,6 +1,6 @@
 #![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs
-fn main() {
+// compile-flags: -C opt-level=2
+fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
     // Initialize test constants in a way that cannot be determined at compile time, to ensure
     // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
     // dependent conditions.
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt b/tests/run-coverage/closure_macro.coverage
index 87f7014760e..87f7014760e 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt
+++ b/tests/run-coverage/closure_macro.coverage
diff --git a/tests/run-make/coverage/closure_macro.rs b/tests/run-coverage/closure_macro.rs
index 5e3b00d1ef5..5e3b00d1ef5 100644
--- a/tests/run-make/coverage/closure_macro.rs
+++ b/tests/run-coverage/closure_macro.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt b/tests/run-coverage/closure_macro_async.coverage
index 2b5418132c3..2b5418132c3 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt
+++ b/tests/run-coverage/closure_macro_async.coverage
diff --git a/tests/run-make/coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs
index e3e89e9c8b3..e3e89e9c8b3 100644
--- a/tests/run-make/coverage/closure_macro_async.rs
+++ b/tests/run-coverage/closure_macro_async.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt b/tests/run-coverage/conditions.coverage
index 2d8a98a5d0c..2d8a98a5d0c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt
+++ b/tests/run-coverage/conditions.coverage
diff --git a/tests/run-make/coverage/conditions.rs b/tests/run-coverage/conditions.rs
index 057599d1b47..057599d1b47 100644
--- a/tests/run-make/coverage/conditions.rs
+++ b/tests/run-coverage/conditions.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt b/tests/run-coverage/continue.coverage
index bf42924b191..bf42924b191 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt
+++ b/tests/run-coverage/continue.coverage
diff --git a/tests/run-make/coverage/continue.rs b/tests/run-coverage/continue.rs
index 624aa98341b..624aa98341b 100644
--- a/tests/run-make/coverage/continue.rs
+++ b/tests/run-coverage/continue.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt b/tests/run-coverage/dead_code.coverage
index 09ff14c6f27..09ff14c6f27 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt
+++ b/tests/run-coverage/dead_code.coverage
diff --git a/tests/run-make/coverage/dead_code.rs b/tests/run-coverage/dead_code.rs
index a1285df0ec6..a1285df0ec6 100644
--- a/tests/run-make/coverage/dead_code.rs
+++ b/tests/run-coverage/dead_code.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt b/tests/run-coverage/drop_trait.coverage
index fe6a9e93cbf..293001e9590 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt
+++ b/tests/run-coverage/drop_trait.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|       |struct Firework {
     5|       |    strength: i32,
diff --git a/tests/run-make/coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs
index d15bfc0f877..a9b5d1d1e7f 100644
--- a/tests/run-make/coverage/drop_trait.rs
+++ b/tests/run-coverage/drop_trait.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 struct Firework {
     strength: i32,
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generator.txt b/tests/run-coverage/generator.coverage
index 0fb3808ff2e..0fb3808ff2e 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.generator.txt
+++ b/tests/run-coverage/generator.coverage
diff --git a/tests/run-make/coverage/generator.rs b/tests/run-coverage/generator.rs
index 4319991021e..4319991021e 100644
--- a/tests/run-make/coverage/generator.rs
+++ b/tests/run-coverage/generator.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt b/tests/run-coverage/generics.coverage
index 7eb33a29a92..7a7649674ca 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt
+++ b/tests/run-coverage/generics.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|       |struct Firework<T> where T: Copy + std::fmt::Display {
     5|       |    strength: T,
diff --git a/tests/run-make/coverage/generics.rs b/tests/run-coverage/generics.rs
index 18b38868496..150ffb9db39 100644
--- a/tests/run-make/coverage/generics.rs
+++ b/tests/run-coverage/generics.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 struct Firework<T> where T: Copy + std::fmt::Display {
     strength: T,
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if.txt b/tests/run-coverage/if.coverage
index 0c9eff227ed..0c9eff227ed 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.if.txt
+++ b/tests/run-coverage/if.coverage
diff --git a/tests/run-make/coverage/if.rs b/tests/run-coverage/if.rs
index 8ad5042ff7b..8ad5042ff7b 100644
--- a/tests/run-make/coverage/if.rs
+++ b/tests/run-coverage/if.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt b/tests/run-coverage/if_else.coverage
index 4285d318686..4285d318686 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt
+++ b/tests/run-coverage/if_else.coverage
diff --git a/tests/run-make/coverage/if_else.rs b/tests/run-coverage/if_else.rs
index 3244e1e3afd..3244e1e3afd 100644
--- a/tests/run-make/coverage/if_else.rs
+++ b/tests/run-coverage/if_else.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt b/tests/run-coverage/inline-dead.coverage
index a59fe1146f4..a59fe1146f4 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt
+++ b/tests/run-coverage/inline-dead.coverage
diff --git a/tests/run-make/coverage/inline-dead.rs b/tests/run-coverage/inline-dead.rs
index 854fa062967..854fa062967 100644
--- a/tests/run-make/coverage/inline-dead.rs
+++ b/tests/run-coverage/inline-dead.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline.txt b/tests/run-coverage/inline.coverage
index 6f5d1544fa0..6f5d1544fa0 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.inline.txt
+++ b/tests/run-coverage/inline.coverage
diff --git a/tests/run-make/coverage/inline.rs b/tests/run-coverage/inline.rs
index 9cfab9ddbad..9cfab9ddbad 100644
--- a/tests/run-make/coverage/inline.rs
+++ b/tests/run-coverage/inline.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt b/tests/run-coverage/inner_items.coverage
index 883254a09ba..883254a09ba 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt
+++ b/tests/run-coverage/inner_items.coverage
diff --git a/tests/run-make/coverage/inner_items.rs b/tests/run-coverage/inner_items.rs
index bcb62b3031c..bcb62b3031c 100644
--- a/tests/run-make/coverage/inner_items.rs
+++ b/tests/run-coverage/inner_items.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/tests/run-coverage/issue-83601.coverage
index 25c74ab2e70..25c74ab2e70 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
+++ b/tests/run-coverage/issue-83601.coverage
diff --git a/tests/run-make/coverage/issue-83601.rs b/tests/run-coverage/issue-83601.rs
index 0b72a81947c..0b72a81947c 100644
--- a/tests/run-make/coverage/issue-83601.rs
+++ b/tests/run-coverage/issue-83601.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/tests/run-coverage/issue-84561.coverage
index 4a60432c14c..7a97e353245 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
+++ b/tests/run-coverage/issue-84561.coverage
@@ -1,6 +1,6 @@
     1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
     2|       |
-    3|       |// expect-exit-status-101
+    3|       |// failure-status: 101
     4|     21|#[derive(PartialEq, Eq)]
     5|       |struct Foo(u32);
     6|      1|fn test3() {
diff --git a/tests/run-make/coverage/issue-84561.rs b/tests/run-coverage/issue-84561.rs
index b39a289c45e..facf5b5b4cf 100644
--- a/tests/run-make/coverage/issue-84561.rs
+++ b/tests/run-coverage/issue-84561.rs
@@ -1,6 +1,6 @@
 // This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
 
-// expect-exit-status-101
+// failure-status: 101
 #[derive(PartialEq, Eq)]
 struct Foo(u32);
 fn test3() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt b/tests/run-coverage/issue-85461.coverage
index 1aa4a22c33e..d78a4a1129c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt
+++ b/tests/run-coverage/issue-85461.coverage
@@ -1,16 +1,4 @@
-../coverage/issue-85461.rs:
-    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
-    2|       |
-    3|       |extern crate inline_always_with_dead_code;
-    4|       |
-    5|       |use inline_always_with_dead_code::{bar, baz};
-    6|       |
-    7|      1|fn main() {
-    8|      1|    bar::call_me();
-    9|      1|    baz::call_me();
-   10|      1|}
-
-../coverage/lib/inline_always_with_dead_code.rs:
+$DIR/auxiliary/inline_always_with_dead_code.rs:
     1|       |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
     2|       |
     3|       |#![allow(dead_code)]
@@ -34,3 +22,15 @@
    21|      1|    }
    22|       |}
 
+$DIR/issue-85461.rs:
+    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+    2|       |// aux-build:inline_always_with_dead_code.rs
+    3|       |extern crate inline_always_with_dead_code;
+    4|       |
+    5|       |use inline_always_with_dead_code::{bar, baz};
+    6|       |
+    7|      1|fn main() {
+    8|      1|    bar::call_me();
+    9|      1|    baz::call_me();
+   10|      1|}
+
diff --git a/tests/run-make/coverage/issue-85461.rs b/tests/run-coverage/issue-85461.rs
index a1b9ebb1ed3..6f626b4a65b 100644
--- a/tests/run-make/coverage/issue-85461.rs
+++ b/tests/run-coverage/issue-85461.rs
@@ -1,5 +1,5 @@
 // Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
-
+// aux-build:inline_always_with_dead_code.rs
 extern crate inline_always_with_dead_code;
 
 use inline_always_with_dead_code::{bar, baz};
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt b/tests/run-coverage/issue-93054.coverage
index a1655adedd4..a1655adedd4 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt
+++ b/tests/run-coverage/issue-93054.coverage
diff --git a/tests/run-make/coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs
index c160b3db03f..c160b3db03f 100644
--- a/tests/run-make/coverage/issue-93054.rs
+++ b/tests/run-coverage/issue-93054.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt b/tests/run-coverage/lazy_boolean.coverage
index bd349df2fbc..bd349df2fbc 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt
+++ b/tests/run-coverage/lazy_boolean.coverage
diff --git a/tests/run-make/coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs
index bb6219e851c..bb6219e851c 100644
--- a/tests/run-make/coverage/lazy_boolean.rs
+++ b/tests/run-coverage/lazy_boolean.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt b/tests/run-coverage/loop_break_value.coverage
index 022fe4c5962..022fe4c5962 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt
+++ b/tests/run-coverage/loop_break_value.coverage
diff --git a/tests/run-make/coverage/loop_break_value.rs b/tests/run-coverage/loop_break_value.rs
index dbc4fad7a23..dbc4fad7a23 100644
--- a/tests/run-make/coverage/loop_break_value.rs
+++ b/tests/run-coverage/loop_break_value.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt b/tests/run-coverage/loops_branches.coverage
index b7ad79a2484..b7ad79a2484 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt
+++ b/tests/run-coverage/loops_branches.coverage
diff --git a/tests/run-make/coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs
index 7116ce47f4b..7116ce47f4b 100644
--- a/tests/run-make/coverage/loops_branches.rs
+++ b/tests/run-coverage/loops_branches.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt b/tests/run-coverage/match_or_pattern.coverage
index a0fccb24f99..a0fccb24f99 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt
+++ b/tests/run-coverage/match_or_pattern.coverage
diff --git a/tests/run-make/coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs
index 4c6a8a9b703..4c6a8a9b703 100644
--- a/tests/run-make/coverage/match_or_pattern.rs
+++ b/tests/run-coverage/match_or_pattern.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt b/tests/run-coverage/nested_loops.coverage
index 0dbd6bcf313..0dbd6bcf313 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt
+++ b/tests/run-coverage/nested_loops.coverage
diff --git a/tests/run-make/coverage/nested_loops.rs b/tests/run-coverage/nested_loops.rs
index 4c7c7842796..4c7c7842796 100644
--- a/tests/run-make/coverage/nested_loops.rs
+++ b/tests/run-coverage/nested_loops.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt b/tests/run-coverage/no_cov_crate.coverage
index 83a9204136f..83a9204136f 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt
+++ b/tests/run-coverage/no_cov_crate.coverage
diff --git a/tests/run-make/coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs
index 0bfbdda2cab..0bfbdda2cab 100644
--- a/tests/run-make/coverage/no_cov_crate.rs
+++ b/tests/run-coverage/no_cov_crate.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt b/tests/run-coverage/overflow.coverage
index 25e822bffd1..95043759166 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt
+++ b/tests/run-coverage/overflow.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-101
+    2|       |// failure-status: 101
     3|       |
     4|      4|fn might_overflow(to_add: u32) -> u32 {
     5|      4|    if to_add > 5 {
diff --git a/tests/run-make/coverage/overflow.rs b/tests/run-coverage/overflow.rs
index e537b0e95c3..7df8de6f3cd 100644
--- a/tests/run-make/coverage/overflow.rs
+++ b/tests/run-coverage/overflow.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-101
+// failure-status: 101
 
 fn might_overflow(to_add: u32) -> u32 {
     if to_add > 5 {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt b/tests/run-coverage/panic_unwind.coverage
index 114507dc9fd..58b9ba448ee 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt
+++ b/tests/run-coverage/panic_unwind.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-101
+    2|       |// failure-status: 101
     3|       |
     4|      4|fn might_panic(should_panic: bool) {
     5|      4|    if should_panic {
diff --git a/tests/run-make/coverage/panic_unwind.rs b/tests/run-coverage/panic_unwind.rs
index 03128c2cce6..638d2eb6aaa 100644
--- a/tests/run-make/coverage/panic_unwind.rs
+++ b/tests/run-coverage/panic_unwind.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-101
+// failure-status: 101
 
 fn might_panic(should_panic: bool) {
     if should_panic {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/tests/run-coverage/partial_eq.coverage
index a77175af663..a77175af663 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
+++ b/tests/run-coverage/partial_eq.coverage
diff --git a/tests/run-make/coverage/partial_eq.rs b/tests/run-coverage/partial_eq.rs
index 4ceaba9b111..4ceaba9b111 100644
--- a/tests/run-make/coverage/partial_eq.rs
+++ b/tests/run-coverage/partial_eq.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt b/tests/run-coverage/simple_loop.coverage
index feb83bad674..feb83bad674 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt
+++ b/tests/run-coverage/simple_loop.coverage
diff --git a/tests/run-make/coverage/simple_loop.rs b/tests/run-coverage/simple_loop.rs
index 6f7f23475b8..6f7f23475b8 100644
--- a/tests/run-make/coverage/simple_loop.rs
+++ b/tests/run-coverage/simple_loop.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt b/tests/run-coverage/simple_match.coverage
index b9298213111..b9298213111 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt
+++ b/tests/run-coverage/simple_match.coverage
diff --git a/tests/run-make/coverage/simple_match.rs b/tests/run-coverage/simple_match.rs
index be99e59a826..be99e59a826 100644
--- a/tests/run-make/coverage/simple_match.rs
+++ b/tests/run-coverage/simple_match.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt b/tests/run-coverage/sort_groups.coverage
index 81468cb35da..81468cb35da 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt
+++ b/tests/run-coverage/sort_groups.coverage
diff --git a/tests/run-make/coverage/sort_groups.rs b/tests/run-coverage/sort_groups.rs
index f89f9f3ec61..f89f9f3ec61 100644
--- a/tests/run-make/coverage/sort_groups.rs
+++ b/tests/run-coverage/sort_groups.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt b/tests/run-coverage/test_harness.coverage
index 93bd1cfcb48..93bd1cfcb48 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt
+++ b/tests/run-coverage/test_harness.coverage
diff --git a/tests/run-make/coverage/test_harness.rs b/tests/run-coverage/test_harness.rs
index 12a755734c1..12a755734c1 100644
--- a/tests/run-make/coverage/test_harness.rs
+++ b/tests/run-coverage/test_harness.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/tests/run-coverage/tight_inf_loop.coverage
index 2d4c57f451a..2d4c57f451a 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt
+++ b/tests/run-coverage/tight_inf_loop.coverage
diff --git a/tests/run-make/coverage/tight_inf_loop.rs b/tests/run-coverage/tight_inf_loop.rs
index cef99027aaa..cef99027aaa 100644
--- a/tests/run-make/coverage/tight_inf_loop.rs
+++ b/tests/run-coverage/tight_inf_loop.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt b/tests/run-coverage/try_error_result.coverage
index 0ad0180b761..efe573a5607 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt
+++ b/tests/run-coverage/try_error_result.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|      6|fn call(return_error: bool) -> Result<(),()> {
     5|      6|    if return_error {
diff --git a/tests/run-make/coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs
index cd0acf72302..9eb1d2db218 100644
--- a/tests/run-make/coverage/try_error_result.rs
+++ b/tests/run-coverage/try_error_result.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 fn call(return_error: bool) -> Result<(),()> {
     if return_error {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused.txt b/tests/run-coverage/unused.coverage
index 15fcf21c0ef..15fcf21c0ef 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.unused.txt
+++ b/tests/run-coverage/unused.coverage
diff --git a/tests/run-make/coverage/unused.rs b/tests/run-coverage/unused.rs
index fb6113eb01c..fb6113eb01c 100644
--- a/tests/run-make/coverage/unused.rs
+++ b/tests/run-coverage/unused.rs
diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage
new file mode 100644
index 00000000000..e1d82f66f75
--- /dev/null
+++ b/tests/run-coverage/unused_mod.coverage
@@ -0,0 +1,13 @@
+$DIR/auxiliary/unused_mod_helper.rs:
+    1|      0|pub fn never_called_function() {
+    2|      0|    println!("I am never called");
+    3|      0|}
+
+$DIR/unused_mod.rs:
+    1|       |#[path = "auxiliary/unused_mod_helper.rs"]
+    2|       |mod unused_module;
+    3|       |
+    4|      1|fn main() {
+    5|      1|    println!("hello world!");
+    6|      1|}
+
diff --git a/tests/run-make/coverage/unused_mod.rs b/tests/run-coverage/unused_mod.rs
index 679b4e53188..6e62839c998 100644
--- a/tests/run-make/coverage/unused_mod.rs
+++ b/tests/run-coverage/unused_mod.rs
@@ -1,4 +1,4 @@
-#[path = "lib/unused_mod_helper.rs"]
+#[path = "auxiliary/unused_mod_helper.rs"]
 mod unused_module;
 
 fn main() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/tests/run-coverage/uses_crate.coverage
index 412f4a93b9c..a3b78e21405 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt
+++ b/tests/run-coverage/uses_crate.coverage
@@ -1,6 +1,7 @@
+$DIR/auxiliary/used_crate.rs:
     1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-    3|       |use std::fmt::Debug;
+    2|       |// compile-flags: -C opt-level=3
+    3|       |use std::fmt::Debug; // ^^ validates coverage now works with optimizations
     4|       |
     5|      1|pub fn used_function() {
     6|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
@@ -146,3 +147,24 @@
    99|       |// functions" list, which would then omit coverage results for
   100|       |// `unused_generic_function<T>()`, below.
 
+$DIR/uses_crate.rs:
+    1|       |// FIXME #110395
+    2|       |// ignore-linux
+    3|       |
+    4|       |// Validates coverage now works with optimizations
+    5|       |// compile-flags: -C opt-level=3
+    6|       |
+    7|       |#![allow(unused_assignments, unused_variables)]
+    8|       |
+    9|       |// aux-build:used_crate.rs
+   10|       |extern crate used_crate;
+   11|       |
+   12|      1|fn main() {
+   13|      1|    used_crate::used_function();
+   14|      1|    let some_vec = vec![1, 2, 3, 4];
+   15|      1|    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   16|      1|    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   17|      1|    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   18|      1|    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+   19|      1|}
+
diff --git a/tests/run-make/coverage/uses_crate.rs b/tests/run-coverage/uses_crate.rs
index 1ee8037a1e7..ab466970f8e 100644
--- a/tests/run-make/coverage/uses_crate.rs
+++ b/tests/run-coverage/uses_crate.rs
@@ -1,8 +1,12 @@
 // FIXME #110395
-// ignore-llvm-cov-show-diffs
+// ignore-linux
+
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
 
 #![allow(unused_assignments, unused_variables)]
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+
+// aux-build:used_crate.rs
 extern crate used_crate;
 
 fn main() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/tests/run-coverage/uses_inline_crate.coverage
index 66ca9e80a32..f878d8107c5 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt
+++ b/tests/run-coverage/uses_inline_crate.coverage
@@ -1,7 +1,8 @@
+$DIR/auxiliary/used_inline_crate.rs:
     1|       |#![allow(unused_assignments, unused_variables)]
     2|       |
-    3|       |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
-    4|       |
+    3|       |// compile-flags: -C opt-level=3
+    4|       |// ^^ validates coverage now works with optimizations
     5|       |use std::fmt::Debug;
     6|       |
     7|      1|pub fn used_function() {
@@ -137,3 +138,27 @@
    89|      2|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
    90|      2|}
 
+$DIR/uses_inline_crate.rs:
+    1|       |// FIXME #110395
+    2|       |// ignore-linux
+    3|       |
+    4|       |// Validates coverage now works with optimizations
+    5|       |// compile-flags: -C opt-level=3
+    6|       |
+    7|       |#![allow(unused_assignments, unused_variables)]
+    8|       |
+    9|       |// aux-build:used_inline_crate.rs
+   10|       |extern crate used_inline_crate;
+   11|       |
+   12|      1|fn main() {
+   13|      1|    used_inline_crate::used_function();
+   14|      1|    used_inline_crate::used_inline_function();
+   15|      1|    let some_vec = vec![1, 2, 3, 4];
+   16|      1|    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   17|      1|    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   18|      1|    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   19|      1|    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   20|      1|        "interesting?",
+   21|      1|    );
+   22|      1|}
+
diff --git a/tests/run-make/coverage/uses_inline_crate.rs b/tests/run-coverage/uses_inline_crate.rs
index f7aff3c3f8a..4bd66d2f89c 100644
--- a/tests/run-make/coverage/uses_inline_crate.rs
+++ b/tests/run-coverage/uses_inline_crate.rs
@@ -1,10 +1,12 @@
 // FIXME #110395
-// ignore-llvm-cov-show-diffs
+// ignore-linux
 
-#![allow(unused_assignments, unused_variables)]
+// Validates coverage now works with optimizations
+// compile-flags: -C opt-level=3
 
-// compile-flags: -C opt-level=3 # validates coverage now works with optimizations
+#![allow(unused_assignments, unused_variables)]
 
+// aux-build:used_inline_crate.rs
 extern crate used_inline_crate;
 
 fn main() {
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while.txt b/tests/run-coverage/while.coverage
index efa7d083f0c..efa7d083f0c 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.while.txt
+++ b/tests/run-coverage/while.coverage
diff --git a/tests/run-make/coverage/while.rs b/tests/run-coverage/while.rs
index 781b90b3566..781b90b3566 100644
--- a/tests/run-make/coverage/while.rs
+++ b/tests/run-coverage/while.rs
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt b/tests/run-coverage/while_early_ret.coverage
index d19afc0de61..2ce94e0131d 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt
+++ b/tests/run-coverage/while_early_ret.coverage
@@ -1,5 +1,5 @@
     1|       |#![allow(unused_assignments)]
-    2|       |// expect-exit-status-1
+    2|       |// failure-status: 1
     3|       |
     4|      1|fn main() -> Result<(),u8> {
     5|      1|    let mut countdown = 10;
diff --git a/tests/run-make/coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs
index 1fcea9c85c4..1c83c8fc7a8 100644
--- a/tests/run-make/coverage/while_early_ret.rs
+++ b/tests/run-coverage/while_early_ret.rs
@@ -1,5 +1,5 @@
 #![allow(unused_assignments)]
-// expect-exit-status-1
+// failure-status: 1
 
 fn main() -> Result<(),u8> {
     let mut countdown = 10;
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.yield.txt b/tests/run-coverage/yield.coverage
index 6e2f23ee77b..6e2f23ee77b 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.yield.txt
+++ b/tests/run-coverage/yield.coverage
diff --git a/tests/run-make/coverage/yield.rs b/tests/run-coverage/yield.rs
index ff7616656ff..ff7616656ff 100644
--- a/tests/run-make/coverage/yield.rs
+++ b/tests/run-coverage/yield.rs
diff --git a/tests/run-make/coverage-llvmir/Makefile b/tests/run-make/coverage-llvmir/Makefile
index 7be65505332..be92f8ac8fc 100644
--- a/tests/run-make/coverage-llvmir/Makefile
+++ b/tests/run-make/coverage-llvmir/Makefile
@@ -6,7 +6,7 @@
 # version during testing, with an additional directive at the top of this file
 # that sets, for example: `min-llvm-version: 12.0`
 
-include ../coverage/coverage_tools.mk
+include ../tools.mk
 
 BASEDIR=../coverage-llvmir
 
diff --git a/tests/run-make/coverage-reports/Makefile b/tests/run-make/coverage-reports/Makefile
deleted file mode 100644
index 0ae409c4119..00000000000
--- a/tests/run-make/coverage-reports/Makefile
+++ /dev/null
@@ -1,178 +0,0 @@
-# needs-profiler-support
-# ignore-windows-gnu
-
-# FIXME(pietroalbini): this test currently does not work on cross-compiled
-# targets because remote-test is not capable of sending back the *.profraw
-# files generated by the LLVM instrumentation.
-# ignore-cross-compile
-
-# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
-# corresponding with LLVM versions 12 and 13, respectively.
-# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
-# version during testing, with an additional directive at the top of this file
-# that sets, for example: `min-llvm-version: 12.0`
-
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
-include ../coverage/coverage_tools.mk
-
-BASEDIR=../coverage-reports
-SOURCEDIR=../coverage
-
-# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only
-# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not
-# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting
-# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is
-# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)`
-# directory, for inspection and debugging support. They are *not* copied to `expected_*`
-# files when `--bless`ed.)
-LLVM_COV_DEBUG := $(shell \
-		"$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \
-		grep -q "Unknown command line argument '--debug'"; \
-		echo $$?)
-ifeq ($(LLVM_COV_DEBUG), 1)
-DEBUG_FLAG=--debug
-endif
-
-# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce
-# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a
-# workaround for two problems causing tests to fail on Windows:
-#
-# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can
-#    appear in different a different order. Whether this is random or, somehow, platform-specific,
-#    the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs`
-#    test, the only test-unique (interesting) results we care about are the results for only one
-#    of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file.
-#    In the future, we may want a more sophisticated solution that splits apart `llvm-cov show`
-#    results into separate results files for each result (taking care not to create new file
-#    paths that might be too long for Windows MAX_PATH limits when creating these new sub-results,
-#    as well).
-# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are
-#    prefixed with their filename, including platform-specific path separators (`\` for Windows,
-#    and `/` everywhere else). This could be filtered or normalized of course, but by ignoring
-#    coverage results for all but one of the file, the filenames are no longer included anyway.
-#    If this changes (if/when we decide to support `llvm-cov show` results for multiple files),
-#    the file path separator differences may need to be addressed.
-#
-# Since this is only a workaround, I decided to implement the override by adding an option for
-# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than
-# implement some more sophisticated solution with a new custom test directive in the test file
-# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still
-# be a workaround, with the same result, with no benefit.
-#
-# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show`
-# for now, but it is effectively ignored for all tests that don't include this file anyway.
-#
-# (Note that it's also possible the `_counters.<test>.txt` and `<test>.json` files (if generated)
-# may order results from multiple files inconsistently, which might also have to be accommodated
-# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators
-# appear to be normalized to `/` in those files, thankfully.)
-LLVM_COV_IGNORE_FILES=\
-	--ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)'
-
-all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs))
-
-# Ensure there are no `expected` results for tests that may have been removed or renamed
-.PHONY: clear_expected_if_blessed
-clear_expected_if_blessed:
-ifdef RUSTC_BLESS_TEST
-	rm -f expected_*
-endif
-
--include clear_expected_if_blessed
-
-%: $(SOURCEDIR)/lib/%.rs
-	# Compile the test library with coverage instrumentation
-	$(RUSTC) $(SOURCEDIR)/lib/$@.rs \
-			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
-			--crate-type rlib -Cinstrument-coverage --target $(TARGET)
-
-%: $(SOURCEDIR)/%.rs
-	# Compile the test program with coverage instrumentation
-	$(RUSTC) $(SOURCEDIR)/$@.rs \
-			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
-			-L "$(TMPDIR)" -Cinstrument-coverage --target $(TARGET)
-
-	# Run it in order to generate some profiling data,
-	# with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
-	# output the coverage stats for this run.
-	LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \
-			$(call RUN,$@) || \
-			( \
-				status=$$?; \
-				grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \
-				( >&2 echo "program exited with an unexpected exit status: $$status"; \
-					false \
-				) \
-			)
-
-	# Run it through rustdoc as well to cover doctests.
-	# `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone
-	# might result in overwritten files and failed tests, as rustdoc spawns each
-	# doctest as its own process, so make sure the filename is as unique as possible.
-	LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \
-			$(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \
-			$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
-			-L "$(TMPDIR)" -Cinstrument-coverage \
-			-Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@
-
-	# Postprocess the profiling data so it can be used by the llvm-cov tool
-	"$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
-			"$(TMPDIR)"/$@*.profraw \
-			-o "$(TMPDIR)"/$@.profdata
-
-	# Generate a coverage report using `llvm-cov show`.
-	"$(LLVM_BIN_DIR)"/llvm-cov show \
-			$(DEBUG_FLAG) \
-			$(LLVM_COV_IGNORE_FILES) \
-			--compilation-dir=. \
-			--Xdemangler="$(RUST_DEMANGLER)" \
-			--show-line-counts-or-regions \
-			--instr-profile="$(TMPDIR)"/$@.profdata \
-			$(call BIN,"$(TMPDIR)"/$@) \
-			$$( \
-				for file in $(TMPDIR)/rustdoc-$@/*/rust_out*; do \
-				[ -x "$$file" ] && printf "%s %s " -object $$file; \
-				done \
-			) \
-		2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \
-		| "$(PYTHON)" $(BASEDIR)/normalize_paths.py \
-		| "$(PYTHON)" $(BASEDIR)/sort_subviews.py \
-		> "$(TMPDIR)"/actual_show_coverage.$@.txt || \
-	( status=$$? ; \
-		>&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \
-		exit $$status \
-	)
-
-ifdef DEBUG_FLAG
-	# The first line (beginning with "Args:" contains hard-coded, build-specific
-	# file paths. Strip that line and keep the remaining lines with counter debug
-	# data.
-	tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \
-		> "$(TMPDIR)"/actual_show_coverage_counters.$@.txt
-endif
-
-ifdef RUSTC_BLESS_TEST
-	cp "$(TMPDIR)"/actual_show_coverage.$@.txt \
-			expected_show_coverage.$@.txt
-else
-	# Compare the show coverage output (`--bless` refreshes `typical` files).
-	#
-	# `llvm-cov show` normally prints instantiation groups in an unpredictable
-	# order, but we have used `sort_subviews.py` to sort them, so we can still
-	# check the output directly with `diff`.
-	#
-	# Some of the test cases are currently not working (since #110393) and have
-	# been marked with `// ignore-llvm-cov-show-diffs` so that they don't fail
-	# the build.
-
-	$(DIFF) \
-		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
-		( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
-			>&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
-		) || \
-		( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \
-			false \
-		)
-endif
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt b/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
deleted file mode 100644
index 82d6fccc271..00000000000
--- a/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-    1|      0|pub fn never_called_function() {
-    2|      0|    println!("I am never called");
-    3|      0|}
-
diff --git a/tests/run-make/coverage-reports/normalize_paths.py b/tests/run-make/coverage-reports/normalize_paths.py
deleted file mode 100755
index e5777ad2512..00000000000
--- a/tests/run-make/coverage-reports/normalize_paths.py
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-import sys
-
-# Normalize file paths in output
-for line in sys.stdin:
-    if line.startswith("..") and line.rstrip().endswith(".rs:"):
-        print(line.replace("\\", "/"), end='')
-    else:
-        print(line, end='')
diff --git a/tests/run-make/coverage-reports/sort_subviews.py b/tests/run-make/coverage-reports/sort_subviews.py
deleted file mode 100755
index 10cfc51d447..00000000000
--- a/tests/run-make/coverage-reports/sort_subviews.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python3
-
-# `llvm-cov show` prints grouped subviews (e.g. for generic functions) in an
-# unstable order, which is inconvenient when checking output snapshots with
-# `diff`. To work around that, this script detects consecutive subviews in its
-# piped input, and sorts them while preserving their contents.
-
-from __future__ import print_function
-
-import sys
-
-
-def main():
-    subviews = []
-
-    def flush_subviews():
-        if not subviews:
-            return
-
-        # The last "subview" should be just a boundary line on its own, so
-        # temporarily remove it before sorting the accumulated subviews.
-        terminator = subviews.pop()
-        subviews.sort()
-        subviews.append(terminator)
-
-        for view in subviews:
-            for line in view:
-                print(line, end="")
-
-        subviews.clear()
-
-    for line in sys.stdin:
-        if line.startswith("  ------------------"):
-            # This is a subview boundary line, so start a new subview.
-            subviews.append([line])
-        elif line.startswith("  |"):
-            # Add this line to the current subview.
-            subviews[-1].append(line)
-        else:
-            # This line is not part of a subview, so sort and print any
-            # accumulated subviews, and then print the line as-is.
-            flush_subviews()
-            print(line, end="")
-
-    flush_subviews()
-    assert not subviews
-
-
-if __name__ == "__main__":
-    main()
diff --git a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt b/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
deleted file mode 100644
index 6a1403b8a00..00000000000
--- a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-IMPORTANT: The Rust test programs in this directory generate various output
-files in the `../coverage*` directories (`expected` and `actual` files).
-
-Microsoft Windows has a relatively short limit on file paths (not individual
-path components, but the entire path). The files generated by these
-`../coverage*` tests typically have file paths that include the program
-source file name plus function and type names (depending on the program).
-
-Keep the test file names short, and keep function names and other symbols
-short as well, to avoid hitting the Windows limits.
diff --git a/tests/run-make/coverage/compiletest-ignore-dir b/tests/run-make/coverage/compiletest-ignore-dir
deleted file mode 100644
index 470ff996098..00000000000
--- a/tests/run-make/coverage/compiletest-ignore-dir
+++ /dev/null
@@ -1,3 +0,0 @@
-# Directory "coverage" supports the tests at prefix ../coverage-*
-
-# Use ./x.py [options] test tests/run-make/coverage to run all related tests.
diff --git a/tests/run-make/coverage/coverage_tools.mk b/tests/run-make/coverage/coverage_tools.mk
deleted file mode 100644
index 028c020a461..00000000000
--- a/tests/run-make/coverage/coverage_tools.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# Common Makefile include for Rust `run-make/coverage-* tests. Include this
-# file with the line:
-#
-# include ../coverage/coverage_tools.mk
-
-include ../tools.mk
diff --git a/tests/run-make/optimization-remarks-dir/Makefile b/tests/run-make/optimization-remarks-dir/Makefile
new file mode 100644
index 00000000000..a8342c8ad14
--- /dev/null
+++ b/tests/run-make/optimization-remarks-dir/Makefile
@@ -0,0 +1,12 @@
+include ../tools.mk
+
+PROFILE_DIR=$(TMPDIR)/profiles
+
+all: check_inline check_filter
+
+check_inline:
+	$(RUSTC) -O foo.rs --crate-type=lib -Cremark=all -Zremark-dir=$(PROFILE_DIR)
+	cat $(PROFILE_DIR)/*.opt.yaml | $(CGREP) -e "inline"
+check_filter:
+	$(RUSTC) -O foo.rs --crate-type=lib -Cremark=foo -Zremark-dir=$(PROFILE_DIR)
+	cat $(PROFILE_DIR)/*.opt.yaml | $(CGREP) -e -v "inline"
diff --git a/tests/run-make/optimization-remarks-dir/foo.rs b/tests/run-make/optimization-remarks-dir/foo.rs
new file mode 100644
index 00000000000..6ac3af0dcad
--- /dev/null
+++ b/tests/run-make/optimization-remarks-dir/foo.rs
@@ -0,0 +1,6 @@
+#[inline(never)]
+pub fn bar() {}
+
+pub fn foo() {
+    bar();
+}
diff --git a/tests/run-make/rust-lld/Makefile b/tests/run-make/rust-lld/Makefile
new file mode 100644
index 00000000000..f8526530d4d
--- /dev/null
+++ b/tests/run-make/rust-lld/Makefile
@@ -0,0 +1,8 @@
+include ../tools.mk
+
+# ignore-msvc
+# needs-rust-lld
+# ignore-s390x lld does not yet support s390x as target
+all:
+	RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Clink-self-contained=+linker -Clinker-flavor=gnu-lld-cc -Zunstable-options -Clink-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
+	$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/tests/run-make/rust-lld/main.rs b/tests/run-make/rust-lld/main.rs
new file mode 100644
index 00000000000..bf159cd941c
--- /dev/null
+++ b/tests/run-make/rust-lld/main.rs
@@ -0,0 +1,4 @@
+// Test linking using `cc` with `rust-lld`, using the unstable CLI described in MCP 510
+// see https://github.com/rust-lang/compiler-team/issues/510 for more info
+
+fn main() {}
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index 371931d51fc..e10bb538f07 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -175,11 +175,11 @@ call-function: (
     "check-colors",
     {
         "theme": "ayu",
-        "link_color": "rgb(57, 175, 215)",
-        "content_color": "rgb(230, 225, 207)",
-        "header_color": "rgb(255, 255, 255)",
-        "type_color": "rgb(255, 160, 165)",
-        "trait_color": "rgb(57, 175, 215)",
+        "link_color": "#39afd7",
+        "content_color": "#e6e1cf",
+        "header_color": "#fff",
+        "type_color": "#ffa0a5",
+        "trait_color": "#39afd7",
     },
 )
 
@@ -187,11 +187,11 @@ call-function: (
     "check-colors",
     {
         "theme": "dark",
-        "link_color": "rgb(210, 153, 29)",
-        "content_color": "rgb(221, 221, 221)",
-        "header_color": "rgb(221, 221, 221)",
-        "type_color": "rgb(45, 191, 184)",
-        "trait_color": "rgb(183, 140, 242)",
+        "link_color": "#d2991d",
+        "content_color": "#ddd",
+        "header_color": "#ddd",
+        "type_color": "#2dbfb8",
+        "trait_color": "#b78cf2",
     },
 )
 
@@ -199,11 +199,11 @@ call-function: (
     "check-colors",
     {
         "theme": "light",
-        "link_color": "rgb(56, 115, 173)",
-        "content_color": "rgb(0, 0, 0)",
-        "header_color": "rgb(0, 0, 0)",
-        "type_color": "rgb(173, 55, 138)",
-        "trait_color": "rgb(110, 79, 201)",
+        "link_color": "#3873ad",
+        "content_color": "black",
+        "header_color": "black",
+        "type_color": "#ad378a",
+        "trait_color": "#6e4fc9",
     },
 )
 
diff --git a/tests/rustdoc-gui/search-filter.goml b/tests/rustdoc-gui/search-filter.goml
index d739471a625..9e2855b5e02 100644
--- a/tests/rustdoc-gui/search-filter.goml
+++ b/tests/rustdoc-gui/search-filter.goml
@@ -65,9 +65,9 @@ reload:
 set-timeout: 2000
 wait-for: "#crate-search"
 assert-css: ("#crate-search", {
-    "border": "1px solid rgb(224, 224, 224)",
-    "color": "rgb(0, 0, 0)",
-    "background-color": "rgb(255, 255, 255)",
+    "border": "1px solid #e0e0e0",
+    "color": "black",
+    "background-color": "white",
 })
 
 // We now check the dark theme.
@@ -75,15 +75,15 @@ click: "#settings-menu"
 wait-for: "#settings"
 click: "#theme-dark"
 wait-for-css: ("#crate-search", {
-    "border": "1px solid rgb(224, 224, 224)",
-    "color": "rgb(221, 221, 221)",
-    "background-color": "rgb(53, 53, 53)",
+    "border": "1px solid #e0e0e0",
+    "color": "#ddd",
+    "background-color": "#353535",
 })
 
 // And finally we check the ayu theme.
 click: "#theme-ayu"
 wait-for-css: ("#crate-search", {
-    "border": "1px solid rgb(92, 103, 115)",
-    "color": "rgb(255, 255, 255)",
-    "background-color": "rgb(15, 20, 25)",
+    "border": "1px solid #5c6773",
+    "color": "#fff",
+    "background-color": "#0f1419",
 })
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index e3c628b366f..7a7785fd9ac 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -61,7 +61,7 @@ assert-css: (
     {"color": "#c5c5c5"},
 )
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']",
+    "//*[@class='result-name']//*[text()='test_docs::']",
     {"color": "#0096cf"},
 )
 
@@ -138,7 +138,7 @@ call-function: (
 move-cursor-to: ".search-input"
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a",
     {"color": "#0096cf", "background-color": "transparent"},
     ALL,
 )
@@ -146,11 +146,11 @@ assert-css: (
 // Checking color and background on hover.
 move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']"
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']",
+    "//*[@class='result-name']//*[text()='test_docs::']",
     {"color": "#fff"},
 )
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a",
     {"color": "#fff", "background-color": "rgb(60, 60, 60)"},
 )
 
@@ -173,7 +173,7 @@ assert-css: (
     {"color": "#ddd"},
 )
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']",
+    "//*[@class='result-name']//*[text()='test_docs::']",
     {"color": "#ddd"},
 )
 
@@ -250,7 +250,7 @@ call-function: (
 move-cursor-to: ".search-input"
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a",
     {"color": "#ddd", "background-color": "transparent"},
 )
 
@@ -270,7 +270,7 @@ assert-css: (
     {"color": "#000"},
 )
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']",
+    "//*[@class='result-name']//*[text()='test_docs::']",
     {"color": "#000"},
 )
 
@@ -347,7 +347,7 @@ call-function: (
 move-cursor-to: ".search-input"
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
-    "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
+    "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a",
     {"color": "#000", "background-color": "transparent"},
 )
 
diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml
index 6593c1a9c45..6ce13b8c3d3 100644
--- a/tests/rustdoc-gui/search-result-display.goml
+++ b/tests/rustdoc-gui/search-result-display.goml
@@ -1,3 +1,4 @@
+// ignore-tidy-linelength
 // Checks that the search results have the expected width.
 go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 set-window-size: (900, 1000)
@@ -7,15 +8,41 @@ press-key: 'Enter'
 wait-for: "#crate-search"
 // The width is returned by "getComputedStyle" which returns the exact number instead of the
 // CSS rule which is "50%"...
-assert-size: (".search-results div.desc", {"width": 310})
+assert-size: (".search-results div.desc", {"width": 248})
+store-size: (".search-results .result-name .typename", {"width": width})
 set-window-size: (600, 100)
 // As counter-intuitive as it may seem, in this width, the width is "100%", which is why
 // when computed it's larger.
 assert-size: (".search-results div.desc", {"width": 566})
 
 // The result set is all on one line.
-assert-css: (".search-results .result-name > span:not(.typename)", {"display": "inline"})
-assert-css: (".search-results .result-name > span.typename", {"display": "inline-block"})
+compare-elements-position-near: (
+    ".search-results .result-name .typename",
+    ".search-results .result-name .path",
+    {"y": 2},
+)
+compare-elements-position-near-false: (
+    ".search-results .result-name .typename",
+    ".search-results .result-name .path",
+    {"x": 5},
+)
+// The width of the "typename" isn't fixed anymore in this display mode.
+store-size: (".search-results .result-name .typename", {"width": new_width})
+assert: |new_width| < |width| - 10
+
+// Check that if the search is too long on mobile, it'll go under the "typename".
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName"
+wait-for: "#crate-search"
+compare-elements-position-near: (
+    ".search-results .result-name .typename",
+    ".search-results .result-name .path",
+    {"y": 2, "x": 0},
+)
+compare-elements-size-near: (
+    ".search-results .result-name",
+    ".search-results .result-name .path",
+    {"width": 8, "height": 8},
+)
 
 // Check that the crate filter `<select>` is correctly handled when it goes to next line.
 // To do so we need to update the length of one of its `<option>`.
diff --git a/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml b/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml
index b3f9ae9283f..156d8d03ca2 100644
--- a/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml
+++ b/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml
@@ -55,7 +55,7 @@ assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Return Types"
 
 // Try with a search-by-parameter
 go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
-write: (".search-input", "usize pattern")
+write: (".search-input", "usize,pattern")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index af7f63f99cb..b32bfea5439 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -33,15 +33,24 @@ const PARSED = [
         original: "\"P\" \"P\"",
         returned: [],
         userQuery: "\"p\" \"p\"",
+        error: "Cannot have more than one element if you use quotes",
+    },
+    {
+        query: '"P","P"',
+        elems: [],
+        foundElems: 0,
+        original: "\"P\",\"P\"",
+        returned: [],
+        userQuery: "\"p\",\"p\"",
         error: "Cannot have more than one literal search element",
     },
     {
-        query: 'P "P"',
+        query: "P,\"P\"",
         elems: [],
         foundElems: 0,
-        original: "P \"P\"",
+        original: "P,\"P\"",
         returned: [],
-        userQuery: "p \"p\"",
+        userQuery: "p,\"p\"",
         error: "Cannot use literal search when there is more than one element",
     },
     {
@@ -51,7 +60,16 @@ const PARSED = [
         original: "\"p\" p",
         returned: [],
         userQuery: "\"p\" p",
-        error: "You cannot have more than one element if you use quotes",
+        error: "Cannot have more than one element if you use quotes",
+    },
+    {
+        query: '"p",p',
+        elems: [],
+        foundElems: 0,
+        original: "\"p\",p",
+        returned: [],
+        userQuery: "\"p\",p",
+        error: "Cannot have more than one element if you use quotes",
     },
     {
         query: '"const": p',
@@ -60,7 +78,7 @@ const PARSED = [
         original: "\"const\": p",
         returned: [],
         userQuery: "\"const\": p",
-        error: "You cannot use quotes on type filter",
+        error: "Cannot use quotes on type filter",
     },
     {
         query: "a<:a>",
@@ -108,6 +126,15 @@ const PARSED = [
         error: "Paths cannot start with `::`",
     },
     {
+        query: " ::a::b",
+        elems: [],
+        foundElems: 0,
+        original: "::a::b",
+        returned: [],
+        userQuery: "::a::b",
+        error: "Paths cannot start with `::`",
+    },
+    {
         query: "a::::b",
         elems: [],
         foundElems: 0,
@@ -135,13 +162,13 @@ const PARSED = [
         error: "Expected type filter before `:`",
     },
     {
-        query: "a b:",
+        query: "a,b:",
         elems: [],
         foundElems: 0,
-        original: "a b:",
+        original: "a,b:",
         returned: [],
-        userQuery: "a b:",
-        error: "Unexpected `:` (expected path after type filter)",
+        userQuery: "a,b:",
+        error: "Unexpected `:` (expected path after type filter `b:`)",
     },
     {
         query: "a (b:",
@@ -159,7 +186,7 @@ const PARSED = [
         original: "_:",
         returned: [],
         userQuery: "_:",
-        error: "Unexpected `:` (expected path after type filter)",
+        error: "Unexpected `:` (expected path after type filter `_:`)",
     },
     {
         query: "_:a",
@@ -213,6 +240,15 @@ const PARSED = [
         original: '"p" <a>',
         returned: [],
         userQuery: '"p" <a>',
+        error: "Cannot have more than one element if you use quotes",
+    },
+    {
+        query: '"p",<a>',
+        elems: [],
+        foundElems: 0,
+        original: '"p",<a>',
+        returned: [],
+        userQuery: '"p",<a>',
         error: "Found generics without a path",
     },
     {
@@ -222,7 +258,16 @@ const PARSED = [
         original: '"p" a<a>',
         returned: [],
         userQuery: '"p" a<a>',
-        error: "You cannot have more than one element if you use quotes",
+        error: "Cannot have more than one element if you use quotes",
+    },
+    {
+        query: '"p",a<a>',
+        elems: [],
+        foundElems: 0,
+        original: '"p",a<a>',
+        returned: [],
+        userQuery: '"p",a<a>',
+        error: "Cannot have more than one element if you use quotes",
     },
     {
         query: "a,<",
@@ -240,7 +285,7 @@ const PARSED = [
         original: 'aaaaa<>b',
         returned: [],
         userQuery: 'aaaaa<>b',
-        error: 'Expected `,`, ` `, `:` or `->`, found `b`',
+        error: 'Expected `,`, `:` or `->` after `>`, found `b`',
     },
     {
         query: "fn:aaaaa<>b",
@@ -249,7 +294,7 @@ const PARSED = [
         original: 'fn:aaaaa<>b',
         returned: [],
         userQuery: 'fn:aaaaa<>b',
-        error: 'Expected `,`, ` `, `:` or `->`, found `b`',
+        error: 'Expected `,`, `:` or `->` after `>`, found `b`',
     },
     {
         query: "->a<>b",
@@ -258,7 +303,7 @@ const PARSED = [
         original: '->a<>b',
         returned: [],
         userQuery: '->a<>b',
-        error: 'Expected `,` or ` `, found `b`',
+        error: 'Expected `,` after `>`, found `b`',
     },
     {
         query: "a<->",
@@ -276,7 +321,7 @@ const PARSED = [
         original: 'a:: a',
         returned: [],
         userQuery: 'a:: a',
-        error: 'Paths cannot end with `::`',
+        error: 'Unexpected `:: `',
     },
     {
         query: "a ::a",
@@ -285,7 +330,7 @@ const PARSED = [
         original: 'a ::a',
         returned: [],
         userQuery: 'a ::a',
-        error: 'Paths cannot start with `::`',
+        error: 'Unexpected ` ::`',
     },
     {
         query: "a<a>:",
@@ -294,7 +339,7 @@ const PARSED = [
         original: "a<a>:",
         returned: [],
         userQuery: "a<a>:",
-        error: 'Unexpected `<` in type filter',
+        error: 'Unexpected `<` in type filter (before `:`)',
     },
     {
         query: "a<>:",
@@ -303,7 +348,7 @@ const PARSED = [
         original: "a<>:",
         returned: [],
         userQuery: "a<>:",
-        error: 'Unexpected `<` in type filter',
+        error: 'Unexpected `<` in type filter (before `:`)',
     },
     {
         query: "a,:",
@@ -312,7 +357,7 @@ const PARSED = [
         original: "a,:",
         returned: [],
         userQuery: "a,:",
-        error: 'Unexpected `,` in type filter',
+        error: 'Unexpected `,` in type filter (before `:`)',
     },
     {
         query: "  a<>  :",
@@ -321,7 +366,7 @@ const PARSED = [
         original: "a<>  :",
         returned: [],
         userQuery: "a<>  :",
-        error: 'Unexpected `<` in type filter',
+        error: 'Unexpected `<` in type filter (before `:`)',
     },
     {
         query: "mod : :",
@@ -330,7 +375,16 @@ const PARSED = [
         original: "mod : :",
         returned: [],
         userQuery: "mod : :",
-        error: 'Unexpected `:`',
+        error: 'Unexpected `:` (expected path after type filter `mod:`)',
+    },
+    {
+        query: "mod: :",
+        elems: [],
+        foundElems: 0,
+        original: "mod: :",
+        returned: [],
+        userQuery: "mod: :",
+        error: 'Unexpected `:` (expected path after type filter `mod:`)',
     },
     {
         query: "a!a",
@@ -386,4 +440,108 @@ const PARSED = [
         userQuery: "a<",
         error: "Unclosed `<`",
     },
+    {
+        query: "p<x> , y",
+        elems: [
+            {
+                name: "p",
+                fullPath: ["p"],
+                pathWithoutLast: [],
+                pathLast: "p",
+                generics: [
+                    {
+                        name: "x",
+                        fullPath: ["x"],
+                        pathWithoutLast: [],
+                        pathLast: "x",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: -1,
+            },
+            {
+                name: "y",
+                fullPath: ["y"],
+                pathWithoutLast: [],
+                pathLast: "y",
+                generics: [],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 2,
+        original: "p<x> , y",
+        returned: [],
+        userQuery: "p<x> , y",
+        error: null,
+    },
+    {
+        query: "p<x , y>",
+        elems: [
+            {
+                name: "p",
+                fullPath: ["p"],
+                pathWithoutLast: [],
+                pathLast: "p",
+                generics: [
+                    {
+                        name: "x",
+                        fullPath: ["x"],
+                        pathWithoutLast: [],
+                        pathLast: "x",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                    {
+                        name: "y",
+                        fullPath: ["y"],
+                        pathWithoutLast: [],
+                        pathLast: "y",
+                        generics: [],
+                        typeFilter: -1,
+                    },
+                ],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 1,
+        original: "p<x , y>",
+        returned: [],
+        userQuery: "p<x , y>",
+        error: null,
+    },
+    {
+        query: "p ,x , y",
+        elems: [
+            {
+                name: "p",
+                fullPath: ["p"],
+                pathWithoutLast: [],
+                pathLast: "p",
+                generics: [],
+                typeFilter: -1,
+            },
+            {
+                name: "x",
+                fullPath: ["x"],
+                pathWithoutLast: [],
+                pathLast: "x",
+                generics: [],
+                typeFilter: -1,
+            },
+            {
+                name: "y",
+                fullPath: ["y"],
+                pathWithoutLast: [],
+                pathLast: "y",
+                generics: [],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 3,
+        original: "p ,x , y",
+        returned: [],
+        userQuery: "p ,x , y",
+        error: null,
+    },
 ];
diff --git a/tests/rustdoc-js-std/parser-filter.js b/tests/rustdoc-js-std/parser-filter.js
index 6f5d66e57ba..3b9cc5b1bf0 100644
--- a/tests/rustdoc-js-std/parser-filter.js
+++ b/tests/rustdoc-js-std/parser-filter.js
@@ -38,7 +38,7 @@ const PARSED = [
         original: "macro<f>:foo",
         returned: [],
         userQuery: "macro<f>:foo",
-        error: "Unexpected `<` in type filter",
+        error: "Unexpected `<` in type filter (before `:`)",
     },
     {
         query: 'macro!',
diff --git a/tests/rustdoc-js-std/parser-generics.js b/tests/rustdoc-js-std/parser-generics.js
index eb3cf455155..726ee56c2c1 100644
--- a/tests/rustdoc-js-std/parser-generics.js
+++ b/tests/rustdoc-js-std/parser-generics.js
@@ -9,7 +9,7 @@ const PARSED = [
         error: 'Unclosed `<`',
     },
     {
-        query: 'p<> u8',
+        query: 'p<>,u8',
         elems: [
             {
                 name: "p",
@@ -29,9 +29,9 @@ const PARSED = [
             },
         ],
         foundElems: 2,
-        original: "p<> u8",
+        original: "p<>,u8",
         returned: [],
-        userQuery: "p<> u8",
+        userQuery: "p<>,u8",
         error: null,
     },
     {
diff --git a/tests/rustdoc-js-std/parser-quote.js b/tests/rustdoc-js-std/parser-quote.js
index 9d2a3620ed7..731673cf463 100644
--- a/tests/rustdoc-js-std/parser-quote.js
+++ b/tests/rustdoc-js-std/parser-quote.js
@@ -38,7 +38,7 @@ const PARSED = [
         original: '"p" -> a',
         returned: [],
         userQuery: '"p" -> a',
-        error: "You cannot have more than one element if you use quotes",
+        error: "Cannot have more than one element if you use quotes",
     },
     {
         query: '"a" -> "p"',
diff --git a/tests/rustdoc-js-std/parser-separators.js b/tests/rustdoc-js-std/parser-separators.js
index 69f9ac29ad3..00c489b51a6 100644
--- a/tests/rustdoc-js-std/parser-separators.js
+++ b/tests/rustdoc-js-std/parser-separators.js
@@ -5,6 +5,24 @@ const PARSED = [
         query: 'aaaaaa	b',
         elems: [
             {
+                name: 'aaaaaa\tb',
+                fullPath: ['aaaaaa', 'b'],
+                pathWithoutLast: ['aaaaaa'],
+                pathLast: 'b',
+                generics: [],
+                typeFilter: -1,
+            },
+        ],
+        foundElems: 1,
+        original: "aaaaaa	b",
+        returned: [],
+        userQuery: "aaaaaa	b",
+        error: null,
+    },
+    {
+        query: "aaaaaa,	b",
+        elems: [
+            {
                 name: 'aaaaaa',
                 fullPath: ['aaaaaa'],
                 pathWithoutLast: [],
@@ -22,32 +40,24 @@ const PARSED = [
             },
         ],
         foundElems: 2,
-        original: "aaaaaa	b",
+        original: "aaaaaa,	b",
         returned: [],
-        userQuery: "aaaaaa	b",
+        userQuery: "aaaaaa,	b",
         error: null,
     },
     {
         query: 'a b',
         elems: [
             {
-                name: 'a',
-                fullPath: ['a'],
-                pathWithoutLast: [],
-                pathLast: 'a',
-                generics: [],
-                typeFilter: -1,
-            },
-            {
-                name: 'b',
-                fullPath: ['b'],
-                pathWithoutLast: [],
+                name: 'a b',
+                fullPath: ['a', 'b'],
+                pathWithoutLast: ['a'],
                 pathLast: 'b',
                 generics: [],
                 typeFilter: -1,
             },
         ],
-        foundElems: 2,
+        foundElems: 1,
         original: "a b",
         returned: [],
         userQuery: "a b",
@@ -83,23 +93,15 @@ const PARSED = [
         query: 'a\tb',
         elems: [
             {
-                name: 'a',
-                fullPath: ['a'],
-                pathWithoutLast: [],
-                pathLast: 'a',
-                generics: [],
-                typeFilter: -1,
-            },
-            {
-                name: 'b',
-                fullPath: ['b'],
-                pathWithoutLast: [],
+                name: 'a\tb',
+                fullPath: ['a', 'b'],
+                pathWithoutLast: ['a'],
                 pathLast: 'b',
                 generics: [],
                 typeFilter: -1,
             },
         ],
-        foundElems: 2,
+        foundElems: 1,
         original: "a\tb",
         returned: [],
         userQuery: "a\tb",
@@ -115,16 +117,9 @@ const PARSED = [
                 pathLast: 'a',
                 generics: [
                     {
-                        name: 'b',
-                        fullPath: ['b'],
-                        pathWithoutLast: [],
-                        pathLast: 'b',
-                        generics: [],
-                    },
-                    {
-                        name: 'c',
-                        fullPath: ['c'],
-                        pathWithoutLast: [],
+                        name: 'b c',
+                        fullPath: ['b', 'c'],
+                        pathWithoutLast: ['b'],
                         pathLast: 'c',
                         generics: [],
                     },
@@ -181,16 +176,9 @@ const PARSED = [
                 pathLast: 'a',
                 generics: [
                     {
-                        name: 'b',
-                        fullPath: ['b'],
-                        pathWithoutLast: [],
-                        pathLast: 'b',
-                        generics: [],
-                    },
-                    {
-                        name: 'c',
-                        fullPath: ['c'],
-                        pathWithoutLast: [],
+                        name: 'b\tc',
+                        fullPath: ['b', 'c'],
+                        pathWithoutLast: ['b'],
                         pathLast: 'c',
                         generics: [],
                     },
diff --git a/tests/rustdoc-js-std/parser-slice-array.js b/tests/rustdoc-js-std/parser-slice-array.js
index f85dd199741..c22b7870dbf 100644
--- a/tests/rustdoc-js-std/parser-slice-array.js
+++ b/tests/rustdoc-js-std/parser-slice-array.js
@@ -62,7 +62,7 @@ const PARSED = [
         error: null,
     },
     {
-        query: '[] u8',
+        query: '[],u8',
         elems: [
             {
                 name: "[]",
@@ -82,9 +82,9 @@ const PARSED = [
             },
         ],
         foundElems: 2,
-        original: "[] u8",
+        original: "[],u8",
         returned: [],
-        userQuery: "[] u8",
+        userQuery: "[],u8",
         error: null,
     },
     {
diff --git a/tests/rustdoc-js-std/parser-weird-queries.js b/tests/rustdoc-js-std/parser-weird-queries.js
index 0e08eaf73c8..720ef66c165 100644
--- a/tests/rustdoc-js-std/parser-weird-queries.js
+++ b/tests/rustdoc-js-std/parser-weird-queries.js
@@ -7,23 +7,14 @@ const PARSED = [
         query: 'a b',
         elems: [
             {
-                name: "a",
-                fullPath: ["a"],
-                pathWithoutLast: [],
-                pathLast: "a",
-                generics: [],
-                typeFilter: -1,
-            },
-            {
-                name: "b",
-                fullPath: ["b"],
-                pathWithoutLast: [],
+                name: "a b",
+                fullPath: ["a", "b"],
+                pathWithoutLast: ["a"],
                 pathLast: "b",
                 generics: [],
-                typeFilter: -1,
             },
         ],
-        foundElems: 2,
+        foundElems: 1,
         original: "a b",
         returned: [],
         userQuery: "a b",
@@ -33,23 +24,14 @@ const PARSED = [
         query: 'a   b',
         elems: [
             {
-                name: "a",
-                fullPath: ["a"],
-                pathWithoutLast: [],
-                pathLast: "a",
-                generics: [],
-                typeFilter: -1,
-            },
-            {
-                name: "b",
-                fullPath: ["b"],
-                pathWithoutLast: [],
+                name: "a   b",
+                fullPath: ["a", "b"],
+                pathWithoutLast: ["a"],
                 pathLast: "b",
                 generics: [],
-                typeFilter: -1,
             },
         ],
-        foundElems: 2,
+        foundElems: 1,
         original: "a   b",
         returned: [],
         userQuery: "a   b",
@@ -73,7 +55,6 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "aaa",
                 generics: [],
-                typeFilter: -1,
             },
             {
                 name: "a",
@@ -81,7 +62,6 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "a",
                 generics: [],
-                typeFilter: -1,
             },
         ],
         foundElems: 2,
@@ -106,7 +86,7 @@ const PARSED = [
         original: 'mod    :',
         returned: [],
         userQuery: 'mod    :',
-        error: "Unexpected `:` (expected path after type filter)",
+        error: "Unexpected `:` (expected path after type filter `mod:`)",
     },
     {
         query: 'mod\t:',
@@ -115,6 +95,6 @@ const PARSED = [
         original: 'mod\t:',
         returned: [],
         userQuery: 'mod\t:',
-        error: "Unexpected `:` (expected path after type filter)",
+        error: "Unexpected `:` (expected path after type filter `mod:`)",
     },
 ];
diff --git a/tests/rustdoc-js-std/vec-new.js b/tests/rustdoc-js-std/vec-new.js
index 309f3543faf..9823a417a5d 100644
--- a/tests/rustdoc-js-std/vec-new.js
+++ b/tests/rustdoc-js-std/vec-new.js
@@ -1,9 +1,20 @@
-const EXPECTED = {
-    'query': 'Vec::new',
-    'others': [
-        { 'path': 'std::vec::Vec', 'name': 'new' },
-        { 'path': 'alloc::vec::Vec', 'name': 'new' },
-        { 'path': 'std::vec::Vec', 'name': 'new_in' },
-        { 'path': 'alloc::vec::Vec', 'name': 'new_in' },
-    ],
-};
+const EXPECTED = [
+    {
+        'query': 'Vec::new',
+        'others': [
+            { 'path': 'std::vec::Vec', 'name': 'new' },
+            { 'path': 'alloc::vec::Vec', 'name': 'new' },
+            { 'path': 'std::vec::Vec', 'name': 'new_in' },
+            { 'path': 'alloc::vec::Vec', 'name': 'new_in' },
+        ],
+    },
+    {
+        'query': 'Vec new',
+        'others': [
+            { 'path': 'std::vec::Vec', 'name': 'new' },
+            { 'path': 'alloc::vec::Vec', 'name': 'new' },
+            { 'path': 'std::vec::Vec', 'name': 'new_in' },
+            { 'path': 'alloc::vec::Vec', 'name': 'new_in' },
+        ],
+    },
+];
diff --git a/tests/ui/associated-inherent-types/private-in-public.rs b/tests/ui/associated-inherent-types/private-in-public.rs
index 44a20a79ad6..e9e189f95c9 100644
--- a/tests/ui/associated-inherent-types/private-in-public.rs
+++ b/tests/ui/associated-inherent-types/private-in-public.rs
@@ -1,7 +1,7 @@
 #![feature(inherent_associated_types)]
+#![feature(type_privacy_lints)]
 #![allow(incomplete_features)]
 #![crate_type = "lib"]
-
 #![deny(private_in_public)]
 #![warn(private_interfaces)]
 
@@ -12,12 +12,15 @@
 pub type PubAlias0 = PubTy::PrivAssocTy;
 //~^ ERROR private associated type `PubTy::PrivAssocTy` in public interface (error E0446)
 //~| WARNING this was previously accepted
+//~| WARNING associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0`
 pub type PubAlias1 = PrivTy::PubAssocTy;
 //~^ ERROR private type `PrivTy` in public interface (error E0446)
 //~| WARNING this was previously accepted
+//~| WARNING type `PrivTy` is more private than the item `PubAlias1`
 pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>;
 //~^ ERROR private type `PrivTy` in public interface (error E0446)
 //~| WARNING this was previously accepted
+//~| WARNING type `PrivTy` is more private than the item `PubAlias2`
 
 pub struct PubTy;
 impl PubTy {
diff --git a/tests/ui/associated-inherent-types/private-in-public.stderr b/tests/ui/associated-inherent-types/private-in-public.stderr
index d40db83707b..65d187c1bcd 100644
--- a/tests/ui/associated-inherent-types/private-in-public.stderr
+++ b/tests/ui/associated-inherent-types/private-in-public.stderr
@@ -13,14 +13,13 @@ LL | #![deny(private_in_public)]
    |         ^^^^^^^^^^^^^^^^^
 
 warning: associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0`
-   |
-note: type alias `PubAlias0` is reachable at visibility `pub`
   --> $DIR/private-in-public.rs:12:1
    |
 LL | pub type PubAlias0 = PubTy::PrivAssocTy;
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^ type alias `PubAlias0` is reachable at visibility `pub`
+   |
 note: but associated type `PubTy::PrivAssocTy` is only usable at visibility `pub(crate)`
-  --> $DIR/private-in-public.rs:24:5
+  --> $DIR/private-in-public.rs:27:5
    |
 LL |     type PrivAssocTy = ();
    |     ^^^^^^^^^^^^^^^^
@@ -31,7 +30,7 @@ LL | #![warn(private_interfaces)]
    |         ^^^^^^^^^^^^^^^^^^
 
 error: private type `PrivTy` in public interface (error E0446)
-  --> $DIR/private-in-public.rs:15:1
+  --> $DIR/private-in-public.rs:16:1
    |
 LL | pub type PubAlias1 = PrivTy::PubAssocTy;
    | ^^^^^^^^^^^^^^^^^^
@@ -40,20 +39,19 @@ LL | pub type PubAlias1 = PrivTy::PubAssocTy;
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: type `PrivTy` is more private than the item `PubAlias1`
-   |
-note: type alias `PubAlias1` is reachable at visibility `pub`
-  --> $DIR/private-in-public.rs:15:1
+  --> $DIR/private-in-public.rs:16:1
    |
 LL | pub type PubAlias1 = PrivTy::PubAssocTy;
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^ type alias `PubAlias1` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
-  --> $DIR/private-in-public.rs:28:1
+  --> $DIR/private-in-public.rs:31:1
    |
 LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 error: private type `PrivTy` in public interface (error E0446)
-  --> $DIR/private-in-public.rs:18:1
+  --> $DIR/private-in-public.rs:20:1
    |
 LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>;
    | ^^^^^^^^^^^^^^^^^^
@@ -62,14 +60,13 @@ LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>;
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: type `PrivTy` is more private than the item `PubAlias2`
-   |
-note: type alias `PubAlias2` is reachable at visibility `pub`
-  --> $DIR/private-in-public.rs:18:1
+  --> $DIR/private-in-public.rs:20:1
    |
 LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>;
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^ type alias `PubAlias2` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
-  --> $DIR/private-in-public.rs:28:1
+  --> $DIR/private-in-public.rs:31:1
    |
 LL | struct PrivTy;
    | ^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
index d5481d277e4..9869a8d71c2 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
@@ -1,5 +1,7 @@
 // check-pass
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs
index f298e45d239..ecbd1910ac4 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes.rs
@@ -1,5 +1,7 @@
 // check-pass
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
new file mode 100644
index 00000000000..c4008f2b7e7
--- /dev/null
+++ b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
@@ -0,0 +1,64 @@
+// build-pass
+// edition:2021
+// compile-flags: -Cdebuginfo=2
+
+// We were not normalizing opaques with escaping bound vars during codegen,
+// leading to later errors during debuginfo computation.
+
+#![feature(async_fn_in_trait)]
+
+#[derive(Clone, Copy)]
+pub struct SharedState {}
+
+pub trait State {
+    async fn execute(self, shared_state: &SharedState);
+}
+
+pub trait StateComposer {
+    fn and_then<T, F>(self, map_fn: F) -> AndThen<Self, F>
+    where
+        Self: State + Sized,
+        T: State,
+        F: FnOnce() -> T,
+    {
+        AndThen { previous: self, map_fn }
+    }
+}
+
+impl<T> StateComposer for T where T: State {}
+pub struct AndThen<T, F> {
+    previous: T,
+    map_fn: F,
+}
+
+impl<T, U, F> State for AndThen<T, F>
+where
+    T: State,
+    U: State,
+    F: FnOnce() -> U,
+{
+    async fn execute(self, shared_state: &SharedState)
+    where
+        Self: Sized,
+    {
+        self.previous.execute(shared_state).await;
+        (self.map_fn)().execute(shared_state).await
+    }
+}
+
+pub struct SomeState {}
+
+impl State for SomeState {
+    async fn execute(self, shared_state: &SharedState) {}
+}
+
+pub fn main() {
+    let shared_state = SharedState {};
+    async {
+        SomeState {}
+            .and_then(|| SomeState {})
+            .and_then(|| SomeState {})
+            .execute(&shared_state)
+            .await;
+    };
+}
diff --git a/tests/ui/closures/issue-113087.rs b/tests/ui/closures/issue-113087.rs
new file mode 100644
index 00000000000..a4edc2f2f0b
--- /dev/null
+++ b/tests/ui/closures/issue-113087.rs
@@ -0,0 +1,11 @@
+fn some_fn<'a>(_: &'a i32, _: impl FnOnce(&'a i32)) {}
+
+fn main() {
+    let some_closure = |_| {};
+
+    for a in [1] {
+        some_fn(&a, |c| { //~ ERROR does not live long enough
+            some_closure(c);
+        });
+    }
+}
diff --git a/tests/ui/closures/issue-113087.stderr b/tests/ui/closures/issue-113087.stderr
new file mode 100644
index 00000000000..8ccef4a54f5
--- /dev/null
+++ b/tests/ui/closures/issue-113087.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-113087.rs:7:17
+   |
+LL |     for a in [1] {
+   |         - binding `a` declared here
+LL |         some_fn(&a, |c| {
+   |                 ^^ borrowed value does not live long enough
+LL |             some_closure(c);
+   |             ------------ borrow later captured here by closure
+LL |         });
+LL |     }
+   |     - `a` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
index 96b769699cc..e5464a4253f 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
+++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs
@@ -1,7 +1,7 @@
 #![crate_type = "lib"]
 #![feature(generic_const_exprs)]
+#![feature(type_privacy_lints)]
 #![allow(incomplete_features)]
-
 #![warn(private_interfaces)]
 
 // In this test both old and new private-in-public diagnostic were emitted.
@@ -21,6 +21,7 @@ where
 {
     type AssocTy = Const<{ my_const_fn(U) }>;
     //~^ ERROR private type
+    //~| WARNING type `fn(u8) -> u8 {my_const_fn}` is more private than the item `<Const<U> as Trait>::AssocTy`
     fn assoc_fn() -> Self::AssocTy {
         Const
     }
diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
index 465621619b4..16fae6b5c63 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr
@@ -8,14 +8,13 @@ LL | const fn my_const_fn(val: u8) -> u8 {
    | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
 
 warning: type `fn(u8) -> u8 {my_const_fn}` is more private than the item `<Const<U> as Trait>::AssocTy`
-   |
-note: associated type `<Const<U> as Trait>::AssocTy` is reachable at visibility `pub`
   --> $DIR/eval-privacy.rs:22:5
    |
 LL |     type AssocTy = Const<{ my_const_fn(U) }>;
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ associated type `<Const<U> as Trait>::AssocTy` is reachable at visibility `pub`
+   |
 note: but type `fn(u8) -> u8 {my_const_fn}` is only usable at visibility `pub(crate)`
-  --> $DIR/eval-privacy.rs:29:1
+  --> $DIR/eval-privacy.rs:30:1
    |
 LL | const fn my_const_fn(val: u8) -> u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/error-codes/E0445.rs b/tests/ui/error-codes/E0445.rs
index f5f35fb8a4d..9f29c81673e 100644
--- a/tests/ui/error-codes/E0445.rs
+++ b/tests/ui/error-codes/E0445.rs
@@ -1,3 +1,4 @@
+#![feature(type_privacy_lints)]
 #[warn(private_bounds)]
 #[warn(private_interfaces)]
 
@@ -11,9 +12,12 @@ trait Foo {
 
 pub trait Bar : Foo {}
 //~^ ERROR private trait `Foo` in public interface [E0445]
+//~| WARNING trait `Foo` is more private than the item `Bar`
 pub struct Bar2<T: Foo>(pub T);
 //~^ ERROR private trait `Foo` in public interface [E0445]
+//~| WARNING trait `Foo` is more private than the item `Bar2`
 pub fn foo<T: Foo> (t: T) {}
 //~^ ERROR private trait `Foo` in public interface [E0445]
+//~| WARNING trait `Foo` is more private than the item `foo`
 
 fn main() {}
diff --git a/tests/ui/error-codes/E0445.stderr b/tests/ui/error-codes/E0445.stderr
index ac3637a8218..4f940868ff9 100644
--- a/tests/ui/error-codes/E0445.stderr
+++ b/tests/ui/error-codes/E0445.stderr
@@ -1,5 +1,5 @@
 error[E0445]: private trait `Foo` in public interface
-  --> $DIR/E0445.rs:12:1
+  --> $DIR/E0445.rs:13:1
    |
 LL | trait Foo {
    | --------- `Foo` declared as private
@@ -8,25 +8,24 @@ LL | pub trait Bar : Foo {}
    | ^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 warning: trait `Foo` is more private than the item `Bar`
-   |
-note: trait `Bar` is reachable at visibility `pub`
-  --> $DIR/E0445.rs:12:1
+  --> $DIR/E0445.rs:13:1
    |
 LL | pub trait Bar : Foo {}
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ trait `Bar` is reachable at visibility `pub`
+   |
 note: but trait `Foo` is only usable at visibility `pub(crate)`
-  --> $DIR/E0445.rs:8:1
+  --> $DIR/E0445.rs:9:1
    |
 LL | trait Foo {
    | ^^^^^^^^^
 note: the lint level is defined here
-  --> $DIR/E0445.rs:1:8
+  --> $DIR/E0445.rs:2:8
    |
 LL | #[warn(private_bounds)]
    |        ^^^^^^^^^^^^^^
 
 error[E0445]: private trait `Foo` in public interface
-  --> $DIR/E0445.rs:14:1
+  --> $DIR/E0445.rs:16:1
    |
 LL | trait Foo {
    | --------- `Foo` declared as private
@@ -35,20 +34,19 @@ LL | pub struct Bar2<T: Foo>(pub T);
    | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 warning: trait `Foo` is more private than the item `Bar2`
-   |
-note: struct `Bar2` is reachable at visibility `pub`
-  --> $DIR/E0445.rs:14:1
+  --> $DIR/E0445.rs:16:1
    |
 LL | pub struct Bar2<T: Foo>(pub T);
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^ struct `Bar2` is reachable at visibility `pub`
+   |
 note: but trait `Foo` is only usable at visibility `pub(crate)`
-  --> $DIR/E0445.rs:8:1
+  --> $DIR/E0445.rs:9:1
    |
 LL | trait Foo {
    | ^^^^^^^^^
 
 error[E0445]: private trait `Foo` in public interface
-  --> $DIR/E0445.rs:16:1
+  --> $DIR/E0445.rs:19:1
    |
 LL | trait Foo {
    | --------- `Foo` declared as private
@@ -57,14 +55,13 @@ LL | pub fn foo<T: Foo> (t: T) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
 warning: trait `Foo` is more private than the item `foo`
-   |
-note: function `foo` is reachable at visibility `pub`
-  --> $DIR/E0445.rs:16:1
+  --> $DIR/E0445.rs:19:1
    |
 LL | pub fn foo<T: Foo> (t: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ function `foo` is reachable at visibility `pub`
+   |
 note: but trait `Foo` is only usable at visibility `pub(crate)`
-  --> $DIR/E0445.rs:8:1
+  --> $DIR/E0445.rs:9:1
    |
 LL | trait Foo {
    | ^^^^^^^^^
diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr
index 78341735e19..d9db89ddb0c 100644
--- a/tests/ui/error-codes/E0637.stderr
+++ b/tests/ui/error-codes/E0637.stderr
@@ -22,11 +22,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
 LL |     T: Into<&u32>,
    |             ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/E0637.rs:13:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: Into<&u32>,
-   |        ^
+LL |     T: for<'a> Into<&'a u32>,
+   |        +++++++       ++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs b/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs
new file mode 100644
index 00000000000..aad64c9d073
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-type_privacy_lints.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![warn(private_interfaces)] //~ WARN unknown lint
+                             //~| WARN unknown lint
+                             //~| WARN unknown lint
+#![warn(private_bounds)] //~ WARN unknown lint
+                         //~| WARN unknown lint
+                         //~| WARN unknown lint
+#![warn(unnameable_types)] //~ WARN unknown lint
+                           //~| WARN unknown lint
+                           //~| WARN unknown lint
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr
new file mode 100644
index 00000000000..79cc974cca1
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr
@@ -0,0 +1,93 @@
+warning: unknown lint: `private_interfaces`
+  --> $DIR/feature-gate-type_privacy_lints.rs:3:1
+   |
+LL | #![warn(private_interfaces)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `private_interfaces` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+   = note: `#[warn(unknown_lints)]` on by default
+
+warning: unknown lint: `private_bounds`
+  --> $DIR/feature-gate-type_privacy_lints.rs:6:1
+   |
+LL | #![warn(private_bounds)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `private_bounds` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `unnameable_types`
+  --> $DIR/feature-gate-type_privacy_lints.rs:9:1
+   |
+LL | #![warn(unnameable_types)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `unnameable_types` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `private_interfaces`
+  --> $DIR/feature-gate-type_privacy_lints.rs:3:1
+   |
+LL | #![warn(private_interfaces)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `private_interfaces` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `private_bounds`
+  --> $DIR/feature-gate-type_privacy_lints.rs:6:1
+   |
+LL | #![warn(private_bounds)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `private_bounds` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `unnameable_types`
+  --> $DIR/feature-gate-type_privacy_lints.rs:9:1
+   |
+LL | #![warn(unnameable_types)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `unnameable_types` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `private_interfaces`
+  --> $DIR/feature-gate-type_privacy_lints.rs:3:1
+   |
+LL | #![warn(private_interfaces)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `private_interfaces` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `private_bounds`
+  --> $DIR/feature-gate-type_privacy_lints.rs:6:1
+   |
+LL | #![warn(private_bounds)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `private_bounds` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: unknown lint: `unnameable_types`
+  --> $DIR/feature-gate-type_privacy_lints.rs:9:1
+   |
+LL | #![warn(unnameable_types)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `unnameable_types` lint is unstable
+   = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
+   = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+
+warning: 9 warnings emitted
+
diff --git a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
index faf4c9eb872..bcd1fbc55ed 100644
--- a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
+++ b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -4,11 +4,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
 LL | fn should_error<T>() where T : Into<&u32> {}
    |                                     ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32
+help: consider introducing a higher-ranked lifetime here
    |
-LL | fn should_error<T>() where T : Into<&u32> {}
-   |                                ^
+LL | fn should_error<T>() where T : for<'a> Into<&'a u32> {}
+   |                                +++++++       ++
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20
diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs
index 98417b343a1..b0fbe3a3d4a 100644
--- a/tests/ui/impl-trait/in-trait/foreign.rs
+++ b/tests/ui/impl-trait/in-trait/foreign.rs
@@ -14,6 +14,10 @@ impl Foo for Local {
     fn bar(self) -> Arc<String> { Arc::new(String::new()) }
 }
 
+fn generic(f: impl Foo) {
+    let x = &*f.bar();
+}
+
 fn main() {
     // Witness an RPITIT from another crate.
     let &() = Foreign.bar();
diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr
index f604ada6ac7..239c4b35c72 100644
--- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr
+++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr
@@ -5,7 +5,7 @@ LL |     fn early<'late, T>(_: &'late ()) {}
    |                     -     ^^^^^^^^^
    |                     |     |
    |                     |     expected type parameter `T`, found `()`
-   |                     |     help: change the parameter type to match the trait: `&'early T`
+   |                     |     help: change the parameter type to match the trait: `&T`
    |                     this type parameter
    |
 note: type in trait
@@ -13,8 +13,8 @@ note: type in trait
    |
 LL |     fn early<'early, T>(x: &'early T) -> impl Sized;
    |                            ^^^^^^^^^
-   = note: expected signature `fn(&'early T)`
-              found signature `fn(&())`
+   = note: expected signature `fn(&T)`
+              found signature `fn(&'late ())`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.current.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.current.stderr
index eba270af7f0..8c9dd403174 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.current.stderr
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.current.stderr
@@ -1,16 +1,61 @@
-error: `impl` item signature doesn't match `trait` item signature
-  --> $DIR/signature-mismatch.rs:17:5
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:36:47
+   |
+LL |     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+   |                 -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:17:40
    |
 LL |     fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
-   |     ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
+
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:41:57
+   |
+LL |     fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+   |                       -- this lifetime was captured     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:18:57
+   |
+LL |     fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
+
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:49:10
+   |
+LL |     fn async_fn_multiple<'a, 'b>(
+   |                              -- this lifetime was captured
 ...
-LL |     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
+LL |     ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:20:12
+   |
+LL |         -> impl Future<Output = Vec<u8>> + Captures<'a>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + Captures2<'a, 'b>`
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/signature-mismatch.rs:58:10
+   |
+LL |     ) -> impl Future<Output = Vec<u8>> {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future<Output = Vec<u8>>` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/signature-mismatch.rs:25:42
+   |
+LL |     ) -> impl Future<Output = Vec<u8>> + 'a;
+   |                                          ^^
+help: consider adding an explicit lifetime bound...
    |
-   = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
-              found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
-   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
-   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+LL |     fn async_fn_reduce_outlive<'a, 'b, T: 'a>(
+   |                                         ++++
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.next.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.next.stderr
index eba270af7f0..8c9dd403174 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.next.stderr
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.next.stderr
@@ -1,16 +1,61 @@
-error: `impl` item signature doesn't match `trait` item signature
-  --> $DIR/signature-mismatch.rs:17:5
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:36:47
+   |
+LL |     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+   |                 -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:17:40
    |
 LL |     fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
-   |     ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
+
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:41:57
+   |
+LL |     fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+   |                       -- this lifetime was captured     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:18:57
+   |
+LL |     fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
+
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:49:10
+   |
+LL |     fn async_fn_multiple<'a, 'b>(
+   |                              -- this lifetime was captured
 ...
-LL |     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
+LL |     ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:20:12
+   |
+LL |         -> impl Future<Output = Vec<u8>> + Captures<'a>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + Captures2<'a, 'b>`
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/signature-mismatch.rs:58:10
+   |
+LL |     ) -> impl Future<Output = Vec<u8>> {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future<Output = Vec<u8>>` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/signature-mismatch.rs:25:42
+   |
+LL |     ) -> impl Future<Output = Vec<u8>> + 'a;
+   |                                          ^^
+help: consider adding an explicit lifetime bound...
    |
-   = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
-              found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
-   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
-   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
+LL |     fn async_fn_reduce_outlive<'a, 'b, T: 'a>(
+   |                                         ++++
 
-error: aborting due to previous error
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs
index 38c902a97a9..23dd71acecb 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs
@@ -7,17 +7,70 @@
 
 use std::future::Future;
 
+trait Captures<'a> {}
+impl<T> Captures<'_> for T {}
+
+trait Captures2<'a, 'b> {}
+impl<T> Captures2<'_, '_> for T {}
+
 pub trait AsyncTrait {
     fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
+    fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
+    fn async_fn_multiple<'a>(&'a self, buff: &[u8])
+        -> impl Future<Output = Vec<u8>> + Captures<'a>;
+    fn async_fn_reduce_outlive<'a, T>(
+        &'a self,
+        buff: &[u8],
+        t: T,
+    ) -> impl Future<Output = Vec<u8>> + 'a;
+    fn async_fn_reduce<'a, T>(
+        &'a self,
+        buff: &[u8],
+        t: T,
+    ) -> impl Future<Output = Vec<u8>> + Captures<'a>;
 }
 
 pub struct Struct;
 
 impl AsyncTrait for Struct {
     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
-        //~^ ERROR `impl` item signature doesn't match `trait` item signature
+        //~^ ERROR return type captures more lifetimes than trait definition
+        async move { buff.to_vec() }
+    }
+
+    fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+        //~^ ERROR return type captures more lifetimes than trait definition
+        async move { buff.to_vec() }
+    }
+
+    fn async_fn_multiple<'a, 'b>(
+        &'a self,
+        buff: &'b [u8],
+    ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
+        //~^ ERROR return type captures more lifetimes than trait definition
         async move { buff.to_vec() }
     }
+
+    fn async_fn_reduce_outlive<'a, 'b, T>(
+        &'a self,
+        buff: &'b [u8],
+        t: T,
+    ) -> impl Future<Output = Vec<u8>> {
+        //~^ ERROR the parameter type `T` may not live long enough
+        async move {
+            let _t = t;
+            vec![]
+        }
+    }
+
+    // OK: We remove the `Captures<'a>`, providing a guarantee that we don't capture `'a`,
+    // but we still fulfill the `Captures<'a>` trait bound.
+    fn async_fn_reduce<'a, 'b, T>(&'a self, buff: &'b [u8], t: T) -> impl Future<Output = Vec<u8>> {
+        async move {
+            let _t = t;
+            vec![]
+        }
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/variances-of-gat.rs b/tests/ui/impl-trait/in-trait/variances-of-gat.rs
new file mode 100644
index 00000000000..4008ece94da
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/variances-of-gat.rs
@@ -0,0 +1,19 @@
+// check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
+#![feature(return_position_impl_trait_in_trait)]
+
+trait Foo {}
+
+impl Foo for () {}
+
+trait ThreeCellFragment {
+    fn ext_cells<'a>(&'a self) -> impl Foo + 'a {
+        self.ext_adjacent_cells()
+    }
+
+    fn ext_adjacent_cells<'a>(&'a self) -> impl Foo + 'a;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs
new file mode 100644
index 00000000000..1025c2c7e8a
--- /dev/null
+++ b/tests/ui/impl-trait/normalize-opaque-with-bound-vars.rs
@@ -0,0 +1,27 @@
+// build-pass
+// edition:2021
+// compile-flags: -Cdebuginfo=2
+
+// We were not normalizing opaques with escaping bound vars during codegen,
+// leading to later linker errors because of differences in mangled symbol name.
+
+fn func<T>() -> impl Sized {}
+
+trait Trait<'a> {
+    type Assoc;
+
+    fn call() {
+        let _ = async {
+            let _value = func::<Self::Assoc>();
+            std::future::ready(()).await
+        };
+    }
+}
+
+impl Trait<'static> for () {
+    type Assoc = ();
+}
+
+fn main() {
+    <()>::call();
+}
diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.rs b/tests/ui/impl-trait/universal_wrong_hrtb.rs
index b9551c2ceb0..48561710143 100644
--- a/tests/ui/impl-trait/universal_wrong_hrtb.rs
+++ b/tests/ui/impl-trait/universal_wrong_hrtb.rs
@@ -3,6 +3,6 @@ trait Trait<'a> {
 }
 
 fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
+//~^ ERROR `impl Trait` can only mention lifetimes from an fn or impl
 
 fn main() {}
diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.stderr b/tests/ui/impl-trait/universal_wrong_hrtb.stderr
index 37eb8dfa1a1..b5a091b61fa 100644
--- a/tests/ui/impl-trait/universal_wrong_hrtb.stderr
+++ b/tests/ui/impl-trait/universal_wrong_hrtb.stderr
@@ -1,14 +1,8 @@
-error: `impl Trait` can only mention lifetimes bound at the fn or impl level
+error: `impl Trait` can only mention lifetimes from an fn or impl
   --> $DIR/universal_wrong_hrtb.rs:5:73
    |
 LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-   |                                                                         ^^
-   |
-note: lifetime declared here
-  --> $DIR/universal_wrong_hrtb.rs:5:39
-   |
-LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
-   |                                       ^^
+   |                                       -- lifetime declared here         ^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-1.rs b/tests/ui/imports/auxiliary/issue-85992-extern-1.rs
new file mode 100644
index 00000000000..a2d0e206065
--- /dev/null
+++ b/tests/ui/imports/auxiliary/issue-85992-extern-1.rs
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! m {
+   () => {
+        use issue_85992_extern_2::Outcome;
+   }
+}
diff --git a/tests/ui/imports/auxiliary/issue-85992-extern-2.rs b/tests/ui/imports/auxiliary/issue-85992-extern-2.rs
new file mode 100644
index 00000000000..e9b6a44cfe2
--- /dev/null
+++ b/tests/ui/imports/auxiliary/issue-85992-extern-2.rs
@@ -0,0 +1 @@
+// nothing
diff --git a/tests/ui/imports/issue-56125.stderr b/tests/ui/imports/issue-56125.stderr
index 3448f311977..15477fb6f10 100644
--- a/tests/ui/imports/issue-56125.stderr
+++ b/tests/ui/imports/issue-56125.stderr
@@ -22,7 +22,7 @@ error[E0659]: `issue_56125` is ambiguous
 LL |     use issue_56125::last_segment::*;
    |         ^^^^^^^^^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `issue_56125` could refer to a crate passed with `--extern`
    = help: use `::issue_56125` to refer to this crate unambiguously
 note: `issue_56125` could also refer to the module imported here
@@ -30,7 +30,8 @@ note: `issue_56125` could also refer to the module imported here
    |
 LL |     use issue_56125::last_segment::*;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: use `self::issue_56125` to refer to this module unambiguously
+   = help: consider adding an explicit import of `issue_56125` to disambiguate
+   = help: or use `self::issue_56125` to refer to this module unambiguously
 
 error[E0659]: `issue_56125` is ambiguous
   --> $DIR/issue-56125.rs:11:9
@@ -38,7 +39,7 @@ error[E0659]: `issue_56125` is ambiguous
 LL |     use issue_56125::non_last_segment::non_last_segment::*;
    |         ^^^^^^^^^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `issue_56125` could refer to a crate passed with `--extern`
    = help: use `::issue_56125` to refer to this crate unambiguously
 note: `issue_56125` could also refer to the module imported here
@@ -46,7 +47,8 @@ note: `issue_56125` could also refer to the module imported here
    |
 LL |     use issue_56125::non_last_segment::non_last_segment::*;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: use `self::issue_56125` to refer to this module unambiguously
+   = help: consider adding an explicit import of `issue_56125` to disambiguate
+   = help: or use `self::issue_56125` to refer to this module unambiguously
 
 error[E0659]: `issue_56125` is ambiguous
   --> $DIR/issue-56125.rs:18:9
@@ -54,7 +56,7 @@ error[E0659]: `issue_56125` is ambiguous
 LL |     use issue_56125::*;
    |         ^^^^^^^^^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `issue_56125` could refer to a crate passed with `--extern`
    = help: use `::issue_56125` to refer to this crate unambiguously
 note: `issue_56125` could also refer to the module imported here
@@ -62,7 +64,8 @@ note: `issue_56125` could also refer to the module imported here
    |
 LL |     use issue_56125::*;
    |         ^^^^^^^^^^^^^^
-   = help: use `self::issue_56125` to refer to this module unambiguously
+   = help: consider adding an explicit import of `issue_56125` to disambiguate
+   = help: or use `self::issue_56125` to refer to this module unambiguously
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/imports/issue-57539.stderr b/tests/ui/imports/issue-57539.stderr
index 1a3ca4edaca..88cc42ccf66 100644
--- a/tests/ui/imports/issue-57539.stderr
+++ b/tests/ui/imports/issue-57539.stderr
@@ -4,7 +4,7 @@ error[E0659]: `core` is ambiguous
 LL |     use core;
    |         ^^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `core` could refer to a built-in crate
    = help: use `::core` to refer to this crate unambiguously
 note: `core` could also refer to the module imported here
@@ -12,7 +12,8 @@ note: `core` could also refer to the module imported here
    |
 LL |     use crate::*;
    |         ^^^^^^^^
-   = help: use `self::core` to refer to this module unambiguously
+   = help: consider adding an explicit import of `core` to disambiguate
+   = help: or use `self::core` to refer to this module unambiguously
 
 error: aborting due to previous error
 
diff --git a/tests/ui/imports/issue-85992.rs b/tests/ui/imports/issue-85992.rs
new file mode 100644
index 00000000000..d5524109144
--- /dev/null
+++ b/tests/ui/imports/issue-85992.rs
@@ -0,0 +1,11 @@
+// edition: 2021
+// compile-flags: --extern issue_85992_extern_1 --extern issue_85992_extern_2
+// aux-build: issue-85992-extern-1.rs
+// aux-build: issue-85992-extern-2.rs
+
+issue_85992_extern_1::m!();
+
+use crate::issue_85992_extern_2;
+//~^ ERROR unresolved import `crate::issue_85992_extern_2`
+
+fn main() {}
diff --git a/tests/ui/imports/issue-85992.stderr b/tests/ui/imports/issue-85992.stderr
new file mode 100644
index 00000000000..810d41009c5
--- /dev/null
+++ b/tests/ui/imports/issue-85992.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `crate::issue_85992_extern_2`
+  --> $DIR/issue-85992.rs:8:5
+   |
+LL | use crate::issue_85992_extern_2;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `issue_85992_extern_2` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/issues/issue-18389.rs b/tests/ui/issues/issue-18389.rs
index 3686afc48af..05a5decf462 100644
--- a/tests/ui/issues/issue-18389.rs
+++ b/tests/ui/issues/issue-18389.rs
@@ -1,3 +1,4 @@
+#![feature(type_privacy_lints)]
 #![warn(private_bounds)]
 
 // In this test both old and new private-in-public diagnostic were emitted.
@@ -12,6 +13,7 @@ trait Private<P, R> {
 }
 pub trait Public: Private<
 //~^ ERROR private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
+//~| WARNING trait `Private<<Self as Public>::P, <Self as Public>::R>` is more private than the item `Public`
     <Self as Public>::P,
     <Self as Public>::R
 > {
diff --git a/tests/ui/issues/issue-18389.stderr b/tests/ui/issues/issue-18389.stderr
index f9ebde48a45..18ffc4177d7 100644
--- a/tests/ui/issues/issue-18389.stderr
+++ b/tests/ui/issues/issue-18389.stderr
@@ -1,34 +1,35 @@
 error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
-  --> $DIR/issue-18389.rs:13:1
+  --> $DIR/issue-18389.rs:14:1
    |
 LL |   trait Private<P, R> {
    |   ------------------- `Private<<Self as Public>::P, <Self as Public>::R>` declared as private
 ...
 LL | / pub trait Public: Private<
 LL | |
+LL | |
 LL | |     <Self as Public>::P,
 LL | |     <Self as Public>::R
 LL | | > {
    | |_^ can't leak private trait
 
 warning: trait `Private<<Self as Public>::P, <Self as Public>::R>` is more private than the item `Public`
-   |
-note: trait `Public` is reachable at visibility `pub`
-  --> $DIR/issue-18389.rs:13:1
+  --> $DIR/issue-18389.rs:14:1
    |
 LL | / pub trait Public: Private<
 LL | |
+LL | |
 LL | |     <Self as Public>::P,
 LL | |     <Self as Public>::R
 LL | | > {
-   | |_^
+   | |_^ trait `Public` is reachable at visibility `pub`
+   |
 note: but trait `Private<<Self as Public>::P, <Self as Public>::R>` is only usable at visibility `pub(crate)`
-  --> $DIR/issue-18389.rs:10:1
+  --> $DIR/issue-18389.rs:11:1
    |
 LL | trait Private<P, R> {
    | ^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
-  --> $DIR/issue-18389.rs:1:9
+  --> $DIR/issue-18389.rs:2:9
    |
 LL | #![warn(private_bounds)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/linkage-attr/incompatible-flavor.stderr b/tests/ui/linkage-attr/incompatible-flavor.stderr
index e07e778521c..aabdd14b69b 100644
--- a/tests/ui/linkage-attr/incompatible-flavor.stderr
+++ b/tests/ui/linkage-attr/incompatible-flavor.stderr
@@ -1,6 +1,6 @@
 error: linker flavor `msvc` is incompatible with the current target
    |
-   = note: compatible flavors are: gcc, ld, ld.lld
+   = note: compatible flavors are: gnu, gnu-lld, gnu-cc, gnu-lld-cc, gcc, ld, ld.lld
 
 error: aborting due to previous error
 
diff --git a/tests/ui/linkage-attr/unstable-flavor.bpf.stderr b/tests/ui/linkage-attr/unstable-flavor.bpf.stderr
index 3346d12c20e..594a461769b 100644
--- a/tests/ui/linkage-attr/unstable-flavor.bpf.stderr
+++ b/tests/ui/linkage-attr/unstable-flavor.bpf.stderr
@@ -1,2 +1,2 @@
-error: linker flavor `bpf-linker` is unstable, `-Z unstable-options` flag must also be passed to explicitly use it
+error: the linker flavor `bpf-linker` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values
 
diff --git a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr
index 03ca2a01246..714c09df53f 100644
--- a/tests/ui/linkage-attr/unstable-flavor.ptx.stderr
+++ b/tests/ui/linkage-attr/unstable-flavor.ptx.stderr
@@ -1,2 +1,2 @@
-error: linker flavor `ptx-linker` is unstable, `-Z unstable-options` flag must also be passed to explicitly use it
+error: the linker flavor `ptx-linker` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values
 
diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs
index 5487882dc24..b58fd055fdc 100644
--- a/tests/ui/linkage-attr/unstable-flavor.rs
+++ b/tests/ui/linkage-attr/unstable-flavor.rs
@@ -1,9 +1,13 @@
+// Even though this test only checks 2 of the 10 or so unstable linker flavors, it exercizes the
+// unique codepath checking all unstable options (see `LinkerFlavorCli::is_unstable` and its
+// caller). If it passes, all the other unstable options are rejected as well.
+//
 // revisions: bpf ptx
 // [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf-linker --crate-type=rlib
-// [bpf] error-pattern: linker flavor `bpf-linker` is unstable, `-Z unstable-options` flag
+// [bpf] error-pattern: linker flavor `bpf-linker` is unstable, the `-Z unstable-options` flag
 // [bpf] needs-llvm-components:
 // [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx-linker --crate-type=rlib
-// [ptx] error-pattern: linker flavor `ptx-linker` is unstable, `-Z unstable-options` flag
+// [ptx] error-pattern: linker flavor `ptx-linker` is unstable, the `-Z unstable-options` flag
 // [ptx] needs-llvm-components:
 
 #![feature(no_core)]
diff --git a/tests/ui/lint/dropping_copy_types.rs b/tests/ui/lint/dropping_copy_types.rs
index 2937320e5d8..2412222d6d1 100644
--- a/tests/ui/lint/dropping_copy_types.rs
+++ b/tests/ui/lint/dropping_copy_types.rs
@@ -77,3 +77,22 @@ fn issue9482(x: u8) {
         _ => (),
     }
 }
+
+fn issue112653() {
+    fn foo() -> Result<u8, ()> {
+        println!("doing foo");
+        Ok(0) // result is not always useful, the side-effect matters
+    }
+    fn bar() {
+        println!("doing bar");
+    }
+
+    fn stuff() -> Result<(), ()> {
+        match 42 {
+            0 => drop(foo()?),  // drop is needed because we only care about side-effects
+            1 => bar(),
+            _ => (),  // doing nothing (no side-effects needed here)
+        }
+        Ok(())
+    }
+}
diff --git a/tests/ui/lint/dropping_references.rs b/tests/ui/lint/dropping_references.rs
index 0d5d484f451..bb02cb75a90 100644
--- a/tests/ui/lint/dropping_references.rs
+++ b/tests/ui/lint/dropping_references.rs
@@ -97,3 +97,22 @@ fn issue10122(x: u8) {
         _ => (),
     }
 }
+
+fn issue112653() {
+    fn foo() -> Result<&'static u8, ()> {
+        println!("doing foo");
+        Ok(&0) // result is not always useful, the side-effect matters
+    }
+    fn bar() {
+        println!("doing bar");
+    }
+
+    fn stuff() -> Result<(), ()> {
+        match 42 {
+            0 => drop(foo()?),  // drop is needed because we only care about side-effects
+            1 => bar(),
+            _ => (),  // doing nothing (no side-effects needed here)
+        }
+        Ok(())
+    }
+}
diff --git a/tests/ui/match/issue-113012.rs b/tests/ui/match/issue-113012.rs
new file mode 100644
index 00000000000..da7a8b65b97
--- /dev/null
+++ b/tests/ui/match/issue-113012.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+#![allow(dead_code)]
+struct Foo(());
+
+const FOO: Foo = Foo(match 0 {
+    0.. => (),
+    _ => (),
+});
+
+fn main() {
+}
diff --git a/tests/ui/privacy/effective_visibilities_full_priv.rs b/tests/ui/privacy/effective_visibilities_full_priv.rs
index cc708917586..a26ae3bd122 100644
--- a/tests/ui/privacy/effective_visibilities_full_priv.rs
+++ b/tests/ui/privacy/effective_visibilities_full_priv.rs
@@ -6,7 +6,7 @@ struct SemiPriv;
 mod m {
     #[rustc_effective_visibility]
     struct Priv;
-    //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+    //~^ ERROR not in the table
     //~| ERROR not in the table
 
     #[rustc_effective_visibility]
diff --git a/tests/ui/privacy/effective_visibilities_full_priv.stderr b/tests/ui/privacy/effective_visibilities_full_priv.stderr
index a856aa20d92..29d82e2ee01 100644
--- a/tests/ui/privacy/effective_visibilities_full_priv.stderr
+++ b/tests/ui/privacy/effective_visibilities_full_priv.stderr
@@ -1,4 +1,4 @@
-error: Direct: pub(self), Reexported: pub(self), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+error: not in the table
   --> $DIR/effective_visibilities_full_priv.rs:8:5
    |
 LL |     struct Priv;
diff --git a/tests/ui/privacy/private-in-public-non-principal.rs b/tests/ui/privacy/private-in-public-non-principal.rs
index a80c1541463..a2284c93027 100644
--- a/tests/ui/privacy/private-in-public-non-principal.rs
+++ b/tests/ui/privacy/private-in-public-non-principal.rs
@@ -1,6 +1,6 @@
 #![feature(auto_traits)]
 #![feature(negative_impls)]
-
+#![feature(type_privacy_lints)]
 #![deny(private_interfaces)]
 
 // In this test both old and new private-in-public diagnostic were emitted.
@@ -13,6 +13,7 @@ auto trait PrivNonPrincipal {}
 pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
 //~^ WARN private trait `PrivNonPrincipal` in public interface
 //~| WARN this was previously accepted
+//~| ERROR trait `PrivNonPrincipal` is more private than the item `leak_dyn_nonprincipal`
 
 #[deny(missing_docs)]
 fn container() {
diff --git a/tests/ui/privacy/private-in-public-non-principal.stderr b/tests/ui/privacy/private-in-public-non-principal.stderr
index 9fc12affe4b..1387f59cbde 100644
--- a/tests/ui/privacy/private-in-public-non-principal.stderr
+++ b/tests/ui/privacy/private-in-public-non-principal.stderr
@@ -9,12 +9,11 @@ LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal>
    = note: `#[warn(private_in_public)]` on by default
 
 error: trait `PrivNonPrincipal` is more private than the item `leak_dyn_nonprincipal`
-   |
-note: function `leak_dyn_nonprincipal` is reachable at visibility `pub`
   --> $DIR/private-in-public-non-principal.rs:13:1
    |
 LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `leak_dyn_nonprincipal` is reachable at visibility `pub`
+   |
 note: but trait `PrivNonPrincipal` is only usable at visibility `pub(crate)`
   --> $DIR/private-in-public-non-principal.rs:11:1
    |
@@ -27,13 +26,13 @@ LL | #![deny(private_interfaces)]
    |         ^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for an associated function
-  --> $DIR/private-in-public-non-principal.rs:20:9
+  --> $DIR/private-in-public-non-principal.rs:21:9
    |
 LL |         pub fn check_doc_lint() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/private-in-public-non-principal.rs:17:8
+  --> $DIR/private-in-public-non-principal.rs:18:8
    |
 LL | #[deny(missing_docs)]
    |        ^^^^^^^^^^^^
diff --git a/tests/ui/privacy/unnameable_types.rs b/tests/ui/privacy/unnameable_types.rs
index 8b53f372fc9..eae20dd9df3 100644
--- a/tests/ui/privacy/unnameable_types.rs
+++ b/tests/ui/privacy/unnameable_types.rs
@@ -1,4 +1,4 @@
-#![allow(unused)]
+#![feature(type_privacy_lints)]
 #![allow(private_in_public)]
 #![deny(unnameable_types)]
 
diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs
index 9899902dd88..2e0a6b3e72c 100644
--- a/tests/ui/privacy/where-priv-type.rs
+++ b/tests/ui/privacy/where-priv-type.rs
@@ -3,8 +3,8 @@
 
 #![crate_type = "lib"]
 #![feature(generic_const_exprs)]
+#![feature(type_privacy_lints)]
 #![allow(incomplete_features)]
-
 #![warn(private_bounds)]
 #![warn(private_interfaces)]
 
@@ -25,6 +25,7 @@ impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; }
 pub struct S
 //~^ WARNING private type `PrivTy` in public interface
 //~| WARNING hard error
+//~| WARNING type `PrivTy` is more private than the item `S`
 where
     PrivTy:
 {}
@@ -33,6 +34,7 @@ where
 pub enum E
 //~^ WARNING private type `PrivTy` in public interface
 //~| WARNING hard error
+//~| WARNING type `PrivTy` is more private than the item `E`
 where
     PrivTy:
 {}
@@ -41,6 +43,7 @@ where
 pub fn f()
 //~^ WARNING private type `PrivTy` in public interface
 //~| WARNING hard error
+//~| WARNING type `PrivTy` is more private than the item `f`
 where
     PrivTy:
 {}
@@ -48,12 +51,14 @@ where
 
 impl S
 //~^ ERROR private type `PrivTy` in public interface
+//~| WARNING type `PrivTy` is more private than the item `S`
 where
     PrivTy:
 {
     pub fn f()
     //~^ WARNING private type `PrivTy` in public interface
     //~| WARNING hard error
+    //~| WARNING type `PrivTy` is more private than the item `S::f`
     where
         PrivTy:
     {}
@@ -85,6 +90,7 @@ where
 {
     type AssocTy = Const<{ my_const_fn(U) }>;
     //~^ ERROR private type
+    //~| WARNING type `fn(u8) -> u8 {my_const_fn}` is more private than the item `<Const<U> as Trait>::AssocTy`
     fn assoc_fn() -> Self::AssocTy {
         Const
     }
diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr
index 2830fa6cd44..d6baf22b3fb 100644
--- a/tests/ui/privacy/where-priv-type.stderr
+++ b/tests/ui/privacy/where-priv-type.stderr
@@ -9,12 +9,11 @@ LL | pub struct S
    = note: `#[warn(private_in_public)]` on by default
 
 warning: type `PrivTy` is more private than the item `S`
-   |
-note: struct `S` is reachable at visibility `pub`
   --> $DIR/where-priv-type.rs:25:1
    |
 LL | pub struct S
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:15:1
    |
@@ -27,7 +26,7 @@ LL | #![warn(private_bounds)]
    |         ^^^^^^^^^^^^^^
 
 warning: private type `PrivTy` in public interface (error E0446)
-  --> $DIR/where-priv-type.rs:33:1
+  --> $DIR/where-priv-type.rs:34:1
    |
 LL | pub enum E
    | ^^^^^^^^^^
@@ -36,12 +35,11 @@ LL | pub enum E
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: type `PrivTy` is more private than the item `E`
-   |
-note: enum `E` is reachable at visibility `pub`
-  --> $DIR/where-priv-type.rs:33:1
+  --> $DIR/where-priv-type.rs:34:1
    |
 LL | pub enum E
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ enum `E` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:15:1
    |
@@ -49,11 +47,12 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 warning: private type `PrivTy` in public interface (error E0446)
-  --> $DIR/where-priv-type.rs:41:1
+  --> $DIR/where-priv-type.rs:43:1
    |
 LL | / pub fn f()
 LL | |
 LL | |
+LL | |
 LL | | where
 LL | |     PrivTy:
    | |___________^
@@ -62,16 +61,16 @@ LL | |     PrivTy:
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: type `PrivTy` is more private than the item `f`
-   |
-note: function `f` is reachable at visibility `pub`
-  --> $DIR/where-priv-type.rs:41:1
+  --> $DIR/where-priv-type.rs:43:1
    |
 LL | / pub fn f()
 LL | |
 LL | |
+LL | |
 LL | | where
 LL | |     PrivTy:
-   | |___________^
+   | |___________^ function `f` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:15:1
    |
@@ -79,7 +78,7 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 error[E0446]: private type `PrivTy` in public interface
-  --> $DIR/where-priv-type.rs:49:1
+  --> $DIR/where-priv-type.rs:52:1
    |
 LL | struct PrivTy;
    | ------------- `PrivTy` declared as private
@@ -88,12 +87,11 @@ LL | impl S
    | ^^^^^^ can't leak private type
 
 warning: type `PrivTy` is more private than the item `S`
-   |
-note: implementation `S` is reachable at visibility `pub`
-  --> $DIR/where-priv-type.rs:49:1
+  --> $DIR/where-priv-type.rs:52:1
    |
 LL | impl S
-   | ^^^^^^
+   | ^^^^^^ implementation `S` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:15:1
    |
@@ -101,11 +99,12 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 warning: private type `PrivTy` in public interface (error E0446)
-  --> $DIR/where-priv-type.rs:54:5
+  --> $DIR/where-priv-type.rs:58:5
    |
 LL | /     pub fn f()
 LL | |
 LL | |
+LL | |
 LL | |     where
 LL | |         PrivTy:
    | |_______________^
@@ -114,16 +113,16 @@ LL | |         PrivTy:
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: type `PrivTy` is more private than the item `S::f`
-   |
-note: associated function `S::f` is reachable at visibility `pub`
-  --> $DIR/where-priv-type.rs:54:5
+  --> $DIR/where-priv-type.rs:58:5
    |
 LL | /     pub fn f()
 LL | |
 LL | |
+LL | |
 LL | |     where
 LL | |         PrivTy:
-   | |_______________^
+   | |_______________^ associated function `S::f` is reachable at visibility `pub`
+   |
 note: but type `PrivTy` is only usable at visibility `pub(crate)`
   --> $DIR/where-priv-type.rs:15:1
    |
@@ -131,7 +130,7 @@ LL | struct PrivTy;
    | ^^^^^^^^^^^^^
 
 error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
-  --> $DIR/where-priv-type.rs:86:5
+  --> $DIR/where-priv-type.rs:91:5
    |
 LL |     type AssocTy = Const<{ my_const_fn(U) }>;
    |     ^^^^^^^^^^^^ can't leak private type
@@ -140,14 +139,13 @@ LL | const fn my_const_fn(val: u8) -> u8 {
    | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
 
 warning: type `fn(u8) -> u8 {my_const_fn}` is more private than the item `<Const<U> as Trait>::AssocTy`
-   |
-note: associated type `<Const<U> as Trait>::AssocTy` is reachable at visibility `pub`
-  --> $DIR/where-priv-type.rs:86:5
+  --> $DIR/where-priv-type.rs:91:5
    |
 LL |     type AssocTy = Const<{ my_const_fn(U) }>;
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ associated type `<Const<U> as Trait>::AssocTy` is reachable at visibility `pub`
+   |
 note: but type `fn(u8) -> u8 {my_const_fn}` is only usable at visibility `pub(crate)`
-  --> $DIR/where-priv-type.rs:93:1
+  --> $DIR/where-priv-type.rs:99:1
    |
 LL | const fn my_const_fn(val: u8) -> u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs
index 3aad893eae2..c59fdb7c7a9 100644
--- a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs
+++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs
@@ -2,8 +2,8 @@
 
 #![crate_type = "lib"]
 #![feature(generic_const_exprs)]
+#![feature(type_privacy_lints)]
 #![allow(incomplete_features)]
-
 #![warn(private_bounds)]
 
 // In this test both old and new private-in-public diagnostic were emitted.
@@ -23,6 +23,7 @@ impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; }
 
 pub struct S
 //~^ ERROR private trait `PrivTr` in public interface
+//~| WARNING trait `PrivTr` is more private than the item `S`
 where
     PubTy: PrivTr
 {}
@@ -30,6 +31,7 @@ where
 
 pub enum E
 //~^ ERROR private trait `PrivTr` in public interface
+//~| WARNING trait `PrivTr` is more private than the item `E`
 where
     PubTy: PrivTr
 {}
@@ -37,6 +39,7 @@ where
 
 pub fn f()
 //~^ ERROR private trait `PrivTr` in public interface
+//~| WARNING trait `PrivTr` is more private than the item `f`
 where
     PubTy: PrivTr
 {}
@@ -44,11 +47,13 @@ where
 
 impl S
 //~^ ERROR private trait `PrivTr` in public interface
+//~| WARNING trait `PrivTr` is more private than the item `S`
 where
     PubTy: PrivTr
 {
     pub fn f()
     //~^ ERROR private trait `PrivTr` in public interface
+    //~| WARNING trait `PrivTr` is more private than the item `S::f`
     where
         PubTy: PrivTr
     {}
diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr
index 413f7f781cd..e2d7ce44692 100644
--- a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr
+++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr
@@ -8,12 +8,11 @@ LL | pub struct S
    | ^^^^^^^^^^^^ can't leak private trait
 
 warning: trait `PrivTr` is more private than the item `S`
-   |
-note: struct `S` is reachable at visibility `pub`
   --> $DIR/where-pub-type-impls-priv-trait.rs:24:1
    |
 LL | pub struct S
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub`
+   |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
   --> $DIR/where-pub-type-impls-priv-trait.rs:14:1
    |
@@ -26,7 +25,7 @@ LL | #![warn(private_bounds)]
    |         ^^^^^^^^^^^^^^
 
 error[E0445]: private trait `PrivTr` in public interface
-  --> $DIR/where-pub-type-impls-priv-trait.rs:31:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:32:1
    |
 LL | trait PrivTr {}
    | ------------ `PrivTr` declared as private
@@ -35,12 +34,11 @@ LL | pub enum E
    | ^^^^^^^^^^ can't leak private trait
 
 warning: trait `PrivTr` is more private than the item `E`
-   |
-note: enum `E` is reachable at visibility `pub`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:31:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:32:1
    |
 LL | pub enum E
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ enum `E` is reachable at visibility `pub`
+   |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
   --> $DIR/where-pub-type-impls-priv-trait.rs:14:1
    |
@@ -48,27 +46,28 @@ LL | trait PrivTr {}
    | ^^^^^^^^^^^^
 
 error[E0445]: private trait `PrivTr` in public interface
-  --> $DIR/where-pub-type-impls-priv-trait.rs:38:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:40:1
    |
 LL |   trait PrivTr {}
    |   ------------ `PrivTr` declared as private
 ...
 LL | / pub fn f()
 LL | |
+LL | |
 LL | | where
 LL | |     PubTy: PrivTr
    | |_________________^ can't leak private trait
 
 warning: trait `PrivTr` is more private than the item `f`
-   |
-note: function `f` is reachable at visibility `pub`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:38:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:40:1
    |
 LL | / pub fn f()
 LL | |
+LL | |
 LL | | where
 LL | |     PubTy: PrivTr
-   | |_________________^
+   | |_________________^ function `f` is reachable at visibility `pub`
+   |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
   --> $DIR/where-pub-type-impls-priv-trait.rs:14:1
    |
@@ -76,7 +75,7 @@ LL | trait PrivTr {}
    | ^^^^^^^^^^^^
 
 error[E0445]: private trait `PrivTr` in public interface
-  --> $DIR/where-pub-type-impls-priv-trait.rs:45:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:48:1
    |
 LL | trait PrivTr {}
    | ------------ `PrivTr` declared as private
@@ -85,12 +84,11 @@ LL | impl S
    | ^^^^^^ can't leak private trait
 
 warning: trait `PrivTr` is more private than the item `S`
-   |
-note: implementation `S` is reachable at visibility `pub`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:45:1
+  --> $DIR/where-pub-type-impls-priv-trait.rs:48:1
    |
 LL | impl S
-   | ^^^^^^
+   | ^^^^^^ implementation `S` is reachable at visibility `pub`
+   |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
   --> $DIR/where-pub-type-impls-priv-trait.rs:14:1
    |
@@ -98,27 +96,28 @@ LL | trait PrivTr {}
    | ^^^^^^^^^^^^
 
 error[E0445]: private trait `PrivTr` in public interface
-  --> $DIR/where-pub-type-impls-priv-trait.rs:50:5
+  --> $DIR/where-pub-type-impls-priv-trait.rs:54:5
    |
 LL |   trait PrivTr {}
    |   ------------ `PrivTr` declared as private
 ...
 LL | /     pub fn f()
 LL | |
+LL | |
 LL | |     where
 LL | |         PubTy: PrivTr
    | |_____________________^ can't leak private trait
 
 warning: trait `PrivTr` is more private than the item `S::f`
-   |
-note: associated function `S::f` is reachable at visibility `pub`
-  --> $DIR/where-pub-type-impls-priv-trait.rs:50:5
+  --> $DIR/where-pub-type-impls-priv-trait.rs:54:5
    |
 LL | /     pub fn f()
 LL | |
+LL | |
 LL | |     where
 LL | |         PubTy: PrivTr
-   | |_____________________^
+   | |_____________________^ associated function `S::f` is reachable at visibility `pub`
+   |
 note: but trait `PrivTr` is only usable at visibility `pub(crate)`
   --> $DIR/where-pub-type-impls-priv-trait.rs:14:1
    |
diff --git a/tests/ui/proc-macro/derive-helper-shadowing.rs b/tests/ui/proc-macro/derive-helper-shadowing.rs
index 80d982d2504..4f25b4b0dca 100644
--- a/tests/ui/proc-macro/derive-helper-shadowing.rs
+++ b/tests/ui/proc-macro/derive-helper-shadowing.rs
@@ -23,7 +23,7 @@ macro_rules! gen_helper_use {
 struct S {
     #[empty_helper] // OK, no ambiguity, derive helpers have highest priority
     field: [u8; {
-        use empty_helper; //~ ERROR `empty_helper` is ambiguous
+        use empty_helper; // OK, no ambiguity, derive helpers have highest priority
 
         #[empty_helper] // OK, no ambiguity, derive helpers have highest priority
         struct U;
diff --git a/tests/ui/proc-macro/derive-helper-shadowing.stderr b/tests/ui/proc-macro/derive-helper-shadowing.stderr
index 566c4130846..f284b1c54dd 100644
--- a/tests/ui/proc-macro/derive-helper-shadowing.stderr
+++ b/tests/ui/proc-macro/derive-helper-shadowing.stderr
@@ -38,25 +38,6 @@ LL +             use crate::empty_helper;
    |
 
 error[E0659]: `empty_helper` is ambiguous
-  --> $DIR/derive-helper-shadowing.rs:26:13
-   |
-LL |         use empty_helper;
-   |             ^^^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-note: `empty_helper` could refer to the derive helper attribute defined here
-  --> $DIR/derive-helper-shadowing.rs:22:10
-   |
-LL | #[derive(Empty)]
-   |          ^^^^^
-note: `empty_helper` could also refer to the attribute macro imported here
-  --> $DIR/derive-helper-shadowing.rs:10:5
-   |
-LL | use test_macros::empty_attr as empty_helper;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
-
-error[E0659]: `empty_helper` is ambiguous
   --> $DIR/derive-helper-shadowing.rs:19:3
    |
 LL | #[empty_helper]
@@ -88,6 +69,6 @@ LL | #[derive(Empty)]
    = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
    = note: `#[warn(legacy_derive_helpers)]` on by default
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs
index 9e4ba80a784..cdeea6224b2 100644
--- a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs
+++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs
@@ -1,3 +1,4 @@
+#![feature(type_privacy_lints)]
 #![allow(non_camel_case_types)] // genus is always capitalized
 #![warn(private_interfaces)]
 //~^ NOTE the lint level is defined here
@@ -26,14 +27,17 @@ pub struct Shell<T> {
 
 pub type Helix_pomatia = Shell<Snail>;
 //~^ ERROR private type `Snail` in public interface
+//~| WARNING type `Snail` is more private than the item `Helix_pomatia`
 //~| NOTE can't leak private type
 //~| NOTE type alias `Helix_pomatia` is reachable at visibility `pub`
 pub type Dermochelys_coriacea = Shell<sea::Turtle>;
 //~^ ERROR crate-private type `Turtle` in public interface
+//~| WARNING type `Turtle` is more private than the item `Dermochelys_coriacea`
 //~| NOTE can't leak crate-private type
 //~| NOTE type alias `Dermochelys_coriacea` is reachable at visibility `pub`
 pub type Testudo_graeca = Shell<Tortoise>;
 //~^ ERROR private type `Tortoise` in public interface
+//~| WARNING type `Tortoise` is more private than the item `Testudo_graeca`
 //~| NOTE can't leak private type
 //~| NOTE type alias `Testudo_graeca` is reachable at visibility `pub`
 
diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
index 52f67d4cdd5..20e51e1901f 100644
--- a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
+++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr
@@ -1,5 +1,5 @@
 error[E0446]: private type `Snail` in public interface
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:27:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:28:1
    |
 LL | pub(crate) struct Snail;
    | ----------------------- `Snail` declared as private
@@ -8,25 +8,24 @@ LL | pub type Helix_pomatia = Shell<Snail>;
    | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 warning: type `Snail` is more private than the item `Helix_pomatia`
-   |
-note: type alias `Helix_pomatia` is reachable at visibility `pub`
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:27:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:28:1
    |
 LL | pub type Helix_pomatia = Shell<Snail>;
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^ type alias `Helix_pomatia` is reachable at visibility `pub`
+   |
 note: but type `Snail` is only usable at visibility `pub(crate)`
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:9:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:10:1
    |
 LL | pub(crate) struct Snail;
    | ^^^^^^^^^^^^^^^^^^^^^^^
 note: the lint level is defined here
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:2:9
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:3:9
    |
 LL | #![warn(private_interfaces)]
    |         ^^^^^^^^^^^^^^^^^^
 
 error[E0446]: crate-private type `Turtle` in public interface
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:31:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:33:1
    |
 LL |     pub(super) struct Turtle;
    |     ------------------------ `Turtle` declared as crate-private
@@ -35,20 +34,19 @@ LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-private type
 
 warning: type `Turtle` is more private than the item `Dermochelys_coriacea`
-   |
-note: type alias `Dermochelys_coriacea` is reachable at visibility `pub`
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:31:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:33:1
    |
 LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type alias `Dermochelys_coriacea` is reachable at visibility `pub`
+   |
 note: but type `Turtle` is only usable at visibility `pub(crate)`
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:14:5
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:15:5
    |
 LL |     pub(super) struct Turtle;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0446]: private type `Tortoise` in public interface
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:35:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:38:1
    |
 LL | struct Tortoise;
    | --------------- `Tortoise` declared as private
@@ -57,14 +55,13 @@ LL | pub type Testudo_graeca = Shell<Tortoise>;
    | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 warning: type `Tortoise` is more private than the item `Testudo_graeca`
-   |
-note: type alias `Testudo_graeca` is reachable at visibility `pub`
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:35:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:38:1
    |
 LL | pub type Testudo_graeca = Shell<Tortoise>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^ type alias `Testudo_graeca` is reachable at visibility `pub`
+   |
 note: but type `Tortoise` is only usable at visibility `pub(crate)`
-  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:19:1
+  --> $DIR/issue-33174-restricted-type-in-public-interface.rs:20:1
    |
 LL | struct Tortoise;
    | ^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
index 7e008d46574..a5c79366bf0 100644
--- a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
+++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
@@ -4,7 +4,7 @@ error[E0659]: `std` is ambiguous
 LL |     pub use std::io;
    |             ^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
    = note: `std` could refer to a built-in crate
    = help: use `::std` to refer to this crate unambiguously
 note: `std` could also refer to the module defined here
diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
index 771d2c10c1d..8045f3a45b6 100644
--- a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
+++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
@@ -4,7 +4,7 @@ error[E0659]: `std` is ambiguous
 LL | use std::io;
    |     ^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
    = note: `std` could refer to a built-in crate
    = help: use `::std` to refer to this crate unambiguously
 note: `std` could also refer to the module defined here
diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs
index 50c8fc8229c..0ef580d7aa5 100644
--- a/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs
+++ b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs
@@ -1,3 +1,4 @@
+// check-pass
 // edition:2018
 
 // This test is similar to `ambiguity.rs`, but nested in a module.
@@ -5,8 +6,7 @@
 #![allow(non_camel_case_types)]
 
 mod foo {
-    pub use std::io;
-    //~^ ERROR `std` is ambiguous
+    pub use std::io; // OK
 
     mod std {
         pub struct io;
diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr
deleted file mode 100644
index defb16f7970..00000000000
--- a/tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0659]: `std` is ambiguous
-  --> $DIR/ambiguity-nested.rs:8:13
-   |
-LL |     pub use std::io;
-   |             ^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-   = note: `std` could refer to a built-in crate
-   = help: use `::std` to refer to this crate unambiguously
-note: `std` could also refer to the module defined here
-  --> $DIR/ambiguity-nested.rs:11:5
-   |
-LL | /     mod std {
-LL | |         pub struct io;
-LL | |     }
-   | |_____^
-   = help: use `self::std` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity.rs b/tests/ui/rust-2018/uniform-paths/ambiguity.rs
index 60f77a1c663..890e8b7b3c0 100644
--- a/tests/ui/rust-2018/uniform-paths/ambiguity.rs
+++ b/tests/ui/rust-2018/uniform-paths/ambiguity.rs
@@ -1,9 +1,9 @@
+// check-pass
 // edition:2018
 
 #![allow(non_camel_case_types)]
 
-use std::io;
-//~^ ERROR `std` is ambiguous
+use std::io; // OK
 
 mod std {
     pub struct io;
diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity.stderr
deleted file mode 100644
index 2d735c7e3fd..00000000000
--- a/tests/ui/rust-2018/uniform-paths/ambiguity.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0659]: `std` is ambiguous
-  --> $DIR/ambiguity.rs:5:5
-   |
-LL | use std::io;
-   |     ^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-   = note: `std` could refer to a built-in crate
-   = help: use `::std` to refer to this crate unambiguously
-note: `std` could also refer to the module defined here
-  --> $DIR/ambiguity.rs:8:1
-   |
-LL | / mod std {
-LL | |     pub struct io;
-LL | | }
-   | |_^
-   = help: use `crate::std` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs
index 3f5897901a0..4cba0949802 100644
--- a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs
+++ b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs
@@ -1,3 +1,4 @@
+// check-pass
 // edition:2018
 
 mod my {
@@ -13,7 +14,7 @@ mod sub {
 fn foo() {
     use my::sub;
     {
-        use sub::bar; //~ ERROR `sub` is ambiguous
+        use sub::bar; // OK
     }
 }
 
diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
deleted file mode 100644
index 3d45a814029..00000000000
--- a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0659]: `sub` is ambiguous
-  --> $DIR/block-scoped-shadow-nested.rs:16:13
-   |
-LL |         use sub::bar;
-   |             ^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-note: `sub` could refer to the module imported here
-  --> $DIR/block-scoped-shadow-nested.rs:14:9
-   |
-LL |     use my::sub;
-   |         ^^^^^^^
-note: `sub` could also refer to the module defined here
-  --> $DIR/block-scoped-shadow-nested.rs:9:1
-   |
-LL | / mod sub {
-LL | |     pub fn bar() {}
-LL | | }
-   | |_^
-   = help: use `crate::sub` to refer to this module unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs
index 828ee4fe474..c902d133e7c 100644
--- a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs
+++ b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs
@@ -1,3 +1,4 @@
+// check-pass
 // edition:2018
 
 #![allow(non_camel_case_types)]
@@ -8,14 +9,11 @@ struct std;
 
 fn main() {
     enum Foo { A, B }
-    use Foo::*;
-    //~^ ERROR `Foo` is ambiguous
+    use Foo::*; // OK
 
     let _ = (A, B);
 
     fn std() {}
     enum std {}
-    use std as foo;
-    //~^ ERROR `std` is ambiguous
-    //~| ERROR `std` is ambiguous
+    use std as foo; // OK
 }
diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
deleted file mode 100644
index b068312cedd..00000000000
--- a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
+++ /dev/null
@@ -1,60 +0,0 @@
-error[E0659]: `Foo` is ambiguous
-  --> $DIR/block-scoped-shadow.rs:11:9
-   |
-LL |     use Foo::*;
-   |         ^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-note: `Foo` could refer to the enum defined here
-  --> $DIR/block-scoped-shadow.rs:10:5
-   |
-LL |     enum Foo { A, B }
-   |     ^^^^^^^^^^^^^^^^^
-note: `Foo` could also refer to the enum defined here
-  --> $DIR/block-scoped-shadow.rs:5:1
-   |
-LL | enum Foo {}
-   | ^^^^^^^^^^^
-   = help: use `crate::Foo` to refer to this enum unambiguously
-
-error[E0659]: `std` is ambiguous
-  --> $DIR/block-scoped-shadow.rs:18:9
-   |
-LL |     use std as foo;
-   |         ^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-note: `std` could refer to the enum defined here
-  --> $DIR/block-scoped-shadow.rs:17:5
-   |
-LL |     enum std {}
-   |     ^^^^^^^^^^^
-note: `std` could also refer to the struct defined here
-  --> $DIR/block-scoped-shadow.rs:7:1
-   |
-LL | struct std;
-   | ^^^^^^^^^^^
-   = help: use `crate::std` to refer to this struct unambiguously
-
-error[E0659]: `std` is ambiguous
-  --> $DIR/block-scoped-shadow.rs:18:9
-   |
-LL |     use std as foo;
-   |         ^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-note: `std` could refer to the function defined here
-  --> $DIR/block-scoped-shadow.rs:16:5
-   |
-LL |     fn std() {}
-   |     ^^^^^^^^^^^
-note: `std` could also refer to the unit struct defined here
-  --> $DIR/block-scoped-shadow.rs:7:1
-   |
-LL | struct std;
-   | ^^^^^^^^^^^
-   = help: use `crate::std` to refer to this unit struct unambiguously
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/rust-2018/uniform-paths/issue-56596.stderr b/tests/ui/rust-2018/uniform-paths/issue-56596.stderr
index 8b8ab26dce2..849d6275eb8 100644
--- a/tests/ui/rust-2018/uniform-paths/issue-56596.stderr
+++ b/tests/ui/rust-2018/uniform-paths/issue-56596.stderr
@@ -4,7 +4,7 @@ error[E0659]: `issue_56596` is ambiguous
 LL | use issue_56596;
    |     ^^^^^^^^^^^ ambiguous name
    |
-   = note: ambiguous because of multiple potential import sources
+   = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution
    = note: `issue_56596` could refer to a crate passed with `--extern`
    = help: use `::issue_56596` to refer to this crate unambiguously
 note: `issue_56596` could also refer to the module imported here
@@ -12,7 +12,8 @@ note: `issue_56596` could also refer to the module imported here
    |
 LL | use m::*;
    |     ^^^^
-   = help: use `crate::issue_56596` to refer to this module unambiguously
+   = help: consider adding an explicit import of `issue_56596` to disambiguate
+   = help: or use `crate::issue_56596` to refer to this module unambiguously
 
 error: aborting due to previous error
 
diff --git a/tests/ui/rust-2018/uniform-paths/macro-rules.rs b/tests/ui/rust-2018/uniform-paths/macro-rules.rs
index 2d9a6a9a924..1084f5e8b34 100644
--- a/tests/ui/rust-2018/uniform-paths/macro-rules.rs
+++ b/tests/ui/rust-2018/uniform-paths/macro-rules.rs
@@ -27,8 +27,7 @@ mod m3 {
     fn f() {
         macro_rules! legacy_macro { () => () }
 
-        // Legacy macro imports create ambiguities with other names in the same namespace.
-        use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
+        use legacy_macro as _; // OK
     }
 }
 
diff --git a/tests/ui/rust-2018/uniform-paths/macro-rules.stderr b/tests/ui/rust-2018/uniform-paths/macro-rules.stderr
index 9f8c928c32c..8a978c98a44 100644
--- a/tests/ui/rust-2018/uniform-paths/macro-rules.stderr
+++ b/tests/ui/rust-2018/uniform-paths/macro-rules.stderr
@@ -10,26 +10,6 @@ help: consider adding a `#[macro_export]` to the macro in the imported module
 LL |     macro_rules! legacy_macro { () => () }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0659]: `legacy_macro` is ambiguous
-  --> $DIR/macro-rules.rs:31:13
-   |
-LL |         use legacy_macro as _;
-   |             ^^^^^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of multiple potential import sources
-note: `legacy_macro` could refer to the macro defined here
-  --> $DIR/macro-rules.rs:28:9
-   |
-LL |         macro_rules! legacy_macro { () => () }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: `legacy_macro` could also refer to the macro defined here
-  --> $DIR/macro-rules.rs:25:5
-   |
-LL |     macro legacy_macro() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   = help: use `self::legacy_macro` to refer to this macro unambiguously
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0364, E0659.
-For more information about an error, try `rustc --explain E0364`.
+For more information about this error, try `rustc --explain E0364`.
diff --git a/tests/ui/suggestions/issue-102972.rs b/tests/ui/suggestions/issue-102972.rs
new file mode 100644
index 00000000000..106288b054d
--- /dev/null
+++ b/tests/ui/suggestions/issue-102972.rs
@@ -0,0 +1,16 @@
+fn test1() {
+    let mut chars = "Hello".chars();
+    for _c in chars.by_ref() {
+        chars.next(); //~ ERROR cannot borrow `chars` as mutable more than once at a time
+    }
+}
+
+fn test2() {
+    let v = vec![1, 2, 3];
+    let mut iter = v.iter();
+    for _i in iter {
+        iter.next(); //~ ERROR borrow of moved value: `iter`
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-102972.stderr b/tests/ui/suggestions/issue-102972.stderr
new file mode 100644
index 00000000000..03f9dbb6c89
--- /dev/null
+++ b/tests/ui/suggestions/issue-102972.stderr
@@ -0,0 +1,33 @@
+error[E0499]: cannot borrow `chars` as mutable more than once at a time
+  --> $DIR/issue-102972.rs:4:9
+   |
+LL |     for _c in chars.by_ref() {
+   |               --------------
+   |               |
+   |               first mutable borrow occurs here
+   |               first borrow later used here
+LL |         chars.next();
+   |         ^^^^^^^^^^^^ second mutable borrow occurs here
+   |
+   = note: a for loop advances the iterator for you, the result is stored in `_c`.
+   = help: if you want to call `next` on a iterator within the loop, consider using `while let`.
+
+error[E0382]: borrow of moved value: `iter`
+  --> $DIR/issue-102972.rs:12:9
+   |
+LL |     let mut iter = v.iter();
+   |         -------- move occurs because `iter` has type `std::slice::Iter<'_, i32>`, which does not implement the `Copy` trait
+LL |     for _i in iter {
+   |               ---- `iter` moved due to this implicit call to `.into_iter()`
+LL |         iter.next();
+   |         ^^^^^^^^^^^ value borrowed here after move
+   |
+   = note: a for loop advances the iterator for you, the result is stored in `_i`.
+   = help: if you want to call `next` on a iterator within the loop, consider using `while let`.
+note: `into_iter` takes ownership of the receiver `self`, which moves `iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0382, E0499.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/suggestions/suggest-split-at-mut.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr
index 330f012b2a9..bb185138383 100644
--- a/tests/ui/suggestions/suggest-split-at-mut.stderr
+++ b/tests/ui/suggestions/suggest-split-at-mut.stderr
@@ -9,6 +9,7 @@ LL |     *a = 5;
    |     ------ first borrow later used here
    |
    = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
+   = help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
 
 error: aborting due to previous error
 
diff --git a/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs b/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
index 585874e273d..02fee1a00da 100644
--- a/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
+++ b/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
@@ -1,5 +1,5 @@
 // run-pass
-// needs-unwind (#73509)
+// ignore-fuchsia Test must be run out-of-process
 
 #![feature(test)]
 
diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs
index 931b7993c81..08e5242af66 100644
--- a/tests/ui/test-attrs/test-panic-abort.rs
+++ b/tests/ui/test-attrs/test-panic-abort.rs
@@ -11,9 +11,13 @@
 // ignore-sgx no subprocess support
 
 #![cfg(test)]
+#![feature(test)]
+
+extern crate test;
 
 use std::io::Write;
 use std::env;
+use test::Bencher;
 
 #[test]
 fn it_works() {
@@ -48,3 +52,8 @@ fn no_residual_environment() {
         }
     }
 }
+
+#[bench]
+fn benchmark(b: &mut Bencher) {
+    b.iter(|| assert_eq!(1 + 1, 2));
+}
diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout
index f608a8cdc55..b6b9c2560fe 100644
--- a/tests/ui/test-attrs/test-panic-abort.run.stdout
+++ b/tests/ui/test-attrs/test-panic-abort.run.stdout
@@ -1,5 +1,6 @@
 
-running 5 tests
+running 6 tests
+test benchmark ... ok
 test it_exits ... FAILED
 test it_fails ... FAILED
 test it_panics - should panic ... ok
@@ -18,7 +19,7 @@ testing123
 testing321
 thread 'main' panicked at 'assertion failed: `(left == right)`
   left: `2`,
- right: `5`', $DIR/test-panic-abort.rs:34:5
+ right: `5`', $DIR/test-panic-abort.rs:38:5
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 
@@ -26,5 +27,5 @@ failures:
     it_exits
     it_fails
 
-test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+test result: FAILED. 4 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/tests/ui/traits/auxiliary/trivial3.rs b/tests/ui/traits/auxiliary/trivial3.rs
new file mode 100644
index 00000000000..0a47fdc74d7
--- /dev/null
+++ b/tests/ui/traits/auxiliary/trivial3.rs
@@ -0,0 +1 @@
+pub trait Trait {}
diff --git a/tests/ui/traits/auxiliary/trivial4.rs b/tests/ui/traits/auxiliary/trivial4.rs
new file mode 100644
index 00000000000..a527d1a9526
--- /dev/null
+++ b/tests/ui/traits/auxiliary/trivial4.rs
@@ -0,0 +1,3 @@
+pub trait Trait {}
+
+impl Trait for () {}
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
new file mode 100644
index 00000000000..e9ae00df7a0
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait<Input> {
+    type Assoc;
+}
+
+fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
+//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
new file mode 100644
index 00000000000..1124076c23c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `impl Trait` can only mention type parameters from an fn or impl
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52
+   |
+LL | fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
+   |                    - type parameter declared here  ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/traits/trivial_impl.rs b/tests/ui/traits/trivial_impl.rs
new file mode 100644
index 00000000000..6ac8c744bc4
--- /dev/null
+++ b/tests/ui/traits/trivial_impl.rs
@@ -0,0 +1,18 @@
+//! This test checks that we do need to implement
+//! all members, even if their where bounds only hold
+//! due to other impls.
+
+trait Foo<T> {
+    fn foo()
+    where
+        Self: Foo<()>;
+}
+
+impl Foo<()> for () {
+    fn foo() {}
+}
+
+impl Foo<u32> for () {}
+//~^ ERROR: not all trait items implemented, missing: `foo`
+
+fn main() {}
diff --git a/tests/ui/traits/trivial_impl.stderr b/tests/ui/traits/trivial_impl.stderr
new file mode 100644
index 00000000000..4b29b55bea1
--- /dev/null
+++ b/tests/ui/traits/trivial_impl.stderr
@@ -0,0 +1,14 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/trivial_impl.rs:15:1
+   |
+LL | /     fn foo()
+LL | |     where
+LL | |         Self: Foo<()>;
+   | |______________________- `foo` from trait
+...
+LL |   impl Foo<u32> for () {}
+   |   ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/traits/trivial_impl2.rs b/tests/ui/traits/trivial_impl2.rs
new file mode 100644
index 00000000000..be58096007f
--- /dev/null
+++ b/tests/ui/traits/trivial_impl2.rs
@@ -0,0 +1,13 @@
+//! This test checks that we currently need to implement
+//! members, even if their where bounds don't hold for the impl type.
+
+trait Foo<T> {
+    fn foo()
+    where
+        Self: Foo<()>;
+}
+
+impl Foo<u32> for () {}
+//~^ ERROR: not all trait items implemented, missing: `foo`
+
+fn main() {}
diff --git a/tests/ui/traits/trivial_impl2.stderr b/tests/ui/traits/trivial_impl2.stderr
new file mode 100644
index 00000000000..04c05df0616
--- /dev/null
+++ b/tests/ui/traits/trivial_impl2.stderr
@@ -0,0 +1,14 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/trivial_impl2.rs:10:1
+   |
+LL | /     fn foo()
+LL | |     where
+LL | |         Self: Foo<()>;
+   | |______________________- `foo` from trait
+...
+LL |   impl Foo<u32> for () {}
+   |   ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/traits/trivial_impl3.rs b/tests/ui/traits/trivial_impl3.rs
new file mode 100644
index 00000000000..714f643bc99
--- /dev/null
+++ b/tests/ui/traits/trivial_impl3.rs
@@ -0,0 +1,19 @@
+//! Check that we don't break orphan rules.
+//! The dependency may add an impl for `u8` later,
+//! which would break this crate. We want to avoid adding
+//! more ways in which adding an impl can be a breaking change.
+
+// aux-build:trivial3.rs
+
+extern crate trivial3;
+
+pub trait Foo {
+    fn foo()
+    where
+        Self: trivial3::Trait;
+}
+
+impl Foo for u8 {}
+//~^ ERROR not all trait items implemented, missing: `foo`
+
+fn main() {}
diff --git a/tests/ui/traits/trivial_impl3.stderr b/tests/ui/traits/trivial_impl3.stderr
new file mode 100644
index 00000000000..dfb39d6ce15
--- /dev/null
+++ b/tests/ui/traits/trivial_impl3.stderr
@@ -0,0 +1,14 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/trivial_impl3.rs:16:1
+   |
+LL | /     fn foo()
+LL | |     where
+LL | |         Self: trivial3::Trait;
+   | |______________________________- `foo` from trait
+...
+LL |   impl Foo for u8 {}
+   |   ^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/traits/trivial_impl4.rs b/tests/ui/traits/trivial_impl4.rs
new file mode 100644
index 00000000000..518f159c1fb
--- /dev/null
+++ b/tests/ui/traits/trivial_impl4.rs
@@ -0,0 +1,21 @@
+//! Check that we don't break orphan rules.
+//! The dependency may add an impl for `u8` later,
+//! which would break this crate. We want to avoid adding
+//! more ways in which adding an impl can be a breaking change.
+//! This test differs from `trivial_impl3` because there actually
+//! exists any impl for `Trait`, which has an effect on coherence.
+
+// aux-build:trivial4.rs
+
+extern crate trivial4;
+
+pub trait Foo {
+    fn foo()
+    where
+        Self: trivial4::Trait;
+}
+
+impl Foo for u8 {}
+//~^ ERROR not all trait items implemented, missing: `foo`
+
+fn main() {}
diff --git a/tests/ui/traits/trivial_impl4.stderr b/tests/ui/traits/trivial_impl4.stderr
new file mode 100644
index 00000000000..04b29ed7734
--- /dev/null
+++ b/tests/ui/traits/trivial_impl4.stderr
@@ -0,0 +1,14 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/trivial_impl4.rs:18:1
+   |
+LL | /     fn foo()
+LL | |     where
+LL | |         Self: trivial4::Trait;
+   | |______________________________- `foo` from trait
+...
+LL |   impl Foo for u8 {}
+   |   ^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/traits/trivial_impl_sized.rs b/tests/ui/traits/trivial_impl_sized.rs
new file mode 100644
index 00000000000..501a3405090
--- /dev/null
+++ b/tests/ui/traits/trivial_impl_sized.rs
@@ -0,0 +1,26 @@
+//! This test checks that we currently need to implement
+//! members, even if their where bounds don't hold for the impl type.
+
+trait Foo {
+    fn foo()
+    where
+        Self: Sized;
+}
+
+impl Foo for () {
+    fn foo() {}
+}
+
+// Must not be allowed
+impl Foo for i32 {}
+//~^ ERROR: not all trait items implemented, missing: `foo`
+
+// Should be allowed
+impl Foo for dyn std::fmt::Debug {}
+//~^ ERROR: not all trait items implemented, missing: `foo`
+
+impl Foo for dyn std::fmt::Display {
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trivial_impl_sized.stderr b/tests/ui/traits/trivial_impl_sized.stderr
new file mode 100644
index 00000000000..ebf6dfc9dd2
--- /dev/null
+++ b/tests/ui/traits/trivial_impl_sized.stderr
@@ -0,0 +1,25 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/trivial_impl_sized.rs:15:1
+   |
+LL | /     fn foo()
+LL | |     where
+LL | |         Self: Sized;
+   | |____________________- `foo` from trait
+...
+LL |   impl Foo for i32 {}
+   |   ^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/trivial_impl_sized.rs:19:1
+   |
+LL | /     fn foo()
+LL | |     where
+LL | |         Self: Sized;
+   | |____________________- `foo` from trait
+...
+LL |   impl Foo for dyn std::fmt::Debug {}
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed
new file mode 100644
index 00000000000..5be6ff8e7e1
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs
new file mode 100644
index 00000000000..d7072aa1181
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr
index 63fc1a19b93..3e197dc9a9d 100644
--- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-trait-impl-region.rs:11:17
+  --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:13:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-trait-impl-region.rs:11:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed
new file mode 100644
index 00000000000..0f1be586589
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed
@@ -0,0 +1,18 @@
+// edition:2018
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs
new file mode 100644
index 00000000000..59f7e472e2d
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs
@@ -0,0 +1,18 @@
+// edition:2018
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+#[allow(dead_code)]
+struct Foo<T> {
+    t: T
+}
+
+impl<T> Foo<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr
index 63fc1a19b93..08b4268e5d2 100644
--- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-trait-impl-region.rs:11:17
+  --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:14:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-trait-impl-region.rs:11:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs
deleted file mode 100644
index 43de30944ca..00000000000
--- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// revisions: rust2015 rust2018
-//[rust2018] edition:2018
-
-trait WithType<T> {}
-trait WithRegion<'a> { }
-
-struct Foo<T> {
-    t: T
-}
-
-impl<T> Foo<T>
-where
-    T: WithType<&u32>
-//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here
-{ }
-
-fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed
new file mode 100644
index 00000000000..55c7470960e
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs
new file mode 100644
index 00000000000..42a35b02161
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr
index f4d14b5f87b..8c5bbb631b4 100644
--- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
+  --> $DIR/where-clause-trait-impl-region-2015.rs:10:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed
new file mode 100644
index 00000000000..09b96fe5ea4
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+// edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: for<'a> WithType<&'a u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs
new file mode 100644
index 00000000000..445f38cbee1
--- /dev/null
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+// edition:2018
+
+trait WithType<T> {}
+trait WithRegion<'a> { }
+
+trait Foo { }
+
+impl<T> Foo for Vec<T>
+where
+    T: WithType<&u32>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+{ }
+
+fn main() {}
diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr
index f4d14b5f87b..0268c59fa4a 100644
--- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr
+++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr
@@ -1,14 +1,13 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17
+  --> $DIR/where-clause-trait-impl-region-2018.rs:11:17
    |
 LL |     T: WithType<&u32>
    |                 ^ explicit lifetime name needed here
    |
-help: consider introducing a higher-ranked lifetime here with `for<'a>`
-  --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8
+help: consider introducing a higher-ranked lifetime here
    |
-LL |     T: WithType<&u32>
-   |        ^
+LL |     T: for<'a> WithType<&'a u32>
+   |        +++++++           ++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs
deleted file mode 100644
index 09e5bbd846d..00000000000
--- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// revisions: rust2015 rust2018
-//[rust2018] edition:2018
-
-trait WithType<T> {}
-trait WithRegion<'a> { }
-
-trait Foo { }
-
-impl<T> Foo for Vec<T>
-where
-    T: WithType<&u32>
-//[rust2015,rust2018]~^ ERROR `&` without an explicit lifetime name cannot be used here
-{ }
-
-fn main() {}