1
1
use clippy_utils:: diagnostics:: span_lint_and_sugg;
2
2
use clippy_utils:: sugg:: Sugg ;
3
- use clippy_utils:: ty:: is_type_diagnostic_item;
4
3
use clippy_utils:: {
5
4
can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_lang_ctor, peel_blocks,
6
5
peel_hir_expr_while, CaptureKind ,
7
6
} ;
8
7
use if_chain:: if_chain;
9
8
use rustc_errors:: Applicability ;
10
- use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
9
+ use rustc_hir:: LangItem :: { OptionNone , OptionSome , ResultErr , ResultOk } ;
11
10
use rustc_hir:: {
12
11
def:: Res , Arm , BindingAnnotation , Expr , ExprKind , MatchSource , Mutability , Pat , PatKind , Path , QPath , UnOp ,
13
12
} ;
14
13
use rustc_lint:: { LateContext , LateLintPass } ;
15
14
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
16
- use rustc_span:: sym;
17
15
18
16
declare_clippy_lint ! {
19
17
/// ### What it does
@@ -74,16 +72,6 @@ declare_clippy_lint! {
74
72
75
73
declare_lint_pass ! ( OptionIfLetElse => [ OPTION_IF_LET_ELSE ] ) ;
76
74
77
- /// Returns true iff the given expression is the result of calling `Result::ok`
78
- fn is_result_ok ( cx : & LateContext < ' _ > , expr : & ' _ Expr < ' _ > ) -> bool {
79
- if let ExprKind :: MethodCall ( path, & [ ref receiver] , _) = & expr. kind {
80
- path. ident . name . as_str ( ) == "ok"
81
- && is_type_diagnostic_item ( cx, cx. typeck_results ( ) . expr_ty ( receiver) , sym:: Result )
82
- } else {
83
- false
84
- }
85
- }
86
-
87
75
/// A struct containing information about occurrences of construct that this lint detects
88
76
///
89
77
/// Such as:
@@ -130,9 +118,8 @@ fn try_get_option_occurence<'tcx>(
130
118
ExprKind :: Unary ( UnOp :: Deref , inner_expr) | ExprKind :: AddrOf ( _, _, inner_expr) => inner_expr,
131
119
_ => expr,
132
120
} ;
121
+ let inner_pat = try_get_inner_pat ( cx, pat) ?;
133
122
if_chain ! {
134
- if !is_result_ok( cx, cond_expr) ; // Don't lint on Result::ok because a different lint does it already
135
- let inner_pat = try_get_inner_pat( cx, pat) ?;
136
123
if let PatKind :: Binding ( bind_annotation, _, id, None ) = inner_pat. kind;
137
124
if let Some ( some_captures) = can_move_expr_to_closure( cx, if_then) ;
138
125
if let Some ( none_captures) = can_move_expr_to_closure( cx, if_else) ;
@@ -185,7 +172,7 @@ fn try_get_option_occurence<'tcx>(
185
172
186
173
fn try_get_inner_pat < ' tcx > ( cx : & LateContext < ' tcx > , pat : & Pat < ' tcx > ) -> Option < & ' tcx Pat < ' tcx > > {
187
174
if let PatKind :: TupleStruct ( ref qpath, [ inner_pat] , ..) = pat. kind {
188
- if is_lang_ctor ( cx, qpath, OptionSome ) {
175
+ if is_lang_ctor ( cx, qpath, OptionSome ) || is_lang_ctor ( cx , qpath , ResultOk ) {
189
176
return Some ( inner_pat) ;
190
177
}
191
178
}
@@ -224,9 +211,9 @@ fn try_convert_match<'tcx>(
224
211
arms : & [ Arm < ' tcx > ] ,
225
212
) -> Option < ( & ' tcx Pat < ' tcx > , & ' tcx Expr < ' tcx > , & ' tcx Expr < ' tcx > ) > {
226
213
if arms. len ( ) == 2 {
227
- return if is_none_arm ( cx, & arms[ 1 ] ) {
214
+ return if is_none_or_err_arm ( cx, & arms[ 1 ] ) {
228
215
Some ( ( arms[ 0 ] . pat , arms[ 0 ] . body , arms[ 1 ] . body ) )
229
- } else if is_none_arm ( cx, & arms[ 0 ] ) {
216
+ } else if is_none_or_err_arm ( cx, & arms[ 0 ] ) {
230
217
Some ( ( arms[ 1 ] . pat , arms[ 1 ] . body , arms[ 0 ] . body ) )
231
218
} else {
232
219
None
@@ -235,9 +222,12 @@ fn try_convert_match<'tcx>(
235
222
None
236
223
}
237
224
238
- fn is_none_arm ( cx : & LateContext < ' _ > , arm : & Arm < ' _ > ) -> bool {
225
+ fn is_none_or_err_arm ( cx : & LateContext < ' _ > , arm : & Arm < ' _ > ) -> bool {
239
226
match arm. pat . kind {
240
227
PatKind :: Path ( ref qpath) => is_lang_ctor ( cx, qpath, OptionNone ) ,
228
+ PatKind :: TupleStruct ( ref qpath, [ first_pat] , _) => {
229
+ is_lang_ctor ( cx, qpath, ResultErr ) && matches ! ( first_pat. kind, PatKind :: Wild )
230
+ } ,
241
231
PatKind :: Wild => true ,
242
232
_ => false ,
243
233
}
0 commit comments