@@ -420,103 +420,84 @@ fn is_zero(expr: &Expr<'_>) -> bool {
420420 }
421421}
422422
423- fn check_custom_abs ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) {
424- if let Some ( ( cond, body, Some ( else_body) ) ) = higher:: if_block ( & expr) {
423+ /// If the expressions are not opposites, return None
424+ /// Otherwise, return true if expr2 = -expr1, false if expr1 = -expr2 and return the positive
425+ /// expression
426+ fn are_opposites < ' a > (
427+ cx : & LateContext < ' _ , ' _ > ,
428+ expr1 : & ' a Expr < ' a > ,
429+ expr2 : & ' a Expr < ' a > ,
430+ ) -> Option < ( bool , & ' a Expr < ' a > ) > {
431+ if let ExprKind :: Block (
432+ Block {
433+ stmts : [ ] ,
434+ expr : Some ( expr1_inner) ,
435+ ..
436+ } ,
437+ _,
438+ ) = & expr1. kind
439+ {
425440 if let ExprKind :: Block (
426441 Block {
427442 stmts : [ ] ,
428- expr :
429- Some ( Expr {
430- kind : ExprKind :: Unary ( UnOp :: UnNeg , else_expr) ,
431- ..
432- } ) ,
443+ expr : Some ( expr2_inner) ,
433444 ..
434445 } ,
435446 _,
436- ) = else_body . kind
447+ ) = & expr2 . kind
437448 {
438- if let ExprKind :: Block (
439- Block {
440- stmts : [ ] ,
441- expr : Some ( body) ,
442- ..
443- } ,
444- _,
445- ) = & body. kind
446- {
447- if are_exprs_equal ( cx, else_expr, body) {
448- if is_testing_positive ( cx, cond, body) {
449- span_lint_and_sugg (
450- cx,
451- SUBOPTIMAL_FLOPS ,
452- expr. span ,
453- "This looks like you've implemented your own absolute value function" ,
454- "try" ,
455- format ! ( "{}.abs()" , Sugg :: hir( cx, body, ".." ) ) ,
456- Applicability :: MachineApplicable ,
457- ) ;
458- } else if is_testing_negative ( cx, cond, body) {
459- span_lint_and_sugg (
460- cx,
461- SUBOPTIMAL_FLOPS ,
462- expr. span ,
463- "This looks like you've implemented your own negative absolute value function" ,
464- "try" ,
465- format ! ( "-{}.abs()" , Sugg :: hir( cx, body, ".." ) ) ,
466- Applicability :: MachineApplicable ,
467- ) ;
468- }
449+ if let ExprKind :: Unary ( UnOp :: UnNeg , expr1_neg) = & expr1_inner. kind {
450+ if are_exprs_equal ( cx, expr1_neg, expr2_inner) {
451+ return Some ( ( false , expr2_inner) ) ;
469452 }
470453 }
471- }
472- if let ExprKind :: Block (
473- Block {
474- stmts : [ ] ,
475- expr :
476- Some ( Expr {
477- kind : ExprKind :: Unary ( UnOp :: UnNeg , else_expr) ,
478- ..
479- } ) ,
480- ..
481- } ,
482- _,
483- ) = & body. kind
484- {
485- if let ExprKind :: Block (
486- Block {
487- stmts : [ ] ,
488- expr : Some ( body) ,
489- ..
490- } ,
491- _,
492- ) = & else_body. kind
493- {
494- if are_exprs_equal ( cx, else_expr, body) {
495- if is_testing_negative ( cx, cond, body) {
496- span_lint_and_sugg (
497- cx,
498- SUBOPTIMAL_FLOPS ,
499- expr. span ,
500- "This looks like you've implemented your own absolute value function" ,
501- "try" ,
502- format ! ( "{}.abs()" , Sugg :: hir( cx, body, ".." ) ) ,
503- Applicability :: MachineApplicable ,
504- ) ;
505- } else if is_testing_positive ( cx, cond, body) {
506- span_lint_and_sugg (
507- cx,
508- SUBOPTIMAL_FLOPS ,
509- expr. span ,
510- "This looks like you've implemented your own negative absolute value function" ,
511- "try" ,
512- format ! ( "-{}.abs()" , Sugg :: hir( cx, body, ".." ) ) ,
513- Applicability :: MachineApplicable ,
514- ) ;
515- }
454+ if let ExprKind :: Unary ( UnOp :: UnNeg , expr2_neg) = & expr2_inner. kind {
455+ if are_exprs_equal ( cx, expr1_inner, expr2_neg) {
456+ return Some ( ( true , expr1_inner) ) ;
516457 }
517458 }
518459 }
519460 }
461+ None
462+ }
463+
464+ fn check_custom_abs ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) {
465+ if let Some ( ( cond, body, Some ( else_body) ) ) = higher:: if_block ( & expr) {
466+ if let Some ( ( expr1_pos, body) ) = are_opposites ( cx, body, else_body) {
467+ let pos_abs_sugg = (
468+ "This looks like you've implemented your own absolute value function" ,
469+ format ! ( "{}.abs()" , Sugg :: hir( cx, body, ".." ) ) ,
470+ ) ;
471+ let neg_abs_sugg = (
472+ "This looks like you've implemented your own negative absolute value function" ,
473+ format ! ( "-{}.abs()" , Sugg :: hir( cx, body, ".." ) ) ,
474+ ) ;
475+ let sugg = if is_testing_positive ( cx, cond, body) {
476+ if expr1_pos {
477+ pos_abs_sugg
478+ } else {
479+ neg_abs_sugg
480+ }
481+ } else if is_testing_negative ( cx, cond, body) {
482+ if expr1_pos {
483+ neg_abs_sugg
484+ } else {
485+ pos_abs_sugg
486+ }
487+ } else {
488+ return ;
489+ } ;
490+ span_lint_and_sugg (
491+ cx,
492+ SUBOPTIMAL_FLOPS ,
493+ expr. span ,
494+ sugg. 0 ,
495+ "try" ,
496+ sugg. 1 ,
497+ Applicability :: MachineApplicable ,
498+ ) ;
499+ }
500+ }
520501}
521502
522503impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for FloatingPointArithmetic {
0 commit comments