about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/reference.rs88
-rw-r--r--tests/ui/deref_addrof.fixed32
-rw-r--r--tests/ui/deref_addrof.rs32
-rw-r--r--tests/ui/deref_addrof.stderr54
4 files changed, 73 insertions, 133 deletions
diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs
index 0b8993ee1e1..3bbcad12a31 100644
--- a/clippy_lints/src/reference.rs
+++ b/clippy_lints/src/reference.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
+use clippy_utils::source::snippet;
+use clippy_utils::sugg::{Sugg, has_enclosing_paren};
 use clippy_utils::ty::adjust_derefs_manually_drop;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, Mutability, Node, UnOp};
+use rustc_hir::{Expr, ExprKind, HirId, Node, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{BytePos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -40,79 +40,43 @@ declare_lint_pass!(DerefAddrOf => [DEREF_ADDROF]);
 
 impl LateLintPass<'_> for DerefAddrOf {
     fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
-        if let ExprKind::Unary(UnOp::Deref, deref_target) = e.kind
-            && let ExprKind::AddrOf(_, mutability, addrof_target) = deref_target.kind
+        if !e.span.from_expansion()
+            && let ExprKind::Unary(UnOp::Deref, deref_target) = e.kind
+            && !deref_target.span.from_expansion()
+            && let ExprKind::AddrOf(_, _, addrof_target) = deref_target.kind
             // NOTE(tesuji): `*&` forces rustc to const-promote the array to `.rodata` section.
             // See #12854 for details.
             && !matches!(addrof_target.kind, ExprKind::Array(_))
             && deref_target.span.eq_ctxt(e.span)
             && !addrof_target.span.from_expansion()
         {
+            let mut applicability = Applicability::MachineApplicable;
+            let mut sugg = || Sugg::hir_with_applicability(cx, addrof_target, "_", &mut applicability);
+
             // If this expression is an explicit `DerefMut` of a `ManuallyDrop` reached through a
             // union, we may remove the reference if we are at the point where the implicit
             // dereference would take place. Otherwise, we should not lint.
-            let keep_deref = match is_manually_drop_through_union(cx, e.hir_id, addrof_target) {
-                ManuallyDropThroughUnion::Directly => true,
+            let sugg = match is_manually_drop_through_union(cx, e.hir_id, addrof_target) {
+                ManuallyDropThroughUnion::Directly => sugg().deref(),
                 ManuallyDropThroughUnion::Indirect => return,
-                ManuallyDropThroughUnion::No => false,
+                ManuallyDropThroughUnion::No => sugg(),
             };
 
-            let mut applicability = Applicability::MachineApplicable;
-            let sugg = if e.span.from_expansion() {
-                if let Some(macro_source) = e.span.get_source_text(cx) {
-                    // Remove leading whitespace from the given span
-                    // e.g: ` $visitor` turns into `$visitor`
-                    let trim_leading_whitespaces = |span: Span| {
-                        span.get_source_text(cx)
-                            .and_then(|snip| {
-                                #[expect(clippy::cast_possible_truncation)]
-                                snip.find(|c: char| !c.is_whitespace())
-                                    .map(|pos| span.lo() + BytePos(pos as u32))
-                            })
-                            .map_or(span, |start_no_whitespace| e.span.with_lo(start_no_whitespace))
-                    };
-
-                    let mut generate_snippet = |pattern: &str| {
-                        #[expect(clippy::cast_possible_truncation)]
-                        macro_source.rfind(pattern).map(|pattern_pos| {
-                            let rpos = pattern_pos + pattern.len();
-                            let span_after_ref = e.span.with_lo(BytePos(e.span.lo().0 + rpos as u32));
-                            let span = trim_leading_whitespaces(span_after_ref);
-                            snippet_with_applicability(cx, span, "_", &mut applicability)
-                        })
-                    };
-
-                    if mutability == Mutability::Mut {
-                        generate_snippet("mut")
-                    } else {
-                        generate_snippet("&")
-                    }
-                } else {
-                    Some(snippet_with_applicability(cx, e.span, "_", &mut applicability))
-                }
+            let sugg = if has_enclosing_paren(snippet(cx, e.span, "")) {
+                sugg.maybe_paren()
             } else {
-                Some(snippet_with_applicability(
-                    cx,
-                    addrof_target.span,
-                    "_",
-                    &mut applicability,
-                ))
+                sugg
             };
-            if let Some(sugg) = sugg {
-                span_lint_and_sugg(
-                    cx,
-                    DEREF_ADDROF,
-                    e.span,
-                    "immediately dereferencing a reference",
-                    "try",
-                    if keep_deref {
-                        format!("(*{sugg})")
-                    } else {
-                        sugg.to_string()
-                    },
-                    applicability,
-                );
-            }
+
+            span_lint_and_sugg(
+                cx,
+                DEREF_ADDROF,
+                e.span,
+                "immediately dereferencing a reference",
+                "try",
+                sugg.to_string(),
+                applicability,
+            );
         }
     }
 }
diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed
index ae8ed0dc114..ffe7f7d1440 100644
--- a/tests/ui/deref_addrof.fixed
+++ b/tests/ui/deref_addrof.fixed
@@ -1,5 +1,3 @@
-//@aux-build:proc_macros.rs
-
 #![allow(
     dangerous_implicit_autorefs,
     clippy::explicit_auto_deref,
@@ -8,9 +6,6 @@
 )]
 #![warn(clippy::deref_addrof)]
 
-extern crate proc_macros;
-use proc_macros::inline_macros;
-
 fn get_number() -> usize {
     10
 }
@@ -61,21 +56,22 @@ fn main() {
     //~^ deref_addrof
     // do NOT lint for array as semantic differences with/out `*&`.
     let _arr = *&[0, 1, 2, 3, 4];
-}
 
-#[derive(Copy, Clone)]
-pub struct S;
-#[inline_macros]
-impl S {
-    pub fn f(&self) -> &Self {
-        inline!($(@expr self))
-        //~^ deref_addrof
-    }
-    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
-    pub fn f_mut(mut self) -> Self {
-        inline!($(@expr self))
-        //~^ deref_addrof
+    // Do not lint when text comes from macro
+    macro_rules! mac {
+        (dr) => {
+            *&0
+        };
+        (dr $e:expr) => {
+            *&$e
+        };
+        (r $e:expr) => {
+            &$e
+        };
     }
+    let b = mac!(dr);
+    let b = mac!(dr a);
+    let b = *mac!(r a);
 }
 
 fn issue14386() {
diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs
index 4ff01405916..bc253716aff 100644
--- a/tests/ui/deref_addrof.rs
+++ b/tests/ui/deref_addrof.rs
@@ -1,5 +1,3 @@
-//@aux-build:proc_macros.rs
-
 #![allow(
     dangerous_implicit_autorefs,
     clippy::explicit_auto_deref,
@@ -8,9 +6,6 @@
 )]
 #![warn(clippy::deref_addrof)]
 
-extern crate proc_macros;
-use proc_macros::inline_macros;
-
 fn get_number() -> usize {
     10
 }
@@ -61,21 +56,22 @@ fn main() {
     //~^ deref_addrof
     // do NOT lint for array as semantic differences with/out `*&`.
     let _arr = *&[0, 1, 2, 3, 4];
-}
 
-#[derive(Copy, Clone)]
-pub struct S;
-#[inline_macros]
-impl S {
-    pub fn f(&self) -> &Self {
-        inline!(*& $(@expr self))
-        //~^ deref_addrof
-    }
-    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
-    pub fn f_mut(mut self) -> Self {
-        inline!(*&mut $(@expr self))
-        //~^ deref_addrof
+    // Do not lint when text comes from macro
+    macro_rules! mac {
+        (dr) => {
+            *&0
+        };
+        (dr $e:expr) => {
+            *&$e
+        };
+        (r $e:expr) => {
+            &$e
+        };
     }
+    let b = mac!(dr);
+    let b = mac!(dr a);
+    let b = *mac!(r a);
 }
 
 fn issue14386() {
diff --git a/tests/ui/deref_addrof.stderr b/tests/ui/deref_addrof.stderr
index adfa542765c..65dd904a8f7 100644
--- a/tests/ui/deref_addrof.stderr
+++ b/tests/ui/deref_addrof.stderr
@@ -1,5 +1,5 @@
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:28:13
+  --> tests/ui/deref_addrof.rs:23:13
    |
 LL |     let b = *&a;
    |             ^^^ help: try: `a`
@@ -8,122 +8,106 @@ LL |     let b = *&a;
    = help: to override `-D warnings` add `#[allow(clippy::deref_addrof)]`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:31:13
+  --> tests/ui/deref_addrof.rs:26:13
    |
 LL |     let b = *&get_number();
    |             ^^^^^^^^^^^^^^ help: try: `get_number()`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:37:13
+  --> tests/ui/deref_addrof.rs:32:13
    |
 LL |     let b = *&bytes[1..2][0];
    |             ^^^^^^^^^^^^^^^^ help: try: `bytes[1..2][0]`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:42:13
+  --> tests/ui/deref_addrof.rs:37:13
    |
 LL |     let b = *&(a);
    |             ^^^^^ help: try: `(a)`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:45:13
+  --> tests/ui/deref_addrof.rs:40:13
    |
 LL |     let b = *(&a);
    |             ^^^^^ help: try: `a`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:49:13
+  --> tests/ui/deref_addrof.rs:44:13
    |
 LL |     let b = *((&a));
    |             ^^^^^^^ help: try: `a`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:52:13
+  --> tests/ui/deref_addrof.rs:47:13
    |
 LL |     let b = *&&a;
    |             ^^^^ help: try: `&a`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:55:14
+  --> tests/ui/deref_addrof.rs:50:14
    |
 LL |     let b = **&aref;
    |              ^^^^^^ help: try: `aref`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:60:19
+  --> tests/ui/deref_addrof.rs:55:19
    |
 LL |     let _repeat = *&[0; 64];
    |                   ^^^^^^^^^ help: try: `[0; 64]`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:71:17
-   |
-LL |         inline!(*& $(@expr self))
-   |                 ^^^^^^^^^^^^^^^^ help: try: `$(@expr self)`
-   |
-   = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:76:17
-   |
-LL |         inline!(*&mut $(@expr self))
-   |                 ^^^^^^^^^^^^^^^^^^^ help: try: `$(@expr self)`
-   |
-   = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:108:9
+  --> tests/ui/deref_addrof.rs:104:9
    |
 LL |         (*&mut a.padding) = [1; size_of::<DataWithPadding>()];
    |         ^^^^^^^^^^^^^^^^^ help: try: `a.padding`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:110:9
+  --> tests/ui/deref_addrof.rs:106:9
    |
 LL |         (*&mut a.tup).1 = ();
    |         ^^^^^^^^^^^^^ help: try: `a.tup`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:112:10
+  --> tests/ui/deref_addrof.rs:108:10
    |
 LL |         **&mut a.prim = 0;
    |          ^^^^^^^^^^^^ help: try: `a.prim`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:115:9
+  --> tests/ui/deref_addrof.rs:111:9
    |
 LL |         (*&mut a.data).num = 42;
    |         ^^^^^^^^^^^^^^ help: try: `(*a.data)`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:117:9
+  --> tests/ui/deref_addrof.rs:113:9
    |
 LL |         (*&mut a.indirect.md)[3] = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^ help: try: `(*a.indirect.md)`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:119:9
+  --> tests/ui/deref_addrof.rs:115:9
    |
 LL |         (*&mut a.indirect_arr[1].md)[3] = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*a.indirect_arr[1].md)`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:121:9
+  --> tests/ui/deref_addrof.rs:117:9
    |
 LL |         (*&mut a.indirect_ref.md)[3] = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*a.indirect_ref.md)`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:125:10
+  --> tests/ui/deref_addrof.rs:121:10
    |
 LL |         **&raw mut a.prim = 0;
    |          ^^^^^^^^^^^^^^^^ help: try: `a.prim`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:127:9
+  --> tests/ui/deref_addrof.rs:123:9
    |
 LL |         (*&raw mut a.data).num = 42;
    |         ^^^^^^^^^^^^^^^^^^ help: try: `(*a.data)`
 
-error: aborting due to 20 previous errors
+error: aborting due to 18 previous errors