Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2817c5f

Browse files
Extend result_map_or_into_option lint to handle Result::map_or_else(|_| None, Some)
1 parent 30c743f commit 2817c5f

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ mod read_line_without_trim;
8181
mod readonly_write_lock;
8282
mod redundant_as_str;
8383
mod repeat_once;
84+
mod result_map_or_else_none;
8485
mod search_is_some;
8586
mod seek_from_current;
8687
mod seek_to_start_instead_of_rewind;
@@ -4335,6 +4336,9 @@ impl Methods {
43354336
option_map_or_none::check(cx, expr, recv, def, map);
43364337
manual_ok_or::check(cx, expr, recv, def, map);
43374338
},
4339+
("map_or_else", [def, map]) => {
4340+
result_map_or_else_none::check(cx, expr, recv, def, map);
4341+
},
43384342
("next", []) => {
43394343
if let Some((name2, recv2, args2, _, _)) = method_call(recv) {
43404344
match (name2, args2) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::source::snippet;
3+
use clippy_utils::ty::is_type_diagnostic_item;
4+
use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
5+
use rustc_errors::Applicability;
6+
use rustc_hir as hir;
7+
use rustc_hir::LangItem::{OptionNone, OptionSome};
8+
use rustc_lint::LateContext;
9+
use rustc_span::symbol::sym;
10+
11+
use super::RESULT_MAP_OR_INTO_OPTION;
12+
13+
/// lint use of `_.map_or_else(|_| None, Some)` for `Result`s
14+
pub(super) fn check<'tcx>(
15+
cx: &LateContext<'tcx>,
16+
expr: &'tcx hir::Expr<'_>,
17+
recv: &'tcx hir::Expr<'_>,
18+
def_arg: &'tcx hir::Expr<'_>,
19+
map_arg: &'tcx hir::Expr<'_>,
20+
) {
21+
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
22+
23+
if !is_result {
24+
return;
25+
}
26+
27+
let f_arg_is_some = is_res_lang_ctor(cx, path_res(cx, map_arg), OptionSome);
28+
29+
if f_arg_is_some
30+
&& let hir::ExprKind::Closure(&hir::Closure { body, .. }) = def_arg.kind
31+
&& let body = cx.tcx.hir().body(body)
32+
&& is_res_lang_ctor(cx, path_res(cx, peel_blocks(body.value)), OptionNone)
33+
{
34+
let msg = "called `map_or_else(|_| None, Some)` on a `Result` value";
35+
let self_snippet = snippet(cx, recv.span, "..");
36+
span_lint_and_sugg(
37+
cx,
38+
RESULT_MAP_OR_INTO_OPTION,
39+
expr.span,
40+
msg,
41+
"try using `ok` instead",
42+
format!("{self_snippet}.ok()"),
43+
Applicability::MachineApplicable,
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)