@@ -13,7 +13,7 @@ use rustc_ast::Mutability;
1313use rustc_ast:: ast:: RangeLimits ;
1414use rustc_errors:: Applicability ;
1515use rustc_hir:: { BinOpKind , Expr , ExprKind , HirId , LangItem , Node } ;
16- use rustc_lint:: { LateContext , LateLintPass } ;
16+ use rustc_lint:: { LateContext , LateLintPass , Lint } ;
1717use rustc_middle:: ty:: { self , ClauseKind , GenericArgKind , PredicatePolarity , Ty } ;
1818use rustc_session:: impl_lint_pass;
1919use rustc_span:: source_map:: Spanned ;
@@ -468,70 +468,70 @@ fn can_switch_ranges<'tcx>(
468468
469469// exclusive range plus one: `x..(y+1)`
470470fn 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+ ) ;
506480}
507481
508482// inclusive range minus one: `x..=(y-1)`
509483fn 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+ ) {
510506 if expr. span . can_be_used_for_suggestions ( )
511507 && let Some ( higher:: Range {
512508 start,
513509 end : Some ( end) ,
514- limits : RangeLimits :: Closed ,
510+ limits,
515511 } ) = 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) )
518515 {
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+ } ) ;
535535 }
536536}
537537
@@ -618,7 +618,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
618618 }
619619}
620620
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 > > {
622622 match expr. kind {
623623 ExprKind :: Binary (
624624 Spanned {
@@ -639,7 +639,7 @@ fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'
639639 }
640640}
641641
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 > > {
643643 match expr. kind {
644644 ExprKind :: Binary (
645645 Spanned {
0 commit comments