about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-12 20:05:18 +0000
committerbors <bors@rust-lang.org>2023-01-12 20:05:18 +0000
commit61a415be590113b4935464ef0aaf3b4e7713a077 (patch)
treec743bcfc04170cf8b2dcb171cb8805e76683190e
parent1bc3683b3275a5eb2ed13d24edcdcbc59afe5d70 (diff)
parent01c75848eb94e96210e74b8dd43a5a270464ac25 (diff)
downloadrust-61a415be590113b4935464ef0aaf3b4e7713a077.tar.gz
rust-61a415be590113b4935464ef0aaf3b4e7713a077.zip
Auto merge of #106780 - flip1995:clippyup, r=Manishearth
Update Clippy

r? `@Manishearth`
-rw-r--r--src/tools/clippy/.github/driver.sh7
-rw-r--r--src/tools/clippy/CHANGELOG.md1
-rw-r--r--src/tools/clippy/book/src/installation.md2
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs161
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs174
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs37
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs270
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs11
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs5
-rw-r--r--src/tools/clippy/tests/integration.rs9
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr36
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs225
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr480
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed18
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs10
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr16
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed67
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs13
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr66
-rw-r--r--src/tools/clippy/tests/ui/clone_on_copy.stderr2
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.stderr52
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.fixed8
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.stderr16
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed21
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs23
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr23
-rw-r--r--src/tools/clippy/tests/ui/derive.rs11
-rw-r--r--src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr59
-rw-r--r--src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs (renamed from src/tools/clippy/tests/ui/derive_hash_xor_eq.rs)21
-rw-r--r--src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr29
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.rs23
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.stderr38
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs21
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.fixed35
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.rs39
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.stderr114
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed13
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs13
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.stderr8
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed10
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs10
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr18
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed6
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.rs6
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.stderr14
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr90
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.fixed27
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.rs26
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.stderr29
-rw-r--r--src/tools/clippy/tests/ui/suspicious_to_owned.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clone.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unused_self.rs10
-rw-r--r--src/tools/clippy/tests/ui/unused_self.stderr18
85 files changed, 1879 insertions, 850 deletions
diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh
index 6ff189fc859..798782340ee 100644
--- a/src/tools/clippy/.github/driver.sh
+++ b/src/tools/clippy/.github/driver.sh
@@ -17,6 +17,13 @@ test "$sysroot" = $desired_sysroot
 sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot)
 test "$sysroot" = $desired_sysroot
 
+# Check that the --sysroot argument is only passed once (SYSROOT is ignored)
+(
+    cd rustc_tools_util
+    touch src/lib.rs
+    SYSROOT=/tmp RUSTFLAGS="--sysroot=$(rustc --print sysroot)" ../target/debug/cargo-clippy clippy --verbose
+)
+
 # Make sure this isn't set - clippy-driver should cope without it
 unset CARGO_MANIFEST_DIR
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 02f3188f8be..8e31e8f0d98 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4137,6 +4137,7 @@ Released 2018-09-13
 [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
 [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
 [`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
+[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq
 [`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
 [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
 [`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods
diff --git a/src/tools/clippy/book/src/installation.md b/src/tools/clippy/book/src/installation.md
index b2a28d0be62..cce888b17d4 100644
--- a/src/tools/clippy/book/src/installation.md
+++ b/src/tools/clippy/book/src/installation.md
@@ -1,6 +1,6 @@
 # Installation
 
-If you're using `rustup` to install and manage you're Rust toolchains, Clippy is
+If you're using `rustup` to install and manage your Rust toolchains, Clippy is
 usually **already installed**. In that case you can skip this chapter and go to
 the [Usage] chapter.
 
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 80bb83af43b..e70488165b9 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -5,6 +5,9 @@
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
+// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
+#[allow(unused_extern_crates)]
+extern crate rustc_driver;
 extern crate rustc_lexer;
 
 use std::path::PathBuf;
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index 91900542af8..9d98a6bab71 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -8,7 +8,7 @@ use rustc_hir::{
     Block, Expr, ExprKind, Local, Node, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
+use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
@@ -59,7 +59,7 @@ impl LateLintPass<'_> for BoxDefault {
                 if is_plain_default(arg_path) || given_type(cx, expr) {
                     "Box::default()".into()
                 } else {
-                    format!("Box::<{arg_ty}>::default()")
+                    with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
                 },
                 Applicability::MachineApplicable
             );
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 0e3d9317590..f10c35cde52 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -525,7 +525,11 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
             .iter()
             .filter(|&&(_, name)| !name.as_str().starts_with('_'))
             .any(|&(_, name)| {
-                let mut walker = ContainsName { name, result: false };
+                let mut walker = ContainsName {
+                    name,
+                    result: false,
+                    cx,
+                };
 
                 // Scan block
                 block
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index fe9f4f9ae3c..799e71e847a 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -10,11 +10,11 @@ use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for usage of dbg!() macro.
+    /// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro.
     ///
     /// ### Why is this bad?
-    /// `dbg!` macro is intended as a debugging tool. It
-    /// should not be in version control.
+    /// The `dbg!` macro is intended as a debugging tool. It should not be present in released
+    /// software or committed to a version control system.
     ///
     /// ### Example
     /// ```rust,ignore
@@ -91,8 +91,8 @@ impl LateLintPass<'_> for DbgMacro {
                 cx,
                 DBG_MACRO,
                 macro_call.span,
-                "`dbg!` macro is intended as a debugging tool",
-                "ensure to avoid having uses of it in version control",
+                "the `dbg!` macro is intended as a debugging tool",
+                "remove the invocation before committing it to a version control system",
                 suggestion,
                 applicability,
             );
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 2982460c9cf..91ca73633f0 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -111,7 +111,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::dereference::NEEDLESS_BORROW_INFO,
     crate::dereference::REF_BINDING_TO_REFERENCE_INFO,
     crate::derivable_impls::DERIVABLE_IMPLS_INFO,
-    crate::derive::DERIVE_HASH_XOR_EQ_INFO,
+    crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO,
     crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO,
     crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO,
     crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 7f937de1dd3..a04693f4637 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -11,6 +11,7 @@ use rustc_hir::def::Res;
 use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
@@ -98,9 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
             if let ty::Adt(def, ..) = expr_ty.kind();
             if !is_from_proc_macro(cx, expr);
             then {
-                // TODO: Work out a way to put "whatever the imported way of referencing
-                // this type in this file" rather than a fully-qualified type.
-                let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did()));
+                let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
                 span_lint_and_sugg(
                     cx,
                     DEFAULT_TRAIT_ACCESS,
@@ -170,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                 // find out if and which field was set by this `consecutive_statement`
                 if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
                     // interrupt and cancel lint if assign_rhs references the original binding
-                    if contains_name(binding_name, assign_rhs) {
+                    if contains_name(binding_name, assign_rhs, cx) {
                         cancel_lint = true;
                         break;
                     }
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index f327c9a71b3..05f2b92c037 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>(
             possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
         }
         let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
-        // If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The
-        // reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible
-        // borrower of itself. See the comment in that method for an explanation as to why.
-        possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location)
+        // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
+        // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
+        // itself. See the comment in that method for an explanation as to why.
+        possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
             && used_exactly_once(mir, place.local).unwrap_or(false)
     } else {
         false
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index ae8f6b79449..bc18e2e5ed5 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -1,12 +1,15 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::indent_of;
 use clippy_utils::{is_default_equivalent, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{
-    def::{DefKind, Res},
-    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
+    def::{CtorKind, CtorOf, DefKind, Res},
+    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_middle::ty::{AdtDef, DefIdTree};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::sym;
 
 declare_clippy_lint! {
@@ -51,7 +54,18 @@ declare_clippy_lint! {
     "manual implementation of the `Default` trait which is equal to a derive"
 }
 
-declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
+pub struct DerivableImpls {
+    msrv: Msrv,
+}
+
+impl DerivableImpls {
+    #[must_use]
+    pub fn new(msrv: Msrv) -> Self {
+        DerivableImpls { msrv }
+    }
+}
+
+impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
 
 fn is_path_self(e: &Expr<'_>) -> bool {
     if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind {
@@ -61,6 +75,98 @@ fn is_path_self(e: &Expr<'_>) -> bool {
     }
 }
 
+fn check_struct<'tcx>(
+    cx: &LateContext<'tcx>,
+    item: &'tcx Item<'_>,
+    self_ty: &Ty<'_>,
+    func_expr: &Expr<'_>,
+    adt_def: AdtDef<'_>,
+) {
+    if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
+        if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
+            for arg in a.args {
+                if !matches!(arg, GenericArg::Lifetime(_)) {
+                    return;
+                }
+            }
+        }
+    }
+    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)),
+        _ => false,
+    };
+
+    if should_emit {
+        let struct_span = cx.tcx.def_span(adt_def.did());
+        span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
+            diag.span_suggestion_hidden(
+                item.span,
+                "remove the manual implementation...",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
+            diag.span_suggestion(
+                struct_span.shrink_to_lo(),
+                "...and instead derive it",
+                "#[derive(Default)]\n".to_string(),
+                Applicability::MachineApplicable,
+            );
+        });
+    }
+}
+
+fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) {
+    if_chain! {
+        if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind;
+        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res;
+        if let variant_id = cx.tcx.parent(id);
+        if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id);
+        if variant_def.fields.is_empty();
+        if !variant_def.is_field_list_non_exhaustive();
+
+        then {
+            let enum_span = cx.tcx.def_span(adt_def.did());
+            let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
+            let variant_span = cx.tcx.def_span(variant_def.def_id);
+            let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
+            span_lint_and_then(
+                cx,
+                DERIVABLE_IMPLS,
+                item.span,
+                "this `impl` can be derived",
+                |diag| {
+                    diag.span_suggestion_hidden(
+                        item.span,
+                        "remove the manual implementation...",
+                        String::new(),
+                        Applicability::MachineApplicable
+                    );
+                    diag.span_suggestion(
+                        enum_span.shrink_to_lo(),
+                        "...and instead derive it...",
+                        format!(
+                            "#[derive(Default)]\n{indent}",
+                            indent = " ".repeat(indent_enum),
+                        ),
+                        Applicability::MachineApplicable
+                    );
+                    diag.span_suggestion(
+                        variant_span.shrink_to_lo(),
+                        "...and mark the default variant",
+                        format!(
+                            "#[default]\n{indent}",
+                            indent = " ".repeat(indent_variant),
+                        ),
+                        Applicability::MachineApplicable
+                    );
+                }
+            );
+        }
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if_chain! {
@@ -83,49 +189,16 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             if !attrs.iter().any(|attr| attr.doc_str().is_some());
             if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
             if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
-            if adt_def.is_struct();
-            then {
-                if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
-                    if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
-                        for arg in a.args {
-                            if !matches!(arg, GenericArg::Lifetime(_)) {
-                                return;
-                            }
-                        }
-                    }
-                }
-                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)),
-                    _ => false,
-                };
 
-                if should_emit {
-                    let struct_span = cx.tcx.def_span(adt_def.did());
-                    span_lint_and_then(
-                        cx,
-                        DERIVABLE_IMPLS,
-                        item.span,
-                        "this `impl` can be derived",
-                        |diag| {
-                            diag.span_suggestion_hidden(
-                                item.span,
-                                "remove the manual implementation...",
-                                String::new(),
-                                Applicability::MachineApplicable
-                            );
-                            diag.span_suggestion(
-                                struct_span.shrink_to_lo(),
-                                "...and instead derive it",
-                                "#[derive(Default)]\n".to_string(),
-                                Applicability::MachineApplicable
-                            );
-                        }
-                    );
+            then {
+                if adt_def.is_struct() {
+                    check_struct(cx, item, self_ty, func_expr, adt_def);
+                } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
+                    check_enum(cx, item, func_expr, adt_def);
                 }
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index cf3483d4c00..f4b15e0916d 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, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
-    Ty, TyCtxt,
+    self, Binder, BoundConstness, Clause, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind,
+    TraitPredicate, Ty, TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -46,7 +46,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     #[clippy::version = "pre 1.29.0"]
-    pub DERIVE_HASH_XOR_EQ,
+    pub DERIVED_HASH_WITH_MANUAL_EQ,
     correctness,
     "deriving `Hash` but implementing `PartialEq` explicitly"
 }
@@ -197,7 +197,7 @@ declare_clippy_lint! {
 
 declare_lint_pass!(Derive => [
     EXPL_IMPL_CLONE_ON_COPY,
-    DERIVE_HASH_XOR_EQ,
+    DERIVED_HASH_WITH_MANUAL_EQ,
     DERIVE_ORD_XOR_PARTIAL_ORD,
     UNSAFE_DERIVE_DESERIALIZE,
     DERIVE_PARTIAL_EQ_WITHOUT_EQ
@@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
     }
 }
 
-/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
+/// Implementation of the `DERIVED_HASH_WITH_MANUAL_EQ` lint.
 fn check_hash_peq<'tcx>(
     cx: &LateContext<'tcx>,
     span: Span,
@@ -243,7 +243,7 @@ fn check_hash_peq<'tcx>(
             cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
                 let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
 
-                if peq_is_automatically_derived == hash_is_automatically_derived {
+                if !hash_is_automatically_derived || peq_is_automatically_derived {
                     return;
                 }
 
@@ -252,17 +252,11 @@ fn check_hash_peq<'tcx>(
                 // Only care about `impl PartialEq<Foo> for Foo`
                 // For `impl PartialEq<B> for A, input_types is [A, B]
                 if trait_ref.substs.type_at(1) == ty {
-                    let mess = if peq_is_automatically_derived {
-                        "you are implementing `Hash` explicitly but have derived `PartialEq`"
-                    } else {
-                        "you are deriving `Hash` but have implemented `PartialEq` explicitly"
-                    };
-
                     span_lint_and_then(
                         cx,
-                        DERIVE_HASH_XOR_EQ,
+                        DERIVED_HASH_WITH_MANUAL_EQ,
                         span,
-                        mess,
+                        "you are deriving `Hash` but have implemented `PartialEq` explicitly",
                         |diag| {
                             if let Some(local_def_id) = impl_id.as_local() {
                                 let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
@@ -366,6 +360,15 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
     if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) {
         return;
     }
+    // `#[repr(packed)]` structs with type/const parameters can't derive `Clone`.
+    // https://github.com/rust-lang/rust-clippy/issues/10188
+    if ty_adt.repr().packed()
+        && ty_subs
+            .iter()
+            .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
+    {
+        return;
+    }
 
     span_lint_and_note(
         cx,
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 4721a7b3705..11e1bcdf12d 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
             let is_copy = is_copy(cx, arg_ty);
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             let (lint, msg) = match fn_name {
-                sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY),
+                sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
                 sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
                 sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
                 sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
diff --git a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
index 08bf80a4229..c3a020433de 100644
--- a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
@@ -45,7 +45,7 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
                         span_after_ident,
                         "remove the brackets",
                         ";",
-                        Applicability::MachineApplicable);
+                        Applicability::Unspecified);
                     },
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index dcd8ca81ae8..d8e2ae02c5a 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -639,7 +639,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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));
-    store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls));
+    store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(msrv())));
     store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
     store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
     store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 27ba27202bf..3bca93d80aa 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(
 
                 let skip = if starts_at_zero {
                     String::new()
-                } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start) {
+                } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
                     return;
                 } else {
                     format!(".skip({})", snippet(cx, start.span, ".."))
@@ -109,7 +109,7 @@ pub(super) fn check<'tcx>(
 
                     if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
                         String::new()
-                    } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr) {
+                    } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
                         return;
                     } else {
                         match limits {
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index f4b47808dfa..744fd61bd13 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -1,6 +1,7 @@
 use super::SINGLE_ELEMENT_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, snippet_with_applicability};
+use clippy_utils::visitors::contains_break_or_continue;
 use if_chain::if_chain;
 use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_ast::Mutability;
@@ -67,6 +68,7 @@ pub(super) fn check<'tcx>(
     if_chain! {
         if let ExprKind::Block(block, _) = body.kind;
         if !block.stmts.is_empty();
+        if !contains_break_or_continue(body);
         then {
             let mut applicability = Applicability::MachineApplicable;
             let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index d226c0bba65..0b3bf22743f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -1,7 +1,10 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{indent_of, reindent_multiline};
 use clippy_utils::ty::is_type_lang_item;
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
+use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
 use rustc_span::{source_map::Spanned, Span};
@@ -15,6 +18,15 @@ pub(super) fn check<'tcx>(
     recv: &'tcx Expr<'_>,
     arg: &'tcx Expr<'_>,
 ) {
+    if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
+        if matches!(
+            path_segment.ident.name.as_str(),
+            "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
+        ) {
+            return;
+        }
+    }
+
     if_chain! {
         if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
@@ -28,13 +40,37 @@ pub(super) fn check<'tcx>(
         let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
         if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
         then {
-            span_lint_and_help(
+            span_lint_and_then(
                 cx,
                 CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
-                call_span,
+                recv.span.to(call_span),
                 "case-sensitive file extension comparison",
-                None,
-                "consider using a case-insensitive comparison instead",
+                |diag| {
+                    diag.help("consider using a case-insensitive comparison instead");
+                    if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
+
+                        if !cx.typeck_results().expr_ty(recv).is_ref() {
+                            recv_source = format!("&{recv_source}");
+                        }
+
+                        let suggestion_source = reindent_multiline(
+                            format!(
+                                "std::path::Path::new({})
+                                    .extension()
+                                    .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
+                                recv_source, ext_str.strip_prefix('.').unwrap()).into(),
+                            true,
+                            Some(indent_of(cx, call_span).unwrap_or(0) + 4)
+                        );
+
+                        diag.span_suggestion(
+                            recv.span.to(call_span),
+                            "use std::path::Path",
+                            suggestion_source,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 7c7938dd2e8..3795c0ec250 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -6,7 +6,7 @@ use clippy_utils::ty::is_copy;
 use rustc_errors::Applicability;
 use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, adjustment::Adjust};
+use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
 use rustc_span::symbol::{sym, Symbol};
 
 use super::CLONE_DOUBLE_REF;
@@ -47,10 +47,10 @@ pub(super) fn check(
                 cx,
                 CLONE_DOUBLE_REF,
                 expr.span,
-                &format!(
+                &with_forced_trimmed_paths!(format!(
                     "using `clone` on a double-reference; \
                     this will copy the reference of type `{ty}` instead of cloning the inner type"
-                ),
+                )),
                 |diag| {
                     if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
                         let mut ty = innermost;
@@ -61,11 +61,11 @@ pub(super) fn check(
                         }
                         let refs = "&".repeat(n + 1);
                         let derefs = "*".repeat(n);
-                        let explicit = format!("<{refs}{ty}>::clone({snip})");
+                        let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})"));
                         diag.span_suggestion(
                             expr.span,
                             "try dereferencing it",
-                            format!("{refs}({derefs}{}).clone()", snip.deref()),
+                            with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())),
                             Applicability::MaybeIncorrect,
                         );
                         diag.span_suggestion(
@@ -129,7 +129,9 @@ pub(super) fn check(
             cx,
             CLONE_ON_COPY,
             expr.span,
-            &format!("using `clone` on type `{ty}` which implements the `Copy` trait"),
+            &with_forced_trimmed_paths!(format!(
+                "using `clone` on type `{ty}` which implements the `Copy` trait"
+            )),
             help,
             sugg,
             app,
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index f888c58a72d..fc80f2eeae0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -30,12 +30,12 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
             match closure_expr.kind {
                 hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
                     if_chain! {
-                    if ident.name == method_name;
-                    if let hir::ExprKind::Path(path) = &receiver.kind;
-                    if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
-                    then {
-                        return arg_id == *local
-                    }
+                        if ident.name == method_name;
+                        if let hir::ExprKind::Path(path) = &receiver.kind;
+                        if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
+                        then {
+                            return arg_id == *local
+                        }
                     }
                     false
                 },
@@ -92,92 +92,92 @@ pub(super) fn check(
     }
 
     if_chain! {
-            if is_trait_method(cx, map_recv, sym::Iterator);
-
-            // filter(|x| ...is_some())...
-            if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
-            let filter_body = cx.tcx.hir().body(filter_body_id);
-            if let [filter_param] = filter_body.params;
-            // optional ref pattern: `filter(|&x| ..)`
-            let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
-                (ref_pat, true)
-            } else {
-                (filter_param.pat, false)
+        if is_trait_method(cx, map_recv, sym::Iterator);
+
+        // filter(|x| ...is_some())...
+        if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
+        let filter_body = cx.tcx.hir().body(filter_body_id);
+        if let [filter_param] = filter_body.params;
+        // optional ref pattern: `filter(|&x| ..)`
+        let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
+            (ref_pat, true)
+        } else {
+            (filter_param.pat, false)
+        };
+        // closure ends with is_some() or is_ok()
+        if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
+        if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
+        if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
+        if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
+            Some(false)
+        } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
+            Some(true)
+        } else {
+            None
+        };
+        if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
+
+        // ...map(|x| ...unwrap())
+        if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
+        let map_body = cx.tcx.hir().body(map_body_id);
+        if let [map_param] = map_body.params;
+        if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
+        // closure ends with expect() or unwrap()
+        if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
+        if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
+
+        // .filter(..).map(|y| f(y).copied().unwrap())
+        //                     ~~~~
+        let map_arg_peeled = match map_arg.kind {
+            ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
+                original_arg
+            },
+            _ => map_arg,
+        };
+
+        // .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
+        let simple_equal = path_to_local_id(filter_arg, filter_param_id)
+            && path_to_local_id(map_arg_peeled, map_param_id);
+
+        let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
+            // in `filter(|x| ..)`, replace `*x` with `x`
+            let a_path = if_chain! {
+                if !is_filter_param_ref;
+                if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
+                then { expr_path } else { a }
             };
-            // closure ends with is_some() or is_ok()
-            if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
-            if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
-            if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
-            if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
-                Some(false)
-            } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
-                Some(true)
+            // let the filter closure arg and the map closure arg be equal
+            path_to_local_id(a_path, filter_param_id)
+                && path_to_local_id(b, map_param_id)
+                && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
+        };
+
+        if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
+        then {
+            let span = filter_span.with_hi(expr.span.hi());
+            let (filter_name, lint) = if is_find {
+                ("find", MANUAL_FIND_MAP)
             } else {
-                None
-            };
-            if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
-
-            // ...map(|x| ...unwrap())
-            if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
-            let map_body = cx.tcx.hir().body(map_body_id);
-            if let [map_param] = map_body.params;
-            if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
-            // closure ends with expect() or unwrap()
-            if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
-            if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
-
-            // .filter(..).map(|y| f(y).copied().unwrap())
-            //                     ~~~~
-            let map_arg_peeled = match map_arg.kind {
-                ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
-                    original_arg
-                },
-                _ => map_arg,
+                ("filter", MANUAL_FILTER_MAP)
             };
+            let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
+            let (to_opt, deref) = if is_result {
+                (".ok()", String::new())
+            } else {
+                let derefs = cx.typeck_results()
+                    .expr_adjustments(map_arg)
+                    .iter()
+                    .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
+                    .count();
 
-            // .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
-            let simple_equal = path_to_local_id(filter_arg, filter_param_id)
-                && path_to_local_id(map_arg_peeled, map_param_id);
-
-            let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
-                // in `filter(|x| ..)`, replace `*x` with `x`
-                let a_path = if_chain! {
-                    if !is_filter_param_ref;
-                    if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
-                    then { expr_path } else { a }
-                };
-                // let the filter closure arg and the map closure arg be equal
-                path_to_local_id(a_path, filter_param_id)
-                    && path_to_local_id(b, map_param_id)
-                    && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
+                ("", "*".repeat(derefs))
             };
-
-            if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
-            then {
-                let span = filter_span.with_hi(expr.span.hi());
-                let (filter_name, lint) = if is_find {
-                    ("find", MANUAL_FIND_MAP)
-                } else {
-                    ("filter", MANUAL_FILTER_MAP)
-                };
-                let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
-                let (to_opt, deref) = if is_result {
-                    (".ok()", String::new())
-                } else {
-                    let derefs = cx.typeck_results()
-                        .expr_adjustments(map_arg)
-                        .iter()
-                        .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
-                        .count();
-
-                    ("", "*".repeat(derefs))
-                };
-                let sugg = format!(
-                    "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
-                    snippet(cx, map_arg.span, ".."),
-                );
-                span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
-            }
+            let sugg = format!(
+                "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
+                snippet(cx, map_arg.span, ".."),
+            );
+            span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 2244ebfb129..c87f5daab6f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::is_local_used;
-use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
+use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
 use rustc_span::sym;
@@ -30,9 +30,9 @@ pub(super) fn check<'tcx>(
         if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
         if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
 
-        let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
-            (key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
-            (PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
+        let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
+            (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
+            (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
             _ => return,
         };
 
@@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(
             if_chain! {
                 if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
                 if let [local_ident] = path.segments;
-                if local_ident.ident.as_str() == binded_ident.as_str();
+                if local_ident.ident.as_str() == bound_ident.as_str();
 
                 then {
                     span_lint_and_sugg(
@@ -60,13 +60,23 @@ pub(super) fn check<'tcx>(
                         applicability,
                     );
                 } else {
+                    let ref_annotation = if annotation.0 == ByRef::Yes {
+                        "ref "
+                    } else {
+                        ""
+                    };
+                    let mut_annotation = if annotation.1 == Mutability::Mut {
+                        "mut "
+                    } else {
+                        ""
+                    };
                     span_lint_and_sugg(
                         cx,
                         ITER_KV_MAP,
                         expr.span,
                         &format!("iterating on a map's {replacement_kind}s"),
                         "try",
-                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
+                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
                             snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
                         applicability,
                     );
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
index 15c1c618c51..fe88fa41fd9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
@@ -5,7 +5,7 @@ use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, print::with_forced_trimmed_paths};
 use rustc_span::sym;
 
 use super::SUSPICIOUS_TO_OWNED;
@@ -24,7 +24,9 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
                 cx,
                 SUSPICIOUS_TO_OWNED,
                 expr.span,
-                &format!("this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"),
+                &with_forced_trimmed_paths!(format!(
+                    "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
+                )),
                 "consider using, depending on intent",
                 format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
                 app,
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index 09cb5333176..dc866ab6373 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -1,6 +1,6 @@
 //! Checks for uses of mutex where an atomic value could be used
 //!
-//! This lint is **warn** by default
+//! This lint is **allow** by default
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_diagnostic_item;
@@ -20,6 +20,10 @@ declare_clippy_lint! {
     /// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
     /// faster.
     ///
+    /// On the other hand, `Mutex`es are, in general, easier to
+    /// verify correctness. An atomic does not behave the same as
+    /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s commentary for more details.
+    ///
     /// ### Known problems
     /// This lint cannot detect if the mutex is actually used
     /// for waiting before a critical section.
@@ -39,8 +43,8 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "pre 1.29.0"]
     pub MUTEX_ATOMIC,
-    nursery,
-    "using a mutex where an atomic value could be used instead"
+    restriction,
+    "using a mutex where an atomic value could be used instead."
 }
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index 4fbc8398e37..cff82b875f1 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -2,7 +2,7 @@ use super::ARITHMETIC_SIDE_EFFECTS;
 use clippy_utils::{
     consts::{constant, constant_simple},
     diagnostics::span_lint,
-    peel_hir_expr_refs,
+    peel_hir_expr_refs, peel_hir_expr_unary,
 };
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -98,8 +98,11 @@ impl ArithmeticSideEffects {
     }
 
     /// If `expr` is not a literal integer like `1`, returns `None`.
+    ///
+    /// Returns the absolute value of the expression, if this is an integer literal.
     fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
-        if let hir::ExprKind::Lit(ref lit) = expr.kind && let ast::LitKind::Int(n, _) = lit.node {
+        let actual = peel_hir_expr_unary(expr).0;
+        if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
             Some(n)
         }
         else {
@@ -123,12 +126,12 @@ impl ArithmeticSideEffects {
         if !matches!(
             op.node,
             hir::BinOpKind::Add
-                | hir::BinOpKind::Sub
-                | hir::BinOpKind::Mul
                 | hir::BinOpKind::Div
+                | hir::BinOpKind::Mul
                 | hir::BinOpKind::Rem
                 | hir::BinOpKind::Shl
                 | hir::BinOpKind::Shr
+                | hir::BinOpKind::Sub
         ) {
             return;
         };
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 0a1b9d173cf..fc655fe2d0b 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -103,7 +103,7 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for range expressions `x..y` where both `x` and `y`
-    /// are constant and `x` is greater or equal to `y`.
+    /// are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop.
     ///
     /// ### Why is this bad?
     /// Empty ranges yield no values so iterating them is a no-op.
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 0e7c5cca724..c1677fb3da1 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 // `res = clone(arg)` can be turned into `res = move arg;`
                 // if `arg` is the only borrow of `cloned` at this point.
 
-                if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg], cloned, loc) {
+                if cannot_move_out || !possible_borrower.only_borrowers(&[arg], cloned, loc) {
                     continue;
                 }
 
@@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 // StorageDead(pred_arg);
                 // res = to_path_buf(cloned);
                 // ```
-                if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg, cloned], local, loc) {
+                if cannot_move_out || !possible_borrower.only_borrowers(&[arg, cloned], local, loc) {
                     continue;
                 }
 
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 72c25592609..9f487dedb8c 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -9,6 +9,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::box_vec", "clippy::box_collection"),
     ("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
     ("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
+    ("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"),
     ("clippy::disallowed_method", "clippy::disallowed_methods"),
     ("clippy::disallowed_type", "clippy::disallowed_types"),
     ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index d4d50660520..bbbd9e4989e 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -210,22 +210,25 @@ fn check_final_expr<'tcx>(
             // if desugar of `do yeet`, don't lint
             if let Some(inner_expr) = inner
                 && let ExprKind::Call(path_expr, _) = inner_expr.kind
-                && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind {
-                    return;
+                && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
+            {
+                return;
             }
-            if cx.tcx.hir().attrs(expr.hir_id).is_empty() {
-                let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
-                if !borrows {
-                    // check if expr return nothing
-                    let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
-                        extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
-                    } else {
-                        peeled_drop_expr.span
-                    };
-
-                    emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
-                }
+            if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
+                return;
+            }
+            let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
+            if borrows {
+                return;
             }
+            // check if expr return nothing
+            let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
+                extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
+            } else {
+                peeled_drop_expr.span
+            };
+
+            emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
         },
         ExprKind::If(_, then, else_clause_opt) => {
             check_block_return(cx, &then.kind, semi_spans.clone());
@@ -292,7 +295,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
         {
             ControlFlow::Break(())
         } else {
-            ControlFlow::Continue(Descend::from(!expr.span.from_expansion()))
+            ControlFlow::Continue(Descend::from(!e.span.from_expansion()))
         }
     })
     .is_some()
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index c14f056a1f2..229478b7ce3 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -127,7 +127,7 @@ declare_clippy_lint! {
     /// `Vec` or a `VecDeque` (formerly called `RingBuf`).
     ///
     /// ### Why is this bad?
-    /// Gankro says:
+    /// Gankra says:
     ///
     /// > The TL;DR of `LinkedList` is that it's built on a massive amount of
     /// pointers and indirection.
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 42bccc7212b..f864c520302 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -1,9 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::visitors::is_local_used;
 use if_chain::if_chain;
-use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
+use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use std::ops::ControlFlow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -57,6 +59,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
         let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
         let parent_item = cx.tcx.hir().expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
+        let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
+            clippy_utils::visitors::for_each_expr(body.value, |e| {
+                if let Some(macro_call) = root_macro_call_first_node(cx, e) {
+                    if cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(())
+                    }
+                } else {
+                    ControlFlow::Continue(())
+                }
+            })
+            .is_some()
+        };
         if_chain! {
             if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
             if assoc_item.fn_has_self_parameter;
@@ -65,6 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             let body = cx.tcx.hir().body(*body_id);
             if let [self_param, ..] = body.params;
             if !is_local_used(cx, body, self_param.pat.hir_id);
+            if !contains_todo(cx, body);
             then {
                 span_lint_and_help(
                     cx,
@@ -72,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
                     self_param.span,
                     "unused `self` argument",
                     None,
-                    "consider refactoring to a associated function",
+                    "consider refactoring to an associated function",
                 );
             }
         }
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 c86f24cbd37..c4d8c28f060 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
@@ -1058,7 +1058,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -
 fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
     let map = cx.tcx.hir();
 
-    match map.find_parent((hir_id)) {
+    match map.find_parent(hir_id) {
         Some(hir::Node::Local(local)) => Some(local),
         Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id),
         _ => None,
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 8290fe9ecb4..7a4a9036dd3 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -22,6 +22,9 @@ extern crate rustc_ast;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
 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)]
+extern crate rustc_driver;
 extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_hir_typeck;
@@ -116,6 +119,8 @@ use crate::consts::{constant, Constant};
 use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
 use crate::visitors::for_each_expr;
 
+use rustc_middle::hir::nested_filter;
+
 #[macro_export]
 macro_rules! extract_msrv_attr {
     ($context:ident) => {
@@ -1253,22 +1258,33 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
     }
 }
 
-pub struct ContainsName {
+pub struct ContainsName<'a, 'tcx> {
+    pub cx: &'a LateContext<'tcx>,
     pub name: Symbol,
     pub result: bool,
 }
 
-impl<'tcx> Visitor<'tcx> for ContainsName {
+impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
+    type NestedFilter = nested_filter::OnlyBodies;
+
     fn visit_name(&mut self, name: Symbol) {
         if self.name == name {
             self.result = true;
         }
     }
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
+    }
 }
 
 /// Checks if an `Expr` contains a certain name.
-pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
-    let mut cn = ContainsName { name, result: false };
+pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
+    let mut cn = ContainsName {
+        name,
+        result: false,
+        cx,
+    };
     cn.visit_expr(expr);
     cn.result
 }
@@ -1304,6 +1320,7 @@ pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId)
     }
 }
 
+/// Gets the enclosing block, if any.
 pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
     let map = &cx.tcx.hir();
     let enclosing_node = map
@@ -2244,6 +2261,18 @@ pub fn peel_n_hir_expr_refs<'a>(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'
     (e, count - remaining)
 }
 
+/// Peels off all unary operators of an expression. Returns the underlying expression and the number
+/// of operators removed.
+pub fn peel_hir_expr_unary<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
+    let mut count: usize = 0;
+    let mut curr_expr = expr;
+    while let ExprKind::Unary(_, local_expr) = curr_expr.kind {
+        count = count.wrapping_add(1);
+        curr_expr = local_expr;
+    }
+    (curr_expr, count)
+}
+
 /// Peels off all references on the expression. Returns the underlying expression and the number of
 /// references removed.
 pub fn peel_hir_expr_refs<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index 395d46e7a2f..9adae773389 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -1,16 +1,11 @@
-use super::possible_origin::PossibleOriginVisitor;
+use super::{possible_origin::PossibleOriginVisitor, transitive_relation::TransitiveRelation};
 use crate::ty::is_copy;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::{BitSet, HybridBitSet};
 use rustc_lint::LateContext;
-use rustc_middle::mir::{
-    self, visit::Visitor as _, BasicBlock, Local, Location, Mutability, Statement, StatementKind, Terminator,
-};
-use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt};
-use rustc_mir_dataflow::{
-    fmt::DebugWithContext, impls::MaybeStorageLive, lattice::JoinSemiLattice, Analysis, AnalysisDomain,
-    CallReturnPlaces, ResultsCursor,
-};
+use rustc_middle::mir::{self, visit::Visitor as _, Mutability};
+use rustc_middle::ty::{self, visit::TypeVisitor};
+use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor};
 use std::borrow::Cow;
 use std::ops::ControlFlow;
 
@@ -18,120 +13,78 @@ use std::ops::ControlFlow;
 /// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
 /// possible borrowers of `a`.
 #[allow(clippy::module_name_repetitions)]
-struct PossibleBorrowerAnalysis<'b, 'tcx> {
-    tcx: TyCtxt<'tcx>,
+struct PossibleBorrowerVisitor<'a, 'b, 'tcx> {
+    possible_borrower: TransitiveRelation,
     body: &'b mir::Body<'tcx>,
+    cx: &'a LateContext<'tcx>,
     possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
-struct PossibleBorrowerState {
-    map: FxIndexMap<Local, BitSet<Local>>,
-    domain_size: usize,
-}
-
-impl PossibleBorrowerState {
-    fn new(domain_size: usize) -> Self {
+impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
+    fn new(
+        cx: &'a LateContext<'tcx>,
+        body: &'b mir::Body<'tcx>,
+        possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+    ) -> Self {
         Self {
-            map: FxIndexMap::default(),
-            domain_size,
+            possible_borrower: TransitiveRelation::default(),
+            cx,
+            body,
+            possible_origin,
         }
     }
 
-    #[allow(clippy::similar_names)]
-    fn add(&mut self, borrowed: Local, borrower: Local) {
-        self.map
-            .entry(borrowed)
-            .or_insert(BitSet::new_empty(self.domain_size))
-            .insert(borrower);
-    }
-}
-
-impl<C> DebugWithContext<C> for PossibleBorrowerState {
-    fn fmt_with(&self, _ctxt: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        <_ as std::fmt::Debug>::fmt(self, f)
-    }
-    fn fmt_diff_with(&self, _old: &Self, _ctxt: &C, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        unimplemented!()
-    }
-}
+    fn into_map(
+        self,
+        cx: &'a LateContext<'tcx>,
+        maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
+    ) -> PossibleBorrowerMap<'b, 'tcx> {
+        let mut map = FxHashMap::default();
+        for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
+            if is_copy(cx, self.body.local_decls[row].ty) {
+                continue;
+            }
 
-impl JoinSemiLattice for PossibleBorrowerState {
-    fn join(&mut self, other: &Self) -> bool {
-        let mut changed = false;
-        for (&borrowed, borrowers) in other.map.iter() {
+            let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len());
+            borrowers.remove(mir::Local::from_usize(0));
             if !borrowers.is_empty() {
-                changed |= self
-                    .map
-                    .entry(borrowed)
-                    .or_insert(BitSet::new_empty(self.domain_size))
-                    .union(borrowers);
+                map.insert(row, borrowers);
             }
         }
-        changed
-    }
-}
-
-impl<'b, 'tcx> AnalysisDomain<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
-    type Domain = PossibleBorrowerState;
-
-    const NAME: &'static str = "possible_borrower";
-
-    fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
-        PossibleBorrowerState::new(body.local_decls.len())
-    }
-
-    fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _entry_set: &mut Self::Domain) {}
-}
 
-impl<'b, 'tcx> PossibleBorrowerAnalysis<'b, 'tcx> {
-    fn new(
-        tcx: TyCtxt<'tcx>,
-        body: &'b mir::Body<'tcx>,
-        possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
-    ) -> Self {
-        Self {
-            tcx,
-            body,
-            possible_origin,
+        let bs = BitSet::new_empty(self.body.local_decls.len());
+        PossibleBorrowerMap {
+            map,
+            maybe_live,
+            bitset: (bs.clone(), bs),
         }
     }
 }
 
-impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
-    fn apply_call_return_effect(
-        &self,
-        _state: &mut Self::Domain,
-        _block: BasicBlock,
-        _return_places: CallReturnPlaces<'_, 'tcx>,
-    ) {
-    }
-
-    fn apply_statement_effect(&self, state: &mut Self::Domain, statement: &Statement<'tcx>, _location: Location) {
-        if let StatementKind::Assign(box (place, rvalue)) = &statement.kind {
-            let lhs = place.local;
-            match rvalue {
-                mir::Rvalue::Ref(_, _, borrowed) => {
-                    state.add(borrowed.local, lhs);
-                },
-                other => {
-                    if ContainsRegion
-                        .visit_ty(place.ty(&self.body.local_decls, self.tcx).ty)
-                        .is_continue()
-                    {
-                        return;
+impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> {
+    fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
+        let lhs = place.local;
+        match rvalue {
+            mir::Rvalue::Ref(_, _, borrowed) => {
+                self.possible_borrower.add(borrowed.local, lhs);
+            },
+            other => {
+                if ContainsRegion
+                    .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
+                    .is_continue()
+                {
+                    return;
+                }
+                rvalue_locals(other, |rhs| {
+                    if lhs != rhs {
+                        self.possible_borrower.add(rhs, lhs);
                     }
-                    rvalue_locals(other, |rhs| {
-                        if lhs != rhs {
-                            state.add(rhs, lhs);
-                        }
-                    });
-                },
-            }
+                });
+            },
         }
     }
 
-    fn apply_terminator_effect(&self, state: &mut Self::Domain, terminator: &Terminator<'tcx>, _location: Location) {
+    fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) {
         if let mir::TerminatorKind::Call {
             args,
             destination: mir::Place { local: dest, .. },
@@ -171,10 +124,10 @@ impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
 
             for y in mutable_variables {
                 for x in &immutable_borrowers {
-                    state.add(*x, y);
+                    self.possible_borrower.add(*x, y);
                 }
                 for x in &mutable_borrowers {
-                    state.add(*x, y);
+                    self.possible_borrower.add(*x, y);
                 }
             }
         }
@@ -210,98 +163,73 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
     }
 }
 
-/// Result of `PossibleBorrowerAnalysis`.
+/// Result of `PossibleBorrowerVisitor`.
 #[allow(clippy::module_name_repetitions)]
 pub struct PossibleBorrowerMap<'b, 'tcx> {
-    body: &'b mir::Body<'tcx>,
-    possible_borrower: ResultsCursor<'b, 'tcx, PossibleBorrowerAnalysis<'b, 'tcx>>,
-    maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'b>>,
-    pushed: BitSet<Local>,
-    stack: Vec<Local>,
+    /// Mapping `Local -> its possible borrowers`
+    pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+    maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
+    // Caches to avoid allocation of `BitSet` on every query
+    pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
 }
 
-impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
-    pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
+impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
+    pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
         let possible_origin = {
             let mut vis = PossibleOriginVisitor::new(mir);
             vis.visit_body(mir);
             vis.into_map(cx)
         };
-        let possible_borrower = PossibleBorrowerAnalysis::new(cx.tcx, mir, possible_origin)
+        let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
             .into_engine(cx.tcx, mir)
-            .pass_name("possible_borrower")
+            .pass_name("redundant_clone")
             .iterate_to_fixpoint()
             .into_results_cursor(mir);
-        let maybe_live = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
-            .into_engine(cx.tcx, mir)
-            .pass_name("possible_borrower")
-            .iterate_to_fixpoint()
-            .into_results_cursor(mir);
-        PossibleBorrowerMap {
-            body: mir,
-            possible_borrower,
-            maybe_live,
-            pushed: BitSet::new_empty(mir.local_decls.len()),
-            stack: Vec::with_capacity(mir.local_decls.len()),
-        }
+        let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
+        vis.visit_body(mir);
+        vis.into_map(cx, maybe_storage_live_result)
     }
 
-    /// Returns true if the set of borrowers of `borrowed` living at `at` includes no more than
-    /// `borrowers`.
-    /// Notes:
-    /// 1. It would be nice if `PossibleBorrowerMap` could store `cx` so that `at_most_borrowers`
-    /// would not require it to be passed in. But a `PossibleBorrowerMap` is stored in `LintPass`
-    /// `Dereferencing`, which outlives any `LateContext`.
-    /// 2. In all current uses of `at_most_borrowers`, `borrowers` is a slice of at most two
-    /// elements. Thus, `borrowers.contains(...)` is effectively a constant-time operation. If
-    /// `at_most_borrowers`'s uses were to expand beyond this, its implementation might have to be
-    /// adjusted.
-    pub fn at_most_borrowers(
+    /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
+    pub fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
+        self.bounded_borrowers(borrowers, borrowers, borrowed, at)
+    }
+
+    /// Returns true if the set of borrowers of `borrowed` living at `at` includes at least `below`
+    /// but no more than `above`.
+    pub fn bounded_borrowers(
         &mut self,
-        cx: &LateContext<'tcx>,
-        borrowers: &[mir::Local],
+        below: &[mir::Local],
+        above: &[mir::Local],
         borrowed: mir::Local,
         at: mir::Location,
     ) -> bool {
-        if is_copy(cx, self.body.local_decls[borrowed].ty) {
-            return true;
-        }
-
-        self.possible_borrower.seek_before_primary_effect(at);
-        self.maybe_live.seek_before_primary_effect(at);
-
-        let possible_borrower = &self.possible_borrower.get().map;
-        let maybe_live = &self.maybe_live;
-
-        self.pushed.clear();
-        self.stack.clear();
+        self.maybe_live.seek_after_primary_effect(at);
 
-        if let Some(borrowers) = possible_borrower.get(&borrowed) {
-            for b in borrowers.iter() {
-                if self.pushed.insert(b) {
-                    self.stack.push(b);
-                }
+        self.bitset.0.clear();
+        let maybe_live = &mut self.maybe_live;
+        if let Some(bitset) = self.map.get(&borrowed) {
+            for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) {
+                self.bitset.0.insert(b);
             }
         } else {
-            // Nothing borrows `borrowed` at `at`.
-            return true;
+            return false;
         }
 
-        while let Some(borrower) = self.stack.pop() {
-            if maybe_live.contains(borrower) && !borrowers.contains(&borrower) {
-                return false;
-            }
+        self.bitset.1.clear();
+        for b in below {
+            self.bitset.1.insert(*b);
+        }
 
-            if let Some(borrowers) = possible_borrower.get(&borrower) {
-                for b in borrowers.iter() {
-                    if self.pushed.insert(b) {
-                        self.stack.push(b);
-                    }
-                }
-            }
+        if !self.bitset.0.superset(&self.bitset.1) {
+            return false;
+        }
+
+        for b in above {
+            self.bitset.0.remove(*b);
         }
 
-        true
+        self.bitset.0.is_empty()
     }
 
     pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index ba5bc9c3135..dbf9f3b621d 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -20,8 +20,9 @@ macro_rules! msrv_aliases {
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
     1,65,0 { LET_ELSE }
-    1,62,0 { BOOL_THEN_SOME }
+    1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
     1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
+    1,55,0 { SEEK_REWIND }
     1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
@@ -45,7 +46,6 @@ msrv_aliases! {
     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,55,0 { SEEK_REWIND }
 }
 
 fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 9ca50105ae5..95eebab7567 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -47,7 +47,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 #[cfg(feature = "internal")]
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
 pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
-pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"];
 pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
 pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 #[cfg(feature = "internal")]
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 863fb60fcfc..14c01a60b4c 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -724,3 +724,14 @@ pub fn for_each_local_assignment<'tcx, B>(
         ControlFlow::Continue(())
     }
 }
+
+pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool {
+    for_each_expr(expr, |e| {
+        if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::Continue(())
+        }
+    })
+    .is_some()
+}
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 9399d422036..40a6f47095e 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2022-12-29"
+channel = "nightly-2023-01-12"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index bcc096c570e..d521e8d8839 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -256,11 +256,14 @@ pub fn main() {
     LazyLock::force(&ICE_HOOK);
     exit(rustc_driver::catch_with_exit_code(move || {
         let mut orig_args: Vec<String> = env::args().collect();
+        let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some();
 
         let sys_root_env = std::env::var("SYSROOT").ok();
         let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
             if let Some(sys_root) = sys_root_env {
-                args.extend(vec!["--sysroot".into(), sys_root]);
+                if !has_sysroot_arg {
+                    args.extend(vec!["--sysroot".into(), sys_root]);
+                }
             };
         };
 
diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs
index 818ff70b33f..a771d8b87c8 100644
--- a/src/tools/clippy/tests/integration.rs
+++ b/src/tools/clippy/tests/integration.rs
@@ -1,3 +1,12 @@
+//! This test is meant to only be run in CI. To run it locally use:
+//!
+//! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
+//!
+//! You can use a different `INTEGRATION` value to test different repositories.
+//!
+//! This test will clone the specified repository and run Clippy on it. The test succeeds, if
+//! Clippy doesn't produce an ICE. Lint warnings are ignored by this test.
+
 #![cfg(feature = "integration")]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
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 36db9e54a22..fb5b1b193f8 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
@@ -107,7 +107,7 @@ fn rhs_is_different() {
 fn unary() {
     // is explicitly on the list
     let _ = -OutOfNames;
-    // is specifically on the list
+    // is explicitly on the list
     let _ = -Foo;
     // not on the list
     let _ = -Bar;
diff --git a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
index 46efb86dcfc..859383a7119 100644
--- a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
@@ -1,99 +1,99 @@
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:5:22
    |
 LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
    |                      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::dbg-macro` implied by `-D warnings`
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:9:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     if n <= 1 {
    |        ~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:10:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |         1
    |
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:12:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |         n * factorial(n - 1)
    |
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:17:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     42;
    |     ~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:18:5
    |
 LL |     dbg!(dbg!(dbg!(42)));
    |     ^^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     dbg!(dbg!(42));
    |     ~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:19:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     foo(3) + factorial(4);
    |              ~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:20:5
    |
 LL |     dbg!(1, 2, dbg!(3, 4));
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     (1, 2, dbg!(3, 4));
    |     ~~~~~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:21:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index b5ed8988a51..918cf81c600 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -2,6 +2,7 @@
     clippy::assign_op_pattern,
     clippy::erasing_op,
     clippy::identity_op,
+    clippy::no_effect,
     clippy::op_ref,
     clippy::unnecessary_owned_empty_strings,
     arithmetic_overflow,
@@ -12,31 +13,95 @@
 
 use core::num::{Saturating, Wrapping};
 
+#[derive(Clone, Copy)]
 pub struct Custom;
 
 macro_rules! impl_arith {
-    ( $( $_trait:ident, $ty:ty, $method:ident; )* ) => {
+    ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
         $(
-            impl core::ops::$_trait<$ty> for Custom {
-                type Output = Self;
-                fn $method(self, _: $ty) -> Self::Output { Self }
+            impl core::ops::$_trait<$lhs> for $rhs {
+                type Output = Custom;
+                fn $method(self, _: $lhs) -> Self::Output { todo!() }
+            }
+        )*
+    }
+}
+
+macro_rules! impl_assign_arith {
+    ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
+        $(
+            impl core::ops::$_trait<$lhs> for $rhs {
+                fn $method(&mut self, _: $lhs) {}
             }
         )*
     }
 }
 
 impl_arith!(
-    Add, i32, add;
-    Div, i32, div;
-    Mul, i32, mul;
-    Sub, i32, sub;
-
-    Add, f64, add;
-    Div, f64, div;
-    Mul, f64, mul;
-    Sub, f64, sub;
+    Add, Custom, Custom, add;
+    Div, Custom, Custom, div;
+    Mul, Custom, Custom, mul;
+    Rem, Custom, Custom, rem;
+    Sub, Custom, Custom, sub;
+
+    Add, Custom, &Custom, add;
+    Div, Custom, &Custom, div;
+    Mul, Custom, &Custom, mul;
+    Rem, Custom, &Custom, rem;
+    Sub, Custom, &Custom, sub;
+
+    Add, &Custom, Custom, add;
+    Div, &Custom, Custom, div;
+    Mul, &Custom, Custom, mul;
+    Rem, &Custom, Custom, rem;
+    Sub, &Custom, Custom, sub;
+
+    Add, &Custom, &Custom, add;
+    Div, &Custom, &Custom, div;
+    Mul, &Custom, &Custom, mul;
+    Rem, &Custom, &Custom, rem;
+    Sub, &Custom, &Custom, sub;
+);
+
+impl_assign_arith!(
+    AddAssign, Custom, Custom, add_assign;
+    DivAssign, Custom, Custom, div_assign;
+    MulAssign, Custom, Custom, mul_assign;
+    RemAssign, Custom, Custom, rem_assign;
+    SubAssign, Custom, Custom, sub_assign;
+
+    AddAssign, Custom, &Custom, add_assign;
+    DivAssign, Custom, &Custom, div_assign;
+    MulAssign, Custom, &Custom, mul_assign;
+    RemAssign, Custom, &Custom, rem_assign;
+    SubAssign, Custom, &Custom, sub_assign;
+
+    AddAssign, &Custom, Custom, add_assign;
+    DivAssign, &Custom, Custom, div_assign;
+    MulAssign, &Custom, Custom, mul_assign;
+    RemAssign, &Custom, Custom, rem_assign;
+    SubAssign, &Custom, Custom, sub_assign;
+
+    AddAssign, &Custom, &Custom, add_assign;
+    DivAssign, &Custom, &Custom, div_assign;
+    MulAssign, &Custom, &Custom, mul_assign;
+    RemAssign, &Custom, &Custom, rem_assign;
+    SubAssign, &Custom, &Custom, sub_assign;
 );
 
+impl core::ops::Neg for Custom {
+    type Output = Custom;
+    fn neg(self) -> Self::Output {
+        todo!()
+    }
+}
+impl core::ops::Neg for &Custom {
+    type Output = Custom;
+    fn neg(self) -> Self::Output {
+        todo!()
+    }
+}
+
 pub fn association_with_structures_should_not_trigger_the_lint() {
     enum Foo {
         Bar = -2,
@@ -125,6 +190,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n *= &0;
     _n *= 1;
     _n *= &1;
+    _n += -0;
+    _n += &-0;
+    _n -= -0;
+    _n -= &-0;
+    _n /= -99;
+    _n /= &-99;
+    _n %= -99;
+    _n %= &-99;
+    _n *= -0;
+    _n *= &-0;
+    _n *= -1;
+    _n *= &-1;
 
     // Binary
     _n = _n + 0;
@@ -158,8 +235,9 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n = -&i32::MIN;
 }
 
-pub fn runtime_ops() {
+pub fn unknown_ops_or_runtime_ops_that_can_overflow() {
     let mut _n = i32::MAX;
+    let mut _custom = Custom;
 
     // Assign
     _n += 1;
@@ -172,6 +250,36 @@ pub fn runtime_ops() {
     _n %= &0;
     _n *= 2;
     _n *= &2;
+    _n += -1;
+    _n += &-1;
+    _n -= -1;
+    _n -= &-1;
+    _n /= -0;
+    _n /= &-0;
+    _n %= -0;
+    _n %= &-0;
+    _n *= -2;
+    _n *= &-2;
+    _custom += Custom;
+    _custom += &Custom;
+    _custom -= Custom;
+    _custom -= &Custom;
+    _custom /= Custom;
+    _custom /= &Custom;
+    _custom %= Custom;
+    _custom %= &Custom;
+    _custom *= Custom;
+    _custom *= &Custom;
+    _custom += -Custom;
+    _custom += &-Custom;
+    _custom -= -Custom;
+    _custom -= &-Custom;
+    _custom /= -Custom;
+    _custom /= &-Custom;
+    _custom %= -Custom;
+    _custom %= &-Custom;
+    _custom *= -Custom;
+    _custom *= &-Custom;
 
     // Binary
     _n = _n + 1;
@@ -193,36 +301,73 @@ pub fn runtime_ops() {
     _n = 23 + &85;
     _n = &23 + 85;
     _n = &23 + &85;
-
-    // Custom
-    let _ = Custom + 0;
-    let _ = Custom + 1;
-    let _ = Custom + 2;
-    let _ = Custom + 0.0;
-    let _ = Custom + 1.0;
-    let _ = Custom + 2.0;
-    let _ = Custom - 0;
-    let _ = Custom - 1;
-    let _ = Custom - 2;
-    let _ = Custom - 0.0;
-    let _ = Custom - 1.0;
-    let _ = Custom - 2.0;
-    let _ = Custom / 0;
-    let _ = Custom / 1;
-    let _ = Custom / 2;
-    let _ = Custom / 0.0;
-    let _ = Custom / 1.0;
-    let _ = Custom / 2.0;
-    let _ = Custom * 0;
-    let _ = Custom * 1;
-    let _ = Custom * 2;
-    let _ = Custom * 0.0;
-    let _ = Custom * 1.0;
-    let _ = Custom * 2.0;
+    _custom = _custom + _custom;
+    _custom = _custom + &_custom;
+    _custom = Custom + _custom;
+    _custom = &Custom + _custom;
+    _custom = _custom - Custom;
+    _custom = _custom - &Custom;
+    _custom = Custom - _custom;
+    _custom = &Custom - _custom;
+    _custom = _custom / Custom;
+    _custom = _custom / &Custom;
+    _custom = _custom % Custom;
+    _custom = _custom % &Custom;
+    _custom = _custom * Custom;
+    _custom = _custom * &Custom;
+    _custom = Custom * _custom;
+    _custom = &Custom * _custom;
+    _custom = Custom + &Custom;
+    _custom = &Custom + Custom;
+    _custom = &Custom + &Custom;
 
     // Unary
     _n = -_n;
     _n = -&_n;
+    _custom = -_custom;
+    _custom = -&_custom;
+}
+
+// Copied and pasted from the `integer_arithmetic` lint for comparison.
+pub fn integer_arithmetic() {
+    let mut i = 1i32;
+    let mut var1 = 0i32;
+    let mut var2 = -1i32;
+
+    1 + i;
+    i * 2;
+    1 % i / 2;
+    i - 2 + 2 - i;
+    -i;
+    i >> 1;
+    i << 1;
+
+    -1;
+    -(-1);
+
+    i & 1;
+    i | 1;
+    i ^ 1;
+
+    i += 1;
+    i -= 1;
+    i *= 2;
+    i /= 2;
+    i /= 0;
+    i /= -1;
+    i /= var1;
+    i /= var2;
+    i %= 2;
+    i %= 0;
+    i %= -1;
+    i %= var1;
+    i %= var2;
+    i <<= 3;
+    i >>= 2;
+
+    i |= 1;
+    i &= 1;
+    i ^= i;
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 9fe4b7cf28d..5e349f6b497 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:165:5
+  --> $DIR/arithmetic_side_effects.rs:243:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
@@ -7,328 +7,592 @@ LL |     _n += 1;
    = 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.rs:166:5
+  --> $DIR/arithmetic_side_effects.rs:244:5
    |
 LL |     _n += &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:167:5
+  --> $DIR/arithmetic_side_effects.rs:245:5
    |
 LL |     _n -= 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:168:5
+  --> $DIR/arithmetic_side_effects.rs:246:5
    |
 LL |     _n -= &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:169:5
+  --> $DIR/arithmetic_side_effects.rs:247:5
    |
 LL |     _n /= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:170:5
+  --> $DIR/arithmetic_side_effects.rs:248:5
    |
 LL |     _n /= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:171:5
+  --> $DIR/arithmetic_side_effects.rs:249:5
    |
 LL |     _n %= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:172:5
+  --> $DIR/arithmetic_side_effects.rs:250:5
    |
 LL |     _n %= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:173:5
+  --> $DIR/arithmetic_side_effects.rs:251:5
    |
 LL |     _n *= 2;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:174:5
+  --> $DIR/arithmetic_side_effects.rs:252:5
    |
 LL |     _n *= &2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:177:10
+  --> $DIR/arithmetic_side_effects.rs:253:5
+   |
+LL |     _n += -1;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:254:5
+   |
+LL |     _n += &-1;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:255:5
+   |
+LL |     _n -= -1;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:256:5
+   |
+LL |     _n -= &-1;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:257:5
+   |
+LL |     _n /= -0;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:258:5
+   |
+LL |     _n /= &-0;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:259:5
+   |
+LL |     _n %= -0;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:260:5
+   |
+LL |     _n %= &-0;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:261:5
+   |
+LL |     _n *= -2;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:262:5
+   |
+LL |     _n *= &-2;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:263:5
+   |
+LL |     _custom += Custom;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:264:5
+   |
+LL |     _custom += &Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:265:5
+   |
+LL |     _custom -= Custom;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:266:5
+   |
+LL |     _custom -= &Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:267:5
+   |
+LL |     _custom /= Custom;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:268:5
+   |
+LL |     _custom /= &Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:269:5
+   |
+LL |     _custom %= Custom;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:270:5
+   |
+LL |     _custom %= &Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:271:5
+   |
+LL |     _custom *= Custom;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:272:5
+   |
+LL |     _custom *= &Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:273:5
+   |
+LL |     _custom += -Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:274:5
+   |
+LL |     _custom += &-Custom;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:275:5
+   |
+LL |     _custom -= -Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:276:5
+   |
+LL |     _custom -= &-Custom;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:277:5
+   |
+LL |     _custom /= -Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:278:5
+   |
+LL |     _custom /= &-Custom;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:279:5
+   |
+LL |     _custom %= -Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:280:5
+   |
+LL |     _custom %= &-Custom;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:281:5
+   |
+LL |     _custom *= -Custom;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:282:5
+   |
+LL |     _custom *= &-Custom;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:285:10
    |
 LL |     _n = _n + 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:178:10
+  --> $DIR/arithmetic_side_effects.rs:286:10
    |
 LL |     _n = _n + &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:179:10
+  --> $DIR/arithmetic_side_effects.rs:287:10
    |
 LL |     _n = 1 + _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:180:10
+  --> $DIR/arithmetic_side_effects.rs:288:10
    |
 LL |     _n = &1 + _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:181:10
+  --> $DIR/arithmetic_side_effects.rs:289:10
    |
 LL |     _n = _n - 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:182:10
+  --> $DIR/arithmetic_side_effects.rs:290:10
    |
 LL |     _n = _n - &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:183:10
+  --> $DIR/arithmetic_side_effects.rs:291:10
    |
 LL |     _n = 1 - _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:184:10
+  --> $DIR/arithmetic_side_effects.rs:292:10
    |
 LL |     _n = &1 - _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:185:10
+  --> $DIR/arithmetic_side_effects.rs:293:10
    |
 LL |     _n = _n / 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:186:10
+  --> $DIR/arithmetic_side_effects.rs:294:10
    |
 LL |     _n = _n / &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:187:10
+  --> $DIR/arithmetic_side_effects.rs:295:10
    |
 LL |     _n = _n % 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:188:10
+  --> $DIR/arithmetic_side_effects.rs:296:10
    |
 LL |     _n = _n % &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:189:10
+  --> $DIR/arithmetic_side_effects.rs:297:10
    |
 LL |     _n = _n * 2;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:190:10
+  --> $DIR/arithmetic_side_effects.rs:298:10
    |
 LL |     _n = _n * &2;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:191:10
+  --> $DIR/arithmetic_side_effects.rs:299:10
    |
 LL |     _n = 2 * _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:192:10
+  --> $DIR/arithmetic_side_effects.rs:300:10
    |
 LL |     _n = &2 * _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:193:10
+  --> $DIR/arithmetic_side_effects.rs:301:10
    |
 LL |     _n = 23 + &85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:194:10
+  --> $DIR/arithmetic_side_effects.rs:302:10
    |
 LL |     _n = &23 + 85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:195:10
+  --> $DIR/arithmetic_side_effects.rs:303:10
    |
 LL |     _n = &23 + &85;
    |          ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:198:13
+  --> $DIR/arithmetic_side_effects.rs:304:15
    |
-LL |     let _ = Custom + 0;
-   |             ^^^^^^^^^^
+LL |     _custom = _custom + _custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:199:13
+  --> $DIR/arithmetic_side_effects.rs:305:15
    |
-LL |     let _ = Custom + 1;
-   |             ^^^^^^^^^^
+LL |     _custom = _custom + &_custom;
+   |               ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:200:13
+  --> $DIR/arithmetic_side_effects.rs:306:15
    |
-LL |     let _ = Custom + 2;
-   |             ^^^^^^^^^^
+LL |     _custom = Custom + _custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:201:13
+  --> $DIR/arithmetic_side_effects.rs:307:15
    |
-LL |     let _ = Custom + 0.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = &Custom + _custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:202:13
+  --> $DIR/arithmetic_side_effects.rs:308:15
    |
-LL |     let _ = Custom + 1.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = _custom - Custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:203:13
+  --> $DIR/arithmetic_side_effects.rs:309:15
    |
-LL |     let _ = Custom + 2.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = _custom - &Custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:204:13
+  --> $DIR/arithmetic_side_effects.rs:310:15
    |
-LL |     let _ = Custom - 0;
-   |             ^^^^^^^^^^
+LL |     _custom = Custom - _custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:205:13
+  --> $DIR/arithmetic_side_effects.rs:311:15
    |
-LL |     let _ = Custom - 1;
-   |             ^^^^^^^^^^
+LL |     _custom = &Custom - _custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:206:13
+  --> $DIR/arithmetic_side_effects.rs:312:15
    |
-LL |     let _ = Custom - 2;
-   |             ^^^^^^^^^^
+LL |     _custom = _custom / Custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:207:13
+  --> $DIR/arithmetic_side_effects.rs:313:15
    |
-LL |     let _ = Custom - 0.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = _custom / &Custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:208:13
+  --> $DIR/arithmetic_side_effects.rs:314:15
    |
-LL |     let _ = Custom - 1.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = _custom % Custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:209:13
+  --> $DIR/arithmetic_side_effects.rs:315:15
    |
-LL |     let _ = Custom - 2.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = _custom % &Custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:210:13
+  --> $DIR/arithmetic_side_effects.rs:316:15
    |
-LL |     let _ = Custom / 0;
-   |             ^^^^^^^^^^
+LL |     _custom = _custom * Custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:211:13
+  --> $DIR/arithmetic_side_effects.rs:317:15
    |
-LL |     let _ = Custom / 1;
-   |             ^^^^^^^^^^
+LL |     _custom = _custom * &Custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:212:13
+  --> $DIR/arithmetic_side_effects.rs:318:15
    |
-LL |     let _ = Custom / 2;
-   |             ^^^^^^^^^^
+LL |     _custom = Custom * _custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:213:13
+  --> $DIR/arithmetic_side_effects.rs:319:15
    |
-LL |     let _ = Custom / 0.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = &Custom * _custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:214:13
+  --> $DIR/arithmetic_side_effects.rs:320:15
    |
-LL |     let _ = Custom / 1.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = Custom + &Custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:215:13
+  --> $DIR/arithmetic_side_effects.rs:321:15
    |
-LL |     let _ = Custom / 2.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = &Custom + Custom;
+   |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:216:13
+  --> $DIR/arithmetic_side_effects.rs:322:15
    |
-LL |     let _ = Custom * 0;
-   |             ^^^^^^^^^^
+LL |     _custom = &Custom + &Custom;
+   |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:217:13
+  --> $DIR/arithmetic_side_effects.rs:325:10
    |
-LL |     let _ = Custom * 1;
-   |             ^^^^^^^^^^
+LL |     _n = -_n;
+   |          ^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:218:13
+  --> $DIR/arithmetic_side_effects.rs:326:10
    |
-LL |     let _ = Custom * 2;
-   |             ^^^^^^^^^^
+LL |     _n = -&_n;
+   |          ^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:219:13
+  --> $DIR/arithmetic_side_effects.rs:327:15
    |
-LL |     let _ = Custom * 0.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = -_custom;
+   |               ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:220:13
+  --> $DIR/arithmetic_side_effects.rs:328:15
    |
-LL |     let _ = Custom * 1.0;
-   |             ^^^^^^^^^^^^
+LL |     _custom = -&_custom;
+   |               ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:221:13
+  --> $DIR/arithmetic_side_effects.rs:337:5
    |
-LL |     let _ = Custom * 2.0;
-   |             ^^^^^^^^^^^^
+LL |     1 + i;
+   |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:224:10
+  --> $DIR/arithmetic_side_effects.rs:338:5
    |
-LL |     _n = -_n;
-   |          ^^^
+LL |     i * 2;
+   |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:225:10
+  --> $DIR/arithmetic_side_effects.rs:340:5
    |
-LL |     _n = -&_n;
-   |          ^^^^
+LL |     i - 2 + 2 - i;
+   |     ^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:341:5
+   |
+LL |     -i;
+   |     ^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:342:5
+   |
+LL |     i >> 1;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:343:5
+   |
+LL |     i << 1;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:352:5
+   |
+LL |     i += 1;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:353:5
+   |
+LL |     i -= 1;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:354:5
+   |
+LL |     i *= 2;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:356:5
+   |
+LL |     i /= 0;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:358:5
+   |
+LL |     i /= var1;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:359:5
+   |
+LL |     i /= var2;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:361:5
+   |
+LL |     i %= 0;
+   |     ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:363:5
+   |
+LL |     i %= var1;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:364:5
+   |
+LL |     i %= var2;
+   |     ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:365:5
+   |
+LL |     i <<= 3;
+   |     ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:366:5
+   |
+LL |     i >>= 2;
+   |     ^^^^^^^
 
-error: aborting due to 55 previous errors
+error: aborting due to 99 previous errors
 
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index 911fa856aa0..7e9f074fdca 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -21,16 +21,16 @@ macro_rules! outer {
 fn main() {
     let _string: Box<String> = Box::default();
     let _byte = Box::<u8>::default();
-    let _vec = Box::<std::vec::Vec<u8>>::default();
+    let _vec = Box::<Vec<u8>>::default();
     let _impl = Box::<ImplementsDefault>::default();
     let _impl2 = Box::<ImplementsDefault>::default();
     let _impl3: Box<ImplementsDefault> = Box::default();
     let _own = Box::new(OwnDefault::default()); // should not lint
-    let _in_macro = outer!(Box::<std::string::String>::default());
-    let _string_default = outer!(Box::<std::string::String>::default());
+    let _in_macro = outer!(Box::<String>::default());
+    let _string_default = outer!(Box::<String>::default());
     let _vec2: Box<Vec<ImplementsDefault>> = Box::default();
     let _vec3: Box<Vec<bool>> = Box::default();
-    let _vec4: Box<_> = Box::<std::vec::Vec<bool>>::default();
+    let _vec4: Box<_> = Box::<Vec<bool>>::default();
     let _more = ret_ty_fn();
     call_ty_fn(Box::default());
 }
@@ -54,4 +54,14 @@ impl Read for ImplementsDefault {
 
 fn issue_9621_dyn_trait() {
     let _: Box<dyn Read> = Box::<ImplementsDefault>::default();
+    issue_10089();
+}
+
+fn issue_10089() {
+    let _closure = || {
+        #[derive(Default)]
+        struct WeirdPathed;
+
+        let _ = Box::<WeirdPathed>::default();
+    };
 }
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 20019c2ee5a..5c8d0b8354c 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -54,4 +54,14 @@ impl Read for ImplementsDefault {
 
 fn issue_9621_dyn_trait() {
     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
+    issue_10089();
+}
+
+fn issue_10089() {
+    let _closure = || {
+        #[derive(Default)]
+        struct WeirdPathed;
+
+        let _ = Box::new(WeirdPathed::default());
+    };
 }
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index 5ea410331af..249eb340f96 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -16,7 +16,7 @@ error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:24:16
    |
 LL |     let _vec = Box::new(Vec::<u8>::new());
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<u8>>::default()`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<u8>>::default()`
 
 error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:25:17
@@ -40,13 +40,13 @@ error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:29:28
    |
 LL |     let _in_macro = outer!(Box::new(String::new()));
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
 
 error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:30:34
    |
 LL |     let _string_default = outer!(Box::new(String::from("")));
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
 
 error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:31:46
@@ -64,7 +64,7 @@ error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:33:25
    |
 LL |     let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<bool>>::default()`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<bool>>::default()`
 
 error: `Box::new(_)` of default value
   --> $DIR/box_default.rs:35:16
@@ -84,5 +84,11 @@ error: `Box::new(_)` of default value
 LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 
-error: aborting due to 14 previous errors
+error: `Box::new(_)` of default value
+  --> $DIR/box_default.rs:65:17
+   |
+LL |         let _ = Box::new(WeirdPathed::default());
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
new file mode 100644
index 00000000000..5fbaa64db39
--- /dev/null
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
@@ -0,0 +1,67 @@
+// run-rustfix
+#![warn(clippy::case_sensitive_file_extension_comparisons)]
+
+use std::string::String;
+
+struct TestStruct;
+
+impl TestStruct {
+    fn ends_with(self, _arg: &str) {}
+}
+
+#[allow(dead_code)]
+fn is_rust_file(filename: &str) -> bool {
+    std::path::Path::new(filename)
+        .extension()
+        .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
+}
+
+fn main() {
+    // std::string::String and &str should trigger the lint failure with .ext12
+    let _ = std::path::Path::new(&String::new())
+        .extension()
+        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+    let _ = std::path::Path::new("str")
+        .extension()
+        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+
+    // The fixup should preserve the indentation level
+    {
+        let _ = std::path::Path::new("str")
+            .extension()
+            .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+    }
+
+    // The test struct should not trigger the lint failure with .ext12
+    TestStruct {}.ends_with(".ext12");
+
+    // std::string::String and &str should trigger the lint failure with .EXT12
+    let _ = std::path::Path::new(&String::new())
+        .extension()
+        .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+    let _ = std::path::Path::new("str")
+        .extension()
+        .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+
+    // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
+    let _ = String::new().to_lowercase().ends_with(".EXT12");
+    let _ = String::new().to_uppercase().ends_with(".EXT12");
+
+    // The test struct should not trigger the lint failure with .EXT12
+    TestStruct {}.ends_with(".EXT12");
+
+    // Should not trigger the lint failure with .eXT12
+    let _ = String::new().ends_with(".eXT12");
+    let _ = "str".ends_with(".eXT12");
+    TestStruct {}.ends_with(".eXT12");
+
+    // Should not trigger the lint failure with .EXT123 (too long)
+    let _ = String::new().ends_with(".EXT123");
+    let _ = "str".ends_with(".EXT123");
+    TestStruct {}.ends_with(".EXT123");
+
+    // Shouldn't fail if it doesn't start with a dot
+    let _ = String::new().ends_with("a.ext");
+    let _ = "str".ends_with("a.extA");
+    TestStruct {}.ends_with("a.ext");
+}
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
index 6f0485b5279..3c0d4821f9f 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 #![warn(clippy::case_sensitive_file_extension_comparisons)]
 
 use std::string::String;
@@ -5,9 +6,10 @@ use std::string::String;
 struct TestStruct;
 
 impl TestStruct {
-    fn ends_with(self, arg: &str) {}
+    fn ends_with(self, _arg: &str) {}
 }
 
+#[allow(dead_code)]
 fn is_rust_file(filename: &str) -> bool {
     filename.ends_with(".rs")
 }
@@ -17,6 +19,11 @@ fn main() {
     let _ = String::new().ends_with(".ext12");
     let _ = "str".ends_with(".ext12");
 
+    // The fixup should preserve the indentation level
+    {
+        let _ = "str".ends_with(".ext12");
+    }
+
     // The test struct should not trigger the lint failure with .ext12
     TestStruct {}.ends_with(".ext12");
 
@@ -24,6 +31,10 @@ fn main() {
     let _ = String::new().ends_with(".EXT12");
     let _ = "str".ends_with(".EXT12");
 
+    // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
+    let _ = String::new().to_lowercase().ends_with(".EXT12");
+    let _ = String::new().to_uppercase().ends_with(".EXT12");
+
     // The test struct should not trigger the lint failure with .EXT12
     TestStruct {}.ends_with(".EXT12");
 
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
index a28dd8bd5ad..44c8e3fdf74 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
@@ -1,43 +1,87 @@
 error: case-sensitive file extension comparison
-  --> $DIR/case_sensitive_file_extension_comparisons.rs:12:14
+  --> $DIR/case_sensitive_file_extension_comparisons.rs:14:5
    |
 LL |     filename.ends_with(".rs")
-   |              ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using a case-insensitive comparison instead
    = note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings`
+help: use std::path::Path
+   |
+LL ~     std::path::Path::new(filename)
+LL +         .extension()
+LL +         .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
+   |
 
 error: case-sensitive file extension comparison
-  --> $DIR/case_sensitive_file_extension_comparisons.rs:17:27
+  --> $DIR/case_sensitive_file_extension_comparisons.rs:19:13
    |
 LL |     let _ = String::new().ends_with(".ext12");
-   |                           ^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+   |
+LL ~     let _ = std::path::Path::new(&String::new())
+LL +         .extension()
+LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+   |
 
 error: case-sensitive file extension comparison
-  --> $DIR/case_sensitive_file_extension_comparisons.rs:18:19
+  --> $DIR/case_sensitive_file_extension_comparisons.rs:20:13
    |
 LL |     let _ = "str".ends_with(".ext12");
-   |                   ^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+   |
+LL ~     let _ = std::path::Path::new("str")
+LL +         .extension()
+LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+   |
 
 error: case-sensitive file extension comparison
-  --> $DIR/case_sensitive_file_extension_comparisons.rs:24:27
+  --> $DIR/case_sensitive_file_extension_comparisons.rs:24:17
+   |
+LL |         let _ = "str".ends_with(".ext12");
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+   |
+LL ~         let _ = std::path::Path::new("str")
+LL +             .extension()
+LL ~             .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+   |
+
+error: case-sensitive file extension comparison
+  --> $DIR/case_sensitive_file_extension_comparisons.rs:31:13
    |
 LL |     let _ = String::new().ends_with(".EXT12");
-   |                           ^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+   |
+LL ~     let _ = std::path::Path::new(&String::new())
+LL +         .extension()
+LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+   |
 
 error: case-sensitive file extension comparison
-  --> $DIR/case_sensitive_file_extension_comparisons.rs:25:19
+  --> $DIR/case_sensitive_file_extension_comparisons.rs:32:13
    |
 LL |     let _ = "str".ends_with(".EXT12");
-   |                   ^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+   |
+LL ~     let _ = std::path::Path::new("str")
+LL +         .extension()
+LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+   |
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/clone_on_copy.stderr b/src/tools/clippy/tests/ui/clone_on_copy.stderr
index 42ae227777c..862234d204b 100644
--- a/src/tools/clippy/tests/ui/clone_on_copy.stderr
+++ b/src/tools/clippy/tests/ui/clone_on_copy.stderr
@@ -48,7 +48,7 @@ error: using `clone` on type `i32` which implements the `Copy` trait
 LL |     vec.push(42.clone());
    |              ^^^^^^^^^^ help: try removing the `clone` call: `42`
 
-error: using `clone` on type `std::option::Option<i32>` which implements the `Copy` trait
+error: using `clone` on type `Option<i32>` which implements the `Copy` trait
   --> $DIR/clone_on_copy.rs:77:17
    |
 LL |     let value = opt.clone()?; // operator precedence needed (*opt)?
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index e6a65b46d97..ddb5f1342e9 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -1,143 +1,143 @@
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:5:22
    |
 LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
    |                      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::dbg-macro` implied by `-D warnings`
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:9:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     if n <= 1 {
    |        ~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:10:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |         1
    |
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:12:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |         n * factorial(n - 1)
    |
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:17:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     42;
    |     ~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:18:5
    |
 LL |     dbg!(dbg!(dbg!(42)));
    |     ^^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     dbg!(dbg!(42));
    |     ~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:19:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     foo(3) + factorial(4);
    |              ~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:20:5
    |
 LL |     dbg!(1, 2, dbg!(3, 4));
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     (1, 2, dbg!(3, 4));
    |     ~~~~~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:21:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:41:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |         2;
    |         ~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:47:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     1;
    |     ~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:52:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |     1;
    |     ~
 
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
   --> $DIR/dbg_macro.rs:58:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
    |
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
    |
 LL |         1;
    |         ~
diff --git a/src/tools/clippy/tests/ui/default_trait_access.fixed b/src/tools/clippy/tests/ui/default_trait_access.fixed
index eedd4361939..5640599d48a 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.fixed
+++ b/src/tools/clippy/tests/ui/default_trait_access.fixed
@@ -12,17 +12,17 @@ use std::default::Default as D2;
 use std::string;
 
 fn main() {
-    let s1: String = std::string::String::default();
+    let s1: String = String::default();
 
     let s2 = String::default();
 
-    let s3: String = std::string::String::default();
+    let s3: String = String::default();
 
-    let s4: String = std::string::String::default();
+    let s4: String = String::default();
 
     let s5 = string::String::default();
 
-    let s6: String = std::string::String::default();
+    let s6: String = String::default();
 
     let s7 = std::string::String::default();
 
diff --git a/src/tools/clippy/tests/ui/default_trait_access.stderr b/src/tools/clippy/tests/ui/default_trait_access.stderr
index 49b2dde3f1e..e4f73c08d19 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.stderr
+++ b/src/tools/clippy/tests/ui/default_trait_access.stderr
@@ -1,8 +1,8 @@
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
   --> $DIR/default_trait_access.rs:15:22
    |
 LL |     let s1: String = Default::default();
-   |                      ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+   |                      ^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
    |
 note: the lint level is defined here
   --> $DIR/default_trait_access.rs:3:9
@@ -10,23 +10,23 @@ note: the lint level is defined here
 LL | #![deny(clippy::default_trait_access)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
   --> $DIR/default_trait_access.rs:19:22
    |
 LL |     let s3: String = D2::default();
-   |                      ^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+   |                      ^^^^^^^^^^^^^ help: try: `String::default()`
 
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
   --> $DIR/default_trait_access.rs:21:22
    |
 LL |     let s4: String = std::default::Default::default();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
 
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
   --> $DIR/default_trait_access.rs:25:22
    |
 LL |     let s6: String = default::Default::default();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
 
 error: calling `GenericDerivedDefault::default()` is more clear than this expression
   --> $DIR/default_trait_access.rs:35:46
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
index 7dcdfb0937e..ee8456f5deb 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.fixed
+++ b/src/tools/clippy/tests/ui/derivable_impls.fixed
@@ -210,4 +210,25 @@ impl Default for IntOrString {
     }
 }
 
+#[derive(Default)]
+pub enum SimpleEnum {
+    Foo,
+    #[default]
+    Bar,
+}
+
+
+
+pub enum NonExhaustiveEnum {
+    Foo,
+    #[non_exhaustive]
+    Bar,
+}
+
+impl Default for NonExhaustiveEnum {
+    fn default() -> Self {
+        NonExhaustiveEnum::Bar
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index 625cbcdde23..14af419bcad 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -244,4 +244,27 @@ impl Default for IntOrString {
     }
 }
 
+pub enum SimpleEnum {
+    Foo,
+    Bar,
+}
+
+impl Default for SimpleEnum {
+    fn default() -> Self {
+        SimpleEnum::Bar
+    }
+}
+
+pub enum NonExhaustiveEnum {
+    Foo,
+    #[non_exhaustive]
+    Bar,
+}
+
+impl Default for NonExhaustiveEnum {
+    fn default() -> Self {
+        NonExhaustiveEnum::Bar
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
index c1db5a58b1f..81963c3be5b 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.stderr
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -113,5 +113,26 @@ help: ...and instead derive it
 LL | #[derive(Default)]
    |
 
-error: aborting due to 7 previous errors
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:252:1
+   |
+LL | / impl Default for SimpleEnum {
+LL | |     fn default() -> Self {
+LL | |         SimpleEnum::Bar
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: remove the manual implementation...
+help: ...and instead derive it...
+   |
+LL | #[derive(Default)]
+   |
+help: ...and mark the default variant
+   |
+LL ~     #[default]
+LL ~     Bar,
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/derive.rs b/src/tools/clippy/tests/ui/derive.rs
index b276c384c04..6e0ce55f57d 100644
--- a/src/tools/clippy/tests/ui/derive.rs
+++ b/src/tools/clippy/tests/ui/derive.rs
@@ -86,4 +86,15 @@ impl<T: Clone, U> Clone for GenericRef<'_, T, U> {
     }
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/10188
+#[repr(packed)]
+#[derive(Copy)]
+struct Packed<T>(T);
+
+impl<T: Copy> Clone for Packed<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr b/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
deleted file mode 100644
index 16c92397804..00000000000
--- a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
+++ /dev/null
@@ -1,59 +0,0 @@
-error: you are deriving `Hash` but have implemented `PartialEq` explicitly
-  --> $DIR/derive_hash_xor_eq.rs:12:10
-   |
-LL | #[derive(Hash)]
-   |          ^^^^
-   |
-note: `PartialEq` implemented here
-  --> $DIR/derive_hash_xor_eq.rs:15:1
-   |
-LL | impl PartialEq for Bar {
-   | ^^^^^^^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
-   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: you are deriving `Hash` but have implemented `PartialEq` explicitly
-  --> $DIR/derive_hash_xor_eq.rs:21:10
-   |
-LL | #[derive(Hash)]
-   |          ^^^^
-   |
-note: `PartialEq` implemented here
-  --> $DIR/derive_hash_xor_eq.rs:24:1
-   |
-LL | impl PartialEq<Baz> for Baz {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: you are implementing `Hash` explicitly but have derived `PartialEq`
-  --> $DIR/derive_hash_xor_eq.rs:33:1
-   |
-LL | / impl std::hash::Hash for Bah {
-LL | |     fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
-LL | | }
-   | |_^
-   |
-note: `PartialEq` implemented here
-  --> $DIR/derive_hash_xor_eq.rs:30:10
-   |
-LL | #[derive(PartialEq)]
-   |          ^^^^^^^^^
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: you are implementing `Hash` explicitly but have derived `PartialEq`
-  --> $DIR/derive_hash_xor_eq.rs:51:5
-   |
-LL | /     impl Hash for Foo3 {
-LL | |         fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
-LL | |     }
-   | |_____^
-   |
-note: `PartialEq` implemented here
-  --> $DIR/derive_hash_xor_eq.rs:48:14
-   |
-LL |     #[derive(PartialEq)]
-   |              ^^^^^^^^^
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/derive_hash_xor_eq.rs b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs
index 813ddc56646..8ad09a8de43 100644
--- a/src/tools/clippy/tests/ui/derive_hash_xor_eq.rs
+++ b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs
@@ -27,6 +27,8 @@ impl PartialEq<Baz> for Baz {
     }
 }
 
+// Implementing `Hash` with a derived `PartialEq` is fine. See #2627
+
 #[derive(PartialEq)]
 struct Bah;
 
@@ -34,23 +36,4 @@ impl std::hash::Hash for Bah {
     fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
 }
 
-#[derive(PartialEq)]
-struct Foo2;
-
-trait Hash {}
-
-// We don't want to lint on user-defined traits called `Hash`
-impl Hash for Foo2 {}
-
-mod use_hash {
-    use std::hash::{Hash, Hasher};
-
-    #[derive(PartialEq)]
-    struct Foo3;
-
-    impl Hash for Foo3 {
-        fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
-    }
-}
-
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
new file mode 100644
index 00000000000..230940f25fb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
@@ -0,0 +1,29 @@
+error: you are deriving `Hash` but have implemented `PartialEq` explicitly
+  --> $DIR/derived_hash_with_manual_eq.rs:12:10
+   |
+LL | #[derive(Hash)]
+   |          ^^^^
+   |
+note: `PartialEq` implemented here
+  --> $DIR/derived_hash_with_manual_eq.rs:15:1
+   |
+LL | impl PartialEq for Bar {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
+   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: you are deriving `Hash` but have implemented `PartialEq` explicitly
+  --> $DIR/derived_hash_with_manual_eq.rs:21:10
+   |
+LL | #[derive(Hash)]
+   |          ^^^^
+   |
+note: `PartialEq` implemented here
+  --> $DIR/derived_hash_with_manual_eq.rs:24:1
+   |
+LL | impl PartialEq<Baz> for Baz {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/drop_ref.rs b/src/tools/clippy/tests/ui/drop_ref.rs
index 7de0b0bbdf9..10044e65f11 100644
--- a/src/tools/clippy/tests/ui/drop_ref.rs
+++ b/src/tools/clippy/tests/ui/drop_ref.rs
@@ -72,3 +72,26 @@ fn test_owl_result_2() -> Result<u8, ()> {
     produce_half_owl_ok().map(drop)?;
     Ok(1)
 }
+
+#[allow(unused)]
+#[allow(clippy::unit_cmp)]
+fn issue10122(x: u8) {
+    // This is a function which returns a reference and has a side-effect, which means
+    // that calling drop() on the function is considered an idiomatic way of achieving the side-effect
+    // in a match arm.
+    fn println_and<T>(t: &T) -> &T {
+        println!("foo");
+        t
+    }
+
+    match x {
+        0 => drop(println_and(&12)), // Don't lint (copy type), we only care about side-effects
+        1 => drop(println_and(&String::new())), // Don't lint (no copy type), we only care about side-effects
+        2 => {
+            drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+        },
+        3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+        4 => drop(&2),                           // Lint, not a fn/method call
+        _ => (),
+    }
+}
diff --git a/src/tools/clippy/tests/ui/drop_ref.stderr b/src/tools/clippy/tests/ui/drop_ref.stderr
index 4743cf79b5d..293b9f6de83 100644
--- a/src/tools/clippy/tests/ui/drop_ref.stderr
+++ b/src/tools/clippy/tests/ui/drop_ref.stderr
@@ -107,5 +107,41 @@ note: argument has type `&SomeStruct`
 LL |     std::mem::drop(&SomeStruct);
    |                    ^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
+  --> $DIR/drop_ref.rs:91:13
+   |
+LL |             drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: argument has type `&i32`
+  --> $DIR/drop_ref.rs:91:18
+   |
+LL |             drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+   |                  ^^^^^^^^^^^^^^^^
+
+error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
+  --> $DIR/drop_ref.rs:93:14
+   |
+LL |         3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: argument has type `&i32`
+  --> $DIR/drop_ref.rs:93:19
+   |
+LL |         3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+   |                   ^^^^^^^^^^^^^^^^
+
+error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
+  --> $DIR/drop_ref.rs:94:14
+   |
+LL |         4 => drop(&2),                           // Lint, not a fn/method call
+   |              ^^^^^^^^
+   |
+note: argument has type `&i32`
+  --> $DIR/drop_ref.rs:94:19
+   |
+LL |         4 => drop(&2),                           // Lint, not a fn/method call
+   |                   ^^
+
+error: aborting due to 12 previous errors
 
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 7367910eaa1..1f989bb1220 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -247,3 +247,24 @@ mod issue6312 {
         }
     }
 }
+
+struct Collection {
+    items: Vec<i32>,
+    len: usize,
+}
+
+impl Default for Collection {
+    fn default() -> Self {
+        Self {
+            items: vec![1, 2, 3],
+            len: 0,
+        }
+    }
+}
+
+#[allow(clippy::redundant_closure_call)]
+fn issue10136() {
+    let mut c = Collection::default();
+    // don't lint, since c.items was used to calculate this value
+    c.len = (|| c.items.len())();
+}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.fixed b/src/tools/clippy/tests/ui/iter_kv_map.fixed
index 83fee04080f..f2a4c284cb1 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.fixed
+++ b/src/tools/clippy/tests/ui/iter_kv_map.fixed
@@ -1,14 +1,15 @@
 // run-rustfix
 
 #![warn(clippy::iter_kv_map)]
-#![allow(clippy::redundant_clone)]
-#![allow(clippy::suspicious_map)]
-#![allow(clippy::map_identity)]
+#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
 
 use std::collections::{BTreeMap, HashMap};
 
 fn main() {
     let get_key = |(key, _val)| key;
+    fn ref_acceptor(v: &u32) -> u32 {
+        *v
+    }
 
     let map: HashMap<u32, u32> = HashMap::new();
 
@@ -36,6 +37,20 @@ fn main() {
     let _ = map.keys().map(|key| key * 9).count();
     let _ = map.values().map(|value| value * 17).count();
 
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone().into_values().map(|mut val| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_values().count();
+
     let map: BTreeMap<u32, u32> = BTreeMap::new();
 
     let _ = map.keys().collect::<Vec<_>>();
@@ -61,4 +76,18 @@ fn main() {
     // Lint
     let _ = map.keys().map(|key| key * 9).count();
     let _ = map.values().map(|value| value * 17).count();
+
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone().into_values().map(|mut val| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_values().count();
 }
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.rs b/src/tools/clippy/tests/ui/iter_kv_map.rs
index 7a1f1fb0198..ad6564df408 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.rs
+++ b/src/tools/clippy/tests/ui/iter_kv_map.rs
@@ -1,14 +1,15 @@
 // run-rustfix
 
 #![warn(clippy::iter_kv_map)]
-#![allow(clippy::redundant_clone)]
-#![allow(clippy::suspicious_map)]
-#![allow(clippy::map_identity)]
+#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
 
 use std::collections::{BTreeMap, HashMap};
 
 fn main() {
     let get_key = |(key, _val)| key;
+    fn ref_acceptor(v: &u32) -> u32 {
+        *v
+    }
 
     let map: HashMap<u32, u32> = HashMap::new();
 
@@ -36,6 +37,22 @@ fn main() {
     let _ = map.iter().map(|(key, _value)| key * 9).count();
     let _ = map.iter().map(|(_key, value)| value * 17).count();
 
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone()
+        .into_iter()
+        .map(|(_, mut val)| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+
     let map: BTreeMap<u32, u32> = BTreeMap::new();
 
     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
@@ -61,4 +78,20 @@ fn main() {
     // Lint
     let _ = map.iter().map(|(key, _value)| key * 9).count();
     let _ = map.iter().map(|(_key, value)| value * 17).count();
+
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone()
+        .into_iter()
+        .map(|(_, mut val)| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
 }
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.stderr b/src/tools/clippy/tests/ui/iter_kv_map.stderr
index 9b9b04c97d8..e00da223b4d 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.stderr
+++ b/src/tools/clippy/tests/ui/iter_kv_map.stderr
@@ -1,5 +1,5 @@
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:15:13
+  --> $DIR/iter_kv_map.rs:16:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
@@ -7,130 +7,198 @@ LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    = note: `-D clippy::iter-kv-map` implied by `-D warnings`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:16:13
+  --> $DIR/iter_kv_map.rs:17:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:17:13
+  --> $DIR/iter_kv_map.rs:18:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:19:13
+  --> $DIR/iter_kv_map.rs:20:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:20:13
+  --> $DIR/iter_kv_map.rs:21:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:22:13
+  --> $DIR/iter_kv_map.rs:23:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:23:13
+  --> $DIR/iter_kv_map.rs:24:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:25:13
+  --> $DIR/iter_kv_map.rs:26:13
    |
 LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:26:13
+  --> $DIR/iter_kv_map.rs:27:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:36:13
+  --> $DIR/iter_kv_map.rs:37:13
    |
 LL |     let _ = map.iter().map(|(key, _value)| key * 9).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:37:13
+  --> $DIR/iter_kv_map.rs:38:13
    |
 LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 
-error: iterating on a map's keys
+error: iterating on a map's values
   --> $DIR/iter_kv_map.rs:41:13
    |
+LL |     let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:44:13
+   |
+LL |       let _ = map
+   |  _____________^
+LL | |         .clone()
+LL | |         .into_iter()
+LL | |         .map(|(_, mut val)| {
+LL | |             val += 2;
+LL | |             val
+LL | |         })
+   | |__________^
+   |
+help: try
+   |
+LL ~     let _ = map
+LL +         .clone().into_values().map(|mut val| {
+LL +             val += 2;
+LL +             val
+LL +         })
+   |
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:54:13
+   |
+LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: iterating on a map's keys
+  --> $DIR/iter_kv_map.rs:58:13
+   |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:42:13
+  --> $DIR/iter_kv_map.rs:59:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:43:13
+  --> $DIR/iter_kv_map.rs:60:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:45:13
+  --> $DIR/iter_kv_map.rs:62:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:46:13
+  --> $DIR/iter_kv_map.rs:63:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:48:13
+  --> $DIR/iter_kv_map.rs:65:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:49:13
+  --> $DIR/iter_kv_map.rs:66:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:51:13
+  --> $DIR/iter_kv_map.rs:68:13
    |
 LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:52:13
+  --> $DIR/iter_kv_map.rs:69:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:62:13
+  --> $DIR/iter_kv_map.rs:79:13
    |
 LL |     let _ = map.iter().map(|(key, _value)| key * 9).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:63:13
+  --> $DIR/iter_kv_map.rs:80:13
    |
 LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 
-error: aborting due to 22 previous errors
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:83:13
+   |
+LL |     let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:86:13
+   |
+LL |       let _ = map
+   |  _____________^
+LL | |         .clone()
+LL | |         .into_iter()
+LL | |         .map(|(_, mut val)| {
+LL | |             val += 2;
+LL | |             val
+LL | |         })
+   | |__________^
+   |
+help: try
+   |
+LL ~     let _ = map
+LL +         .clone().into_values().map(|mut val| {
+LL +             val += 2;
+LL +             val
+LL +         })
+   |
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:96:13
+   |
+LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index 31e1cb6c3d7..4cb7f6b687f 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![feature(custom_inner_attributes, lint_reasons, rustc_private)]
+#![feature(lint_reasons)]
 #![allow(
     unused,
     clippy::uninlined_format_args,
@@ -491,14 +491,3 @@ mod issue_9782_method_variant {
         S.foo::<&[u8; 100]>(&a);
     }
 }
-
-extern crate rustc_lint;
-extern crate rustc_span;
-
-#[allow(dead_code)]
-mod span_lint {
-    use rustc_lint::{LateContext, Lint, LintContext};
-    fn foo(cx: &LateContext<'_>, lint: &'static Lint) {
-        cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(String::new()));
-    }
-}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index 55c2738fcf2..9a01190ed8d 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![feature(custom_inner_attributes, lint_reasons, rustc_private)]
+#![feature(lint_reasons)]
 #![allow(
     unused,
     clippy::uninlined_format_args,
@@ -491,14 +491,3 @@ mod issue_9782_method_variant {
         S.foo::<&[u8; 100]>(&a);
     }
 }
-
-extern crate rustc_lint;
-extern crate rustc_span;
-
-#[allow(dead_code)]
-mod span_lint {
-    use rustc_lint::{LateContext, Lint, LintContext};
-    fn foo(cx: &LateContext<'_>, lint: &'static Lint) {
-        cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new()));
-    }
-}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index 98a48d68317..d26c317124b 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -216,11 +216,5 @@ error: the borrowed expression implements the required traits
 LL |         foo(&a);
    |             ^^ help: change this to: `a`
 
-error: the borrowed expression implements the required traits
-  --> $DIR/needless_borrow.rs:502:85
-   |
-LL |         cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new()));
-   |                                                                                     ^^^^^^^^^^^^^^ help: change this to: `String::new()`
-
-error: aborting due to 37 previous errors
+error: aborting due to 36 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index d451be1f389..ab1c0e590bb 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -277,4 +277,14 @@ fn issue9947() -> Result<(), String> {
     do yeet "hello";
 }
 
+// without anyhow, but triggers the same bug I believe
+#[expect(clippy::useless_format)]
+fn issue10051() -> Result<String, String> {
+    if true {
+        Ok(format!("ok!"))
+    } else {
+        Err(format!("err!"))
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index e1a1bea2c0b..abed338bb9b 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -287,4 +287,14 @@ fn issue9947() -> Result<(), String> {
     do yeet "hello";
 }
 
+// without anyhow, but triggers the same bug I believe
+#[expect(clippy::useless_format)]
+fn issue10051() -> Result<String, String> {
+    if true {
+        return Ok(format!("ok!"));
+    } else {
+        return Err(format!("err!"));
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index ca2253e6586..52eabf6e137 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -386,5 +386,21 @@ LL |         let _ = 42; return;
    |
    = help: remove `return`
 
-error: aborting due to 46 previous errors
+error: unneeded `return` statement
+  --> $DIR/needless_return.rs:294:9
+   |
+LL |         return Ok(format!("ok!"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove `return`
+
+error: unneeded `return` statement
+  --> $DIR/needless_return.rs:296:9
+   |
+LL |         return Err(format!("err!"));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove `return`
+
+error: aborting due to 48 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index a157b6a6f9a..00b42745093 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -239,9 +239,3 @@ fn false_negative_5707() {
     let _z = x.clone(); // pr 7346 can't lint on `x`
     drop(y);
 }
-
-#[allow(unused, clippy::manual_retain)]
-fn possible_borrower_improvements() {
-    let mut s = String::from("foobar");
-    s = s.chars().filter(|&c| c != 'o').collect();
-}
diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs
index 430672e8b8d..f899127db8d 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.rs
+++ b/src/tools/clippy/tests/ui/redundant_clone.rs
@@ -239,9 +239,3 @@ fn false_negative_5707() {
     let _z = x.clone(); // pr 7346 can't lint on `x`
     drop(y);
 }
-
-#[allow(unused, clippy::manual_retain)]
-fn possible_borrower_improvements() {
-    let mut s = String::from("foobar");
-    s = s.chars().filter(|&c| c != 'o').to_owned().collect();
-}
diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr
index 1bacc2c76af..782590034d0 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.stderr
+++ b/src/tools/clippy/tests/ui/redundant_clone.stderr
@@ -179,17 +179,5 @@ note: this value is dropped without further use
 LL |     foo(&x.clone(), move || {
    |          ^
 
-error: redundant clone
-  --> $DIR/redundant_clone.rs:246:40
-   |
-LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
-   |                                        ^^^^^^^^^^^ help: remove this
-   |
-note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:246:9
-   |
-LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 16 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 2f76b575296..5076f61334d 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -10,6 +10,7 @@
 #![allow(clippy::box_collection)]
 #![allow(clippy::redundant_static_lifetimes)]
 #![allow(clippy::cognitive_complexity)]
+#![allow(clippy::derived_hash_with_manual_eq)]
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
@@ -45,6 +46,7 @@
 #![warn(clippy::box_collection)]
 #![warn(clippy::redundant_static_lifetimes)]
 #![warn(clippy::cognitive_complexity)]
+#![warn(clippy::derived_hash_with_manual_eq)]
 #![warn(clippy::disallowed_methods)]
 #![warn(clippy::disallowed_types)]
 #![warn(clippy::mixed_read_write_in_expression)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 699c0ff464e..64bc1ca7116 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -10,6 +10,7 @@
 #![allow(clippy::box_collection)]
 #![allow(clippy::redundant_static_lifetimes)]
 #![allow(clippy::cognitive_complexity)]
+#![allow(clippy::derived_hash_with_manual_eq)]
 #![allow(clippy::disallowed_methods)]
 #![allow(clippy::disallowed_types)]
 #![allow(clippy::mixed_read_write_in_expression)]
@@ -45,6 +46,7 @@
 #![warn(clippy::box_vec)]
 #![warn(clippy::const_static_lifetime)]
 #![warn(clippy::cyclomatic_complexity)]
+#![warn(clippy::derive_hash_xor_eq)]
 #![warn(clippy::disallowed_method)]
 #![warn(clippy::disallowed_type)]
 #![warn(clippy::eval_order_dependence)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 9af58dc75a6..27a0263292e 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:41:9
+  --> $DIR/rename.rs:42:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,244 +7,250 @@ 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:42:9
+  --> $DIR/rename.rs:43: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:43:9
+  --> $DIR/rename.rs:44: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:44:9
+  --> $DIR/rename.rs:45: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:45:9
+  --> $DIR/rename.rs:46:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:46:9
+  --> $DIR/rename.rs:47: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:47:9
+  --> $DIR/rename.rs:48: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:49: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:48:9
+  --> $DIR/rename.rs:50: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:49:9
+  --> $DIR/rename.rs:51: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:50:9
+  --> $DIR/rename.rs:52: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:51:9
+  --> $DIR/rename.rs:53: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:52:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:55: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:54:9
+  --> $DIR/rename.rs:56: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:55:9
+  --> $DIR/rename.rs:57: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:56:9
+  --> $DIR/rename.rs:58: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:57:9
+  --> $DIR/rename.rs:59: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:58:9
+  --> $DIR/rename.rs:60: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:59:9
+  --> $DIR/rename.rs:61: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:60:9
+  --> $DIR/rename.rs:62: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:61:9
+  --> $DIR/rename.rs:63: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:62:9
+  --> $DIR/rename.rs:64: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:63:9
+  --> $DIR/rename.rs:65: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:64:9
+  --> $DIR/rename.rs:66: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:65:9
+  --> $DIR/rename.rs:67: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:66:9
+  --> $DIR/rename.rs:68: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:67:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:71: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:70:9
+  --> $DIR/rename.rs:72: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:71:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:74: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:73:9
+  --> $DIR/rename.rs:75: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:74:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:77: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:76:9
+  --> $DIR/rename.rs:78: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:77:9
+  --> $DIR/rename.rs:79: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:78:9
+  --> $DIR/rename.rs:80: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:79:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:82: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:81:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 41 previous errors
+error: aborting due to 42 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 63d31ff83f9..a0dcc0172e8 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.fixed
+++ b/src/tools/clippy/tests/ui/single_element_loop.fixed
@@ -33,4 +33,31 @@ fn main() {
         let item = 0..5;
         dbg!(item);
     }
+
+    // should not lint (issue #10018)
+    for e in [42] {
+        if e > 0 {
+            continue;
+        }
+    }
+
+    // should not lint (issue #10018)
+    for e in [42] {
+        if e > 0 {
+            break;
+        }
+    }
+
+    // should lint (issue #10018)
+    {
+        let _ = 42;
+        let _f = |n: u32| {
+            for i in 0..n {
+                if i > 10 {
+                    dbg!(i);
+                    break;
+                }
+            }
+        };
+    }
 }
diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs
index 2cda5a329d2..bc014035c98 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.rs
+++ b/src/tools/clippy/tests/ui/single_element_loop.rs
@@ -27,4 +27,30 @@ fn main() {
     for item in [0..5].into_iter() {
         dbg!(item);
     }
+
+    // should not lint (issue #10018)
+    for e in [42] {
+        if e > 0 {
+            continue;
+        }
+    }
+
+    // should not lint (issue #10018)
+    for e in [42] {
+        if e > 0 {
+            break;
+        }
+    }
+
+    // should lint (issue #10018)
+    for _ in [42] {
+        let _f = |n: u32| {
+            for i in 0..n {
+                if i > 10 {
+                    dbg!(i);
+                    break;
+                }
+            }
+        };
+    }
 }
diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr
index 0aeb8da1a2e..14437a59745 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.stderr
+++ b/src/tools/clippy/tests/ui/single_element_loop.stderr
@@ -95,5 +95,32 @@ LL +         dbg!(item);
 LL +     }
    |
 
-error: aborting due to 6 previous errors
+error: for loop over a single element
+  --> $DIR/single_element_loop.rs:46:5
+   |
+LL | /     for _ in [42] {
+LL | |         let _f = |n: u32| {
+LL | |             for i in 0..n {
+LL | |                 if i > 10 {
+...  |
+LL | |         };
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     {
+LL +         let _ = 42;
+LL +         let _f = |n: u32| {
+LL +             for i in 0..n {
+LL +                 if i > 10 {
+LL +                     dbg!(i);
+LL +                     break;
+LL +                 }
+LL +             }
+LL +         };
+LL +     }
+   |
+
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
index ae1aec34d82..dec3f50d6f1 100644
--- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
@@ -1,4 +1,4 @@
-error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
+error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
   --> $DIR/suspicious_to_owned.rs:16:13
    |
 LL |     let _ = cow.to_owned();
@@ -6,19 +6,19 @@ LL |     let _ = cow.to_owned();
    |
    = note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
 
-error: this `to_owned` call clones the std::borrow::Cow<'_, [char; 3]> itself and does not cause the std::borrow::Cow<'_, [char; 3]> contents to become owned
+error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
   --> $DIR/suspicious_to_owned.rs:26:13
    |
 LL |     let _ = cow.to_owned();
    |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
 
-error: this `to_owned` call clones the std::borrow::Cow<'_, std::vec::Vec<char>> itself and does not cause the std::borrow::Cow<'_, std::vec::Vec<char>> contents to become owned
+error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
   --> $DIR/suspicious_to_owned.rs:36:13
    |
 LL |     let _ = cow.to_owned();
    |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
 
-error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
+error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
   --> $DIR/suspicious_to_owned.rs:46:13
    |
 LL |     let _ = cow.to_owned();
diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.stderr b/src/tools/clippy/tests/ui/unnecessary_clone.stderr
index 94cc7777aca..6022d9fa4c5 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clone.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_clone.stderr
@@ -38,13 +38,13 @@ LL |     t.clone();
    |
    = note: `-D clippy::clone-on-copy` implied by `-D warnings`
 
-error: using `clone` on type `std::option::Option<T>` which implements the `Copy` trait
+error: using `clone` on type `Option<T>` which implements the `Copy` trait
   --> $DIR/unnecessary_clone.rs:42:5
    |
 LL |     Some(t).clone();
    |     ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
 
-error: using `clone` on a double-reference; this will copy the reference of type `&std::vec::Vec<i32>` instead of cloning the inner type
+error: using `clone` on a double-reference; this will copy the reference of type `&Vec<i32>` instead of cloning the inner type
   --> $DIR/unnecessary_clone.rs:48:22
    |
 LL |     let z: &Vec<_> = y.clone();
@@ -57,10 +57,10 @@ LL |     let z: &Vec<_> = &(*y).clone();
    |                      ~~~~~~~~~~~~~
 help: or try being explicit if you are sure, that you want to clone a reference
    |
-LL |     let z: &Vec<_> = <&std::vec::Vec<i32>>::clone(y);
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let z: &Vec<_> = <&Vec<i32>>::clone(y);
+   |                      ~~~~~~~~~~~~~~~~~~~~~
 
-error: using `clone` on type `many_derefs::E` which implements the `Copy` trait
+error: using `clone` on type `E` which implements the `Copy` trait
   --> $DIR/unnecessary_clone.rs:84:20
    |
 LL |         let _: E = a.clone();
diff --git a/src/tools/clippy/tests/ui/unused_self.rs b/src/tools/clippy/tests/ui/unused_self.rs
index 92e8e1dba69..55bd5607185 100644
--- a/src/tools/clippy/tests/ui/unused_self.rs
+++ b/src/tools/clippy/tests/ui/unused_self.rs
@@ -60,6 +60,16 @@ mod unused_self_allow {
         // shouldn't trigger for public methods
         pub fn unused_self_move(self) {}
     }
+
+    pub struct E;
+
+    impl E {
+        // shouldn't trigger if body contains todo!()
+        pub fn unused_self_todo(self) {
+            let x = 42;
+            todo!()
+        }
+    }
 }
 
 pub use unused_self_allow::D;
diff --git a/src/tools/clippy/tests/ui/unused_self.stderr b/src/tools/clippy/tests/ui/unused_self.stderr
index 23186122a9a..919f9b6efda 100644
--- a/src/tools/clippy/tests/ui/unused_self.stderr
+++ b/src/tools/clippy/tests/ui/unused_self.stderr
@@ -4,7 +4,7 @@ error: unused `self` argument
 LL |         fn unused_self_move(self) {}
    |                             ^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
    = note: `-D clippy::unused-self` implied by `-D warnings`
 
 error: unused `self` argument
@@ -13,7 +13,7 @@ error: unused `self` argument
 LL |         fn unused_self_ref(&self) {}
    |                            ^^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:13:32
@@ -21,7 +21,7 @@ error: unused `self` argument
 LL |         fn unused_self_mut_ref(&mut self) {}
    |                                ^^^^^^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:14:32
@@ -29,7 +29,7 @@ error: unused `self` argument
 LL |         fn unused_self_pin_ref(self: Pin<&Self>) {}
    |                                ^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:15:36
@@ -37,7 +37,7 @@ error: unused `self` argument
 LL |         fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
    |                                    ^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:16:35
@@ -45,7 +45,7 @@ error: unused `self` argument
 LL |         fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
    |                                   ^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:17:28
@@ -53,7 +53,7 @@ error: unused `self` argument
 LL |         fn unused_self_box(self: Box<Self>) {}
    |                            ^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:18:40
@@ -61,7 +61,7 @@ error: unused `self` argument
 LL |         fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
    |                                        ^^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: unused `self` argument
   --> $DIR/unused_self.rs:21:37
@@ -69,7 +69,7 @@ error: unused `self` argument
 LL |         fn unused_self_class_method(&self) {
    |                                     ^^^^^
    |
-   = help: consider refactoring to a associated function
+   = help: consider refactoring to an associated function
 
 error: aborting due to 9 previous errors