@@ -33,12 +33,12 @@ use crate::consts::{constant, Constant};
33
33
use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
34
34
use crate :: utils:: usage:: mutated_variables;
35
35
use crate :: utils:: {
36
- contains_return, contains_ty, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait ,
37
- in_macro, is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path ,
38
- match_qpath, match_trait_method, match_type, meets_msrv, method_calls, method_chain_args, path_to_local_id , paths ,
39
- remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite ,
40
- span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, strip_pat_refs, sugg , walk_ptrs_ty_depth ,
41
- SpanlessEq ,
36
+ contains_return, contains_ty, expr_or_init , get_parent_expr, get_trait_def_id, has_iter_method, higher,
37
+ implements_trait , in_macro, is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment,
38
+ match_def_path , match_qpath, match_trait_method, match_type, meets_msrv, method_calls, method_chain_args,
39
+ path_to_local_id , paths , remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability,
40
+ snippet_with_macro_callsite , span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, strip_pat_refs,
41
+ sugg , walk_ptrs_ty_depth , SpanlessEq ,
42
42
} ;
43
43
44
44
declare_clippy_lint ! {
@@ -1709,7 +1709,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1709
1709
unnecessary_filter_map:: lint ( cx, expr, arg_lists[ 0 ] ) ;
1710
1710
filter_map_identity:: check ( cx, expr, arg_lists[ 0 ] , method_spans[ 0 ] ) ;
1711
1711
} ,
1712
- [ "count" , "map" ] => lint_suspicious_map ( cx, expr) ,
1712
+ [ "count" , "map" ] => lint_suspicious_map ( cx, expr, & arg_lists [ 1 ] [ 1 ] ) ,
1713
1713
[ "assume_init" ] => lint_maybe_uninit ( cx, & arg_lists[ 0 ] [ 0 ] , expr) ,
1714
1714
[ "unwrap_or" , arith @ ( "checked_add" | "checked_sub" | "checked_mul" ) ] => {
1715
1715
manual_saturating_arithmetic:: lint ( cx, expr, & arg_lists, & arith[ "checked_" . len ( ) ..] )
@@ -3758,15 +3758,29 @@ fn is_maybe_uninit_ty_valid(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
3758
3758
}
3759
3759
}
3760
3760
3761
- fn lint_suspicious_map ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > ) {
3762
- span_lint_and_help (
3763
- cx,
3764
- SUSPICIOUS_MAP ,
3765
- expr. span ,
3766
- "this call to `map()` won't have an effect on the call to `count()`" ,
3767
- None ,
3768
- "make sure you did not confuse `map` with `filter` or `for_each`" ,
3769
- ) ;
3761
+ fn lint_suspicious_map < ' tcx > ( cx : & LateContext < ' tcx > , expr : & hir:: Expr < ' _ > , map_arg : & ' tcx hir:: Expr < ' tcx > ) {
3762
+ let closure = expr_or_init ( cx, map_arg) ;
3763
+ if_chain ! {
3764
+ if let Some ( body_id) = cx. tcx. hir( ) . maybe_body_owned_by( closure. hir_id) ;
3765
+ let closure_body = cx. tcx. hir( ) . body( body_id) ;
3766
+ if !cx. typeck_results( ) . expr_ty( & closure_body. value) . is_unit( ) ;
3767
+ then {
3768
+ if let Some ( map_mutated_vars) = mutated_variables( & closure_body. value, cx) {
3769
+ // A variable is used mutably inside of the closure. Suppress the lint.
3770
+ if !map_mutated_vars. is_empty( ) {
3771
+ return ;
3772
+ }
3773
+ }
3774
+ span_lint_and_help(
3775
+ cx,
3776
+ SUSPICIOUS_MAP ,
3777
+ expr. span,
3778
+ "this call to `map()` won't have an effect on the call to `count()`" ,
3779
+ None ,
3780
+ "make sure you did not confuse `map` with `filter` or `for_each`" ,
3781
+ ) ;
3782
+ }
3783
+ }
3770
3784
}
3771
3785
3772
3786
const OPTION_AS_REF_DEREF_MSRV : RustcVersion = RustcVersion :: new ( 1 , 40 , 0 ) ;
0 commit comments