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