2
2
#![ warn( unused_extern_crates) ]
3
3
#![ feature( let_chains) ]
4
4
5
+ extern crate rustc_errors;
5
6
extern crate rustc_hir;
6
7
extern crate rustc_span;
7
8
8
- use clippy_utils:: { get_trait_def_id, sym, ty:: implements_trait} ;
9
+ use clippy_utils:: { get_trait_def_id, ty:: implements_trait} ;
10
+ use rustc_errors:: Applicability ;
9
11
use rustc_hir:: {
10
12
def:: Res ,
11
13
intravisit:: { walk_expr, Visitor } ,
12
14
Expr , ExprKind , Node ,
13
15
} ;
14
16
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
15
- use rustc_span:: source_map :: SourceMap ;
17
+ use rustc_span:: sym ;
16
18
use utils:: span_to_snippet_macro;
17
19
18
20
dylint_linting:: declare_late_lint! {
@@ -52,17 +54,26 @@ impl<'a, 'tcx> Visitor<'_> for ClosureVisitor<'a, 'tcx> {
52
54
let res: Res = self . cx . typeck_results ( ) . qpath_res ( & path, ex. hir_id ) ;
53
55
54
56
if let Res :: Local ( hir_id) = res {
55
- let ty = self . cx . tcx . type_of ( hir_id) ;
56
-
57
- let hir = self . cx . tcx . hir ( ) ;
58
- if let Some ( node) = hir. find ( hir_id) {
59
- if let rustc_hir:: Node :: Pat ( pat) = node {
60
- let ty = self . cx . tcx . pat_ty ( pat) ;
61
- let ty = typeck_results. pat_ty ( pat) ;
62
-
63
- implements_trait ( self . cx , ty, trait_id, args) ;
64
- self . is_valid = true ;
57
+ let parent = self . cx . tcx . hir ( ) . get_parent ( hir_id) ;
58
+ match parent {
59
+ Node :: Local ( local) => {
60
+ if let Some ( expr) = local. init {
61
+ let ty =
62
+ self . cx . tcx . typeck ( expr. hir_id . owner ) . node_type ( expr. hir_id ) ;
63
+ let implements_send = self
64
+ . cx
65
+ . tcx
66
+ . get_diagnostic_item ( sym:: Send )
67
+ . map_or ( false , |id| implements_trait ( self . cx , ty, id, & [ ] ) ) ;
68
+ let implements_sync = self
69
+ . cx
70
+ . tcx
71
+ . get_diagnostic_item ( sym:: Sync )
72
+ . map_or ( false , |id| implements_trait ( self . cx , ty, id, & [ ] ) ) ;
73
+ self . is_valid = self . is_valid && implements_send && implements_sync;
74
+ } ;
65
75
}
76
+ _ => { }
66
77
}
67
78
}
68
79
}
@@ -83,6 +94,7 @@ impl<'a, 'tcx> Visitor<'_> for Validator<'a, 'tcx> {
83
94
is_valid : true ,
84
95
} ;
85
96
closure_visitor. visit_expr ( expr) ;
97
+ self . is_valid = self . is_valid && closure_visitor. is_valid ;
86
98
}
87
99
}
88
100
_ => walk_expr ( self , ex) ,
@@ -92,11 +104,18 @@ impl<'a, 'tcx> Visitor<'_> for Validator<'a, 'tcx> {
92
104
93
105
impl < ' tcx > LateLintPass < ' tcx > for ParIter {
94
106
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
95
- if let ExprKind :: MethodCall ( path, _recv, _args, _span) = & expr. kind
96
- && ( path. ident . name == sym ! ( into_iter)
97
- || path. ident . name == sym ! ( iter)
98
- || path. ident . name == sym ! ( iter_mut) )
99
- {
107
+ if let ExprKind :: MethodCall ( path, _recv, _args, _span) = & expr. kind {
108
+ let ident_name = & path. ident . name . to_string ( ) [ ..] ;
109
+ let src_map = cx. sess ( ) . source_map ( ) ;
110
+ let mut suggestion = span_to_snippet_macro ( src_map, expr. span ) ;
111
+ match ident_name {
112
+ "into_iter" => suggestion = suggestion. replace ( "into_iter" , "into_par_iter" ) ,
113
+
114
+ "iter" => suggestion = suggestion. replace ( "iter" , "par_iter" ) ,
115
+ "iter_mut" => suggestion = suggestion. replace ( "iter_mut" , "par_iter_mut" ) ,
116
+ _ => return ,
117
+ }
118
+
100
119
let ty = cx. typeck_results ( ) . expr_ty ( expr) ;
101
120
102
121
let mut implements_par_iter = false ;
@@ -119,13 +138,11 @@ impl<'tcx> LateLintPass<'tcx> for ParIter {
119
138
if !implements_par_iter {
120
139
return ;
121
140
}
122
- dbg ! ( "implements_par_iter" ) ;
123
141
124
- // @todo check that all types inside the closures are Send and sync or Copy
142
+ // check that all types inside the closures are Send and sync or Copy
125
143
let mut validator = Validator { cx, is_valid : true } ;
126
- let hir = cx. tcx . hir ( ) ;
127
144
128
- let parent_node = hir. get_parent ( expr. hir_id ) ;
145
+ let parent_node = cx . tcx . hir ( ) . get_parent ( expr. hir_id ) ;
129
146
match parent_node {
130
147
Node :: Expr ( expr) => {
131
148
validator. visit_expr ( expr) ;
@@ -137,7 +154,18 @@ impl<'tcx> LateLintPass<'tcx> for ParIter {
137
154
return ;
138
155
}
139
156
140
- dbg ! ( "the END" ) ;
157
+ cx. struct_span_lint (
158
+ PAR_ITER ,
159
+ expr. span ,
160
+ "found iterator that can be parallelized" ,
161
+ |diag| {
162
+ diag. multipart_suggestion (
163
+ "try using a parallel iterator" ,
164
+ vec ! [ ( expr. span, suggestion) ] ,
165
+ Applicability :: MachineApplicable ,
166
+ )
167
+ } ,
168
+ ) ;
141
169
}
142
170
}
143
171
}
0 commit comments