@@ -2197,13 +2197,13 @@ fn lint_expect_fun_call(
2197
2197
match node {
2198
2198
hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , _, expr) => {
2199
2199
is_call ( & expr. kind )
2200
- }
2200
+ } ,
2201
2201
hir:: ExprKind :: Call ( ..)
2202
2202
| hir:: ExprKind :: MethodCall ( ..)
2203
2203
// These variants are debatable or require further examination
2204
2204
| hir:: ExprKind :: If ( ..)
2205
2205
| hir:: ExprKind :: Match ( ..)
2206
- | hir:: ExprKind :: Block { .. } => true ,
2206
+ | hir:: ExprKind :: Block { .. } => true ,
2207
2207
_ => false ,
2208
2208
}
2209
2209
}
@@ -3113,78 +3113,76 @@ fn lint_skip_while_next<'tcx>(
3113
3113
}
3114
3114
3115
3115
/// lint use of `filter().map()` or `find().map()` for `Iterators`
3116
- fn lint_filter_map < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx hir:: Expr < ' _ > , is_find : bool , span : Span ) {
3116
+ fn lint_filter_map < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx hir:: Expr < ' _ > , is_find : bool , target_span : Span ) {
3117
3117
if_chain ! {
3118
- if let ExprKind :: MethodCall ( _, _, [ map_recv, map_arg] , map_span) = expr. kind;
3119
- if let ExprKind :: MethodCall ( _, _, [ filter_recv, filter_arg] , filter_span) = map_recv. kind;
3120
- let _ = {
3121
- lint_filter_some_map_unwrap( cx, expr, filter_recv, filter_arg, map_arg, span) ;
3122
- } ;
3123
- if match_trait_method( cx, map_recv, & paths:: ITERATOR ) ;
3124
-
3125
- // filter(|x| ...is_some())...
3126
- if let ExprKind :: Closure ( _, _, filter_body_id, ..) = filter_arg. kind;
3127
- let filter_body = cx. tcx. hir( ) . body( filter_body_id) ;
3128
- if let [ filter_param] = filter_body. params;
3129
- // optional ref pattern: `filter(|&x| ..)`
3130
- let ( filter_pat, is_filter_param_ref) = if let PatKind :: Ref ( ref_pat, _) = filter_param. pat. kind {
3131
- ( ref_pat, true )
3132
- } else {
3133
- ( filter_param. pat, false )
3134
- } ;
3135
- // closure ends with is_some() or is_ok()
3136
- if let PatKind :: Binding ( _, filter_param_id, _, None ) = filter_pat. kind;
3137
- if let ExprKind :: MethodCall ( path, _, [ filter_arg] , _) = filter_body. value. kind;
3138
- if let Some ( opt_ty) = cx. typeck_results( ) . expr_ty( filter_arg) . ty_adt_def( ) ;
3139
- if let Some ( is_result) = if cx. tcx. is_diagnostic_item( sym:: option_type, opt_ty. did) {
3140
- Some ( false )
3141
- } else if cx. tcx. is_diagnostic_item( sym:: result_type, opt_ty. did) {
3142
- Some ( true )
3143
- } else {
3144
- None
3145
- } ;
3146
- if path. ident. name. as_str( ) == if is_result { "is_ok" } else { "is_some" } ;
3147
-
3148
- // ...map(|x| ...unwrap())
3149
- if let ExprKind :: Closure ( _, _, map_body_id, ..) = map_arg. kind;
3150
- let map_body = cx. tcx. hir( ) . body( map_body_id) ;
3151
- if let [ map_param] = map_body. params;
3152
- if let PatKind :: Binding ( _, map_param_id, map_param_ident, None ) = map_param. pat. kind;
3153
- // closure ends with expect() or unwrap()
3154
- if let ExprKind :: MethodCall ( seg, _, [ map_arg, ..] , _) = map_body. value. kind;
3155
- if matches!( seg. ident. name, sym:: expect | sym:: unwrap | sym:: unwrap_or) ;
3156
-
3157
- let eq_fallback = |a: & Expr <' _>, b: & Expr <' _>| {
3158
- // in `filter(|x| ..)`, replace `*x` with `x`
3159
- let a_path = if_chain! {
3160
- if !is_filter_param_ref;
3161
- if let ExprKind :: Unary ( UnOp :: Deref , expr_path) = a. kind;
3162
- then { expr_path } else { a }
3118
+ if let ExprKind :: MethodCall ( _, _, [ map_recv, map_arg] , map_span) = expr. kind;
3119
+ if let ExprKind :: MethodCall ( _, _, [ filter_recv, filter_arg] , filter_span) = map_recv. kind;
3120
+ let _ = lint_filter_some_map_unwrap( cx, expr, filter_recv, filter_arg, map_arg, target_span) ;
3121
+ if match_trait_method( cx, map_recv, & paths:: ITERATOR ) ;
3122
+
3123
+ // filter(|x| ...is_some())...
3124
+ if let ExprKind :: Closure ( _, _, filter_body_id, ..) = filter_arg. kind;
3125
+ let filter_body = cx. tcx. hir( ) . body( filter_body_id) ;
3126
+ if let [ filter_param] = filter_body. params;
3127
+ // optional ref pattern: `filter(|&x| ..)`
3128
+ let ( filter_pat, is_filter_param_ref) = if let PatKind :: Ref ( ref_pat, _) = filter_param. pat. kind {
3129
+ ( ref_pat, true )
3130
+ } else {
3131
+ ( filter_param. pat, false )
3163
3132
} ;
3164
- // let the filter closure arg and the map closure arg be equal
3165
- if_chain! {
3166
- if path_to_local_id( a_path, filter_param_id) ;
3167
- if path_to_local_id( b, map_param_id) ;
3168
- if TyS :: same_type( cx. typeck_results( ) . expr_ty_adjusted( a) , cx. typeck_results( ) . expr_ty_adjusted( b) ) ;
3169
- then {
3170
- return true ;
3171
- }
3172
- }
3173
- false
3174
- } ;
3175
- if SpanlessEq :: new( cx) . expr_fallback( eq_fallback) . eq_expr( filter_arg, map_arg) ;
3176
- then {
3177
- let span = filter_span. to( map_span) ;
3178
- let ( filter_name, lint) = if is_find {
3179
- ( "find" , MANUAL_FIND_MAP )
3133
+ // closure ends with is_some() or is_ok()
3134
+ if let PatKind :: Binding ( _, filter_param_id, _, None ) = filter_pat. kind;
3135
+ if let ExprKind :: MethodCall ( path, _, [ filter_arg] , _) = filter_body. value. kind;
3136
+ if let Some ( opt_ty) = cx. typeck_results( ) . expr_ty( filter_arg) . ty_adt_def( ) ;
3137
+ if let Some ( is_result) = if cx. tcx. is_diagnostic_item( sym:: option_type, opt_ty. did) {
3138
+ Some ( false )
3139
+ } else if cx. tcx. is_diagnostic_item( sym:: result_type, opt_ty. did) {
3140
+ Some ( true )
3180
3141
} else {
3181
- ( "filter" , MANUAL_FILTER_MAP )
3142
+ None
3182
3143
} ;
3183
- let msg = format!( "`{}(..).map(..)` can be simplified as `{0}_map(..)`" , filter_name) ;
3184
- let to_opt = if is_result { ".ok()" } else { "" } ;
3185
- let sugg = format!( "{}_map(|{}| {}{})" , filter_name, map_param_ident,
3186
- snippet( cx, map_arg. span, ".." ) , to_opt) ;
3187
- span_lint_and_sugg( cx, lint, span, & msg, "try" , sugg, Applicability :: MachineApplicable ) ;
3144
+ if path. ident. name. as_str( ) == if is_result { "is_ok" } else { "is_some" } ;
3145
+
3146
+ // ...map(|x| ...unwrap())
3147
+ if let ExprKind :: Closure ( _, _, map_body_id, ..) = map_arg. kind;
3148
+ let map_body = cx. tcx. hir( ) . body( map_body_id) ;
3149
+ if let [ map_param] = map_body. params;
3150
+ if let PatKind :: Binding ( _, map_param_id, map_param_ident, None ) = map_param. pat. kind;
3151
+ // closure ends with expect() or unwrap()
3152
+ if let ExprKind :: MethodCall ( seg, _, [ map_arg, ..] , _) = map_body. value. kind;
3153
+ if matches!( seg. ident. name, sym:: expect | sym:: unwrap | sym:: unwrap_or) ;
3154
+
3155
+ let eq_fallback = |a: & Expr <' _>, b: & Expr <' _>| {
3156
+ // in `filter(|x| ..)`, replace `*x` with `x`
3157
+ let a_path = if_chain! {
3158
+ if !is_filter_param_ref;
3159
+ if let ExprKind :: Unary ( UnOp :: Deref , expr_path) = a. kind;
3160
+ then { expr_path } else { a }
3161
+ } ;
3162
+ // let the filter closure arg and the map closure arg be equal
3163
+ if_chain! {
3164
+ if path_to_local_id( a_path, filter_param_id) ;
3165
+ if path_to_local_id( b, map_param_id) ;
3166
+ if TyS :: same_type( cx. typeck_results( ) . expr_ty_adjusted( a) , cx. typeck_results( ) . expr_ty_adjusted( b) ) ;
3167
+ then {
3168
+ return true ;
3169
+ }
3170
+ }
3171
+ false
3172
+ } ;
3173
+ if SpanlessEq :: new( cx) . expr_fallback( eq_fallback) . eq_expr( filter_arg, map_arg) ;
3174
+ then {
3175
+ let span = filter_span. to( map_span) ;
3176
+ let ( filter_name, lint) = if is_find {
3177
+ ( "find" , MANUAL_FIND_MAP )
3178
+ } else {
3179
+ ( "filter" , MANUAL_FILTER_MAP )
3180
+ } ;
3181
+ let msg = format!( "`{}(..).map(..)` can be simplified as `{0}_map(..)`" , filter_name) ;
3182
+ let to_opt = if is_result { ".ok()" } else { "" } ;
3183
+ let sugg = format!( "{}_map(|{}| {}{})" , filter_name, map_param_ident,
3184
+ snippet( cx, map_arg. span, ".." ) , to_opt) ;
3185
+ span_lint_and_sugg( cx, lint, span, & msg, "try" , sugg, Applicability :: MachineApplicable ) ;
3188
3186
}
3189
3187
}
3190
3188
}
@@ -3227,7 +3225,7 @@ fn is_option_filter_map<'tcx>(
3227
3225
filter_arg : & ' tcx hir:: Expr < ' _ > ,
3228
3226
map_arg : & ' tcx hir:: Expr < ' _ > ,
3229
3227
) -> bool {
3230
- is_method ( cx, map_arg, & OPTION_UNWRAP , sym ! ( unwrap) ) &&
3228
+ is_method ( cx, map_arg, & OPTION_UNWRAP , sym ! ( unwrap) ) &&
3231
3229
is_method ( cx, filter_arg, & OPTION_IS_SOME , sym ! ( is_some) )
3232
3230
}
3233
3231
@@ -4044,37 +4042,37 @@ impl ShouldImplTraitCase {
4044
4042
4045
4043
#[ rustfmt:: skip]
4046
4044
const TRAIT_METHODS : [ ShouldImplTraitCase ; 30 ] = [
4047
- ShouldImplTraitCase :: new ( "std::ops::Add" , "add" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4048
- ShouldImplTraitCase :: new ( "std::convert::AsMut" , "as_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4049
- ShouldImplTraitCase :: new ( "std::convert::AsRef" , "as_ref" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4050
- ShouldImplTraitCase :: new ( "std::ops::BitAnd" , "bitand" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4051
- ShouldImplTraitCase :: new ( "std::ops::BitOr" , "bitor" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4052
- ShouldImplTraitCase :: new ( "std::ops::BitXor" , "bitxor" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4053
- ShouldImplTraitCase :: new ( "std::borrow::Borrow" , "borrow" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4054
- ShouldImplTraitCase :: new ( "std::borrow::BorrowMut" , "borrow_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4055
- ShouldImplTraitCase :: new ( "std::clone::Clone" , "clone" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
4056
- ShouldImplTraitCase :: new ( "std::cmp::Ord" , "cmp" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
4045
+ ShouldImplTraitCase :: new ( "std::ops::Add" , "add" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4046
+ ShouldImplTraitCase :: new ( "std::convert::AsMut" , "as_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4047
+ ShouldImplTraitCase :: new ( "std::convert::AsRef" , "as_ref" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4048
+ ShouldImplTraitCase :: new ( "std::ops::BitAnd" , "bitand" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4049
+ ShouldImplTraitCase :: new ( "std::ops::BitOr" , "bitor" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4050
+ ShouldImplTraitCase :: new ( "std::ops::BitXor" , "bitxor" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4051
+ ShouldImplTraitCase :: new ( "std::borrow::Borrow" , "borrow" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4052
+ ShouldImplTraitCase :: new ( "std::borrow::BorrowMut" , "borrow_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4053
+ ShouldImplTraitCase :: new ( "std::clone::Clone" , "clone" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
4054
+ ShouldImplTraitCase :: new ( "std::cmp::Ord" , "cmp" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Any , true ) ,
4057
4055
// FIXME: default doesn't work
4058
- ShouldImplTraitCase :: new ( "std::default::Default" , "default" , 0 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
4059
- ShouldImplTraitCase :: new ( "std::ops::Deref" , "deref" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4060
- ShouldImplTraitCase :: new ( "std::ops::DerefMut" , "deref_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4061
- ShouldImplTraitCase :: new ( "std::ops::Div" , "div" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4062
- ShouldImplTraitCase :: new ( "std::ops::Drop" , "drop" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Unit , true ) ,
4063
- ShouldImplTraitCase :: new ( "std::cmp::PartialEq" , "eq" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Bool , true ) ,
4064
- ShouldImplTraitCase :: new ( "std::iter::FromIterator" , "from_iter" , 1 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
4065
- ShouldImplTraitCase :: new ( "std::str::FromStr" , "from_str" , 1 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
4066
- ShouldImplTraitCase :: new ( "std::hash::Hash" , "hash" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Unit , true ) ,
4067
- ShouldImplTraitCase :: new ( "std::ops::Index" , "index" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4068
- ShouldImplTraitCase :: new ( "std::ops::IndexMut" , "index_mut" , 2 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4069
- ShouldImplTraitCase :: new ( "std::iter::IntoIterator" , "into_iter" , 1 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4070
- ShouldImplTraitCase :: new ( "std::ops::Mul" , "mul" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4071
- ShouldImplTraitCase :: new ( "std::ops::Neg" , "neg" , 1 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4072
- ShouldImplTraitCase :: new ( "std::iter::Iterator" , "next" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Any , false ) ,
4073
- ShouldImplTraitCase :: new ( "std::ops::Not" , "not" , 1 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4074
- ShouldImplTraitCase :: new ( "std::ops::Rem" , "rem" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4075
- ShouldImplTraitCase :: new ( "std::ops::Shl" , "shl" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4076
- ShouldImplTraitCase :: new ( "std::ops::Shr" , "shr" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4077
- ShouldImplTraitCase :: new ( "std::ops::Sub" , "sub" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4056
+ ShouldImplTraitCase :: new ( "std::default::Default" , "default" , 0 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
4057
+ ShouldImplTraitCase :: new ( "std::ops::Deref" , "deref" , 1 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4058
+ ShouldImplTraitCase :: new ( "std::ops::DerefMut" , "deref_mut" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4059
+ ShouldImplTraitCase :: new ( "std::ops::Div" , "div" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4060
+ ShouldImplTraitCase :: new ( "std::ops::Drop" , "drop" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Unit , true ) ,
4061
+ ShouldImplTraitCase :: new ( "std::cmp::PartialEq" , "eq" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Bool , true ) ,
4062
+ ShouldImplTraitCase :: new ( "std::iter::FromIterator" , "from_iter" , 1 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
4063
+ ShouldImplTraitCase :: new ( "std::str::FromStr" , "from_str" , 1 , FN_HEADER , SelfKind :: No , OutType :: Any , true ) ,
4064
+ ShouldImplTraitCase :: new ( "std::hash::Hash" , "hash" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Unit , true ) ,
4065
+ ShouldImplTraitCase :: new ( "std::ops::Index" , "index" , 2 , FN_HEADER , SelfKind :: Ref , OutType :: Ref , true ) ,
4066
+ ShouldImplTraitCase :: new ( "std::ops::IndexMut" , "index_mut" , 2 , FN_HEADER , SelfKind :: RefMut , OutType :: Ref , true ) ,
4067
+ ShouldImplTraitCase :: new ( "std::iter::IntoIterator" , "into_iter" , 1 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4068
+ ShouldImplTraitCase :: new ( "std::ops::Mul" , "mul" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4069
+ ShouldImplTraitCase :: new ( "std::ops::Neg" , "neg" , 1 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4070
+ ShouldImplTraitCase :: new ( "std::iter::Iterator" , "next" , 1 , FN_HEADER , SelfKind :: RefMut , OutType :: Any , false ) ,
4071
+ ShouldImplTraitCase :: new ( "std::ops::Not" , "not" , 1 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4072
+ ShouldImplTraitCase :: new ( "std::ops::Rem" , "rem" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4073
+ ShouldImplTraitCase :: new ( "std::ops::Shl" , "shl" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4074
+ ShouldImplTraitCase :: new ( "std::ops::Shr" , "shr" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4075
+ ShouldImplTraitCase :: new ( "std::ops::Sub" , "sub" , 2 , FN_HEADER , SelfKind :: Value , OutType :: Any , true ) ,
4078
4076
] ;
4079
4077
4080
4078
#[ rustfmt:: skip]
0 commit comments