[ptr_arg]: recognize methods that also exist on slices

This commit is contained in:
y21 2023-11-15 14:59:11 +01:00
parent abf01e469b
commit bb694615b8
6 changed files with 65 additions and 46 deletions

View file

@ -29,6 +29,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`,
@ -661,7 +663,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();
},
_ => (),

View file

@ -58,7 +58,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 {

View file

@ -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

View file

@ -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`

View file

@ -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

View file

@ -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