Skip to content

Commit 129e2f4

Browse files
committed
checkpoint commit
* refactor in prep of using diagnostic items/make using diagnostic items easier * changes from code review * add to_os_string and to_path_buf checks
1 parent 89fba45 commit 129e2f4

File tree

5 files changed

+115
-59
lines changed

5 files changed

+115
-59
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,7 @@ declare_clippy_lint! {
15181518
/// **What it does:** Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar on already owned types.
15191519
///
15201520
/// **Why is this bad?** These methods do the same thing as `_.clone()` but may be confusing as
1521-
/// to why we are calling `to_vec` on something that is already a Vec
1521+
/// to why we are calling `to_vec` on something that is already a `Vec`
15221522
///
15231523
/// **Known problems:** None.
15241524
///
@@ -1537,7 +1537,7 @@ declare_clippy_lint! {
15371537
/// ```
15381538
pub OWNED_TO_OWNED,
15391539
style,
1540-
"using to_owned on already owned type"
1540+
"using `to_owned` on already owned type"
15411541
}
15421542

15431543
pub struct Methods {
@@ -1698,9 +1698,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16981698
["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
16991699
["collect", "map"] => lint_map_collect(cx, expr, arg_lists[1], arg_lists[0]),
17001700
["for_each", "inspect"] => inspect_for_each::lint(cx, expr, method_spans[1]),
1701-
["to_owned", ..] => owned_to_owned::lint(cx, expr, &paths::TO_OWNED_METHOD, None),
1702-
["to_vec", ..] => owned_to_owned::lint(cx, expr, &paths::SLICE_TO_VEC, Some(&paths::VEC)),
1703-
["to_path_buf", ..] => owned_to_owned::lint(cx, expr, &paths::PATH_TO_PATH_BUF, Some(&paths::PATH_BUF)),
1701+
["to_owned", ..] => owned_to_owned::check(cx, expr, Some(&paths::TO_OWNED), None),
1702+
["to_os_string", ..] => owned_to_owned::check(cx, expr, None, Some(&paths::OS_STRING)),
1703+
["to_path_buf", ..] => owned_to_owned::check(cx, expr, None, Some(&paths::PATH_BUF)),
1704+
["to_vec", ..] => owned_to_owned::check(cx, expr, None, Some(&paths::VEC)),
17041705
_ => {},
17051706
}
17061707

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{is_copy, match_def_path, match_type, span_lint_and_sugg, sugg};
1+
use crate::utils::{match_trait_method, match_type, span_lint_and_sugg};
22
use if_chain::if_chain;
33
use rustc_errors::Applicability;
44
use rustc_hir as hir;
@@ -8,36 +8,28 @@ use rustc_middle::ty::TyS;
88

99
use super::OWNED_TO_OWNED;
1010

11-
pub fn lint(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expected_path: &[&str], expected_type: Option<&[&str]>) {
11+
pub fn check(
12+
cx: &LateContext<'_>,
13+
expr: &hir::Expr<'_>,
14+
trait_path: Option<&[&str]>,
15+
expected_type_path: Option<&[&str]>,
16+
) {
1217
if_chain! {
1318
if let ExprKind::MethodCall(method_path, _, [arg], _) = &expr.kind;
14-
if let Some(meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
15-
if let Some(snippet) = sugg::Sugg::hir_opt(cx, arg);
1619
let return_type = cx.typeck_results().expr_ty(&expr);
1720
let input_type = cx.typeck_results().expr_ty(arg);
21+
if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did) );
1822
if TyS::same_type(return_type, input_type);
19-
if match_def_path(cx, meth_did, expected_path) &&
20-
expected_type.map_or(true, |expected_type_path| match_type(cx,input_type,expected_type_path));
23+
if trait_path.map_or(true, |path| match_trait_method(cx, expr, path)) &&
24+
expected_type_path.map_or(true, |path| match_type(cx, input_type, path));
2125
then {
22-
if is_copy(cx,return_type) {
23-
// if return_type is copy, have the suggestion be to replace the call with the variable itself
24-
// this prevents fixing this lint, only to have clone_on_copy complain next.
25-
span_lint_and_sugg(
26-
cx,OWNED_TO_OWNED,expr.span,
27-
&format!("using `{}` on an already owned type",method_path.ident.name),
28-
"replace this with",
29-
snippet.to_string(),
30-
Applicability::MaybeIncorrect
31-
);
32-
} else {
33-
span_lint_and_sugg(
34-
cx,OWNED_TO_OWNED,method_path.ident.span,
35-
&format!("using `{}` on an already owned type",method_path.ident.name),
36-
"replace this with",
37-
"clone".to_string(),
38-
Applicability::MaybeIncorrect
39-
);
40-
}
26+
span_lint_and_sugg(
27+
cx,OWNED_TO_OWNED,method_path.ident.span,
28+
&format!("`{}` called on a `{}`", method_path.ident.name, ty_name),
29+
"consider using",
30+
"clone".to_string(),
31+
Applicability::MaybeIncorrect
32+
);
4133
}
4234
}
4335
}

clippy_lints/src/utils/paths.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
136136
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
137137
pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
138138
pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
139-
pub const SLICE_TO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "to_vec"];
140139
pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
141140
pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
142141
pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];

tests/ui/owned_to_owned.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
#![warn(clippy::owned_to_owned)]
22
#![allow(clippy::redundant_clone)]
33
use std::borrow::Borrow;
4+
use std::ffi::{OsStr, OsString};
45
use std::path::PathBuf;
56

67
fn return_owned_from_slice(slice: &[u32]) -> Vec<u32> {
78
slice.to_owned()
89
}
9-
fn return_owned_from_ref(val: &Kitten) -> Kitten {
10-
val.to_owned()
10+
11+
pub fn own_same<T>(v: T) -> T
12+
where
13+
T: ToOwned<Owned = T>,
14+
{
15+
v.to_owned()
16+
}
17+
18+
pub fn own_same_from_ref<T>(v: &T) -> T
19+
where
20+
T: ToOwned<Owned = T>,
21+
{
22+
v.to_owned()
23+
}
24+
25+
pub fn own_different<T, U>(v: T) -> U
26+
where
27+
T: ToOwned<Owned = U>,
28+
{
29+
v.to_owned()
1130
}
1231

1332
#[derive(Copy, Clone)]
@@ -27,23 +46,56 @@ impl ToOwned for BorrowedKitten {
2746
}
2847
}
2948

49+
mod weird {
50+
#[allow(clippy::ptr_arg)]
51+
pub fn to_vec(v: &Vec<u32>) -> Vec<u32> {
52+
v.clone()
53+
}
54+
}
55+
3056
fn main() {
31-
let result = vec![5];
32-
let _ = return_owned_from_slice(&result);
33-
let _ = result.to_owned();
34-
let _ = result.to_vec();
57+
let vec = vec![5];
58+
let _ = return_owned_from_slice(&vec);
59+
let _ = vec.to_owned();
60+
let _ = vec.to_vec();
61+
62+
// we expect no lints for this
63+
let vec_ref = &vec;
64+
let _ = return_owned_from_slice(&vec_ref);
65+
let _ = vec_ref.to_owned();
66+
let _ = vec_ref.to_vec();
67+
68+
// we expect no lint for this
69+
let _ = weird::to_vec(&vec);
70+
71+
// we expect no lints for this
72+
let slice: &[u32] = &[1, 2, 3, 4, 5];
73+
let _ = return_owned_from_slice(slice);
74+
let _ = slice.to_owned();
75+
let _ = slice.to_vec();
3576

3677
let str = "hello world".to_string();
3778
let _ = str.to_owned();
3879

80+
// testing w/ an arbitrary type
3981
let kitten = Kitten {};
4082
let _ = kitten.to_owned();
41-
let _ = return_owned_from_ref(&kitten);
83+
let _ = own_same_from_ref(&kitten);
4284

85+
// we expect no lints for this
4386
let borrowed = BorrowedKitten {};
4487
let _ = borrowed.to_owned();
4588

4689
let pathbuf = PathBuf::new();
4790
let _ = pathbuf.to_owned();
4891
let _ = pathbuf.to_path_buf();
92+
93+
let os_string = OsString::from("foo");
94+
let _ = os_string.to_owned();
95+
let _ = os_string.to_os_string();
96+
97+
// we expect no lints for this
98+
let os_str = OsStr::new("foo");
99+
let _ = os_str.to_owned();
100+
let _ = os_str.to_os_string();
49101
}

tests/ui/owned_to_owned.stderr

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,52 @@
1-
error: using `to_owned` on an already owned type
2-
--> $DIR/owned_to_owned.rs:33:20
1+
error: `to_owned` called on a `Vec`
2+
--> $DIR/owned_to_owned.rs:59:17
33
|
4-
LL | let _ = result.to_owned();
5-
| ^^^^^^^^ help: replace this with: `clone`
4+
LL | let _ = vec.to_owned();
5+
| ^^^^^^^^ help: consider using: `clone`
66
|
77
= note: `-D clippy::owned-to-owned` implied by `-D warnings`
88

9-
error: using `to_vec` on an already owned type
10-
--> $DIR/owned_to_owned.rs:34:20
9+
error: `to_vec` called on a `Vec`
10+
--> $DIR/owned_to_owned.rs:60:17
1111
|
12-
LL | let _ = result.to_vec();
13-
| ^^^^^^ help: replace this with: `clone`
12+
LL | let _ = vec.to_vec();
13+
| ^^^^^^ help: consider using: `clone`
1414

15-
error: using `to_owned` on an already owned type
16-
--> $DIR/owned_to_owned.rs:37:17
15+
error: `to_owned` called on a `String`
16+
--> $DIR/owned_to_owned.rs:78:17
1717
|
1818
LL | let _ = str.to_owned();
19-
| ^^^^^^^^ help: replace this with: `clone`
19+
| ^^^^^^^^ help: consider using: `clone`
2020

21-
error: using `to_owned` on an already owned type
22-
--> $DIR/owned_to_owned.rs:40:13
21+
error: `to_owned` called on a `Kitten`
22+
--> $DIR/owned_to_owned.rs:82:20
2323
|
2424
LL | let _ = kitten.to_owned();
25-
| ^^^^^^^^^^^^^^^^^ help: replace this with: `kitten`
25+
| ^^^^^^^^ help: consider using: `clone`
2626

27-
error: using `to_owned` on an already owned type
28-
--> $DIR/owned_to_owned.rs:47:21
27+
error: `to_owned` called on a `PathBuf`
28+
--> $DIR/owned_to_owned.rs:90:21
2929
|
3030
LL | let _ = pathbuf.to_owned();
31-
| ^^^^^^^^ help: replace this with: `clone`
31+
| ^^^^^^^^ help: consider using: `clone`
3232

33-
error: using `to_path_buf` on an already owned type
34-
--> $DIR/owned_to_owned.rs:48:21
33+
error: `to_path_buf` called on a `PathBuf`
34+
--> $DIR/owned_to_owned.rs:91:21
3535
|
3636
LL | let _ = pathbuf.to_path_buf();
37-
| ^^^^^^^^^^^ help: replace this with: `clone`
37+
| ^^^^^^^^^^^ help: consider using: `clone`
3838

39-
error: aborting due to 6 previous errors
39+
error: `to_owned` called on a `OsString`
40+
--> $DIR/owned_to_owned.rs:94:23
41+
|
42+
LL | let _ = os_string.to_owned();
43+
| ^^^^^^^^ help: consider using: `clone`
44+
45+
error: `to_os_string` called on a `OsString`
46+
--> $DIR/owned_to_owned.rs:95:23
47+
|
48+
LL | let _ = os_string.to_os_string();
49+
| ^^^^^^^^^^^^ help: consider using: `clone`
50+
51+
error: aborting due to 8 previous errors
4052

0 commit comments

Comments
 (0)