@@ -241,14 +241,26 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
241
241
}
242
242
243
243
fn check_reversed_empty_range ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) {
244
- fn inside_indexing_expr < ' a > ( cx : & ' a LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) -> Option < & ' a Expr < ' a > > {
245
- match get_parent_expr ( cx, expr) {
246
- parent_expr @ Some ( Expr {
244
+ fn inside_indexing_expr ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) -> bool {
245
+ matches ! (
246
+ get_parent_expr( cx, expr) ,
247
+ Some ( Expr {
247
248
kind: ExprKind :: Index ( ..) ,
248
249
..
249
- } ) => parent_expr,
250
- _ => None ,
250
+ } )
251
+ )
252
+ }
253
+
254
+ fn is_for_loop_arg ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) -> bool {
255
+ let mut cur_expr = expr;
256
+ while let Some ( parent_expr) = get_parent_expr ( cx, cur_expr) {
257
+ match higher:: for_loop ( parent_expr) {
258
+ Some ( ( _, args, _) ) if args. hir_id == expr. hir_id => return true ,
259
+ _ => cur_expr = parent_expr,
260
+ }
251
261
}
262
+
263
+ false
252
264
}
253
265
254
266
fn is_empty_range ( limits : RangeLimits , ordering : Ordering ) -> bool {
@@ -267,34 +279,18 @@ fn check_reversed_empty_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
267
279
if let Some ( ordering) = Constant :: partial_cmp( cx. tcx, ty, & start_idx, & end_idx) ;
268
280
if is_empty_range( limits, ordering) ;
269
281
then {
270
- if let Some ( parent_expr) = inside_indexing_expr( cx, expr) {
271
- let ( reason, outcome) = if ordering == Ordering :: Equal {
272
- ( "empty" , "always yield an empty slice" )
273
- } else {
274
- ( "reversed" , "panic at run-time" )
275
- } ;
276
-
277
- span_lint_and_then(
278
- cx,
279
- REVERSED_EMPTY_RANGES ,
280
- expr. span,
281
- & format!( "this range is {} and using it to index a slice will {}" , reason, outcome) ,
282
- |diag| {
283
- if_chain! {
284
- if ordering == Ordering :: Equal ;
285
- if let ty:: Slice ( slice_ty) = cx. tables. expr_ty( parent_expr) . kind;
286
- then {
287
- diag. span_suggestion(
288
- parent_expr. span,
289
- "if you want an empty slice, use" ,
290
- format!( "[] as &[{}]" , slice_ty) ,
291
- Applicability :: MaybeIncorrect
292
- ) ;
293
- }
294
- }
295
- }
296
- ) ;
297
- } else {
282
+ if inside_indexing_expr( cx, expr) {
283
+ // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ...
284
+ if ordering != Ordering :: Equal {
285
+ span_lint(
286
+ cx,
287
+ REVERSED_EMPTY_RANGES ,
288
+ expr. span,
289
+ "this range is reversed and using it to index a slice will panic at run-time" ,
290
+ ) ;
291
+ }
292
+ // ... except in for loop arguments for backwards compatibility with `reverse_range_loop`
293
+ } else if ordering != Ordering :: Equal || is_for_loop_arg( cx, expr) {
298
294
span_lint_and_then(
299
295
cx,
300
296
REVERSED_EMPTY_RANGES ,
0 commit comments