@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
3
3
use clippy_utils:: source:: snippet;
4
4
use clippy_utils:: ty:: has_iter_method;
5
5
use clippy_utils:: visitors:: is_local_used;
6
- use clippy_utils:: { SpanlessEq , contains_name, higher, is_integer_const, sugg} ;
6
+ use clippy_utils:: { SpanlessEq , contains_name, higher, is_integer_const, peel_hir_expr_while , sugg} ;
7
7
use rustc_ast:: ast;
8
8
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
9
9
use rustc_errors:: Applicability ;
@@ -252,13 +252,39 @@ struct VarVisitor<'a, 'tcx> {
252
252
}
253
253
254
254
impl < ' tcx > VarVisitor < ' _ , ' tcx > {
255
- fn check ( & mut self , idx : & ' tcx Expr < ' _ > , seqexpr : & ' tcx Expr < ' _ > , expr : & ' tcx Expr < ' _ > ) -> bool {
256
- let index_used_directly = matches ! ( idx. kind, ExprKind :: Path ( _) ) ;
255
+ fn check < ' a > ( & mut self , idx : & ' tcx Expr < ' a > , seqexpr : & ' tcx Expr < ' a > , expr : & ' tcx Expr < ' _ > ) -> bool {
256
+ let mut used_cnt = 0 ;
257
+ // It is `true` if all indices are direct
258
+ let mut index_used_directly = true ;
259
+
260
+ // Handle initial index
261
+ if is_local_used ( self . cx , idx, self . var ) {
262
+ used_cnt += 1 ;
263
+ index_used_directly &= matches ! ( idx. kind, ExprKind :: Path ( _) ) ;
264
+ }
265
+ // Handle nested indices
266
+ let seqexpr = peel_hir_expr_while ( seqexpr, |e| {
267
+ if let ExprKind :: Index ( e, idx, _) = e. kind {
268
+ if is_local_used ( self . cx , idx, self . var ) {
269
+ used_cnt += 1 ;
270
+ index_used_directly &= matches ! ( idx. kind, ExprKind :: Path ( _) ) ;
271
+ }
272
+ Some ( e)
273
+ } else {
274
+ None
275
+ }
276
+ } ) ;
277
+
278
+ match used_cnt {
279
+ 0 => return true ,
280
+ n if n > 1 => self . nonindex = true , // Optimize code like `a[i][i]`
281
+ _ => { } ,
282
+ }
283
+
257
284
if let ExprKind :: Path ( ref seqpath) = seqexpr. kind
258
285
// the indexed container is referenced by a name
259
286
&& let QPath :: Resolved ( None , seqvar) = * seqpath
260
287
&& seqvar. segments . len ( ) == 1
261
- && is_local_used ( self . cx , idx, self . var )
262
288
{
263
289
if self . prefer_mutable {
264
290
self . indexed_mut . insert ( seqvar. segments [ 0 ] . ident . name ) ;
@@ -320,7 +346,7 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> {
320
346
. and_then ( |def_id| self . cx . tcx . trait_of_assoc ( def_id) )
321
347
&& ( ( meth. ident . name == sym:: index && self . cx . tcx . lang_items ( ) . index_trait ( ) == Some ( trait_id) )
322
348
|| ( meth. ident . name == sym:: index_mut && self . cx . tcx . lang_items ( ) . index_mut_trait ( ) == Some ( trait_id) ) )
323
- && !self . check ( args_1, args_0, expr)
349
+ && !self . check ( args_1, args_0, expr)
324
350
{
325
351
return ;
326
352
}
0 commit comments