Skip to content

Commit 61a3ee7

Browse files
committed
Auto merge of rust-lang#6506 - alex-700:add-path-buf-to-ptr-arg-lint, r=Manishearth
Lint "&PathBuf instead of &Path" in PTR_ARG fixes rust-lang#6502 changelog: lint "`&PathBuf` instead of `&Path`" in `PTR_ARG`
2 parents 3661848 + dfaea9c commit 61a3ee7

File tree

4 files changed

+106
-25
lines changed

4 files changed

+106
-25
lines changed

clippy_dev/src/ra_setup.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::fs;
44
use std::fs::File;
55
use std::io::prelude::*;
6-
use std::path::PathBuf;
6+
use std::path::{Path, PathBuf};
77

88
// This module takes an absolute path to a rustc repo and alters the dependencies to point towards
99
// the respective rustc subcrates instead of using extern crate xyz.
@@ -44,7 +44,7 @@ pub fn run(rustc_path: Option<&str>) {
4444
}
4545

4646
fn inject_deps_into_manifest(
47-
rustc_source_dir: &PathBuf,
47+
rustc_source_dir: &Path,
4848
manifest_path: &str,
4949
cargo_toml: &str,
5050
lib_rs: &str,

clippy_lints/src/ptr.rs

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,6 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
182182

183183
if let ty::Ref(_, ty, Mutability::Not) = ty.kind() {
184184
if is_type_diagnostic_item(cx, ty, sym::vec_type) {
185-
let mut ty_snippet = None;
186-
if_chain! {
187-
if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
188-
if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
189-
then {
190-
let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
191-
GenericArg::Type(ty) => Some(ty),
192-
_ => None,
193-
}).collect();
194-
if types.len() == 1 {
195-
ty_snippet = snippet_opt(cx, types[0].span);
196-
}
197-
}
198-
};
199185
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
200186
span_lint_and_then(
201187
cx,
@@ -204,7 +190,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
204190
"writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
205191
with non-Vec-based slices.",
206192
|diag| {
207-
if let Some(ref snippet) = ty_snippet {
193+
if let Some(ref snippet) = get_only_generic_arg_snippet(cx, arg) {
208194
diag.span_suggestion(
209195
arg.span,
210196
"change this to",
@@ -247,6 +233,33 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
247233
},
248234
);
249235
}
236+
} else if match_type(cx, ty, &paths::PATH_BUF) {
237+
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
238+
span_lint_and_then(
239+
cx,
240+
PTR_ARG,
241+
arg.span,
242+
"writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.",
243+
|diag| {
244+
diag.span_suggestion(
245+
arg.span,
246+
"change this to",
247+
"&Path".into(),
248+
Applicability::Unspecified,
249+
);
250+
for (clonespan, suggestion) in spans {
251+
diag.span_suggestion_short(
252+
clonespan,
253+
&snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
254+
Cow::Owned(format!("change `{}` to", x))
255+
}),
256+
suggestion.into(),
257+
Applicability::Unspecified,
258+
);
259+
}
260+
},
261+
);
262+
}
250263
} else if match_type(cx, ty, &paths::COW) {
251264
if_chain! {
252265
if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind;
@@ -309,6 +322,23 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
309322
}
310323
}
311324

325+
fn get_only_generic_arg_snippet(cx: &LateContext<'_>, arg: &Ty<'_>) -> Option<String> {
326+
if_chain! {
327+
if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
328+
if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
329+
let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
330+
GenericArg::Type(ty) => Some(ty),
331+
_ => None,
332+
}).collect();
333+
if types.len() == 1;
334+
then {
335+
snippet_opt(cx, types[0].span)
336+
} else {
337+
None
338+
}
339+
}
340+
}
341+
312342
fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
313343
if let TyKind::Rptr(ref lt, ref m) = ty.kind {
314344
Some((lt, m.mutbl, ty.span))

tests/ui/ptr_arg.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![warn(clippy::ptr_arg)]
33

44
use std::borrow::Cow;
5+
use std::path::PathBuf;
56

67
fn do_vec(x: &Vec<i64>) {
78
//Nothing here
@@ -21,6 +22,15 @@ fn do_str_mut(x: &mut String) {
2122
//Nothing here either
2223
}
2324

25+
fn do_path(x: &PathBuf) {
26+
//Nothing here either
27+
}
28+
29+
fn do_path_mut(x: &mut PathBuf) {
30+
// no error here
31+
//Nothing here either
32+
}
33+
2434
fn main() {}
2535

2636
trait Foo {
@@ -55,6 +65,14 @@ fn str_cloned(x: &String) -> String {
5565
x.clone()
5666
}
5767

68+
fn path_cloned(x: &PathBuf) -> PathBuf {
69+
let a = x.clone();
70+
let b = x.clone();
71+
let c = b.clone();
72+
let d = a.clone().clone().clone();
73+
x.clone()
74+
}
75+
5876
fn false_positive_capacity(x: &Vec<u8>, y: &String) {
5977
let a = x.capacity();
6078
let b = y.clone();
@@ -87,10 +105,12 @@ impl Foo2 for String {
87105
// Check that the allow attribute on parameters is honored
88106
mod issue_5644 {
89107
use std::borrow::Cow;
108+
use std::path::PathBuf;
90109

91110
fn allowed(
92111
#[allow(clippy::ptr_arg)] _v: &Vec<u32>,
93112
#[allow(clippy::ptr_arg)] _s: &String,
113+
#[allow(clippy::ptr_arg)] _p: &PathBuf,
94114
#[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
95115
) {
96116
}
@@ -100,6 +120,7 @@ mod issue_5644 {
100120
fn allowed(
101121
#[allow(clippy::ptr_arg)] _v: &Vec<u32>,
102122
#[allow(clippy::ptr_arg)] _s: &String,
123+
#[allow(clippy::ptr_arg)] _p: &PathBuf,
103124
#[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
104125
) {
105126
}
@@ -109,6 +130,7 @@ mod issue_5644 {
109130
fn allowed(
110131
#[allow(clippy::ptr_arg)] _v: &Vec<u32>,
111132
#[allow(clippy::ptr_arg)] _s: &String,
133+
#[allow(clippy::ptr_arg)] _p: &PathBuf,
112134
#[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
113135
) {
114136
}

tests/ui/ptr_arg.stderr

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
2-
--> $DIR/ptr_arg.rs:6:14
2+
--> $DIR/ptr_arg.rs:7:14
33
|
44
LL | fn do_vec(x: &Vec<i64>) {
55
| ^^^^^^^^^ help: change this to: `&[i64]`
66
|
77
= note: `-D clippy::ptr-arg` implied by `-D warnings`
88

99
error: writing `&String` instead of `&str` involves a new object where a slice will do.
10-
--> $DIR/ptr_arg.rs:15:14
10+
--> $DIR/ptr_arg.rs:16:14
1111
|
1212
LL | fn do_str(x: &String) {
1313
| ^^^^^^^ help: change this to: `&str`
1414

15+
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
16+
--> $DIR/ptr_arg.rs:25:15
17+
|
18+
LL | fn do_path(x: &PathBuf) {
19+
| ^^^^^^^^ help: change this to: `&Path`
20+
1521
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
16-
--> $DIR/ptr_arg.rs:28:18
22+
--> $DIR/ptr_arg.rs:38:18
1723
|
1824
LL | fn do_vec(x: &Vec<i64>);
1925
| ^^^^^^^^^ help: change this to: `&[i64]`
2026

2127
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
22-
--> $DIR/ptr_arg.rs:41:14
28+
--> $DIR/ptr_arg.rs:51:14
2329
|
2430
LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
2531
| ^^^^^^^^
@@ -38,7 +44,7 @@ LL | x.to_owned()
3844
|
3945

4046
error: writing `&String` instead of `&str` involves a new object where a slice will do.
41-
--> $DIR/ptr_arg.rs:50:18
47+
--> $DIR/ptr_arg.rs:60:18
4248
|
4349
LL | fn str_cloned(x: &String) -> String {
4450
| ^^^^^^^
@@ -60,8 +66,31 @@ help: change `x.clone()` to
6066
LL | x.to_string()
6167
|
6268

69+
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
70+
--> $DIR/ptr_arg.rs:68:19
71+
|
72+
LL | fn path_cloned(x: &PathBuf) -> PathBuf {
73+
| ^^^^^^^^
74+
|
75+
help: change this to
76+
|
77+
LL | fn path_cloned(x: &Path) -> PathBuf {
78+
| ^^^^^
79+
help: change `x.clone()` to
80+
|
81+
LL | let a = x.to_path_buf();
82+
| ^^^^^^^^^^^^^^^
83+
help: change `x.clone()` to
84+
|
85+
LL | let b = x.to_path_buf();
86+
| ^^^^^^^^^^^^^^^
87+
help: change `x.clone()` to
88+
|
89+
LL | x.to_path_buf()
90+
|
91+
6392
error: writing `&String` instead of `&str` involves a new object where a slice will do.
64-
--> $DIR/ptr_arg.rs:58:44
93+
--> $DIR/ptr_arg.rs:76:44
6594
|
6695
LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
6796
| ^^^^^^^
@@ -80,10 +109,10 @@ LL | let c = y;
80109
| ^
81110

82111
error: using a reference to `Cow` is not recommended.
83-
--> $DIR/ptr_arg.rs:72:25
112+
--> $DIR/ptr_arg.rs:90:25
84113
|
85114
LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
86115
| ^^^^^^^^^^^ help: change this to: `&[i32]`
87116

88-
error: aborting due to 7 previous errors
117+
error: aborting due to 9 previous errors
89118

0 commit comments

Comments
 (0)