11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: sugg:: Sugg ;
3- use clippy_utils:: ty:: is_type_diagnostic_item;
43use clippy_utils:: {
54 can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_lang_ctor, peel_blocks,
65 peel_hir_expr_while, CaptureKind ,
76} ;
87use if_chain:: if_chain;
98use rustc_errors:: Applicability ;
10- use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
9+ use rustc_hir:: LangItem :: { OptionNone , OptionSome , ResultErr , ResultOk } ;
1110use rustc_hir:: {
1211 def:: Res , Arm , BindingAnnotation , Expr , ExprKind , MatchSource , Mutability , Pat , PatKind , Path , QPath , UnOp ,
1312} ;
1413use rustc_lint:: { LateContext , LateLintPass } ;
1514use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
16- use rustc_span:: sym;
1715
1816declare_clippy_lint ! {
1917 /// ### What it does
@@ -74,16 +72,6 @@ declare_clippy_lint! {
7472
7573declare_lint_pass ! ( OptionIfLetElse => [ OPTION_IF_LET_ELSE ] ) ;
7674
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-
8775/// A struct containing information about occurrences of construct that this lint detects
8876///
8977/// Such as:
@@ -130,9 +118,8 @@ fn try_get_option_occurence<'tcx>(
130118 ExprKind :: Unary ( UnOp :: Deref , inner_expr) | ExprKind :: AddrOf ( _, _, inner_expr) => inner_expr,
131119 _ => expr,
132120 } ;
121+ let inner_pat = try_get_inner_pat ( cx, pat) ?;
133122 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) ?;
136123 if let PatKind :: Binding ( bind_annotation, _, id, None ) = inner_pat. kind;
137124 if let Some ( some_captures) = can_move_expr_to_closure( cx, if_then) ;
138125 if let Some ( none_captures) = can_move_expr_to_closure( cx, if_else) ;
@@ -185,7 +172,7 @@ fn try_get_option_occurence<'tcx>(
185172
186173fn try_get_inner_pat < ' tcx > ( cx : & LateContext < ' tcx > , pat : & Pat < ' tcx > ) -> Option < & ' tcx Pat < ' tcx > > {
187174 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 ) {
189176 return Some ( inner_pat) ;
190177 }
191178 }
@@ -224,9 +211,9 @@ fn try_convert_match<'tcx>(
224211 arms : & [ Arm < ' tcx > ] ,
225212) -> Option < ( & ' tcx Pat < ' tcx > , & ' tcx Expr < ' tcx > , & ' tcx Expr < ' tcx > ) > {
226213 if arms. len ( ) == 2 {
227- return if is_none_arm ( cx, & arms[ 1 ] ) {
214+ return if is_none_or_err_arm ( cx, & arms[ 1 ] ) {
228215 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 ] ) {
230217 Some ( ( arms[ 1 ] . pat , arms[ 1 ] . body , arms[ 0 ] . body ) )
231218 } else {
232219 None
@@ -235,9 +222,12 @@ fn try_convert_match<'tcx>(
235222 None
236223}
237224
238- fn is_none_arm ( cx : & LateContext < ' _ > , arm : & Arm < ' _ > ) -> bool {
225+ fn is_none_or_err_arm ( cx : & LateContext < ' _ > , arm : & Arm < ' _ > ) -> bool {
239226 match arm. pat . kind {
240227 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+ } ,
241231 PatKind :: Wild => true ,
242232 _ => false ,
243233 }
0 commit comments