Skip to content

Commit 4c00a09

Browse files
committed
extend obfuscated_if_else to support then().unwrap_or_else() and then_some().unwrap_or_else()
1 parent 8c01600 commit 4c00a09

File tree

5 files changed

+76
-12
lines changed

5 files changed

+76
-12
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5328,7 +5328,7 @@ impl Methods {
53285328
option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv);
53295329
},
53305330
Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => {
5331-
obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method);
5331+
obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method, "unwrap_or");
53325332
},
53335333
_ => {},
53345334
}
@@ -5347,6 +5347,9 @@ impl Methods {
53475347
match method_call(recv) {
53485348
Some(("map", recv, [map_arg], _, _))
53495349
if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {},
5350+
Some((then_method @ ("then" | "then_some"), t_recv, [t_arg], _, _)) => {
5351+
obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg, then_method, "unwrap_or_else");
5352+
},
53505353
_ => {
53515354
unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
53525355
},

clippy_lints/src/methods/obfuscated_if_else.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub(super) fn check<'tcx>(
1616
then_arg: &'tcx hir::Expr<'_>,
1717
unwrap_arg: &'tcx hir::Expr<'_>,
1818
then_method_name: &str,
19+
unwrap_method_name: &str,
1920
) {
2021
let recv_ty = cx.typeck_results().expr_ty(then_recv);
2122

@@ -32,14 +33,26 @@ pub(super) fn check<'tcx>(
3233
snippet_with_applicability(cx, body.value.span, "..", &mut applicability)
3334
},
3435
"then_some" => snippet_with_applicability(cx, then_arg.span, "..", &mut applicability),
35-
_ => String::new().into(),
36+
_ => return,
37+
};
38+
39+
let els = match unwrap_method_name {
40+
"unwrap_or" => {
41+
let unwrap_arg_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability);
42+
unwrap_arg_snippet
43+
},
44+
"unwrap_or_else" if let ExprKind::Closure(closure) = unwrap_arg.kind => {
45+
let body = cx.tcx.hir().body(closure.body);
46+
snippet_with_applicability(cx, body.value.span, "..", &mut applicability)
47+
},
48+
_ => return,
3649
};
3750

3851
let sugg = format!(
3952
"if {} {{ {} }} else {{ {} }}",
4053
Sugg::hir_with_applicability(cx, then_recv, "..", &mut applicability),
4154
if_then,
42-
snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability)
55+
els
4356
);
4457

4558
// To be parsed as an expression, the `if { … } else { … }` as the left operand of a binary operator

tests/ui/obfuscated_if_else.fixed

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ fn main() {
2121
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
2222
if true { () } else { a += 2 };
2323
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
24+
25+
let mut n = 1;
26+
if true { n = 1 } else { n = 2 };
27+
if true { 1 } else { n * 2 };
28+
if true { n += 1 } else { () };
29+
30+
let _ = if true { 1 } else { n * 2 };
31+
32+
let partial = true.then_some(1);
33+
partial.unwrap_or_else(|| n * 2); //not lint
2434
}
2535

2636
fn issue11141() {

tests/ui/obfuscated_if_else.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ fn main() {
2121
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
2222
true.then_some(()).unwrap_or(a += 2);
2323
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
24+
25+
let mut n = 1;
26+
true.then(|| n = 1).unwrap_or_else(|| n = 2);
27+
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
28+
true.then_some(1).unwrap_or_else(|| n * 2);
29+
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
30+
true.then_some(n += 1).unwrap_or_else(|| ());
31+
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
32+
33+
let _ = true.then_some(1).unwrap_or_else(|| n * 2);
34+
//~^ ERROR: this method chain can be written more clearly with `if .. else ..`
35+
36+
let partial = true.then_some(1);
37+
partial.unwrap_or_else(|| n * 2); //not lint
2438
}
2539

2640
fn issue11141() {

tests/ui/obfuscated_if_else.stderr

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,52 +38,76 @@ LL | true.then_some(()).unwrap_or(a += 2);
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { () } else { a += 2 }`
3939

4040
error: this method chain can be written more clearly with `if .. else ..`
41-
--> tests/ui/obfuscated_if_else.rs:28:13
41+
--> tests/ui/obfuscated_if_else.rs:26:5
42+
|
43+
LL | true.then(|| n = 1).unwrap_or_else(|| n = 2);
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { n = 1 } else { n = 2 }`
45+
46+
error: this method chain can be written more clearly with `if .. else ..`
47+
--> tests/ui/obfuscated_if_else.rs:27:5
48+
|
49+
LL | true.then_some(1).unwrap_or_else(|| n * 2);
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { n * 2 }`
51+
52+
error: this method chain can be written more clearly with `if .. else ..`
53+
--> tests/ui/obfuscated_if_else.rs:28:5
54+
|
55+
LL | true.then_some(n += 1).unwrap_or_else(|| ());
56+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { n += 1 } else { () }`
57+
58+
error: this method chain can be written more clearly with `if .. else ..`
59+
--> tests/ui/obfuscated_if_else.rs:30:13
60+
|
61+
LL | let _ = true.then_some(1).unwrap_or_else(|| n * 2);
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 1 } else { n * 2 }`
63+
64+
error: this method chain can be written more clearly with `if .. else ..`
65+
--> tests/ui/obfuscated_if_else.rs:38:13
4266
|
4367
LL | let _ = true.then_some(40).unwrap_or(17) | 2;
4468
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(if true { 40 } else { 17 })`
4569

4670
error: this method chain can be written more clearly with `if .. else ..`
47-
--> tests/ui/obfuscated_if_else.rs:32:13
71+
--> tests/ui/obfuscated_if_else.rs:42:13
4872
|
4973
LL | let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1);
5074
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(if true { 30 } else { 17 })`
5175

5276
error: this method chain can be written more clearly with `if .. else ..`
53-
--> tests/ui/obfuscated_if_else.rs:32:48
77+
--> tests/ui/obfuscated_if_else.rs:42:48
5478
|
5579
LL | let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1);
5680
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 2 } else { 3 }`
5781

5882
error: this method chain can be written more clearly with `if .. else ..`
59-
--> tests/ui/obfuscated_if_else.rs:32:81
83+
--> tests/ui/obfuscated_if_else.rs:42:81
6084
|
6185
LL | let _ = true.then_some(30).unwrap_or(17) | true.then_some(2).unwrap_or(3) | true.then_some(10).unwrap_or(1);
6286
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 10 } else { 1 }`
6387

6488
error: this method chain can be written more clearly with `if .. else ..`
65-
--> tests/ui/obfuscated_if_else.rs:36:17
89+
--> tests/ui/obfuscated_if_else.rs:46:17
6690
|
6791
LL | let _ = 2 | true.then_some(40).unwrap_or(17);
6892
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 40 } else { 17 }`
6993

7094
error: this method chain can be written more clearly with `if .. else ..`
71-
--> tests/ui/obfuscated_if_else.rs:40:13
95+
--> tests/ui/obfuscated_if_else.rs:50:13
7296
|
7397
LL | let _ = true.then_some(42).unwrap_or(17) as u8;
7498
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { 42 } else { 17 }`
7599

76100
error: this method chain can be written more clearly with `if .. else ..`
77-
--> tests/ui/obfuscated_if_else.rs:44:14
101+
--> tests/ui/obfuscated_if_else.rs:54:14
78102
|
79103
LL | let _ = *true.then_some(&42).unwrap_or(&17);
80104
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { &42 } else { &17 }`
81105

82106
error: this method chain can be written more clearly with `if .. else ..`
83-
--> tests/ui/obfuscated_if_else.rs:48:14
107+
--> tests/ui/obfuscated_if_else.rs:58:14
84108
|
85109
LL | let _ = *true.then_some(&42).unwrap_or(&17) as u8;
86110
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { &42 } else { &17 }`
87111

88-
error: aborting due to 14 previous errors
112+
error: aborting due to 18 previous errors
89113

0 commit comments

Comments
 (0)