Skip to content

Commit fb30b64

Browse files
committed
Adjust test cases; run cargo dev bless
1 parent c989746 commit fb30b64

File tree

5 files changed

+174
-83
lines changed

5 files changed

+174
-83
lines changed

clippy_lints/src/methods/collapsible_str_replace.rs

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// run-rustfix
2+
13
use clippy_utils::diagnostics::span_lint_and_sugg;
24
use clippy_utils::get_parent_expr;
35
use clippy_utils::visitors::for_each_expr;
@@ -7,7 +9,7 @@ use rustc_ast::ast::LitKind;
79
use rustc_data_structures::fx::FxHashSet;
810
use rustc_errors::Applicability;
911
use rustc_hir as hir;
10-
use rustc_hir::*;
12+
use rustc_hir::{ExprKind, Path, QPath};
1113
use rustc_lint::LateContext;
1214
use rustc_middle::ty;
1315
use rustc_span::source_map::Spanned;
@@ -21,44 +23,31 @@ pub(super) fn check<'tcx>(
2123
expr: &'tcx hir::Expr<'tcx>,
2224
name: &str,
2325
recv: &'tcx hir::Expr<'tcx>,
24-
args: &'tcx [hir::Expr<'tcx>],
2526
) {
26-
match (name, args) {
27-
("replace", ..) => {
28-
// The receiver of the method call must be `str` type to lint `collapsible_str_replace`
29-
let original_recv = find_original_recv(recv);
30-
let original_recv_ty_kind = cx.typeck_results().expr_ty(original_recv).peel_refs().kind();
31-
let original_recv_is_str_kind = matches!(original_recv_ty_kind, ty::Str);
27+
if name == "replace" {
28+
// The receiver of the method call must be `str` type to lint `collapsible_str_replace`
29+
let original_recv = find_original_recv(recv);
30+
let original_recv_ty_kind = cx.typeck_results().expr_ty(original_recv).peel_refs().kind();
31+
let original_recv_is_str_kind = matches!(original_recv_ty_kind, ty::Str);
3232

33-
if_chain! {
34-
if original_recv_is_str_kind;
35-
if let Some(parent) = get_parent_expr(cx, expr);
36-
if let Some((name, ..)) = method_call(parent);
33+
if_chain! {
34+
if original_recv_is_str_kind;
35+
if let Some(parent) = get_parent_expr(cx, expr);
36+
if let Some((name, ..)) = method_call(parent);
37+
if name == "replace";
3738

38-
then {
39-
match name {
40-
// If the parent node is a `str::replace` call, we've already handled the lint, don't lint again
41-
"replace" => return,
42-
_ => {
43-
check_consecutive_replace_calls(cx, expr);
44-
return;
45-
},
46-
}
47-
}
39+
then {
40+
// If the parent node is a `str::replace` call, we've already handled the lint, don't lint again
41+
return;
4842
}
43+
}
4944

50-
match method_call(recv) {
51-
// Check if there's an earlier `str::replace` call
52-
Some(("replace", ..)) => {
53-
if original_recv_is_str_kind {
54-
check_consecutive_replace_calls(cx, expr);
55-
return;
56-
}
57-
},
58-
_ => {},
45+
if let Some(("replace", ..)) = method_call(recv) {
46+
// Check if there's an earlier `str::replace` call
47+
if original_recv_is_str_kind {
48+
check_consecutive_replace_calls(cx, expr);
5949
}
60-
},
61-
_ => {},
50+
}
6251
}
6352
}
6453

@@ -116,7 +105,7 @@ fn check_consecutive_replace_calls<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir
116105

117106
/// Check if all the `from` arguments of a chain of consecutive calls to `str::replace`
118107
/// are all of `ExprKind::Lit` types. If any is not, return false.
119-
fn replace_call_from_args_are_only_lit_chars<'tcx>(from_args: &Vec<&'tcx hir::Expr<'tcx>>) -> bool {
108+
fn replace_call_from_args_are_only_lit_chars<'tcx>(from_args: &[&'tcx hir::Expr<'tcx>]) -> bool {
120109
let mut only_lit_chars = true;
121110

122111
for from_arg in from_args.iter() {
@@ -159,9 +148,9 @@ fn get_replace_call_from_args_if_all_char_ty<'tcx>(
159148

160149
if all_from_args_are_chars {
161150
return Some(from_args);
162-
} else {
163-
return None;
164151
}
152+
153+
None
165154
}
166155

167156
/// Return a unique String representation of the `to` argument used in a chain of `str::replace`
@@ -186,13 +175,13 @@ fn get_replace_call_unique_to_arg_repr<'tcx>(expr: &'tcx hir::Expr<'tcx>) -> Opt
186175

187176
// let mut to_arg_repr_set = FxHashSet::default();
188177
let mut to_arg_reprs = Vec::new();
189-
for &to_arg in to_args.iter() {
178+
for &to_arg in &to_args {
190179
if let Some(to_arg_repr) = get_replace_call_char_arg_repr(to_arg) {
191180
to_arg_reprs.push(to_arg_repr);
192181
}
193182
}
194183

195-
let to_arg_repr_set = FxHashSet::from_iter(to_arg_reprs.iter().cloned());
184+
let to_arg_repr_set = to_arg_reprs.iter().cloned().collect::<FxHashSet<_>>();
196185
// Check if the set of `to` argument representations has more than one unique value
197186
if to_arg_repr_set.len() != 1 {
198187
return None;

clippy_lints/src/methods/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,11 @@ declare_clippy_lint! {
152152
/// let hello = "hesuo worpd"
153153
/// .replace('s', "l")
154154
/// .replace("u", "l")
155-
/// .replace('p', "l")
155+
/// .replace('p', "l");
156156
/// ```
157157
/// Use instead:
158158
/// ```rust
159-
/// let hello = "hesuo worpd".replace(|c| matches!(c, 's' | 'u' | 'p'), "l")
159+
/// let hello = "hesuo worpd".replace(|c| matches!(c, 's' | 'u' | 'p'), "l");
160160
/// ```
161161
#[clippy::version = "1.64.0"]
162162
pub COLLAPSIBLE_STR_REPLACE,
@@ -3521,7 +3521,7 @@ impl Methods {
35213521
},
35223522
("replace" | "replacen", [arg1, arg2] | [arg1, arg2, _]) => {
35233523
no_effect_replace::check(cx, expr, arg1, arg2);
3524-
collapsible_str_replace::check(cx, expr, name, recv, args);
3524+
collapsible_str_replace::check(cx, expr, name, recv);
35253525
},
35263526
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
35273527
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::collapsible_str_replace)]
4+
5+
fn get_filter() -> &'static str {
6+
"u"
7+
}
8+
9+
fn main() {
10+
let misspelled = "hesuo worpd";
11+
12+
let p = 'p';
13+
let s = 's';
14+
let u = 'u';
15+
let l = "l";
16+
17+
// LINT CASES
18+
let _ = misspelled.replace(|c| matches!(c, 'u' | 's'), "l");
19+
20+
let _ = misspelled.replace(|c| matches!(c, 'u' | 's'), l);
21+
22+
let _ = misspelled.replace(|c| matches!(c, 'p' | 'u' | 's'), "l");
23+
24+
let _ = misspelled
25+
.replace(|c| matches!(c, 'd' | 'p' | 'u' | 's'), "l");
26+
27+
// FALLBACK CASES
28+
// If there are consecutive calls to `str::replace` and all or any chars are variables,
29+
// recommend the fallback `misspelled.replace(&[s, u, p], "l")`
30+
let _ = misspelled.replace(&['u' , s], "l");
31+
32+
let _ = misspelled.replace(&['p' , 'u' , s], "l");
33+
34+
let _ = misspelled.replace(&['p' , u , s], "l");
35+
36+
let _ = misspelled.replace(&[p , u , s], "l");
37+
38+
// NO LINT CASES
39+
let _ = misspelled.replace('s', "l");
40+
41+
let _ = misspelled.replace(s, "l");
42+
43+
// If the consecutive `str::replace` calls have different `to` arguments, do not lint
44+
let _ = misspelled.replace('s', "l").replace('u', "p");
45+
46+
let _ = misspelled.replace(&get_filter(), "l");
47+
48+
let _ = misspelled.replace(&['s', 'u', 'p'], "l");
49+
50+
let _ = misspelled.replace(&['s', 'u', 'p'], l);
51+
52+
let _ = misspelled.replace(&['s', 'u'], "l").replace(&['u', 'p'], "l");
53+
54+
let _ = misspelled.replace('s', "l").replace(&['u', 'p'], "l");
55+
56+
let _ = misspelled.replace(&['s', 'u'], "l").replace('p', "l");
57+
58+
let _ = misspelled.replace(&['s', u, 'p'], "l");
59+
60+
let _ = misspelled.replace(&[s, u, 'p'], "l");
61+
62+
let _ = misspelled.replace(&[s, u, p], "l");
63+
64+
let _ = misspelled.replace(&[s, u], "l").replace(&[u, p], "l");
65+
}

tests/ui/collapsible_str_replace.rs

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// run-rustfix
2+
13
#![warn(clippy::collapsible_str_replace)]
24

35
fn get_filter() -> &'static str {
@@ -13,75 +15,54 @@ fn main() {
1315
let l = "l";
1416

1517
// LINT CASES
16-
let replacement = misspelled.replace('s', "l").replace('u', "l");
17-
println!("{replacement}");
18+
let _ = misspelled.replace('s', "l").replace('u', "l");
1819

19-
let replacement = misspelled.replace('s', l).replace('u', l);
20-
println!("{replacement}");
20+
let _ = misspelled.replace('s', l).replace('u', l);
2121

22-
let replacement = misspelled.replace('s', "l").replace('u', "l").replace('p', "l");
23-
println!("{replacement}");
22+
let _ = misspelled.replace('s', "l").replace('u', "l").replace('p', "l");
2423

25-
let replacement = misspelled
24+
let _ = misspelled
2625
.replace('s', "l")
2726
.replace('u', "l")
2827
.replace('p', "l")
2928
.replace('d', "l");
30-
println!("{replacement}");
3129

3230
// FALLBACK CASES
3331
// If there are consecutive calls to `str::replace` and all or any chars are variables,
3432
// recommend the fallback `misspelled.replace(&[s, u, p], "l")`
35-
let replacement = misspelled.replace(s, "l").replace('u', "l");
36-
println!("{replacement}");
33+
let _ = misspelled.replace(s, "l").replace('u', "l");
3734

38-
let replacement = misspelled.replace(s, "l").replace('u', "l").replace('p', "l");
39-
println!("{replacement}");
35+
let _ = misspelled.replace(s, "l").replace('u', "l").replace('p', "l");
4036

41-
let replacement = misspelled.replace(s, "l").replace(u, "l").replace('p', "l");
42-
println!("{replacement}");
37+
let _ = misspelled.replace(s, "l").replace(u, "l").replace('p', "l");
4338

44-
let replacement = misspelled.replace(s, "l").replace(u, "l").replace(p, "l");
45-
println!("{replacement}");
39+
let _ = misspelled.replace(s, "l").replace(u, "l").replace(p, "l");
4640

4741
// NO LINT CASES
48-
let replacement = misspelled.replace('s', "l");
49-
println!("{replacement}");
42+
let _ = misspelled.replace('s', "l");
5043

51-
let replacement = misspelled.replace(s, "l");
52-
println!("{replacement}");
44+
let _ = misspelled.replace(s, "l");
5345

5446
// If the consecutive `str::replace` calls have different `to` arguments, do not lint
55-
let replacement = misspelled.replace('s', "l").replace('u', "p");
56-
println!("{replacement}");
47+
let _ = misspelled.replace('s', "l").replace('u', "p");
5748

58-
let replacement = misspelled.replace(&get_filter(), "l");
59-
println!("{replacement}");
49+
let _ = misspelled.replace(&get_filter(), "l");
6050

61-
let replacement = misspelled.replace(&['s', 'u', 'p'], "l");
62-
println!("{replacement}");
51+
let _ = misspelled.replace(&['s', 'u', 'p'], "l");
6352

64-
let replacement = misspelled.replace(&['s', 'u', 'p'], l);
65-
println!("{replacement}");
53+
let _ = misspelled.replace(&['s', 'u', 'p'], l);
6654

67-
let replacement = misspelled.replace(&['s', 'u'], "l").replace(&['u', 'p'], "l");
68-
println!("{replacement}");
55+
let _ = misspelled.replace(&['s', 'u'], "l").replace(&['u', 'p'], "l");
6956

70-
let replacement = misspelled.replace('s', "l").replace(&['u', 'p'], "l");
71-
println!("{replacement}");
57+
let _ = misspelled.replace('s', "l").replace(&['u', 'p'], "l");
7258

73-
let replacement = misspelled.replace(&['s', 'u'], "l").replace('p', "l");
74-
println!("replacement");
59+
let _ = misspelled.replace(&['s', 'u'], "l").replace('p', "l");
7560

76-
let replacement = misspelled.replace(&['s', u, 'p'], "l");
77-
println!("{replacement}");
61+
let _ = misspelled.replace(&['s', u, 'p'], "l");
7862

79-
let replacement = misspelled.replace(&[s, u, 'p'], "l");
80-
println!("{replacement}");
63+
let _ = misspelled.replace(&[s, u, 'p'], "l");
8164

82-
let replacement = misspelled.replace(&[s, u, p], "l");
83-
println!("{replacement}");
65+
let _ = misspelled.replace(&[s, u, p], "l");
8466

85-
let replacement = misspelled.replace(&[s, u], "l").replace(&[u, p], "l");
86-
println!("{replacement}");
67+
let _ = misspelled.replace(&[s, u], "l").replace(&[u, p], "l");
8768
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error: used consecutive `str::replace` call
2+
--> $DIR/collapsible_str_replace.rs:18:24
3+
|
4+
LL | let _ = misspelled.replace('s', "l").replace('u', "l");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(|c| matches!(c, 'u' | 's'), "l")`
6+
|
7+
= note: `-D clippy::collapsible-str-replace` implied by `-D warnings`
8+
9+
error: used consecutive `str::replace` call
10+
--> $DIR/collapsible_str_replace.rs:20:24
11+
|
12+
LL | let _ = misspelled.replace('s', l).replace('u', l);
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(|c| matches!(c, 'u' | 's'), l)`
14+
15+
error: used consecutive `str::replace` call
16+
--> $DIR/collapsible_str_replace.rs:22:24
17+
|
18+
LL | let _ = misspelled.replace('s', "l").replace('u', "l").replace('p', "l");
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(|c| matches!(c, 'p' | 'u' | 's'), "l")`
20+
21+
error: used consecutive `str::replace` call
22+
--> $DIR/collapsible_str_replace.rs:25:10
23+
|
24+
LL | .replace('s', "l")
25+
| __________^
26+
LL | | .replace('u', "l")
27+
LL | | .replace('p', "l")
28+
LL | | .replace('d', "l");
29+
| |__________________________^ help: replace with: `replace(|c| matches!(c, 'd' | 'p' | 'u' | 's'), "l")`
30+
31+
error: used consecutive `str::replace` call
32+
--> $DIR/collapsible_str_replace.rs:33:24
33+
|
34+
LL | let _ = misspelled.replace(s, "l").replace('u', "l");
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(&['u' , s], "l")`
36+
37+
error: used consecutive `str::replace` call
38+
--> $DIR/collapsible_str_replace.rs:35:24
39+
|
40+
LL | let _ = misspelled.replace(s, "l").replace('u', "l").replace('p', "l");
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(&['p' , 'u' , s], "l")`
42+
43+
error: used consecutive `str::replace` call
44+
--> $DIR/collapsible_str_replace.rs:37:24
45+
|
46+
LL | let _ = misspelled.replace(s, "l").replace(u, "l").replace('p', "l");
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(&['p' , u , s], "l")`
48+
49+
error: used consecutive `str::replace` call
50+
--> $DIR/collapsible_str_replace.rs:39:24
51+
|
52+
LL | let _ = misspelled.replace(s, "l").replace(u, "l").replace(p, "l");
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(&[p , u , s], "l")`
54+
55+
error: aborting due to 8 previous errors
56+

0 commit comments

Comments
 (0)