@@ -6,17 +6,19 @@ use rustc::lint::LateContext;
66use rustc_data_structures:: fx:: FxHashSet ;
77use syntax_pos:: symbol:: Symbol ;
88
9- use super :: OPTION_MAP_UNWRAP_OR ;
9+ use super :: { OPTION_MAP_UNWRAP_OR , RESULT_MAP_UNWRAP_OR } ;
1010
11- /// lint use of `map().unwrap_or()` for `Option`s
11+ /// lint use of `map().unwrap_or()` for `Option`s and `Result`s
1212pub ( super ) fn lint < ' a , ' tcx > (
1313 cx : & LateContext < ' a , ' tcx > ,
1414 expr : & hir:: Expr ,
1515 map_args : & ' tcx [ hir:: Expr ] ,
1616 unwrap_args : & ' tcx [ hir:: Expr ] ,
1717) {
18- // lint if the caller of `map()` is an `Option`
19- if match_type ( cx, cx. tables . expr_ty ( & map_args[ 0 ] ) , & paths:: OPTION ) {
18+ let is_option = match_type ( cx, cx. tables . expr_ty ( & map_args[ 0 ] ) , & paths:: OPTION ) ;
19+ let is_result = match_type ( cx, cx. tables . expr_ty ( & map_args[ 0 ] ) , & paths:: RESULT ) ;
20+
21+ if is_option || is_result {
2022 if !is_copy ( cx, cx. tables . expr_ty ( & unwrap_args[ 1 ] ) ) {
2123 // Do not lint if the `map` argument uses identifiers in the `map`
2224 // argument that are also used in the `unwrap_or` argument
@@ -43,19 +45,27 @@ pub(super) fn lint<'a, 'tcx>(
4345 let map_snippet = snippet ( cx, map_args[ 1 ] . span , ".." ) ;
4446 let unwrap_snippet = snippet ( cx, unwrap_args[ 1 ] . span , ".." ) ;
4547 // lint message
46- // comparing the snippet from source to raw text ("None") below is safe
47- // because we already have checked the type.
48- let arg = if unwrap_snippet == "None" { "None" } else { "a" } ;
49- let suggest = if unwrap_snippet == "None" {
50- "and_then(f)"
48+ let msg = if is_option {
49+ // comparing the snippet from source to raw text ("None") below is safe
50+ // because we already have checked the type.
51+ let arg = if unwrap_snippet == "None" { "None" } else { "a" } ;
52+ let suggest = if unwrap_snippet == "None" {
53+ "and_then(f)"
54+ } else {
55+ "map_or(a, f)"
56+ } ;
57+
58+ format ! (
59+ "called `map(f).unwrap_or({})` on an Option value. \
60+ This can be done more directly by calling `{}` instead",
61+ arg, suggest
62+ )
5163 } else {
52- "map_or(a, f)"
64+ "called `map(f).unwrap_or(a)` on a Result value. \
65+ This can be done more directly by calling `map_or(a, f)` instead"
66+ . to_string ( )
5367 } ;
54- let msg = & format ! (
55- "called `map(f).unwrap_or({})` on an Option value. \
56- This can be done more directly by calling `{}` instead",
57- arg, suggest
58- ) ;
68+
5969 // lint, with note if neither arg is > 1 line and both map() and
6070 // unwrap_or() have the same span
6171 let multiline = map_snippet. lines ( ) . count ( ) > 1 || unwrap_snippet. lines ( ) . count ( ) > 1 ;
@@ -70,9 +80,29 @@ pub(super) fn lint<'a, 'tcx>(
7080 "replace `map({}).unwrap_or({})` with `{}`" ,
7181 map_snippet, unwrap_snippet, suggest
7282 ) ;
73- span_note_and_lint ( cx, OPTION_MAP_UNWRAP_OR , expr. span , msg, expr. span , & note) ;
83+ span_note_and_lint (
84+ cx,
85+ if is_option {
86+ OPTION_MAP_UNWRAP_OR
87+ } else {
88+ RESULT_MAP_UNWRAP_OR
89+ } ,
90+ expr. span ,
91+ & msg,
92+ expr. span ,
93+ & note,
94+ ) ;
7495 } else if same_span && multiline {
75- span_lint ( cx, OPTION_MAP_UNWRAP_OR , expr. span , msg) ;
96+ span_lint (
97+ cx,
98+ if is_option {
99+ OPTION_MAP_UNWRAP_OR
100+ } else {
101+ RESULT_MAP_UNWRAP_OR
102+ } ,
103+ expr. span ,
104+ & msg,
105+ ) ;
76106 } ;
77107 }
78108}
0 commit comments