@@ -2,19 +2,18 @@ use clippy_utils::consts::{constant, Constant};
2
2
use clippy_utils:: diagnostics:: span_lint_and_then;
3
3
use clippy_utils:: higher:: IfLet ;
4
4
use clippy_utils:: ty:: implements_trait;
5
- use clippy_utils:: { in_macro, is_expn_of, is_lint_allowed, meets_msrv, msrvs} ;
5
+ use clippy_utils:: { in_macro, is_expn_of, is_lint_allowed, meets_msrv, msrvs, path_to_local } ;
6
6
use if_chain:: if_chain;
7
7
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
8
use rustc_errors:: Applicability ;
9
9
use rustc_hir as hir;
10
+ use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
10
11
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
11
- use rustc_middle:: mir :: FakeReadCause ;
12
+ use rustc_middle:: hir :: map :: Map ;
12
13
use rustc_middle:: ty;
13
14
use rustc_semver:: RustcVersion ;
14
15
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
15
- use rustc_span:: { symbol:: Ident , Span , Symbol } ;
16
- use rustc_trait_selection:: infer:: TyCtxtInferExt ;
17
- use rustc_typeck:: expr_use_visitor:: { Delegate , ExprUseVisitor , Place , PlaceBase , PlaceWithHirId } ;
16
+ use rustc_span:: { symbol:: Ident , Span } ;
18
17
use std:: convert:: TryInto ;
19
18
20
19
declare_clippy_lint ! {
@@ -89,24 +88,23 @@ impl LateLintPass<'_> for AvoidableSliceIndexing {
89
88
}
90
89
91
90
fn find_slice_values ( cx : & LateContext < ' _ > , pat : & hir:: Pat < ' _ > ) -> Option < FxHashMap < hir:: HirId , SliceLintInformation > > {
92
- let mut removed_pat: FxHashSet < Symbol > = FxHashSet :: default ( ) ;
93
- let mut ident_to_id: FxHashMap < Symbol , hir:: HirId > = FxHashMap :: default ( ) ;
91
+ let mut removed_pat: FxHashSet < hir:: HirId > = FxHashSet :: default ( ) ;
94
92
let mut slices: FxHashMap < hir:: HirId , SliceLintInformation > = FxHashMap :: default ( ) ;
95
93
pat. walk_always ( |pat| {
96
- if let hir:: PatKind :: Binding ( binding, _ , ident, sub_pat) = pat. kind {
94
+ if let hir:: PatKind :: Binding ( binding, value_hir_id , ident, sub_pat) = pat. kind {
97
95
// We'll just ignore mut and ref mut for simplicity sake right now
98
96
if let hir:: BindingAnnotation :: Mutable | hir:: BindingAnnotation :: RefMut = binding {
99
97
return ;
100
98
}
101
99
102
100
// This block catches bindings with sub patterns. It would be hard to build a correct suggestion
103
101
// for them and it's likely that the user knows what they are doing in such a case.
104
- if removed_pat. contains ( & ident . name ) {
102
+ if removed_pat. contains ( & value_hir_id ) {
105
103
return ;
106
104
}
107
105
if sub_pat. is_some ( ) {
108
- removed_pat. insert ( ident . name ) ;
109
- ident_to_id . remove ( & ident . name ) . map ( |key| slices. remove ( & key ) ) ;
106
+ removed_pat. insert ( value_hir_id ) ;
107
+ slices. remove ( & value_hir_id ) ;
110
108
return ;
111
109
}
112
110
@@ -121,9 +119,8 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> Option<FxHashM
121
119
. copy_trait ( )
122
120
. map_or ( false , |trait_id| implements_trait ( cx, inner_ty, trait_id, & [ ] ) ) ;
123
121
124
- let key = * ident_to_id. entry ( ident. name ) . or_insert ( pat. hir_id ) ;
125
122
let slice_info = slices
126
- . entry ( key )
123
+ . entry ( value_hir_id )
127
124
. or_insert_with ( || SliceLintInformation :: new ( ident, needs_ref) ) ;
128
125
slice_info. pattern_spans . push ( pat. span ) ;
129
126
}
@@ -209,23 +206,21 @@ impl SliceLintInformation {
209
206
}
210
207
}
211
208
212
- fn filter_lintable_slices (
213
- cx : & LateContext < ' _ > ,
209
+ fn filter_lintable_slices < ' a , ' tcx > (
210
+ cx : & ' a LateContext < ' tcx > ,
214
211
slice_lint_info : FxHashMap < hir:: HirId , SliceLintInformation > ,
215
212
index_limit : u64 ,
216
- scope : & hir:: Expr < ' _ > ,
213
+ scope : & ' tcx hir:: Expr < ' tcx > ,
217
214
) -> Option < FxHashMap < hir:: HirId , SliceLintInformation > > {
218
- let mut v = SliceIndexLintingDelegate {
215
+ let mut visitor = SliceIndexLintingDelegate {
219
216
cx,
220
217
slice_lint_info,
221
218
index_limit,
222
219
} ;
223
220
224
- cx. tcx . infer_ctxt ( ) . enter ( |infcx| {
225
- ExprUseVisitor :: new ( & mut v, & infcx, scope. hir_id . owner , cx. param_env , cx. typeck_results ( ) ) . consume_expr ( scope) ;
226
- } ) ;
221
+ intravisit:: walk_expr ( & mut visitor, scope) ;
227
222
228
- let slices: FxHashMap < hir:: HirId , SliceLintInformation > = v
223
+ let slices: FxHashMap < hir:: HirId , SliceLintInformation > = visitor
229
224
. slice_lint_info
230
225
. drain ( )
231
226
. filter ( |( _key, value) | !value. index_use . is_empty ( ) )
@@ -239,54 +234,45 @@ struct SliceIndexLintingDelegate<'a, 'tcx> {
239
234
index_limit : u64 ,
240
235
}
241
236
242
- impl < ' a , ' tcx > SliceIndexLintingDelegate < ' a , ' tcx > {
243
- fn check_place ( & mut self , place : & PlaceWithHirId < ' tcx > , hir_id : hir:: HirId ) {
244
- if let PlaceBase :: Local ( slice_id) = place. place . base {
245
- if !self . slice_lint_info . contains_key ( & slice_id) {
246
- return ;
247
- }
237
+ impl < ' a , ' tcx > Visitor < ' tcx > for SliceIndexLintingDelegate < ' a , ' tcx > {
238
+ type Map = Map < ' tcx > ;
248
239
249
- // Get the parent expression
250
- let map = self . cx . tcx . hir ( ) ;
251
- let parent_id = map. get_parent_node ( hir_id) ;
252
- let parent_expr = if let Some ( hir:: Node :: Expr ( parent_expr) ) = map. find ( parent_id) {
253
- parent_expr
254
- } else {
255
- return ;
256
- } ;
240
+ fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
241
+ NestedVisitorMap :: OnlyBodies ( self . cx . tcx . hir ( ) )
242
+ }
257
243
258
- // Checking for slice indexing
244
+ fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
245
+ if let Some ( local_id) = path_to_local ( expr) {
259
246
if_chain ! {
260
- if let hir:: ExprKind :: AddrOf ( _kind, _mut, inner_expr) = parent_expr. kind;
261
- if let hir:: ExprKind :: Index ( _, index_expr) = inner_expr. kind;
247
+ // Check if this is even a local we're interested in
248
+ if self . slice_lint_info. contains_key( & local_id) ;
249
+
250
+ let map = self . cx. tcx. hir( ) ;
251
+
252
+ // Checking for slice indexing
253
+ let parent_id = map. get_parent_node( expr. hir_id) ;
254
+ if let Some ( hir:: Node :: Expr ( parent_expr) ) = map. find( parent_id) ;
255
+ if let hir:: ExprKind :: Index ( _, index_expr) = parent_expr. kind;
262
256
if let Some ( ( Constant :: Int ( index_value) , _) ) = constant( self . cx, self . cx. typeck_results( ) , index_expr) ;
263
257
if let Ok ( index_value) = index_value. try_into( ) ;
264
258
if index_value < self . index_limit;
265
- if let Some ( use_info) = self . slice_lint_info. get_mut( & slice_id) ;
259
+
260
+ // Make sure that this slice index is read only
261
+ let maybe_addrof_id = map. get_parent_node( parent_id) ;
262
+ if let Some ( hir:: Node :: Expr ( maybe_addrof_expr) ) = map. find( maybe_addrof_id) ;
263
+ if let hir:: ExprKind :: AddrOf ( _kind, hir:: Mutability :: Not , _inner_expr) = maybe_addrof_expr. kind;
264
+
265
+ // Get info to later lint this exporession
266
+ if let Some ( use_info) = self . slice_lint_info. get_mut( & local_id) ;
266
267
then {
267
268
use_info. index_use. push( ( index_value, map. span( parent_expr. hir_id) ) ) ;
268
269
return ;
269
270
}
270
271
}
271
272
272
273
// The slice was used for something else than indexing
273
- self . slice_lint_info . remove ( & slice_id ) ;
274
+ self . slice_lint_info . remove ( & local_id ) ;
274
275
}
276
+ intravisit:: walk_expr ( self , expr) ;
275
277
}
276
278
}
277
-
278
- impl < ' a , ' tcx > Delegate < ' tcx > for SliceIndexLintingDelegate < ' a , ' tcx > {
279
- fn consume ( & mut self , place : & PlaceWithHirId < ' tcx > , expr_id : hir:: HirId ) {
280
- self . check_place ( place, expr_id) ;
281
- }
282
-
283
- fn borrow ( & mut self , place : & PlaceWithHirId < ' tcx > , expr_id : hir:: HirId , _bk : ty:: BorrowKind ) {
284
- self . check_place ( place, expr_id) ;
285
- }
286
-
287
- fn mutate ( & mut self , place : & PlaceWithHirId < ' tcx > , expr_id : hir:: HirId ) {
288
- self . check_place ( place, expr_id) ;
289
- }
290
-
291
- fn fake_read ( & mut self , _place : Place < ' tcx > , _cause : FakeReadCause , _diag_expr_id : hir:: HirId ) { }
292
- }
0 commit comments