@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
33use clippy_utils:: source:: snippet;
44use clippy_utils:: ty:: has_iter_method;
55use 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} ;
77use rustc_ast:: ast;
88use rustc_data_structures:: fx:: { FxHashMap , FxHashSet , FxIndexMap } ;
99use rustc_errors:: Applicability ;
@@ -252,13 +252,39 @@ struct VarVisitor<'a, 'tcx> {
252252}
253253
254254impl < ' 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+
257284 if let ExprKind :: Path ( ref seqpath) = seqexpr. kind
258285 // the indexed container is referenced by a name
259286 && let QPath :: Resolved ( None , seqvar) = * seqpath
260287 && seqvar. segments . len ( ) == 1
261- && is_local_used ( self . cx , idx, self . var )
262288 {
263289 if self . prefer_mutable {
264290 self . indexed_mut . insert ( seqvar. segments [ 0 ] . ident . name ) ;
@@ -320,7 +346,7 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> {
320346 . and_then ( |def_id| self . cx . tcx . trait_of_assoc ( def_id) )
321347 && ( ( meth. ident . name == sym:: index && self . cx . tcx . lang_items ( ) . index_trait ( ) == Some ( trait_id) )
322348 || ( 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)
324350 {
325351 return ;
326352 }
0 commit comments