diff options
| -rw-r--r-- | clippy_lints/src/reference.rs | 88 | ||||
| -rw-r--r-- | tests/ui/deref_addrof.fixed | 32 | ||||
| -rw-r--r-- | tests/ui/deref_addrof.rs | 32 | ||||
| -rw-r--r-- | tests/ui/deref_addrof.stderr | 54 |
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 |
