@@ -1068,7 +1068,7 @@ fn check_for_loop_range<'a, 'tcx>(
1068
1068
1069
1069
// linting condition: we only indexed one variable, and indexed it directly
1070
1070
if visitor. indexed_indirectly . is_empty ( ) && visitor. indexed_directly . len ( ) == 1 {
1071
- let ( indexed, indexed_extent) = visitor
1071
+ let ( indexed, ( indexed_extent, indexed_ty ) ) = visitor
1072
1072
. indexed_directly
1073
1073
. into_iter ( )
1074
1074
. next ( )
@@ -1119,7 +1119,7 @@ fn check_for_loop_range<'a, 'tcx>(
1119
1119
}
1120
1120
}
1121
1121
1122
- if is_len_call ( end, indexed) {
1122
+ if is_len_call ( end, indexed) || is_end_eq_array_len ( cx , end , limits , indexed_ty ) {
1123
1123
String :: new ( )
1124
1124
} else {
1125
1125
match limits {
@@ -1207,6 +1207,28 @@ fn is_len_call(expr: &Expr, var: Name) -> bool {
1207
1207
false
1208
1208
}
1209
1209
1210
+ fn is_end_eq_array_len (
1211
+ cx : & LateContext < ' _ , ' _ > ,
1212
+ end : & Expr ,
1213
+ limits : ast:: RangeLimits ,
1214
+ indexed_ty : Ty < ' _ > ,
1215
+ ) -> bool {
1216
+ if_chain ! {
1217
+ if let ExprKind :: Lit ( ref lit) = end. node;
1218
+ if let ast:: LitKind :: Int ( end_int, _) = lit. node;
1219
+ if let ty:: TyKind :: Array ( _, arr_len_const) = indexed_ty. sty;
1220
+ if let Some ( arr_len) = arr_len_const. assert_usize( cx. tcx) ;
1221
+ then {
1222
+ return match limits {
1223
+ ast:: RangeLimits :: Closed => end_int + 1 >= arr_len. into( ) ,
1224
+ ast:: RangeLimits :: HalfOpen => end_int >= arr_len. into( ) ,
1225
+ } ;
1226
+ }
1227
+ }
1228
+
1229
+ false
1230
+ }
1231
+
1210
1232
fn check_for_loop_reverse_range < ' a , ' tcx > ( cx : & LateContext < ' a , ' tcx > , arg : & ' tcx Expr , expr : & ' tcx Expr ) {
1211
1233
// if this for loop is iterating over a two-sided range...
1212
1234
if let Some ( higher:: Range {
@@ -1678,7 +1700,7 @@ struct VarVisitor<'a, 'tcx: 'a> {
1678
1700
indexed_indirectly : FxHashMap < Name , Option < region:: Scope > > ,
1679
1701
/// subset of `indexed` of vars that are indexed directly: `v[i]`
1680
1702
/// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]`
1681
- indexed_directly : FxHashMap < Name , Option < region:: Scope > > ,
1703
+ indexed_directly : FxHashMap < Name , ( Option < region:: Scope > , Ty < ' tcx > ) > ,
1682
1704
/// Any names that are used outside an index operation.
1683
1705
/// Used to detect things like `&mut vec` used together with `vec[i]`
1684
1706
referenced : FxHashSet < Name > ,
@@ -1725,7 +1747,10 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
1725
1747
self . indexed_indirectly. insert( seqvar. segments[ 0 ] . ident. name, Some ( extent) ) ;
1726
1748
}
1727
1749
if index_used_directly {
1728
- self . indexed_directly. insert( seqvar. segments[ 0 ] . ident. name, Some ( extent) ) ;
1750
+ self . indexed_directly. insert(
1751
+ seqvar. segments[ 0 ] . ident. name,
1752
+ ( Some ( extent) , self . cx. tables. node_id_to_type( seqexpr. hir_id) ) ,
1753
+ ) ;
1729
1754
}
1730
1755
return false ; // no need to walk further *on the variable*
1731
1756
}
@@ -1734,7 +1759,10 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
1734
1759
self . indexed_indirectly. insert( seqvar. segments[ 0 ] . ident. name, None ) ;
1735
1760
}
1736
1761
if index_used_directly {
1737
- self . indexed_directly. insert( seqvar. segments[ 0 ] . ident. name, None ) ;
1762
+ self . indexed_directly. insert(
1763
+ seqvar. segments[ 0 ] . ident. name,
1764
+ ( None , self . cx. tables. node_id_to_type( seqexpr. hir_id) ) ,
1765
+ ) ;
1738
1766
}
1739
1767
return false ; // no need to walk further *on the variable*
1740
1768
}
0 commit comments