about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/needless_pass_by_ref_mut.rs7
-rw-r--r--clippy_utils/src/lib.rs11
-rw-r--r--tests/ui/needless_pass_by_ref_mut.rs36
-rw-r--r--tests/ui/needless_pass_by_ref_mut.stderr44
4 files changed, 71 insertions, 27 deletions
diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs
index 3299dca09c3..0e2a101a977 100644
--- a/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -1,7 +1,7 @@
 use super::needless_pass_by_value::requires_exact_signature;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{get_parent_node, is_from_proc_macro, is_self};
+use clippy_utils::{get_parent_node, inherits_cfg, is_from_proc_macro, is_self};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_qpath, FnKind, Visitor};
@@ -192,10 +192,12 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
             let show_semver_warning =
                 self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(*fn_def_id);
 
+            let mut is_cfged = None;
             for input in unused {
                 // If the argument is never used mutably, we emit the warning.
                 let sp = input.span;
                 if let rustc_hir::TyKind::Ref(_, inner_ty) = input.kind {
+                    let is_cfged = is_cfged.get_or_insert_with(|| inherits_cfg(cx.tcx, *fn_def_id));
                     span_lint_hir_and_then(
                         cx,
                         NEEDLESS_PASS_BY_REF_MUT,
@@ -212,6 +214,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                             if show_semver_warning {
                                 diag.warn("changing this function will impact semver compatibility");
                             }
+                            if *is_cfged {
+                                diag.note("this is cfg-gated and may require further changes");
+                            }
                         },
                     );
                 }
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 8429192437c..beff0e6e1ab 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -2451,6 +2451,17 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
         .any(is_cfg_test)
 }
 
+/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
+pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+    let hir = tcx.hir();
+
+    tcx.has_attr(def_id, sym::cfg)
+        || hir
+            .parent_iter(hir.local_def_id_to_hir_id(def_id))
+            .flat_map(|(parent_id, _)| hir.attrs(parent_id))
+            .any(|attr| attr.has_name(sym::cfg))
+}
+
 /// Checks whether item either has `test` attribute applied, or
 /// is a module with `test` in its name.
 ///
diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs
index 49f88978bff..ae7b018d0e2 100644
--- a/tests/ui/needless_pass_by_ref_mut.rs
+++ b/tests/ui/needless_pass_by_ref_mut.rs
@@ -3,8 +3,8 @@
 
 use std::ptr::NonNull;
 
-// Should only warn for `s`.
 fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     *x += *b + s.len() as u32;
 }
 
@@ -28,8 +28,8 @@ fn foo5(s: &mut Vec<u32>) {
     foo2(s);
 }
 
-// Should warn.
 fn foo6(s: &mut Vec<u32>) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     non_mut_ref(s);
 }
 
@@ -41,13 +41,13 @@ impl Bar {
     // Should not warn on `&mut self`.
     fn bar(&mut self) {}
 
-    // Should warn about `vec`
     fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
+        //~^ ERROR: this argument is a mutable reference, but not used mutably
         vec.len()
     }
 
-    // Should warn about `vec` (and not `self`).
     fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
+        //~^ ERROR: this argument is a mutable reference, but not used mutably
         vec.len()
     }
 }
@@ -123,36 +123,36 @@ async fn f7(x: &mut i32, y: i32, z: &mut i32, a: i32) {
     *z += 1;
 }
 
-// Should warn.
 async fn a1(x: &mut i32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", x);
 }
-// Should warn.
 async fn a2(x: &mut i32, y: String) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", x);
 }
-// Should warn.
 async fn a3(x: &mut i32, y: String, z: String) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", x);
 }
-// Should warn.
 async fn a4(x: &mut i32, y: i32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", x);
 }
-// Should warn.
 async fn a5(x: i32, y: &mut i32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", x);
 }
-// Should warn.
 async fn a6(x: i32, y: &mut i32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", x);
 }
-// Should warn.
 async fn a7(x: i32, y: i32, z: &mut i32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", z);
 }
-// Should warn.
 async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
     println!("{:?}", z);
 }
 
@@ -184,6 +184,18 @@ fn used_as_path(s: &mut u32) {}
 #[expect(clippy::needless_pass_by_ref_mut)]
 fn lint_attr(s: &mut u32) {}
 
+#[cfg(not(feature = "a"))]
+fn cfg_warn(s: &mut u32) {}
+//~^ ERROR: this argument is a mutable reference, but not used mutably
+//~| NOTE: this is cfg-gated and may require further changes
+
+#[cfg(not(feature = "a"))]
+mod foo {
+    fn cfg_warn(s: &mut u32) {}
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
+    //~| NOTE: this is cfg-gated and may require further changes
+}
+
 fn main() {
     let mut u = 0;
     let mut v = vec![0];
diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr
index 4ab5b5675ca..0d426ce32f9 100644
--- a/tests/ui/needless_pass_by_ref_mut.stderr
+++ b/tests/ui/needless_pass_by_ref_mut.stderr
@@ -1,5 +1,5 @@
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:7:11
+  --> $DIR/needless_pass_by_ref_mut.rs:6:11
    |
 LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    |           ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
@@ -7,76 +7,92 @@ LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:32:12
+  --> $DIR/needless_pass_by_ref_mut.rs:31:12
    |
 LL | fn foo6(s: &mut Vec<u32>) {
    |            ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:45:29
+  --> $DIR/needless_pass_by_ref_mut.rs:44:29
    |
 LL |     fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
    |                             ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:50:31
+  --> $DIR/needless_pass_by_ref_mut.rs:49:31
    |
 LL |     fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
    |                               ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:127:16
+  --> $DIR/needless_pass_by_ref_mut.rs:126:16
    |
 LL | async fn a1(x: &mut i32) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:131:16
+  --> $DIR/needless_pass_by_ref_mut.rs:130:16
    |
 LL | async fn a2(x: &mut i32, y: String) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:135:16
+  --> $DIR/needless_pass_by_ref_mut.rs:134:16
    |
 LL | async fn a3(x: &mut i32, y: String, z: String) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:139:16
+  --> $DIR/needless_pass_by_ref_mut.rs:138:16
    |
 LL | async fn a4(x: &mut i32, y: i32) {
    |                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:143:24
+  --> $DIR/needless_pass_by_ref_mut.rs:142:24
    |
 LL | async fn a5(x: i32, y: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:147:24
+  --> $DIR/needless_pass_by_ref_mut.rs:146:24
    |
 LL | async fn a6(x: i32, y: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:151:32
+  --> $DIR/needless_pass_by_ref_mut.rs:150:32
    |
 LL | async fn a7(x: i32, y: i32, z: &mut i32) {
    |                                ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:155:24
+  --> $DIR/needless_pass_by_ref_mut.rs:154:24
    |
 LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
    |                        ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:155:45
+  --> $DIR/needless_pass_by_ref_mut.rs:154:45
    |
 LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
    |                                             ^^^^^^^^ help: consider changing to: `&i32`
 
-error: aborting due to 13 previous errors
+error: this argument is a mutable reference, but not used mutably
+  --> $DIR/needless_pass_by_ref_mut.rs:188:16
+   |
+LL | fn cfg_warn(s: &mut u32) {}
+   |                ^^^^^^^^ help: consider changing to: `&u32`
+   |
+   = note: this is cfg-gated and may require further changes
+
+error: this argument is a mutable reference, but not used mutably
+  --> $DIR/needless_pass_by_ref_mut.rs:194:20
+   |
+LL |     fn cfg_warn(s: &mut u32) {}
+   |                    ^^^^^^^^ help: consider changing to: `&u32`
+   |
+   = note: this is cfg-gated and may require further changes
+
+error: aborting due to 15 previous errors