Skip to content

Commit 66d19d8

Browse files
committed
manual_ok_err: blockify the replacement of an else if …
If the part being replaced is an `if` expression following an `else`, the replacement expression must be blockified.
1 parent 735bed7 commit 66d19d8

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

clippy_lints/src/matches/manual_ok_err.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::source::{indent_of, reindent_multiline};
23
use clippy_utils::sugg::Sugg;
34
use clippy_utils::ty::option_arg_ty;
4-
use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks, span_contains_comment};
5+
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res, peel_blocks, span_contains_comment};
56
use rustc_ast::BindingMode;
67
use rustc_errors::Applicability;
78
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr};
@@ -132,13 +133,23 @@ fn apply_lint(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Expr<'_>, is_ok
132133
Applicability::MachineApplicable
133134
};
134135
let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_par();
136+
let sugg = format!("{scrut}.{method}()");
137+
// If the expression being expanded is the `if …` part of an `else if …`, it must be blockified.
138+
let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
139+
&& let ExprKind::If(_, _, Some(else_part)) = parent_expr.kind
140+
&& else_part.hir_id == expr.hir_id
141+
{
142+
reindent_multiline(&format!("{{\n {sugg}\n}}"), true, indent_of(cx, parent_expr.span))
143+
} else {
144+
sugg
145+
};
135146
span_lint_and_sugg(
136147
cx,
137148
MANUAL_OK_ERR,
138149
expr.span,
139150
format!("manual implementation of `{method}`"),
140151
"replace with",
141-
format!("{scrut}.{method}()"),
152+
sugg,
142153
app,
143154
);
144155
}

tests/ui/manual_ok_err.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,12 @@ const fn cf(x: Result<u32, &'static str>) -> Option<u32> {
8989
Err(_) => None,
9090
}
9191
}
92+
93+
fn issue14239() {
94+
let _ = if false {
95+
None
96+
} else {
97+
"1".parse::<u8>().ok()
98+
};
99+
//~^^^^^ manual_ok_err
100+
}

tests/ui/manual_ok_err.rs

+11
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,14 @@ const fn cf(x: Result<u32, &'static str>) -> Option<u32> {
125125
Err(_) => None,
126126
}
127127
}
128+
129+
fn issue14239() {
130+
let _ = if false {
131+
None
132+
} else if let Ok(n) = "1".parse::<u8>() {
133+
Some(n)
134+
} else {
135+
None
136+
};
137+
//~^^^^^ manual_ok_err
138+
}

tests/ui/manual_ok_err.stderr

+19-1
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,23 @@ LL | | _ => None,
9393
LL | | };
9494
| |_____^ help: replace with: `(-S).ok()`
9595

96-
error: aborting due to 8 previous errors
96+
error: manual implementation of `ok`
97+
--> tests/ui/manual_ok_err.rs:132:12
98+
|
99+
LL | } else if let Ok(n) = "1".parse::<u8>() {
100+
| ____________^
101+
LL | | Some(n)
102+
LL | | } else {
103+
LL | | None
104+
LL | | };
105+
| |_____^
106+
|
107+
help: replace with
108+
|
109+
LL ~ } else {
110+
LL + "1".parse::<u8>().ok()
111+
LL ~ };
112+
|
113+
114+
error: aborting due to 9 previous errors
97115

0 commit comments

Comments
 (0)