Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit bb69461

Browse files
committed
[ptr_arg]: recognize methods that also exist on slices
1 parent abf01e4 commit bb69461

File tree

6 files changed

+65
-46
lines changed

6 files changed

+65
-46
lines changed

clippy_lints/src/ptr.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
2929
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
3030
use std::{fmt, iter};
3131

32+
use crate::vec::is_allowed_vec_method;
33+
3234
declare_clippy_lint! {
3335
/// ### What it does
3436
/// 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:
661663
},
662664
// If the types match check for methods which exist on both types. e.g. `Vec::len` and
663665
// `slice::len`
664-
ty::Adt(def, _) if def.did() == args.ty_did => {
666+
ty::Adt(def, _) if def.did() == args.ty_did && !is_allowed_vec_method(self.cx, e) => {
665667
set_skip_flag();
666668
},
667669
_ => (),

clippy_lints/src/vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
5858
/// Checks if the given expression is a method call to a `Vec` method
5959
/// that also exists on slices. If this returns true, it means that
6060
/// this expression does not actually require a `Vec` and could just work with an array.
61-
fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
61+
pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
6262
const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"];
6363

6464
if let ExprKind::MethodCall(path, ..) = e.kind {

tests/ui/needless_pass_by_ref_mut.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
#![allow(clippy::if_same_then_else, clippy::no_effect, clippy::redundant_closure_call)]
1+
#![allow(
2+
clippy::if_same_then_else,
3+
clippy::no_effect,
4+
clippy::redundant_closure_call,
5+
clippy::ptr_arg
6+
)]
27
#![warn(clippy::needless_pass_by_ref_mut)]
38
#![feature(lint_reasons)]
49
//@no-rustfix

tests/ui/needless_pass_by_ref_mut.stderr

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this argument is a mutable reference, but not used mutably
2-
--> $DIR/needless_pass_by_ref_mut.rs:7:11
2+
--> $DIR/needless_pass_by_ref_mut.rs:12:11
33
|
44
LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
55
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
@@ -8,131 +8,131 @@ LL | fn foo(s: &mut Vec<u32>, b: &u32, x: &mut u32) {
88
= help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]`
99

1010
error: this argument is a mutable reference, but not used mutably
11-
--> $DIR/needless_pass_by_ref_mut.rs:32:12
11+
--> $DIR/needless_pass_by_ref_mut.rs:37:12
1212
|
1313
LL | fn foo6(s: &mut Vec<u32>) {
1414
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<u32>`
1515

1616
error: this argument is a mutable reference, but not used mutably
17-
--> $DIR/needless_pass_by_ref_mut.rs:45:29
17+
--> $DIR/needless_pass_by_ref_mut.rs:50:29
1818
|
1919
LL | fn mushroom(&self, vec: &mut Vec<i32>) -> usize {
2020
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
2121

2222
error: this argument is a mutable reference, but not used mutably
23-
--> $DIR/needless_pass_by_ref_mut.rs:50:31
23+
--> $DIR/needless_pass_by_ref_mut.rs:55:31
2424
|
2525
LL | fn badger(&mut self, vec: &mut Vec<i32>) -> usize {
2626
| ^^^^^^^^^^^^^ help: consider changing to: `&Vec<i32>`
2727

2828
error: this argument is a mutable reference, but not used mutably
29-
--> $DIR/needless_pass_by_ref_mut.rs:127:16
29+
--> $DIR/needless_pass_by_ref_mut.rs:132:16
3030
|
3131
LL | async fn a1(x: &mut i32) {
3232
| ^^^^^^^^ help: consider changing to: `&i32`
3333

3434
error: this argument is a mutable reference, but not used mutably
35-
--> $DIR/needless_pass_by_ref_mut.rs:131:16
35+
--> $DIR/needless_pass_by_ref_mut.rs:136:16
3636
|
3737
LL | async fn a2(x: &mut i32, y: String) {
3838
| ^^^^^^^^ help: consider changing to: `&i32`
3939

4040
error: this argument is a mutable reference, but not used mutably
41-
--> $DIR/needless_pass_by_ref_mut.rs:135:16
41+
--> $DIR/needless_pass_by_ref_mut.rs:140:16
4242
|
4343
LL | async fn a3(x: &mut i32, y: String, z: String) {
4444
| ^^^^^^^^ help: consider changing to: `&i32`
4545

4646
error: this argument is a mutable reference, but not used mutably
47-
--> $DIR/needless_pass_by_ref_mut.rs:139:16
47+
--> $DIR/needless_pass_by_ref_mut.rs:144:16
4848
|
4949
LL | async fn a4(x: &mut i32, y: i32) {
5050
| ^^^^^^^^ help: consider changing to: `&i32`
5151

5252
error: this argument is a mutable reference, but not used mutably
53-
--> $DIR/needless_pass_by_ref_mut.rs:143:24
53+
--> $DIR/needless_pass_by_ref_mut.rs:148:24
5454
|
5555
LL | async fn a5(x: i32, y: &mut i32) {
5656
| ^^^^^^^^ help: consider changing to: `&i32`
5757

5858
error: this argument is a mutable reference, but not used mutably
59-
--> $DIR/needless_pass_by_ref_mut.rs:147:24
59+
--> $DIR/needless_pass_by_ref_mut.rs:152:24
6060
|
6161
LL | async fn a6(x: i32, y: &mut i32) {
6262
| ^^^^^^^^ help: consider changing to: `&i32`
6363

6464
error: this argument is a mutable reference, but not used mutably
65-
--> $DIR/needless_pass_by_ref_mut.rs:151:32
65+
--> $DIR/needless_pass_by_ref_mut.rs:156:32
6666
|
6767
LL | async fn a7(x: i32, y: i32, z: &mut i32) {
6868
| ^^^^^^^^ help: consider changing to: `&i32`
6969

7070
error: this argument is a mutable reference, but not used mutably
71-
--> $DIR/needless_pass_by_ref_mut.rs:155:24
71+
--> $DIR/needless_pass_by_ref_mut.rs:160:24
7272
|
7373
LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
7474
| ^^^^^^^^ help: consider changing to: `&i32`
7575

7676
error: this argument is a mutable reference, but not used mutably
77-
--> $DIR/needless_pass_by_ref_mut.rs:155:45
77+
--> $DIR/needless_pass_by_ref_mut.rs:160:45
7878
|
7979
LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) {
8080
| ^^^^^^^^ help: consider changing to: `&i32`
8181

8282
error: this argument is a mutable reference, but not used mutably
83-
--> $DIR/needless_pass_by_ref_mut.rs:189:16
83+
--> $DIR/needless_pass_by_ref_mut.rs:194:16
8484
|
8585
LL | fn cfg_warn(s: &mut u32) {}
8686
| ^^^^^^^^ help: consider changing to: `&u32`
8787
|
8888
= note: this is cfg-gated and may require further changes
8989

9090
error: this argument is a mutable reference, but not used mutably
91-
--> $DIR/needless_pass_by_ref_mut.rs:195:20
91+
--> $DIR/needless_pass_by_ref_mut.rs:200:20
9292
|
9393
LL | fn cfg_warn(s: &mut u32) {}
9494
| ^^^^^^^^ help: consider changing to: `&u32`
9595
|
9696
= note: this is cfg-gated and may require further changes
9797

9898
error: this argument is a mutable reference, but not used mutably
99-
--> $DIR/needless_pass_by_ref_mut.rs:209:39
99+
--> $DIR/needless_pass_by_ref_mut.rs:214:39
100100
|
101101
LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
102102
| ^^^^^^^^ help: consider changing to: `&u32`
103103

104104
error: this argument is a mutable reference, but not used mutably
105-
--> $DIR/needless_pass_by_ref_mut.rs:217:26
105+
--> $DIR/needless_pass_by_ref_mut.rs:222:26
106106
|
107107
LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
108108
| ^^^^^^^^ help: consider changing to: `&i32`
109109

110110
error: this argument is a mutable reference, but not used mutably
111-
--> $DIR/needless_pass_by_ref_mut.rs:236:34
111+
--> $DIR/needless_pass_by_ref_mut.rs:241:34
112112
|
113113
LL | pub async fn call_in_closure1(n: &mut str) {
114114
| ^^^^^^^^ help: consider changing to: `&str`
115115
|
116116
= warning: changing this function will impact semver compatibility
117117

118118
error: this argument is a mutable reference, but not used mutably
119-
--> $DIR/needless_pass_by_ref_mut.rs:248:25
119+
--> $DIR/needless_pass_by_ref_mut.rs:253:25
120120
|
121121
LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() {
122122
| ^^^^^^^^^^ help: consider changing to: `&usize`
123123
|
124124
= warning: changing this function will impact semver compatibility
125125

126126
error: this argument is a mutable reference, but not used mutably
127-
--> $DIR/needless_pass_by_ref_mut.rs:255:20
127+
--> $DIR/needless_pass_by_ref_mut.rs:260:20
128128
|
129129
LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize {
130130
| ^^^^^^^^^^ help: consider changing to: `&usize`
131131
|
132132
= warning: changing this function will impact semver compatibility
133133

134134
error: this argument is a mutable reference, but not used mutably
135-
--> $DIR/needless_pass_by_ref_mut.rs:266:26
135+
--> $DIR/needless_pass_by_ref_mut.rs:271:26
136136
|
137137
LL | pub async fn closure4(n: &mut usize) {
138138
| ^^^^^^^^^^ help: consider changing to: `&usize`

tests/ui/ptr_arg.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ fn do_vec_mut(x: &mut Vec<i64>) {
2222
//Nothing here
2323
}
2424

25+
fn do_vec_mut2(x: &mut Vec<i64>) {
26+
//~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w
27+
x.len();
28+
x.is_empty();
29+
}
30+
2531
fn do_str(x: &String) {
2632
//~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice will d
2733
//Nothing here either

tests/ui/ptr_arg.stderr

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,44 @@ error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a sl
1313
LL | fn do_vec_mut(x: &mut Vec<i64>) {
1414
| ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
1515

16+
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
17+
--> $DIR/ptr_arg.rs:25:19
18+
|
19+
LL | fn do_vec_mut2(x: &mut Vec<i64>) {
20+
| ^^^^^^^^^^^^^ help: change this to: `&mut [i64]`
21+
1622
error: writing `&String` instead of `&str` involves a new object where a slice will do
17-
--> $DIR/ptr_arg.rs:25:14
23+
--> $DIR/ptr_arg.rs:31:14
1824
|
1925
LL | fn do_str(x: &String) {
2026
| ^^^^^^^ help: change this to: `&str`
2127

2228
error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
23-
--> $DIR/ptr_arg.rs:30:18
29+
--> $DIR/ptr_arg.rs:36:18
2430
|
2531
LL | fn do_str_mut(x: &mut String) {
2632
| ^^^^^^^^^^^ help: change this to: `&mut str`
2733

2834
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
29-
--> $DIR/ptr_arg.rs:35:15
35+
--> $DIR/ptr_arg.rs:41:15
3036
|
3137
LL | fn do_path(x: &PathBuf) {
3238
| ^^^^^^^^ help: change this to: `&Path`
3339

3440
error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
35-
--> $DIR/ptr_arg.rs:40:19
41+
--> $DIR/ptr_arg.rs:46:19
3642
|
3743
LL | fn do_path_mut(x: &mut PathBuf) {
3844
| ^^^^^^^^^^^^ help: change this to: `&mut Path`
3945

4046
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
41-
--> $DIR/ptr_arg.rs:49:18
47+
--> $DIR/ptr_arg.rs:55:18
4248
|
4349
LL | fn do_vec(x: &Vec<i64>);
4450
| ^^^^^^^^^ help: change this to: `&[i64]`
4551

4652
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
47-
--> $DIR/ptr_arg.rs:63:14
53+
--> $DIR/ptr_arg.rs:69:14
4854
|
4955
LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
5056
| ^^^^^^^^
@@ -62,7 +68,7 @@ LL ~ x.to_owned()
6268
|
6369

6470
error: writing `&String` instead of `&str` involves a new object where a slice will do
65-
--> $DIR/ptr_arg.rs:73:18
71+
--> $DIR/ptr_arg.rs:79:18
6672
|
6773
LL | fn str_cloned(x: &String) -> String {
6874
| ^^^^^^^
@@ -79,7 +85,7 @@ LL ~ x.to_owned()
7985
|
8086

8187
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
82-
--> $DIR/ptr_arg.rs:82:19
88+
--> $DIR/ptr_arg.rs:88:19
8389
|
8490
LL | fn path_cloned(x: &PathBuf) -> PathBuf {
8591
| ^^^^^^^^
@@ -96,7 +102,7 @@ LL ~ x.to_path_buf()
96102
|
97103

98104
error: writing `&String` instead of `&str` involves a new object where a slice will do
99-
--> $DIR/ptr_arg.rs:91:44
105+
--> $DIR/ptr_arg.rs:97:44
100106
|
101107
LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
102108
| ^^^^^^^
@@ -111,19 +117,19 @@ LL ~ let c = y;
111117
|
112118

113119
error: using a reference to `Cow` is not recommended
114-
--> $DIR/ptr_arg.rs:106:25
120+
--> $DIR/ptr_arg.rs:112:25
115121
|
116122
LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
117123
| ^^^^^^^^^^^ help: change this to: `&[i32]`
118124

119125
error: writing `&String` instead of `&str` involves a new object where a slice will do
120-
--> $DIR/ptr_arg.rs:136:66
126+
--> $DIR/ptr_arg.rs:142:66
121127
|
122128
LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {}
123129
| ^^^^^^^ help: change this to: `&str`
124130

125131
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
126-
--> $DIR/ptr_arg.rs:166:21
132+
--> $DIR/ptr_arg.rs:172:21
127133
|
128134
LL | fn foo_vec(vec: &Vec<u8>) {
129135
| ^^^^^^^^
@@ -137,7 +143,7 @@ LL ~ let _ = vec.to_owned().clone();
137143
|
138144

139145
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
140-
--> $DIR/ptr_arg.rs:172:23
146+
--> $DIR/ptr_arg.rs:178:23
141147
|
142148
LL | fn foo_path(path: &PathBuf) {
143149
| ^^^^^^^^
@@ -151,7 +157,7 @@ LL ~ let _ = path.to_path_buf().clone();
151157
|
152158

153159
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
154-
--> $DIR/ptr_arg.rs:178:21
160+
--> $DIR/ptr_arg.rs:184:21
155161
|
156162
LL | fn foo_str(str: &PathBuf) {
157163
| ^^^^^^^^
@@ -165,46 +171,46 @@ LL ~ let _ = str.to_path_buf().clone();
165171
|
166172

167173
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
168-
--> $DIR/ptr_arg.rs:185:29
174+
--> $DIR/ptr_arg.rs:191:29
169175
|
170176
LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) {
171177
| ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
172178

173179
error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
174-
--> $DIR/ptr_arg.rs:248:17
180+
--> $DIR/ptr_arg.rs:254:17
175181
|
176182
LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
177183
| ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
178184

179185
error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
180-
--> $DIR/ptr_arg.rs:248:35
186+
--> $DIR/ptr_arg.rs:254:35
181187
|
182188
LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
183189
| ^^^^^^^^^^^ help: change this to: `&mut str`
184190

185191
error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
186-
--> $DIR/ptr_arg.rs:248:51
192+
--> $DIR/ptr_arg.rs:254:51
187193
|
188194
LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
189195
| ^^^^^^^^^^^^ help: change this to: `&mut Path`
190196

191197
error: using a reference to `Cow` is not recommended
192-
--> $DIR/ptr_arg.rs:274:39
198+
--> $DIR/ptr_arg.rs:280:39
193199
|
194200
LL | fn cow_elided_lifetime<'a>(input: &'a Cow<str>) -> &'a str {
195201
| ^^^^^^^^^^^^ help: change this to: `&str`
196202

197203
error: using a reference to `Cow` is not recommended
198-
--> $DIR/ptr_arg.rs:280:36
204+
--> $DIR/ptr_arg.rs:286:36
199205
|
200206
LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str {
201207
| ^^^^^^^^^^^^^^^^ help: change this to: `&str`
202208

203209
error: using a reference to `Cow` is not recommended
204-
--> $DIR/ptr_arg.rs:284:40
210+
--> $DIR/ptr_arg.rs:290:40
205211
|
206212
LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
207213
| ^^^^^^^^^^^^^^^^ help: change this to: `&str`
208214

209-
error: aborting due to 23 previous errors
215+
error: aborting due to 24 previous errors
210216

0 commit comments

Comments
 (0)