@@ -331,6 +331,32 @@ declare_clippy_lint! {
331331    "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`" 
332332} 
333333
334+ declare_clippy_lint !  { 
335+     /// **What it does:** Checks for usage of `_.map_or(None, Some)`. 
336+ /// 
337+ /// **Why is this bad?** Readability, this can be written more concisely as 
338+ /// `_.ok()`. 
339+ /// 
340+ /// **Known problems:** None. 
341+ /// 
342+ /// **Example:** 
343+ /// 
344+ /// Bad: 
345+ /// ```rust 
346+ /// # let r: Result<u32, &str> = Ok(1); 
347+ /// assert_eq!(Some(1), r.map_or(None, Some)); 
348+ /// ``` 
349+ /// 
350+ /// Good: 
351+ /// ```rust 
352+ /// # let r: Result<u32, &str> = Ok(1); 
353+ /// assert_eq!(Some(1), r.ok()); 
354+ /// ``` 
355+ pub  RESULT_MAP_OR_INTO_OPTION , 
356+     style, 
357+     "using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`" 
358+ } 
359+ 
334360declare_clippy_lint !  { 
335361    /// **What it does:** Checks for usage of `_.and_then(|x| Some(y))`. 
336362/// 
@@ -1249,6 +1275,7 @@ declare_lint_pass!(Methods => [
12491275    OPTION_MAP_UNWRAP_OR , 
12501276    OPTION_MAP_UNWRAP_OR_ELSE , 
12511277    RESULT_MAP_UNWRAP_OR_ELSE , 
1278+     RESULT_MAP_OR_INTO_OPTION , 
12521279    OPTION_MAP_OR_NONE , 
12531280    OPTION_AND_THEN_SOME , 
12541281    OR_FUN_CALL , 
@@ -2524,38 +2551,78 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
25242551    } 
25252552} 
25262553
2527- /// lint use of `_.map_or(None, _)` for `Option`s 
2554+ /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s  
25282555fn  lint_map_or_none < ' a ,  ' tcx > ( 
25292556    cx :  & LateContext < ' a ,  ' tcx > , 
25302557    expr :  & ' tcx  hir:: Expr < ' _ > , 
25312558    map_or_args :  & ' tcx  [ hir:: Expr < ' _ > ] , 
25322559)  { 
2533-     if  match_type ( cx,  cx. tables . expr_ty ( & map_or_args[ 0 ] ) ,  & paths:: OPTION )  { 
2534-         // check if the first non-self argument to map_or() is None 
2535-         let  map_or_arg_is_none = if  let  hir:: ExprKind :: Path ( ref  qpath)  = map_or_args[ 1 ] . kind  { 
2560+     let  is_option = match_type ( cx,  cx. tables . expr_ty ( & map_or_args[ 0 ] ) ,  & paths:: OPTION ) ; 
2561+     let  is_result = match_type ( cx,  cx. tables . expr_ty ( & map_or_args[ 0 ] ) ,  & paths:: RESULT ) ; 
2562+ 
2563+     // There are two variants of this `map_or` lint: 
2564+     // (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>` 
2565+     // (2) using `map_or` as a combinator instead of `and_then` 
2566+     // 
2567+     // (For this lint) we don't care if any other type calls `map_or` 
2568+     if  !is_option && !is_result { 
2569+         return ; 
2570+     } 
2571+ 
2572+     let  ( lint_name,  msg,  instead,  hint)  = { 
2573+         let  default_arg_is_none = if  let  hir:: ExprKind :: Path ( ref  qpath)  = map_or_args[ 1 ] . kind  { 
25362574            match_qpath ( qpath,  & paths:: OPTION_NONE ) 
2575+         }  else  { 
2576+             return ; 
2577+         } ; 
2578+ 
2579+         if  !default_arg_is_none { 
2580+             // nothing to lint! 
2581+             return ; 
2582+         } 
2583+ 
2584+         let  f_arg_is_some = if  let  hir:: ExprKind :: Path ( ref  qpath)  = map_or_args[ 2 ] . kind  { 
2585+             match_qpath ( qpath,  & paths:: OPTION_SOME ) 
25372586        }  else  { 
25382587            false 
25392588        } ; 
25402589
2541-         if  map_or_arg_is_none { 
2542-             // lint message 
2590+         if  is_option { 
2591+             let  self_snippet = snippet ( cx,  map_or_args[ 0 ] . span ,  ".." ) ; 
2592+             let  func_snippet = snippet ( cx,  map_or_args[ 2 ] . span ,  ".." ) ; 
25432593            let  msg = "called `map_or(None, f)` on an `Option` value. This can be done more directly by calling \  
25442594; 
2545-             let  map_or_self_snippet = snippet ( cx,  map_or_args[ 0 ] . span ,  ".." ) ; 
2546-             let  map_or_func_snippet = snippet ( cx,  map_or_args[ 2 ] . span ,  ".." ) ; 
2547-             let  hint = format ! ( "{0}.and_then({1})" ,  map_or_self_snippet,  map_or_func_snippet) ; 
2548-             span_lint_and_sugg ( 
2549-                 cx, 
2595+             ( 
25502596                OPTION_MAP_OR_NONE , 
2551-                 expr. span , 
25522597                msg, 
25532598                "try using `and_then` instead" , 
2554-                 hint, 
2555-                 Applicability :: MachineApplicable , 
2556-             ) ; 
2599+                 format ! ( "{0}.and_then({1})" ,  self_snippet,  func_snippet) , 
2600+             ) 
2601+         }  else  if  f_arg_is_some { 
2602+             let  msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \  
2603+ ; 
2604+             let  self_snippet = snippet ( cx,  map_or_args[ 0 ] . span ,  ".." ) ; 
2605+             ( 
2606+                 RESULT_MAP_OR_INTO_OPTION , 
2607+                 msg, 
2608+                 "try using `ok` instead" , 
2609+                 format ! ( "{0}.ok()" ,  self_snippet) , 
2610+             ) 
2611+         }  else  { 
2612+             // nothing to lint! 
2613+             return ; 
25572614        } 
2558-     } 
2615+     } ; 
2616+ 
2617+     span_lint_and_sugg ( 
2618+         cx, 
2619+         lint_name, 
2620+         expr. span , 
2621+         msg, 
2622+         instead, 
2623+         hint, 
2624+         Applicability :: MachineApplicable , 
2625+     ) ; 
25592626} 
25602627
25612628/// Lint use of `_.and_then(|x| Some(y))` for `Option`s 
0 commit comments