about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-06-01 16:43:14 +0000
committerbors <bors@rust-lang.org>2022-06-01 16:43:14 +0000
commitc4c413b6fcf707de59ec30ec854915725167a05e (patch)
tree6ae30f3d75c44e7eb5d79b35d0c45efea3d242c4
parentf0bf2003de1e50bc722941dc07b6ca593a136000 (diff)
parent202fdb9c530fa39ae90a23530e49b6746b1a4ec4 (diff)
downloadrust-c4c413b6fcf707de59ec30ec854915725167a05e.tar.gz
rust-c4c413b6fcf707de59ec30ec854915725167a05e.zip
Auto merge of #7930 - lengyijun:needless_deref_new, r=Jarcho
new lint: `borrow_deref_ref`

changelog: ``[`borrow_deref_ref`]``

Related pr: #6837 #7577
`@Jarcho` Could you please give a review?

`cargo lintcheck` gives no false negative (but tested crates are out-of-date).

TODO:
1. Not sure the name. `deref_on_immutable_ref` or some others?
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/borrow_deref_ref.rs118
-rw-r--r--clippy_lints/src/checked_conversions.rs4
-rw-r--r--clippy_lints/src/let_if_seq.rs2
-rw-r--r--clippy_lints/src/lib.register_all.rs1
-rw-r--r--clippy_lints/src/lib.register_complexity.rs1
-rw-r--r--clippy_lints/src/lib.register_lints.rs1
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/loops/never_loop.rs2
-rw-r--r--clippy_lints/src/matches/match_bool.rs4
-rw-r--r--clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--clippy_lints/src/mixed_read_write_in_expression.rs2
-rw-r--r--clippy_lints/src/mut_key.rs2
-rw-r--r--clippy_lints/src/panic_in_result_fn.rs2
-rw-r--r--clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--clippy_lints/src/redundant_clone.rs6
-rw-r--r--clippy_lints/src/redundant_static_lifetimes.rs9
-rw-r--r--clippy_lints/src/size_of_in_element_count.rs2
-rw-r--r--clippy_lints/src/utils/internal_lints.rs8
-rw-r--r--clippy_lints/src/utils/internal_lints/metadata_collector.rs3
-rw-r--r--clippy_utils/src/consts.rs2
-rw-r--r--clippy_utils/src/higher.rs2
-rw-r--r--clippy_utils/src/hir_utils.rs6
-rw-r--r--clippy_utils/src/lib.rs4
-rw-r--r--tests/compile-test.rs1
-rw-r--r--tests/ui-internal/unnecessary_symbol_str.fixed1
-rw-r--r--tests/ui-internal/unnecessary_symbol_str.rs1
-rw-r--r--tests/ui-internal/unnecessary_symbol_str.stderr10
-rw-r--r--tests/ui/borrow_deref_ref.fixed59
-rw-r--r--tests/ui/borrow_deref_ref.rs59
-rw-r--r--tests/ui/borrow_deref_ref.stderr22
-rw-r--r--tests/ui/borrow_deref_ref_unfixable.rs10
-rw-r--r--tests/ui/borrow_deref_ref_unfixable.stderr18
-rw-r--r--tests/ui/collapsible_match2.rs2
-rw-r--r--tests/ui/collapsible_match2.stderr4
-rw-r--r--tests/ui/deref_by_slicing.fixed1
-rw-r--r--tests/ui/deref_by_slicing.rs1
-rw-r--r--tests/ui/deref_by_slicing.stderr18
-rw-r--r--tests/ui/explicit_deref_methods.fixed7
-rw-r--r--tests/ui/explicit_deref_methods.rs7
-rw-r--r--tests/ui/explicit_deref_methods.stderr24
-rw-r--r--tests/ui/forget_ref.rs1
-rw-r--r--tests/ui/forget_ref.stderr36
-rw-r--r--tests/ui/recursive_format_impl.rs3
-rw-r--r--tests/ui/recursive_format_impl.stderr20
45 files changed, 399 insertions, 94 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 731d5cac333..1c7ebfdf035 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3297,6 +3297,7 @@ Released 2018-09-13
 [`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison
 [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
 [`borrow_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr
+[`borrow_deref_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_deref_ref
 [`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
 [`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
 [`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection
diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs
new file mode 100644
index 00000000000..ec2f31cf673
--- /dev/null
+++ b/clippy_lints/src/borrow_deref_ref.rs
@@ -0,0 +1,118 @@
+use crate::reference::DEREF_ADDROF;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{get_parent_expr, is_lint_allowed};
+use rustc_errors::Applicability;
+use rustc_hir::{ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::mir::Mutability;
+use rustc_middle::ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `&*(&T)`.
+    ///
+    /// ### Why is this bad?
+    /// Dereferencing and then borrowing a reference value has no effect in most cases.
+    ///
+    /// ### Known problems
+    /// false negative on such code:
+    /// ```
+    /// let x = &12;
+    /// let addr_x = &x as *const _ as usize;
+    /// let addr_y = &&*x as *const _ as usize; // assert ok now, and lint triggerd.
+    ///                                         // But if we fix it, assert will fail.
+    /// assert_ne!(addr_x, addr_y);
+    /// ```
+    ///
+    /// ### Example
+    /// ```rust
+    /// let s = &String::new();
+    ///
+    /// // Bad
+    /// let a: &String = &* s;
+    /// foo(&*s);
+    ///
+    /// // Good
+    /// let a: &String = s;
+    /// foo(&**s);
+    ///
+    /// fn foo(_: &str){ }
+    /// ```
+    #[clippy::version = "1.59.0"]
+    pub BORROW_DEREF_REF,
+    complexity,
+    "deref on an immutable reference returns the same type as itself"
+}
+
+declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
+
+impl LateLintPass<'_> for BorrowDerefRef {
+    fn check_expr(&mut self, cx: &LateContext<'_>, e: &rustc_hir::Expr<'_>) {
+        if_chain! {
+            if !e.span.from_expansion();
+            if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
+            if !addrof_target.span.from_expansion();
+            if let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind;
+            if !deref_target.span.from_expansion();
+            if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
+            let ref_ty = cx.typeck_results().expr_ty(deref_target);
+            if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
+            then{
+
+                if let Some(parent_expr) = get_parent_expr(cx, e){
+                    if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) &&
+                       !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) {
+                        return;
+                    }
+
+                    // modification to `&mut &*x` is different from `&mut x`
+                    if matches!(deref_target.kind, ExprKind::Path(..)
+                                             | ExprKind::Field(..)
+                                             | ExprKind::Index(..)
+                                             | ExprKind::Unary(UnOp::Deref, ..))
+                     && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) {
+                       return;
+                    }
+                }
+
+                span_lint_and_then(
+                    cx,
+                    BORROW_DEREF_REF,
+                    e.span,
+                    "deref on an immutable reference",
+                    |diag| {
+                        diag.span_suggestion(
+                            e.span,
+                            "if you would like to reborrow, try removing `&*`",
+                            snippet_opt(cx, deref_target.span).unwrap(),
+                            Applicability::MachineApplicable
+                        );
+
+                        // has deref trait -> give 2 help
+                        // doesn't have deref trait -> give 1 help
+                        if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait(){
+                            if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) {
+                                return;
+                            }
+                        }
+
+                        diag.span_suggestion(
+                            e.span,
+                            "if you would like to deref, try using `&**`",
+                            format!(
+                                "&**{}",
+                                &snippet_opt(cx, deref_target.span).unwrap(),
+                             ),
+                            Applicability::MaybeIncorrect
+                        );
+
+                    }
+                );
+
+            }
+        }
+    }
+}
diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs
index 7eeaaa01921..1010340c712 100644
--- a/clippy_lints/src/checked_conversions.rs
+++ b/clippy_lints/src/checked_conversions.rs
@@ -318,7 +318,7 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function:
         if let QPath::TypeRelative(ty, path) = &path;
         if path.ident.name.as_str() == function;
         if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind;
-        if let [int] = &*tp.segments;
+        if let [int] = tp.segments;
         then {
             let name = int.ident.name.as_str();
             candidates.iter().find(|c| &name == *c).copied()
@@ -332,7 +332,7 @@ fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function:
 fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
     if_chain! {
         if let QPath::Resolved(_, path) = *path;
-        if let [ty] = &*path.segments;
+        if let [ty] = path.segments;
         then {
             let name = ty.ident.name.as_str();
             INTS.iter().find(|c| &name == *c).copied()
diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs
index db09d00d730..56bbbbbc819 100644
--- a/clippy_lints/src/let_if_seq.rs
+++ b/clippy_lints/src/let_if_seq.rs
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
                 if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind;
                 if !is_local_used(cx, *cond, canonical_id);
                 if let hir::ExprKind::Block(then, _) = then.kind;
-                if let Some(value) = check_assign(cx, canonical_id, &*then);
+                if let Some(value) = check_assign(cx, canonical_id, then);
                 if !is_local_used(cx, value, canonical_id);
                 then {
                     let span = stmt.span.to(if_.span);
diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs
index 58f8ea7b997..51b3babef7f 100644
--- a/clippy_lints/src/lib.register_all.rs
+++ b/clippy_lints/src/lib.register_all.rs
@@ -25,6 +25,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
     LintId::of(booleans::LOGIC_BUG),
     LintId::of(booleans::NONMINIMAL_BOOL),
+    LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
     LintId::of(bytes_count_to_len::BYTES_COUNT_TO_LEN),
     LintId::of(casts::CAST_ABS_TO_UNSIGNED),
     LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
diff --git a/clippy_lints/src/lib.register_complexity.rs b/clippy_lints/src/lib.register_complexity.rs
index fe8637faf97..29b38a01b7e 100644
--- a/clippy_lints/src/lib.register_complexity.rs
+++ b/clippy_lints/src/lib.register_complexity.rs
@@ -5,6 +5,7 @@
 store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
     LintId::of(attrs::DEPRECATED_CFG_ATTR),
     LintId::of(booleans::NONMINIMAL_BOOL),
+    LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
     LintId::of(bytes_count_to_len::BYTES_COUNT_TO_LEN),
     LintId::of(casts::CHAR_LIT_AS_U8),
     LintId::of(casts::UNNECESSARY_CAST),
diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs
index e04d9f4fb90..93f27187b71 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -65,6 +65,7 @@ store.register_lints(&[
     booleans::LOGIC_BUG,
     booleans::NONMINIMAL_BOOL,
     borrow_as_ptr::BORROW_AS_PTR,
+    borrow_deref_ref::BORROW_DEREF_REF,
     bytecount::NAIVE_BYTECOUNT,
     bytes_count_to_len::BYTES_COUNT_TO_LEN,
     cargo::CARGO_COMMON_METADATA,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 81a231cbebe..8f7c99d011d 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -184,6 +184,7 @@ mod blocks_in_if_conditions;
 mod bool_assert_comparison;
 mod booleans;
 mod borrow_as_ptr;
+mod borrow_deref_ref;
 mod bytecount;
 mod bytes_count_to_len;
 mod cargo;
@@ -640,6 +641,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(mutex_atomic::Mutex));
     store.register_late_pass(|| Box::new(needless_update::NeedlessUpdate));
     store.register_late_pass(|| Box::new(needless_borrowed_ref::NeedlessBorrowedRef));
+    store.register_late_pass(|| Box::new(borrow_deref_ref::BorrowDerefRef));
     store.register_late_pass(|| Box::new(no_effect::NoEffect));
     store.register_late_pass(|| Box::new(temporary_assignment::TemporaryAssignment));
     store.register_late_pass(|| Box::new(transmute::Transmute));
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index 70a118d6b35..c025f5972d5 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -146,7 +146,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
             if arms.is_empty() {
                 e
             } else {
-                let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), main_loop_id);
+                let arms = never_loop_expr_branch(&mut arms.iter().map(|a| a.body), main_loop_id);
                 combine_seq(e, arms)
             }
         },
diff --git a/clippy_lints/src/matches/match_bool.rs b/clippy_lints/src/matches/match_bool.rs
index 90c50b994d2..1c216e13570 100644
--- a/clippy_lints/src/matches/match_bool.rs
+++ b/clippy_lints/src/matches/match_bool.rs
@@ -24,8 +24,8 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
                     let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
                         if let ExprKind::Lit(ref lit) = arm_bool.kind {
                             match lit.node {
-                                LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)),
-                                LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)),
+                                LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
+                                LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
                                 _ => None,
                             }
                         } else {
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index 97c4feb3122..b4c6bfb31ed 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -415,7 +415,7 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id:
 /// Returns true if the named method can be used to convert the receiver to its "owned"
 /// representation.
 fn is_to_owned_like(cx: &LateContext<'_>, method_name: Symbol, method_def_id: DefId) -> bool {
-    is_clone_like(cx, &*method_name.as_str(), method_def_id)
+    is_clone_like(cx, method_name.as_str(), method_def_id)
         || is_cow_into_owned(cx, method_name, method_def_id)
         || is_to_string(cx, method_name, method_def_id)
 }
diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs
index 405fc23e8de..024bd076071 100644
--- a/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -120,7 +120,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
                         self.visit_expr(if_expr);
                     }
                     // make sure top level arm expressions aren't linted
-                    self.maybe_walk_expr(&*arm.body);
+                    self.maybe_walk_expr(arm.body);
                 }
             },
             _ => walk_expr(self, e),
diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index cba54e14212..7e2531c7ca5 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/clippy_lints/src/mut_key.rs
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
         if let hir::PatKind::Wild = local.pat.kind {
             return;
         }
-        check_ty(cx, local.span, cx.typeck_results().pat_ty(&*local.pat));
+        check_ty(cx, local.span, cx.typeck_results().pat_ty(local.pat));
     }
 }
 
diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs
index b7a56970b33..21acf003d92 100644
--- a/clippy_lints/src/panic_in_result_fn.rs
+++ b/clippy_lints/src/panic_in_result_fn.rs
@@ -61,7 +61,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir
     expr_visitor_no_bodies(|expr| {
         let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return true };
         if matches!(
-            &*cx.tcx.item_name(macro_call.def_id).as_str(),
+            cx.tcx.item_name(macro_call.def_id).as_str(),
             "unimplemented" | "unreachable" | "panic" | "todo" | "assert" | "assert_eq" | "assert_ne"
         ) {
             panics.push(macro_call.span);
diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index e3ded716341..5a93431f25a 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/clippy_lints/src/pass_by_ref_or_value.rs
@@ -233,7 +233,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
         }
 
         if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind {
-            self.check_poly_fn(cx, item.def_id, &*method_sig.decl, None);
+            self.check_poly_fn(cx, item.def_id, method_sig.decl, None);
         }
     }
 
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index 0004b8afdd3..f7a6fbac166 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -288,8 +288,8 @@ fn is_call_with_ref_arg<'tcx>(
         if let mir::TerminatorKind::Call { func, args, destination, .. } = kind;
         if args.len() == 1;
         if let mir::Operand::Move(mir::Place { local, .. }) = &args[0];
-        if let ty::FnDef(def_id, _) = *func.ty(&*mir, cx.tcx).kind();
-        if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
+        if let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind();
+        if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx));
         if !is_copy(cx, inner_ty);
         then {
             Some((def_id, *local, inner_ty, destination.as_ref().map(|(dest, _)| dest)?.as_local()?))
@@ -318,7 +318,7 @@ fn find_stmt_assigns_to<'tcx>(
         None
     })?;
 
-    match (by_ref, &*rvalue) {
+    match (by_ref, rvalue) {
         (true, mir::Rvalue::Ref(_, _, place)) | (false, mir::Rvalue::Use(mir::Operand::Copy(place))) => {
             Some(base_local_and_movability(cx, mir, *place))
         },
diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs
index 2d26c49252f..0825f00f421 100644
--- a/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/clippy_lints/src/redundant_static_lifetimes.rs
@@ -51,12 +51,12 @@ impl RedundantStaticLifetimes {
     fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>, reason: &str) {
         match ty.kind {
             // Be careful of nested structures (arrays and tuples)
-            TyKind::Array(ref ty, _) => {
-                self.visit_type(&*ty, cx, reason);
+            TyKind::Array(ref ty, _) | TyKind::Slice(ref ty) => {
+                self.visit_type(ty, cx, reason);
             },
             TyKind::Tup(ref tup) => {
                 for tup_ty in tup {
-                    self.visit_type(&*tup_ty, cx, reason);
+                    self.visit_type(tup_ty, cx, reason);
                 }
             },
             // This is what we are looking for !
@@ -89,9 +89,6 @@ impl RedundantStaticLifetimes {
                 }
                 self.visit_type(&*borrow_type.ty, cx, reason);
             },
-            TyKind::Slice(ref ty) => {
-                self.visit_type(ty, cx, reason);
-            },
             _ => {},
         }
     }
diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs
index 3d7dc49b406..bfb9f0d01e1 100644
--- a/clippy_lints/src/size_of_in_element_count.rs
+++ b/clippy_lints/src/size_of_in_element_count.rs
@@ -110,7 +110,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
         // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
         if let ExprKind::MethodCall(method_path, [ptr_self, .., count], _) = expr.kind;
         let method_ident = method_path.ident.as_str();
-        if METHODS.iter().any(|m| *m == &*method_ident);
+        if METHODS.iter().any(|m| *m == method_ident);
 
         // Get the pointee type
         if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =
diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
index 0e8f40e9210..60f98876994 100644
--- a/clippy_lints/src/utils/internal_lints.rs
+++ b/clippy_lints/src/utils/internal_lints.rs
@@ -422,7 +422,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
             }
         } else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
             if !matches!(
-                &*cx.tcx.item_name(macro_call.def_id).as_str(),
+                cx.tcx.item_name(macro_call.def_id).as_str(),
                 "impl_lint_pass" | "declare_lint_pass"
             ) {
                 return;
@@ -504,7 +504,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
             return;
         }
 
-        if RustcVersion::parse(&*value.as_str()).is_err() {
+        if RustcVersion::parse(value.as_str()).is_err() {
             span_lint_and_help(
                 cx,
                 INVALID_CLIPPY_VERSION_ATTRIBUTE,
@@ -595,7 +595,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
         if_chain! {
             if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
             let fn_name = path.ident;
-            if let Some(sugg) = self.map.get(&*fn_name.as_str());
+            if let Some(sugg) = self.map.get(fn_name.as_str());
             let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
             if match_type(cx, ty, &paths::EARLY_CONTEXT)
                 || match_type(cx, ty, &paths::LATE_CONTEXT);
@@ -679,7 +679,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
             then {
                 let and_then_snippets = get_and_then_snippets(cx, and_then_args);
                 let mut sle = SpanlessEq::new(cx).deny_side_effects();
-                match &*ps.ident.as_str() {
+                match ps.ident.as_str() {
                     "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[1]) => {
                         suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args));
                     },
diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 8c1910b3b2a..53579ccb4c2 100644
--- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -527,12 +527,11 @@ fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<St
 fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
     let attrs = cx.tcx.hir().attrs(item.hir_id());
     let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
-    let mut docs = String::from(&*lines.next()?.as_str());
+    let mut docs = String::from(lines.next()?.as_str());
     let mut in_code_block = false;
     let mut is_code_block_rust = false;
     for line in lines {
         let line = line.as_str();
-        let line = &*line;
 
         // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
         if is_code_block_rust && line.trim_start().starts_with("# ") {
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 9f162a117b2..d487868cafe 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant> {
         if let Some(Constant::Bool(b)) = self.expr(cond) {
             if b {
-                self.expr(&*then)
+                self.expr(then)
             } else {
                 otherwise.as_ref().and_then(|expr| self.expr(expr))
             }
diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs
index 1e0fc789af2..4604ae5c2c7 100644
--- a/clippy_utils/src/higher.rs
+++ b/clippy_utils/src/higher.rs
@@ -35,7 +35,7 @@ impl<'tcx> ForLoop<'tcx> {
             if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind;
             if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind;
             if let hir::ExprKind::Loop(block, ..) = arm.body.kind;
-            if let [stmt] = &*block.stmts;
+            if let [stmt] = block.stmts;
             if let hir::StmtKind::Expr(e) = stmt.kind;
             if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind;
             if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind;
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index c440793b90e..cbd0a257cfb 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -411,10 +411,10 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
             (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
             (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
-                l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
+                l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty)
             },
             (&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => {
-                l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
+                l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
             },
             (&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r),
             (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
@@ -608,7 +608,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_name(i.ident.name);
                 }
                 if let Some(j) = *j {
-                    self.hash_expr(&*j);
+                    self.hash_expr(j);
                 }
             },
             ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index b8a80d4adc3..1ca7cf5c177 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1443,7 +1443,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         },
         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
         PatKind::Struct(ref qpath, fields, _) => {
-            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
+            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
         },
         PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
         PatKind::Slice(head, middle, tail) => {
@@ -1658,7 +1658,7 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
     let mut blocks: Vec<&Block<'_>> = Vec::new();
 
     while let Some(higher::IfOrIfLet { cond, then, r#else }) = higher::IfOrIfLet::hir(expr) {
-        conds.push(&*cond);
+        conds.push(cond);
         if let ExprKind::Block(block, _) = then.kind {
             blocks.push(block);
         } else {
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 3b599351016..7d219835723 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -346,6 +346,7 @@ fn compile_test() {
 
 const RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS: &[&str] = &[
     "assign_ops2.rs",
+    "borrow_deref_ref_unfixable.rs",
     "cast_size_32bit.rs",
     "char_lit_as_u8.rs",
     "cmp_owned/without_suggestion.rs",
diff --git a/tests/ui-internal/unnecessary_symbol_str.fixed b/tests/ui-internal/unnecessary_symbol_str.fixed
index 4f5336663a8..6033d06e4f6 100644
--- a/tests/ui-internal/unnecessary_symbol_str.fixed
+++ b/tests/ui-internal/unnecessary_symbol_str.fixed
@@ -2,6 +2,7 @@
 #![feature(rustc_private)]
 #![deny(clippy::internal)]
 #![allow(
+    clippy::borrow_deref_ref,
     clippy::unnecessary_operation,
     unused_must_use,
     clippy::missing_clippy_version_attribute
diff --git a/tests/ui-internal/unnecessary_symbol_str.rs b/tests/ui-internal/unnecessary_symbol_str.rs
index 894aa1d3bc6..1bb5d55f0b6 100644
--- a/tests/ui-internal/unnecessary_symbol_str.rs
+++ b/tests/ui-internal/unnecessary_symbol_str.rs
@@ -2,6 +2,7 @@
 #![feature(rustc_private)]
 #![deny(clippy::internal)]
 #![allow(
+    clippy::borrow_deref_ref,
     clippy::unnecessary_operation,
     unused_must_use,
     clippy::missing_clippy_version_attribute
diff --git a/tests/ui-internal/unnecessary_symbol_str.stderr b/tests/ui-internal/unnecessary_symbol_str.stderr
index 75367bf4bc5..a1f507f331d 100644
--- a/tests/ui-internal/unnecessary_symbol_str.stderr
+++ b/tests/ui-internal/unnecessary_symbol_str.stderr
@@ -1,5 +1,5 @@
 error: unnecessary `Symbol` to string conversion
-  --> $DIR/unnecessary_symbol_str.rs:15:5
+  --> $DIR/unnecessary_symbol_str.rs:16:5
    |
 LL |     Symbol::intern("foo").as_str() == "clippy";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::sym::clippy`
@@ -12,25 +12,25 @@ LL | #![deny(clippy::internal)]
    = note: `#[deny(clippy::unnecessary_symbol_str)]` implied by `#[deny(clippy::internal)]`
 
 error: unnecessary `Symbol` to string conversion
-  --> $DIR/unnecessary_symbol_str.rs:16:5
+  --> $DIR/unnecessary_symbol_str.rs:17:5
    |
 LL |     Symbol::intern("foo").to_string() == "self";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::symbol::kw::SelfLower`
 
 error: unnecessary `Symbol` to string conversion
-  --> $DIR/unnecessary_symbol_str.rs:17:5
+  --> $DIR/unnecessary_symbol_str.rs:18:5
    |
 LL |     Symbol::intern("foo").to_ident_string() != "Self";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") != rustc_span::symbol::kw::SelfUpper`
 
 error: unnecessary `Symbol` to string conversion
-  --> $DIR/unnecessary_symbol_str.rs:18:5
+  --> $DIR/unnecessary_symbol_str.rs:19:5
    |
 LL |     &*Ident::empty().as_str() == "clippy";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy`
 
 error: unnecessary `Symbol` to string conversion
-  --> $DIR/unnecessary_symbol_str.rs:19:5
+  --> $DIR/unnecessary_symbol_str.rs:20:5
    |
 LL |     "clippy" == Ident::empty().to_string();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name`
diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed
new file mode 100644
index 00000000000..bf4691c5bc9
--- /dev/null
+++ b/tests/ui/borrow_deref_ref.fixed
@@ -0,0 +1,59 @@
+// run-rustfix
+
+#![allow(dead_code, unused_variables)]
+
+fn main() {}
+
+mod should_lint {
+    fn one_help() {
+        let a = &12;
+        let b = a;
+
+        let b = &mut bar(&12);
+    }
+
+    fn bar(x: &u32) -> &u32 {
+        x
+    }
+}
+
+// this mod explains why we should not lint `&mut &* (&T)`
+mod should_not_lint1 {
+    fn foo(x: &mut &u32) {
+        *x = &1;
+    }
+
+    fn main() {
+        let mut x = &0;
+        foo(&mut &*x); // should not lint
+        assert_eq!(*x, 0);
+
+        foo(&mut x);
+        assert_eq!(*x, 1);
+    }
+}
+
+// similar to should_not_lint1
+mod should_not_lint2 {
+    struct S<'a> {
+        a: &'a u32,
+        b: u32,
+    }
+
+    fn main() {
+        let s = S { a: &1, b: 1 };
+        let x = &mut &*s.a;
+        *x = &2;
+    }
+}
+
+// this mod explains why we should not lint `& &* (&T)`
+mod false_negative {
+    fn foo() {
+        let x = &12;
+        let addr_x = &x as *const _ as usize;
+        let addr_y = &x as *const _ as usize; // assert ok
+        // let addr_y = &x as *const _ as usize; // assert fail
+        assert_ne!(addr_x, addr_y);
+    }
+}
diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs
new file mode 100644
index 00000000000..28c005fdbef
--- /dev/null
+++ b/tests/ui/borrow_deref_ref.rs
@@ -0,0 +1,59 @@
+// run-rustfix
+
+#![allow(dead_code, unused_variables)]
+
+fn main() {}
+
+mod should_lint {
+    fn one_help() {
+        let a = &12;
+        let b = &*a;
+
+        let b = &mut &*bar(&12);
+    }
+
+    fn bar(x: &u32) -> &u32 {
+        x
+    }
+}
+
+// this mod explains why we should not lint `&mut &* (&T)`
+mod should_not_lint1 {
+    fn foo(x: &mut &u32) {
+        *x = &1;
+    }
+
+    fn main() {
+        let mut x = &0;
+        foo(&mut &*x); // should not lint
+        assert_eq!(*x, 0);
+
+        foo(&mut x);
+        assert_eq!(*x, 1);
+    }
+}
+
+// similar to should_not_lint1
+mod should_not_lint2 {
+    struct S<'a> {
+        a: &'a u32,
+        b: u32,
+    }
+
+    fn main() {
+        let s = S { a: &1, b: 1 };
+        let x = &mut &*s.a;
+        *x = &2;
+    }
+}
+
+// this mod explains why we should not lint `& &* (&T)`
+mod false_negative {
+    fn foo() {
+        let x = &12;
+        let addr_x = &x as *const _ as usize;
+        let addr_y = &&*x as *const _ as usize; // assert ok
+        // let addr_y = &x as *const _ as usize; // assert fail
+        assert_ne!(addr_x, addr_y);
+    }
+}
diff --git a/tests/ui/borrow_deref_ref.stderr b/tests/ui/borrow_deref_ref.stderr
new file mode 100644
index 00000000000..d72de37c69f
--- /dev/null
+++ b/tests/ui/borrow_deref_ref.stderr
@@ -0,0 +1,22 @@
+error: deref on an immutable reference
+  --> $DIR/borrow_deref_ref.rs:10:17
+   |
+LL |         let b = &*a;
+   |                 ^^^ help: if you would like to reborrow, try removing `&*`: `a`
+   |
+   = note: `-D clippy::borrow-deref-ref` implied by `-D warnings`
+
+error: deref on an immutable reference
+  --> $DIR/borrow_deref_ref.rs:12:22
+   |
+LL |         let b = &mut &*bar(&12);
+   |                      ^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `bar(&12)`
+
+error: deref on an immutable reference
+  --> $DIR/borrow_deref_ref.rs:55:23
+   |
+LL |         let addr_y = &&*x as *const _ as usize; // assert ok
+   |                       ^^^ help: if you would like to reborrow, try removing `&*`: `x`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/borrow_deref_ref_unfixable.rs b/tests/ui/borrow_deref_ref_unfixable.rs
new file mode 100644
index 00000000000..a8e2bbfef0f
--- /dev/null
+++ b/tests/ui/borrow_deref_ref_unfixable.rs
@@ -0,0 +1,10 @@
+#![allow(dead_code, unused_variables)]
+
+fn main() {}
+
+mod should_lint {
+    fn two_helps() {
+        let s = &String::new();
+        let x: &str = &*s;
+    }
+}
diff --git a/tests/ui/borrow_deref_ref_unfixable.stderr b/tests/ui/borrow_deref_ref_unfixable.stderr
new file mode 100644
index 00000000000..738b01e7ec1
--- /dev/null
+++ b/tests/ui/borrow_deref_ref_unfixable.stderr
@@ -0,0 +1,18 @@
+error: deref on an immutable reference
+  --> $DIR/borrow_deref_ref_unfixable.rs:8:23
+   |
+LL |         let x: &str = &*s;
+   |                       ^^^
+   |
+   = note: `-D clippy::borrow-deref-ref` implied by `-D warnings`
+help: if you would like to reborrow, try removing `&*`
+   |
+LL |         let x: &str = s;
+   |                       ~
+help: if you would like to deref, try using `&**`
+   |
+LL |         let x: &str = &**s;
+   |                       ~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/collapsible_match2.rs b/tests/ui/collapsible_match2.rs
index 542e6948427..c8fb0a39e95 100644
--- a/tests/ui/collapsible_match2.rs
+++ b/tests/ui/collapsible_match2.rs
@@ -57,7 +57,7 @@ fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>
 
     // ref pattern and deref
     match Some(&[1]) {
-        Some(ref s) => match &*s {
+        Some(ref s) => match s {
             [n] => foo(n),
             _ => (),
         },
diff --git a/tests/ui/collapsible_match2.stderr b/tests/ui/collapsible_match2.stderr
index 46b645aea13..fe64e469379 100644
--- a/tests/ui/collapsible_match2.stderr
+++ b/tests/ui/collapsible_match2.stderr
@@ -78,7 +78,7 @@ LL |             [n] => foo(n),
 error: this `match` can be collapsed into the outer `match`
   --> $DIR/collapsible_match2.rs:60:24
    |
-LL |           Some(ref s) => match &*s {
+LL |           Some(ref s) => match s {
    |  ________________________^
 LL | |             [n] => foo(n),
 LL | |             _ => (),
@@ -88,7 +88,7 @@ LL | |         },
 help: the outer pattern can be modified to include the inner pattern
   --> $DIR/collapsible_match2.rs:60:14
    |
-LL |         Some(ref s) => match &*s {
+LL |         Some(ref s) => match s {
    |              ^^^^^ replace this binding
 LL |             [n] => foo(n),
    |             ^^^ with this pattern
diff --git a/tests/ui/deref_by_slicing.fixed b/tests/ui/deref_by_slicing.fixed
index b26276218b7..257393e56ff 100644
--- a/tests/ui/deref_by_slicing.fixed
+++ b/tests/ui/deref_by_slicing.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::deref_by_slicing)]
+#![allow(clippy::borrow_deref_ref)]
 
 use std::io::Read;
 
diff --git a/tests/ui/deref_by_slicing.rs b/tests/ui/deref_by_slicing.rs
index 6aa1408ba17..e288046f927 100644
--- a/tests/ui/deref_by_slicing.rs
+++ b/tests/ui/deref_by_slicing.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::deref_by_slicing)]
+#![allow(clippy::borrow_deref_ref)]
 
 use std::io::Read;
 
diff --git a/tests/ui/deref_by_slicing.stderr b/tests/ui/deref_by_slicing.stderr
index ffd76de378d..8f042ef47eb 100644
--- a/tests/ui/deref_by_slicing.stderr
+++ b/tests/ui/deref_by_slicing.stderr
@@ -1,5 +1,5 @@
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:9:13
+  --> $DIR/deref_by_slicing.rs:10:13
    |
 LL |     let _ = &vec[..];
    |             ^^^^^^^^ help: dereference the original value instead: `&*vec`
@@ -7,49 +7,49 @@ LL |     let _ = &vec[..];
    = note: `-D clippy::deref-by-slicing` implied by `-D warnings`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:10:13
+  --> $DIR/deref_by_slicing.rs:11:13
    |
 LL |     let _ = &mut vec[..];
    |             ^^^^^^^^^^^^ help: dereference the original value instead: `&mut *vec`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:13:13
+  --> $DIR/deref_by_slicing.rs:14:13
    |
 LL |     let _ = &ref_vec[..];
    |             ^^^^^^^^^^^^ help: dereference the original value instead: `&**ref_vec`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:14:21
+  --> $DIR/deref_by_slicing.rs:15:21
    |
 LL |     let mut_slice = &mut ref_vec[..];
    |                     ^^^^^^^^^^^^^^^^ help: dereference the original value instead: `&mut **ref_vec`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:15:13
+  --> $DIR/deref_by_slicing.rs:16:13
    |
 LL |     let _ = &mut mut_slice[..]; // Err, re-borrows slice
    |             ^^^^^^^^^^^^^^^^^^ help: reborrow the original value instead: `&mut *mut_slice`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:18:13
+  --> $DIR/deref_by_slicing.rs:19:13
    |
 LL |     let _ = &s[..];
    |             ^^^^^^ help: dereference the original value instead: `&*s`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:21:18
+  --> $DIR/deref_by_slicing.rs:22:18
    |
 LL |     let _ = &mut &S[..]; // Err, re-borrows slice
    |                  ^^^^^^ help: reborrow the original value instead: `&*S`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:25:13
+  --> $DIR/deref_by_slicing.rs:26:13
    |
 LL |     let _ = &slice_ref[..]; // Err, derefs slice
    |             ^^^^^^^^^^^^^^ help: dereference the original value instead: `*slice_ref`
 
 error: slicing when dereferencing would work
-  --> $DIR/deref_by_slicing.rs:28:13
+  --> $DIR/deref_by_slicing.rs:29:13
    |
 LL |     let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice
    |             ^^^^^^^^^^^^ help: reborrow the original value instead: `(&*bytes)`
diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed
index 3de2a51ffa5..92f27e68549 100644
--- a/tests/ui/explicit_deref_methods.fixed
+++ b/tests/ui/explicit_deref_methods.fixed
@@ -1,6 +1,11 @@
 // run-rustfix
 
-#![allow(unused_variables, clippy::clone_double_ref, clippy::needless_borrow)]
+#![allow(
+    unused_variables,
+    clippy::clone_double_ref,
+    clippy::needless_borrow,
+    clippy::borrow_deref_ref
+)]
 #![warn(clippy::explicit_deref_methods)]
 
 use std::ops::{Deref, DerefMut};
diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs
index a08d7596422..d118607f992 100644
--- a/tests/ui/explicit_deref_methods.rs
+++ b/tests/ui/explicit_deref_methods.rs
@@ -1,6 +1,11 @@
 // run-rustfix
 
-#![allow(unused_variables, clippy::clone_double_ref, clippy::needless_borrow)]
+#![allow(
+    unused_variables,
+    clippy::clone_double_ref,
+    clippy::needless_borrow,
+    clippy::borrow_deref_ref
+)]
 #![warn(clippy::explicit_deref_methods)]
 
 use std::ops::{Deref, DerefMut};
diff --git a/tests/ui/explicit_deref_methods.stderr b/tests/ui/explicit_deref_methods.stderr
index 8035d77d18d..8e8b358972b 100644
--- a/tests/ui/explicit_deref_methods.stderr
+++ b/tests/ui/explicit_deref_methods.stderr
@@ -1,5 +1,5 @@
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:30:19
+  --> $DIR/explicit_deref_methods.rs:35:19
    |
 LL |     let b: &str = a.deref();
    |                   ^^^^^^^^^ help: try this: `&*a`
@@ -7,67 +7,67 @@ LL |     let b: &str = a.deref();
    = note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
 
 error: explicit `deref_mut` method call
-  --> $DIR/explicit_deref_methods.rs:32:23
+  --> $DIR/explicit_deref_methods.rs:37:23
    |
 LL |     let b: &mut str = a.deref_mut();
    |                       ^^^^^^^^^^^^^ help: try this: `&mut **a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:35:39
+  --> $DIR/explicit_deref_methods.rs:40:39
    |
 LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
    |                                       ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:35:50
+  --> $DIR/explicit_deref_methods.rs:40:50
    |
 LL |     let b: String = format!("{}, {}", a.deref(), a.deref());
    |                                                  ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:37:20
+  --> $DIR/explicit_deref_methods.rs:42:20
    |
 LL |     println!("{}", a.deref());
    |                    ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:40:11
+  --> $DIR/explicit_deref_methods.rs:45:11
    |
 LL |     match a.deref() {
    |           ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:44:28
+  --> $DIR/explicit_deref_methods.rs:49:28
    |
 LL |     let b: String = concat(a.deref());
    |                            ^^^^^^^^^ help: try this: `&*a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:46:13
+  --> $DIR/explicit_deref_methods.rs:51:13
    |
 LL |     let b = just_return(a).deref();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:48:28
+  --> $DIR/explicit_deref_methods.rs:53:28
    |
 LL |     let b: String = concat(just_return(a).deref());
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `just_return(a)`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:50:19
+  --> $DIR/explicit_deref_methods.rs:55:19
    |
 LL |     let b: &str = a.deref().deref();
    |                   ^^^^^^^^^^^^^^^^^ help: try this: `&**a`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:53:13
+  --> $DIR/explicit_deref_methods.rs:58:13
    |
 LL |     let b = opt_a.unwrap().deref();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`
 
 error: explicit `deref` method call
-  --> $DIR/explicit_deref_methods.rs:79:31
+  --> $DIR/explicit_deref_methods.rs:84:31
    |
 LL |     let b: &str = expr_deref!(a.deref());
    |                               ^^^^^^^^^ help: try this: `&*a`
diff --git a/tests/ui/forget_ref.rs b/tests/ui/forget_ref.rs
index 6c8c4c9c0ed..031b415f56f 100644
--- a/tests/ui/forget_ref.rs
+++ b/tests/ui/forget_ref.rs
@@ -1,6 +1,7 @@
 #![warn(clippy::forget_ref)]
 #![allow(clippy::toplevel_ref_arg)]
 #![allow(clippy::unnecessary_wraps, clippy::forget_non_drop)]
+#![allow(clippy::borrow_deref_ref)]
 
 use std::mem::forget;
 
diff --git a/tests/ui/forget_ref.stderr b/tests/ui/forget_ref.stderr
index 73409388ed1..df5cd8cacdb 100644
--- a/tests/ui/forget_ref.stderr
+++ b/tests/ui/forget_ref.stderr
@@ -1,108 +1,108 @@
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:10:5
+  --> $DIR/forget_ref.rs:11:5
    |
 LL |     forget(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::forget-ref` implied by `-D warnings`
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:10:12
+  --> $DIR/forget_ref.rs:11:12
    |
 LL |     forget(&SomeStruct);
    |            ^^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:13:5
+  --> $DIR/forget_ref.rs:14:5
    |
 LL |     forget(&owned);
    |     ^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:13:12
+  --> $DIR/forget_ref.rs:14:12
    |
 LL |     forget(&owned);
    |            ^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:14:5
+  --> $DIR/forget_ref.rs:15:5
    |
 LL |     forget(&&owned);
    |     ^^^^^^^^^^^^^^^
    |
 note: argument has type `&&SomeStruct`
-  --> $DIR/forget_ref.rs:14:12
+  --> $DIR/forget_ref.rs:15:12
    |
 LL |     forget(&&owned);
    |            ^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:15:5
+  --> $DIR/forget_ref.rs:16:5
    |
 LL |     forget(&mut owned);
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&mut SomeStruct`
-  --> $DIR/forget_ref.rs:15:12
+  --> $DIR/forget_ref.rs:16:12
    |
 LL |     forget(&mut owned);
    |            ^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:19:5
+  --> $DIR/forget_ref.rs:20:5
    |
 LL |     forget(&*reference1);
    |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:19:12
+  --> $DIR/forget_ref.rs:20:12
    |
 LL |     forget(&*reference1);
    |            ^^^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:22:5
+  --> $DIR/forget_ref.rs:23:5
    |
 LL |     forget(reference2);
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&mut SomeStruct`
-  --> $DIR/forget_ref.rs:22:12
+  --> $DIR/forget_ref.rs:23:12
    |
 LL |     forget(reference2);
    |            ^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:25:5
+  --> $DIR/forget_ref.rs:26:5
    |
 LL |     forget(reference3);
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:25:12
+  --> $DIR/forget_ref.rs:26:12
    |
 LL |     forget(reference3);
    |            ^^^^^^^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:30:5
+  --> $DIR/forget_ref.rs:31:5
    |
 LL |     forget(&val);
    |     ^^^^^^^^^^^^
    |
 note: argument has type `&T`
-  --> $DIR/forget_ref.rs:30:12
+  --> $DIR/forget_ref.rs:31:12
    |
 LL |     forget(&val);
    |            ^^^^
 
 error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:38:5
+  --> $DIR/forget_ref.rs:39:5
    |
 LL |     std::mem::forget(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:38:22
+  --> $DIR/forget_ref.rs:39:22
    |
 LL |     std::mem::forget(&SomeStruct);
    |                      ^^^^^^^^^^^
diff --git a/tests/ui/recursive_format_impl.rs b/tests/ui/recursive_format_impl.rs
index f72fc77ab99..cb6ba36b14c 100644
--- a/tests/ui/recursive_format_impl.rs
+++ b/tests/ui/recursive_format_impl.rs
@@ -2,7 +2,8 @@
 #![allow(
     clippy::inherent_to_string_shadow_display,
     clippy::to_string_in_format_args,
-    clippy::deref_addrof
+    clippy::deref_addrof,
+    clippy::borrow_deref_ref
 )]
 
 use std::fmt;
diff --git a/tests/ui/recursive_format_impl.stderr b/tests/ui/recursive_format_impl.stderr
index 1a717ac92d8..84ce69df566 100644
--- a/tests/ui/recursive_format_impl.stderr
+++ b/tests/ui/recursive_format_impl.stderr
@@ -1,5 +1,5 @@
 error: using `self.to_string` in `fmt::Display` implementation will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:29:25
+  --> $DIR/recursive_format_impl.rs:30:25
    |
 LL |         write!(f, "{}", self.to_string())
    |                         ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |         write!(f, "{}", self.to_string())
    = note: `-D clippy::recursive-format-impl` implied by `-D warnings`
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:73:9
+  --> $DIR/recursive_format_impl.rs:74:9
    |
 LL |         write!(f, "{}", self)
    |         ^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL |         write!(f, "{}", self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:82:9
+  --> $DIR/recursive_format_impl.rs:83:9
    |
 LL |         write!(f, "{}", &self)
    |         ^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |         write!(f, "{}", &self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Debug` in `impl Debug` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:88:9
+  --> $DIR/recursive_format_impl.rs:89:9
    |
 LL |         write!(f, "{:?}", &self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |         write!(f, "{:?}", &self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:97:9
+  --> $DIR/recursive_format_impl.rs:98:9
    |
 LL |         write!(f, "{}", &&&self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL |         write!(f, "{}", &&&self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:171:9
+  --> $DIR/recursive_format_impl.rs:172:9
    |
 LL |         write!(f, "{}", &*self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |         write!(f, "{}", &*self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Debug` in `impl Debug` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:177:9
+  --> $DIR/recursive_format_impl.rs:178:9
    |
 LL |         write!(f, "{:?}", &*self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |         write!(f, "{:?}", &*self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:193:9
+  --> $DIR/recursive_format_impl.rs:194:9
    |
 LL |         write!(f, "{}", *self)
    |         ^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@ LL |         write!(f, "{}", *self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:209:9
+  --> $DIR/recursive_format_impl.rs:210:9
    |
 LL |         write!(f, "{}", **&&*self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL |         write!(f, "{}", **&&*self)
    = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: using `self` as `Display` in `impl Display` will cause infinite recursion
-  --> $DIR/recursive_format_impl.rs:225:9
+  --> $DIR/recursive_format_impl.rs:226:9
    |
 LL |         write!(f, "{}", &&**&&*self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^