@@ -6,17 +6,19 @@ use rustc::lint::LateContext;
6
6
use rustc_data_structures:: fx:: FxHashSet ;
7
7
use syntax_pos:: symbol:: Symbol ;
8
8
9
- use super :: OPTION_MAP_UNWRAP_OR ;
9
+ use super :: { OPTION_MAP_UNWRAP_OR , RESULT_MAP_UNWRAP_OR } ;
10
10
11
- /// lint use of `map().unwrap_or()` for `Option`s
11
+ /// lint use of `map().unwrap_or()` for `Option`s and `Result`s
12
12
pub ( super ) fn lint < ' a , ' tcx > (
13
13
cx : & LateContext < ' a , ' tcx > ,
14
14
expr : & hir:: Expr ,
15
15
map_args : & ' tcx [ hir:: Expr ] ,
16
16
unwrap_args : & ' tcx [ hir:: Expr ] ,
17
17
) {
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 {
20
22
if !is_copy ( cx, cx. tables . expr_ty ( & unwrap_args[ 1 ] ) ) {
21
23
// Do not lint if the `map` argument uses identifiers in the `map`
22
24
// argument that are also used in the `unwrap_or` argument
@@ -43,19 +45,27 @@ pub(super) fn lint<'a, 'tcx>(
43
45
let map_snippet = snippet ( cx, map_args[ 1 ] . span , ".." ) ;
44
46
let unwrap_snippet = snippet ( cx, unwrap_args[ 1 ] . span , ".." ) ;
45
47
// 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
+ )
51
63
} 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 ( )
53
67
} ;
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
+
59
69
// lint, with note if neither arg is > 1 line and both map() and
60
70
// unwrap_or() have the same span
61
71
let multiline = map_snippet. lines ( ) . count ( ) > 1 || unwrap_snippet. lines ( ) . count ( ) > 1 ;
@@ -70,9 +80,29 @@ pub(super) fn lint<'a, 'tcx>(
70
80
"replace `map({}).unwrap_or({})` with `{}`" ,
71
81
map_snippet, unwrap_snippet, suggest
72
82
) ;
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
+ ) ;
74
95
} 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
+ ) ;
76
106
} ;
77
107
}
78
108
}
0 commit comments