@@ -12,7 +12,7 @@ use rustc_ast::Mutability;
12
12
use rustc_ast:: ast:: RangeLimits ;
13
13
use rustc_errors:: Applicability ;
14
14
use rustc_hir:: { BinOpKind , Expr , ExprKind , HirId , LangItem } ;
15
- use rustc_lint:: { LateContext , LateLintPass } ;
15
+ use rustc_lint:: { LateContext , LateLintPass , Lint } ;
16
16
use rustc_middle:: ty:: { self , ClauseKind , GenericArgKind , PredicatePolarity , Ty } ;
17
17
use rustc_session:: impl_lint_pass;
18
18
use rustc_span:: source_map:: Spanned ;
@@ -460,70 +460,70 @@ fn can_switch_ranges<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, original: Ra
460
460
461
461
// exclusive range plus one: `x..(y+1)`
462
462
fn check_exclusive_range_plus_one ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
463
- if expr. span . can_be_used_for_suggestions ( )
464
- && let Some ( higher:: Range {
465
- start,
466
- end : Some ( end) ,
467
- limits : RangeLimits :: HalfOpen ,
468
- } ) = higher:: Range :: hir ( expr)
469
- && let Some ( y) = y_plus_one ( cx, end)
470
- && can_switch_ranges ( cx, expr, RangeLimits :: HalfOpen , cx. typeck_results ( ) . expr_ty ( y) )
471
- {
472
- let span = expr. span ;
473
- span_lint_and_then (
474
- cx,
475
- RANGE_PLUS_ONE ,
476
- span,
477
- "an inclusive range would be more readable" ,
478
- |diag| {
479
- let start = start. map_or ( String :: new ( ) , |x| Sugg :: hir ( cx, x, "x" ) . maybe_paren ( ) . to_string ( ) ) ;
480
- let end = Sugg :: hir ( cx, y, "y" ) . maybe_paren ( ) ;
481
- match span. with_source_text ( cx, |src| src. starts_with ( '(' ) && src. ends_with ( ')' ) ) {
482
- Some ( true ) => {
483
- diag. span_suggestion ( span, "use" , format ! ( "({start}..={end})" ) , Applicability :: MaybeIncorrect ) ;
484
- } ,
485
- Some ( false ) => {
486
- diag. span_suggestion (
487
- span,
488
- "use" ,
489
- format ! ( "{start}..={end}" ) ,
490
- Applicability :: MachineApplicable , // snippet
491
- ) ;
492
- } ,
493
- None => { } ,
494
- }
495
- } ,
496
- ) ;
497
- }
463
+ check_range_switch (
464
+ cx,
465
+ expr,
466
+ RangeLimits :: HalfOpen ,
467
+ y_plus_one,
468
+ RANGE_PLUS_ONE ,
469
+ "an inclusive range would be more readable" ,
470
+ "..=" ,
471
+ ) ;
498
472
}
499
473
500
474
// inclusive range minus one: `x..=(y-1)`
501
475
fn check_inclusive_range_minus_one ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
476
+ check_range_switch (
477
+ cx,
478
+ expr,
479
+ RangeLimits :: Closed ,
480
+ y_minus_one,
481
+ RANGE_MINUS_ONE ,
482
+ "an exclusive range would be more readable" ,
483
+ ".." ,
484
+ ) ;
485
+ }
486
+
487
+ /// Check for a `kind` of range in `expr`, check for `predicate` on the end,
488
+ /// and emit the `lint` with `msg` and the `operator`.
489
+ fn check_range_switch (
490
+ cx : & LateContext < ' _ > ,
491
+ expr : & Expr < ' _ > ,
492
+ kind : RangeLimits ,
493
+ predicate : impl for < ' tcx > FnOnce ( & LateContext < ' _ > , & Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > ,
494
+ lint : & ' static Lint ,
495
+ msg : & ' static str ,
496
+ operator : & str ,
497
+ ) {
502
498
if expr. span . can_be_used_for_suggestions ( )
503
499
&& let Some ( higher:: Range {
504
500
start,
505
501
end : Some ( end) ,
506
- limits : RangeLimits :: Closed ,
502
+ limits,
507
503
} ) = higher:: Range :: hir ( expr)
508
- && let Some ( y) = y_minus_one ( cx, end)
509
- && can_switch_ranges ( cx, expr, RangeLimits :: Closed , cx. typeck_results ( ) . expr_ty ( y) )
504
+ && limits == kind
505
+ && let Some ( y) = predicate ( cx, end)
506
+ && can_switch_ranges ( cx, expr, kind, cx. typeck_results ( ) . expr_ty ( y) )
510
507
{
511
- span_lint_and_then (
512
- cx,
513
- RANGE_MINUS_ONE ,
514
- expr. span ,
515
- "an exclusive range would be more readable" ,
516
- |diag| {
517
- let start = start. map_or ( String :: new ( ) , |x| Sugg :: hir ( cx, x, "x" ) . maybe_paren ( ) . to_string ( ) ) ;
518
- let end = Sugg :: hir ( cx, y, "y" ) . maybe_paren ( ) ;
519
- diag. span_suggestion (
520
- expr. span ,
521
- "use" ,
522
- format ! ( "{start}..{end}" ) ,
523
- Applicability :: MachineApplicable , // snippet
524
- ) ;
525
- } ,
526
- ) ;
508
+ let span = expr. span ;
509
+ span_lint_and_then ( cx, lint, span, msg, |diag| {
510
+ let mut app = Applicability :: MachineApplicable ;
511
+ let start = start. map_or ( String :: new ( ) , |x| {
512
+ Sugg :: hir_with_applicability ( cx, x, "<x>" , & mut app)
513
+ . maybe_paren ( )
514
+ . to_string ( )
515
+ } ) ;
516
+ let end = Sugg :: hir_with_applicability ( cx, y, "<y>" , & mut app) . maybe_paren ( ) ;
517
+ match span. with_source_text ( cx, |src| src. starts_with ( '(' ) && src. ends_with ( ')' ) ) {
518
+ Some ( true ) => {
519
+ diag. span_suggestion ( span, "use" , format ! ( "({start}{operator}{end})" ) , app) ;
520
+ } ,
521
+ Some ( false ) => {
522
+ diag. span_suggestion ( span, "use" , format ! ( "{start}{operator}{end}" ) , app) ;
523
+ } ,
524
+ None => { } ,
525
+ }
526
+ } ) ;
527
527
}
528
528
}
529
529
@@ -610,7 +610,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
610
610
}
611
611
}
612
612
613
- fn y_plus_one < ' t > ( cx : & LateContext < ' _ > , expr : & ' t Expr < ' _ > ) -> Option < & ' t Expr < ' t > > {
613
+ fn y_plus_one < ' tcx > ( cx : & LateContext < ' _ > , expr : & Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > {
614
614
match expr. kind {
615
615
ExprKind :: Binary (
616
616
Spanned {
@@ -631,7 +631,7 @@ fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'
631
631
}
632
632
}
633
633
634
- fn y_minus_one < ' t > ( cx : & LateContext < ' _ > , expr : & ' t Expr < ' _ > ) -> Option < & ' t Expr < ' t > > {
634
+ fn y_minus_one < ' tcx > ( cx : & LateContext < ' _ > , expr : & Expr < ' tcx > ) -> Option < & ' tcx Expr < ' tcx > > {
635
635
match expr. kind {
636
636
ExprKind :: Binary (
637
637
Spanned {
0 commit comments