about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-11-27 20:26:31 +0000
committerbors <bors@rust-lang.org>2023-11-27 20:26:31 +0000
commit003e910760ef75196ca26e29c4fc83c2f418f693 (patch)
tree775488d63f5c72bd1f7dc414b67d09c5400fa1e6
parentcaa73941f853a324ee0526387b1bd09526decf50 (diff)
parent3e83a521e45fb6221099673f6d295f0e59b0ecf2 (diff)
downloadrust-003e910760ef75196ca26e29c4fc83c2f418f693.tar.gz
rust-003e910760ef75196ca26e29c4fc83c2f418f693.zip
Auto merge of #11817 - y21:ptr_arg_mut_ref, r=Alexendoo
[`ptr_arg`]: recognize methods that also exist on slices

Fixes #11816

Not a new lint, just a very small improvement to the existing `ptr_arg` lint which would have caught the linked issue.

The problem was that the lint checks if a `Vec`-specific method was called, that is, if the receiver is `Vec<_>`.
This is the case for `len` and `is_empty`, however these methods also exist on slices so we can still lint there.
This logic exists in a different lint, so we can just reuse that here.

Interestingly, there was even a comment up top that explained what it should have been doing, but the logic for it just wasn't there?

changelog: [`ptr_arg`]: recognize methods that also exist on slices

<sub>Also, this is my 100th PR to clippy 🎉 </sub>
-rw-r--r--clippy_lints/src/ptr.rs4
-rw-r--r--clippy_lints/src/vec.rs2
-rw-r--r--lintcheck/src/main.rs4
-rw-r--r--tests/ui/needless_pass_by_ref_mut.rs7
-rw-r--r--tests/ui/needless_pass_by_ref_mut.stderr42
-rw-r--r--tests/ui/ptr_arg.rs6
-rw-r--r--tests/ui/ptr_arg.stderr50
7 files changed, 67 insertions, 48 deletions
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 16581a934f2..90e38fcdc72 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -28,6 +28,8 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use std::{fmt, iter};
 
+use crate::vec::is_allowed_vec_method;
+
 declare_clippy_lint! {
     /// ### What it does
     /// This lint checks for function arguments of type `&String`, `&Vec`,
@@ -660,7 +662,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
                             },
                             // If the types match check for methods which exist on both types. e.g. `Vec::len` and
                             // `slice::len`
-                            ty::Adt(def, _) if def.did() == args.ty_did => {
+                            ty::Adt(def, _) if def.did() == args.ty_did && !is_allowed_vec_method(self.cx, e) => {
                                 set_skip_flag();
                             },
                             _ => (),
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index d49d3cc4cc9..ba958c5b392 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -57,7 +57,7 @@ fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 /// Checks if the given expression is a method call to a `Vec` method
 /// that also exists on slices. If this returns true, it means that
 /// this expression does not actually require a `Vec` and could just work with an array.
-fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"];
 
     if let ExprKind::MethodCall(path, ..) = e.kind {
diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index 58cb42316fd..841b605f5fb 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -309,7 +309,7 @@ impl Crate {
         target_dir_index: &AtomicUsize,
         total_crates_to_lint: usize,
         config: &LintcheckConfig,
-        lint_filter: &Vec<String>,
+        lint_filter: &[String],
         server: &Option<LintcheckServer>,
     ) -> Vec<ClippyWarning> {
         // advance the atomic index by one
@@ -728,7 +728,7 @@ fn read_stats_from_file(file_path: &Path) -> HashMap<String, usize> {
 }
 
 /// print how lint counts changed between runs
-fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, usize>, lint_filter: &Vec<String>) {
+fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, usize>, lint_filter: &[String]) {
     let same_in_both_hashmaps = old_stats
         .iter()
         .filter(|(old_key, old_val)| new_stats.get::<&String>(old_key) == Some(old_val))
diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs
index ea5e74c4c00..25a02bdd2f2 100644
--- a/tests/ui/needless_pass_by_ref_mut.rs
+++ b/tests/ui/needless_pass_by_ref_mut.rs
@@ -1,4 +1,9 @@
-#![allow(clippy::if_same_then_else, clippy::no_effect, clippy::redundant_closure_call)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::no_effect,
+    clippy::redundant_closure_call,
+    clippy::ptr_arg
+)]
 #![warn(clippy::needless_pass_by_ref_mut)]
 #![feature(lint_reasons)]
 //@no-rustfix
diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr
index aa937c3f6af..92b753276ac 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:12:11
    |
 LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    |           ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
@@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
    = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
 
 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:37: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:50: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:55: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:132: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:136: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:140: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:144: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:148: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:152: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:156: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:160: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:160:45
    |
 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:189:16
+  --> $DIR/needless_pass_by_ref_mut.rs:194:16
    |
 LL | fn cfg_warn(s: &mut u32) {}
    |                ^^^^^^^^ help: consider changing to: `&u32`
@@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut 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:195:20
+  --> $DIR/needless_pass_by_ref_mut.rs:200:20
    |
 LL |     fn cfg_warn(s: &mut u32) {}
    |                    ^^^^^^^^ help: consider changing to: `&u32`
@@ -96,19 +96,19 @@ LL |     fn cfg_warn(s: &mut 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:209:39
+  --> $DIR/needless_pass_by_ref_mut.rs:214:39
    |
 LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
    |                                       ^^^^^^^^ help: consider changing to: `&u32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:217:26
+  --> $DIR/needless_pass_by_ref_mut.rs:222:26
    |
 LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
    |                          ^^^^^^^^ help: consider changing to: `&i32`
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:236:34
+  --> $DIR/needless_pass_by_ref_mut.rs:241:34
    |
 LL | pub async fn call_in_closure1(n: &mut str) {
    |                                  ^^^^^^^^ help: consider changing to: `&str`
@@ -116,7 +116,7 @@ LL | pub async fn call_in_closure1(n: &mut str) {
    = warning: changing this function will impact semver compatibility
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:248:25
+  --> $DIR/needless_pass_by_ref_mut.rs:253:25
    |
 LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() {
    |                         ^^^^^^^^^^ help: consider changing to: `&usize`
@@ -124,7 +124,7 @@ LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() {
    = warning: changing this function will impact semver compatibility
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:255:20
+  --> $DIR/needless_pass_by_ref_mut.rs:260:20
    |
 LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
    |                    ^^^^^^^^^^ help: consider changing to: `&usize`
@@ -132,7 +132,7 @@ LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
    = warning: changing this function will impact semver compatibility
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/needless_pass_by_ref_mut.rs:266:26
+  --> $DIR/needless_pass_by_ref_mut.rs:271:26
    |
 LL | pub async fn closure4(n: &mut usize) {
    |                          ^^^^^^^^^^ help: consider changing to: `&usize`
diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs
index 91e2e7fd642..fcd716f4144 100644
--- a/tests/ui/ptr_arg.rs
+++ b/tests/ui/ptr_arg.rs
@@ -22,6 +22,12 @@ fn do_vec_mut(x: &mut Vec<i64>) {
     //Nothing here
 }
 
+fn do_vec_mut2(x: &mut Vec<i64>) {
+    //~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w
+    x.len();
+    x.is_empty();
+}
+
 fn do_str(x: &String) {
     //~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice will d
     //Nothing here either
diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr
index cccf2d62d63..35bd8509205 100644
--- a/tests/ui/ptr_arg.stderr
+++ b/tests/ui/ptr_arg.stderr
@@ -13,38 +13,44 @@ error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a sl
 LL | fn do_vec_mut(x: &mut Vec<i64>) {
    |                  ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
 
+error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
+  --> $DIR/ptr_arg.rs:25:19
+   |
+LL | fn do_vec_mut2(x: &mut Vec<i64>) {
+   |                   ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
+
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:25:14
+  --> $DIR/ptr_arg.rs:31:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
 error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:30:18
+  --> $DIR/ptr_arg.rs:36:18
    |
 LL | fn do_str_mut(x: &mut String) {
    |                  ^^^^^^^^^^^ help: change this to: `&mut str`
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:35:15
+  --> $DIR/ptr_arg.rs:41:15
    |
 LL | fn do_path(x: &PathBuf) {
    |               ^^^^^^^^ help: change this to: `&Path`
 
 error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:40:19
+  --> $DIR/ptr_arg.rs:46:19
    |
 LL | fn do_path_mut(x: &mut PathBuf) {
    |                   ^^^^^^^^^^^^ help: change this to: `&mut Path`
 
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:49:18
+  --> $DIR/ptr_arg.rs:55:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:63:14
+  --> $DIR/ptr_arg.rs:69:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
@@ -62,7 +68,7 @@ LL ~     x.to_owned()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:73:18
+  --> $DIR/ptr_arg.rs:79:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
@@ -79,7 +85,7 @@ LL ~     x.to_owned()
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:82:19
+  --> $DIR/ptr_arg.rs:88:19
    |
 LL | fn path_cloned(x: &PathBuf) -> PathBuf {
    |                   ^^^^^^^^
@@ -96,7 +102,7 @@ LL ~     x.to_path_buf()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:91:44
+  --> $DIR/ptr_arg.rs:97:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
@@ -111,19 +117,19 @@ LL ~     let c = y;
    |
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:106:25
+  --> $DIR/ptr_arg.rs:112:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:136:66
+  --> $DIR/ptr_arg.rs:142:66
    |
 LL |     fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {}
    |                                                                  ^^^^^^^ help: change this to: `&str`
 
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:166:21
+  --> $DIR/ptr_arg.rs:172:21
    |
 LL |     fn foo_vec(vec: &Vec<u8>) {
    |                     ^^^^^^^^
@@ -137,7 +143,7 @@ LL ~         let _ = vec.to_owned().clone();
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:172:23
+  --> $DIR/ptr_arg.rs:178:23
    |
 LL |     fn foo_path(path: &PathBuf) {
    |                       ^^^^^^^^
@@ -151,7 +157,7 @@ LL ~         let _ = path.to_path_buf().clone();
    |
 
 error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:178:21
+  --> $DIR/ptr_arg.rs:184:21
    |
 LL |     fn foo_str(str: &PathBuf) {
    |                     ^^^^^^^^
@@ -165,46 +171,46 @@ LL ~         let _ = str.to_path_buf().clone();
    |
 
 error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:185:29
+  --> $DIR/ptr_arg.rs:191:29
    |
 LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) {
    |                             ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
 
 error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:248:17
+  --> $DIR/ptr_arg.rs:254:17
    |
 LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
    |                 ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
 
 error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:248:35
+  --> $DIR/ptr_arg.rs:254:35
    |
 LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
    |                                   ^^^^^^^^^^^ help: change this to: `&mut str`
 
 error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
-  --> $DIR/ptr_arg.rs:248:51
+  --> $DIR/ptr_arg.rs:254:51
    |
 LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
    |                                                   ^^^^^^^^^^^^ help: change this to: `&mut Path`
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:274:39
+  --> $DIR/ptr_arg.rs:280:39
    |
 LL |     fn cow_elided_lifetime<'a>(input: &'a Cow<str>) -> &'a str {
    |                                       ^^^^^^^^^^^^ help: change this to: `&str`
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:280:36
+  --> $DIR/ptr_arg.rs:286:36
    |
 LL |     fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str {
    |                                    ^^^^^^^^^^^^^^^^ help: change this to: `&str`
 
 error: using a reference to `Cow` is not recommended
-  --> $DIR/ptr_arg.rs:284:40
+  --> $DIR/ptr_arg.rs:290:40
    |
 LL |     fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
    |                                        ^^^^^^^^^^^^^^^^ help: change this to: `&str`
 
-error: aborting due to 23 previous errors
+error: aborting due to 24 previous errors