Skip to content

Commit eb19d41

Browse files
committed
Stop linting on macros and correctly use braces for constructs
1 parent 2fc340b commit eb19d41

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

clippy_lints/src/option_if_let_else.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::utils;
12
use crate::utils::sugg::Sugg;
23
use crate::utils::{match_type, paths, span_lint_and_sugg};
34
use if_chain::if_chain;
@@ -89,6 +90,7 @@ struct OptionIfLetElseOccurence {
8990
method_sugg: String,
9091
some_expr: String,
9192
none_expr: String,
93+
wrap_braces: bool,
9294
}
9395

9496
struct ReturnBreakContinueVisitor<'tcx> {
@@ -140,6 +142,7 @@ fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool {
140142
fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> {
141143
//(String, String, String, String)> {
142144
if_chain! {
145+
// if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly
143146
if let ExprKind::Match(let_body, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
144147
if arms.len() == 2;
145148
if match_type(cx, &cx.tables.expr_ty(let_body), &paths::OPTION);
@@ -170,11 +173,23 @@ fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -
170173
return None;
171174
};
172175
let capture_name = id.name.to_ident_string();
176+
let wrap_braces = utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
177+
if_chain! {
178+
if let Some(Expr { kind: ExprKind::Match(condition, arms, MatchSource::IfDesugar{contains_else_clause: true}|MatchSource::IfLetDesugar{contains_else_clause: true}), .. } ) = parent.expr;
179+
if expr.hir_id == arms[1].body.hir_id;
180+
then {
181+
true
182+
} else {
183+
false
184+
}
185+
}
186+
});
173187
Some(OptionIfLetElseOccurence {
174188
option: format!("{}", Sugg::hir(cx, let_body, "..")),
175189
method_sugg: format!("{}", method_sugg),
176190
some_expr: format!("|{}| {}", capture_name, Sugg::hir(cx, some_body, "..")),
177-
none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, ".."))
191+
none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
192+
wrap_braces,
178193
})
179194
} else {
180195
None
@@ -192,8 +207,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse {
192207
format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
193208
"try",
194209
format!(
195-
"{}.{}({}, {})",
196-
detection.option, detection.method_sugg, detection.none_expr, detection.some_expr
210+
"{}{}.{}({}, {}){}",
211+
if detection.wrap_braces { "{ " } else { "" },
212+
detection.option, detection.method_sugg, detection.none_expr, detection.some_expr,
213+
if detection.wrap_braces { " }" } else { "" },
197214
),
198215
Applicability::MachineApplicable,
199216
);

tests/ui/option_if_let_else.fixed

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ fn bad1(string: Option<&str>) -> (bool, &str) {
55
string.map_or((false, "hello"), |x| (true, x))
66
}
77

8+
fn bad2(string: Option<&str>) -> Option<(bool, &str)> {
9+
if string.is_none() {
10+
None
11+
} else { string.map_or(Some((false, "")), |x| Some((true, x))) }
12+
}
13+
814
fn longer_body(arg: Option<u32>) -> u32 {
915
arg.map_or(13, |x| {
1016
let y = x * x;
@@ -42,6 +48,7 @@ fn main() {
4248
let optional = Some(5);
4349
let _ = optional.map_or(5, |x| x + 2);
4450
let _ = bad1(None);
51+
let _ = bad2(None);
4552
let _ = longer_body(None);
4653
test_map_or_else(None);
4754
let _ = negative_tests(None);

tests/ui/option_if_let_else.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ fn bad1(string: Option<&str>) -> (bool, &str) {
99
}
1010
}
1111

12+
fn bad2(string: Option<&str>) -> Option<(bool, &str)> {
13+
if string.is_none() {
14+
None
15+
} else if let Some(x) = string {
16+
Some((true, x))
17+
} else {
18+
Some((false, ""))
19+
}
20+
}
21+
1222
fn longer_body(arg: Option<u32>) -> u32 {
1323
if let Some(x) = arg {
1424
let y = x * x;
@@ -50,6 +60,7 @@ fn main() {
5060
let optional = Some(5);
5161
let _ = if let Some(x) = optional { x + 2 } else { 5 };
5262
let _ = bad1(None);
63+
let _ = bad2(None);
5364
let _ = longer_body(None);
5465
test_map_or_else(None);
5566
let _ = negative_tests(None);

tests/ui/option_if_let_else.stderr

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,18 @@ LL | | }
1111
= note: `-D clippy::option-if-let-else` implied by `-D warnings`
1212

1313
error: use Option::map_or instead of an if let/else
14-
--> $DIR/option_if_let_else.rs:13:5
14+
--> $DIR/option_if_let_else.rs:15:12
15+
|
16+
LL | } else if let Some(x) = string {
17+
| ____________^
18+
LL | | Some((true, x))
19+
LL | | } else {
20+
LL | | Some((false, ""))
21+
LL | | }
22+
| |_____^ help: try: `{ string.map_or(Some((false, "")), |x| Some((true, x))) }`
23+
24+
error: use Option::map_or instead of an if let/else
25+
--> $DIR/option_if_let_else.rs:23:5
1526
|
1627
LL | / if let Some(x) = arg {
1728
LL | | let y = x * x;
@@ -30,7 +41,7 @@ LL | })
3041
|
3142

3243
error: use Option::map_or_else instead of an if let/else
33-
--> $DIR/option_if_let_else.rs:22:13
44+
--> $DIR/option_if_let_else.rs:32:13
3445
|
3546
LL | let _ = if let Some(x) = arg {
3647
| _____________^
@@ -53,10 +64,10 @@ LL | }, |x| x * x * x * x);
5364
|
5465

5566
error: use Option::map_or instead of an if let/else
56-
--> $DIR/option_if_let_else.rs:51:13
67+
--> $DIR/option_if_let_else.rs:61:13
5768
|
5869
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 };
5970
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
6071

61-
error: aborting due to 4 previous errors
72+
error: aborting due to 5 previous errors
6273

0 commit comments

Comments
 (0)