@@ -55,15 +55,16 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
5555 return ;
5656 }
5757
58- if let ExprKind :: Binary ( op1, .. ) = expr. kind
58+ if let ExprKind :: Binary ( op1, expr1 , right ) = expr. kind
5959 && op1. node == BinOpKind :: Rem
60- && let Some ( ( const1, expr1 ) ) = check_for_positive_int_constant ( cx, expr , false )
61- && let ExprKind :: Binary ( op2, .. ) = expr1. kind
60+ && let Some ( const1) = check_for_unsigned_int_constant ( cx, right )
61+ && let ExprKind :: Binary ( op2, left , right ) = expr1. kind
6262 && op2. node == BinOpKind :: Add
63- && let Some ( ( const2, expr2) ) = check_for_positive_int_constant ( cx, expr1 , true )
64- && let ExprKind :: Binary ( op3, .. ) = expr2. kind
63+ && let Some ( ( const2, expr2) ) = check_for_either_unsigned_int_constant ( cx, left , right )
64+ && let ExprKind :: Binary ( op3, expr3 , right ) = expr2. kind
6565 && op3. node == BinOpKind :: Rem
66- && let Some ( ( const3, expr3) ) = check_for_positive_int_constant ( cx, expr2, false )
66+ && let Some ( const3) = check_for_unsigned_int_constant ( cx, right)
67+ // Also ensures the const is nonzero since zero can't be a divisor
6768 && const1 == const2 && const2 == const3
6869 && let Some ( hir_id) = path_to_local ( expr3)
6970 && let Some ( Node :: Binding ( _) ) = cx. tcx . hir ( ) . find ( hir_id) {
@@ -96,33 +97,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
9697 extract_msrv_attr ! ( LateContext ) ;
9798}
9899
99- // Takes a binary expression and separates the operands into the int constant and the other
100- // operand. Ensures the int constant is positive. Operators that are not commutative must have the
101- // constant appear on the right hand side to return a value.
102- fn check_for_positive_int_constant < ' a > (
100+ // Checks if either the left or right expressions can be an unsigned int constant and returns that
101+ // constant along with the other expression unchanged if so
102+ fn check_for_either_unsigned_int_constant < ' a > (
103103 cx : & ' a LateContext < ' _ > ,
104- expr : & ' a Expr < ' _ > ,
105- is_commutative : bool ,
104+ left : & ' a Expr < ' _ > ,
105+ right : & ' a Expr < ' _ > ,
106106) -> Option < ( u128 , & ' a Expr < ' a > ) > {
107- let ( int_const, other_op) = if let ExprKind :: Binary ( _, left, right) = expr. kind {
108- if let Some ( int_const) = constant_full_int ( cx, cx. typeck_results ( ) , right) {
109- ( int_const, left)
110- } else if is_commutative && let Some ( int_const) = constant_full_int ( cx, cx. typeck_results ( ) , left) {
111- ( int_const, right)
112- } else {
113- return None ;
114- }
115- } else {
116- return None ;
117- } ;
107+ check_for_unsigned_int_constant ( cx, left)
108+ . map ( |int_const| ( int_const, right) )
109+ . or_else ( || check_for_unsigned_int_constant ( cx, right) . map ( |int_const| ( int_const, left) ) )
110+ }
118111
119- if int_const > FullInt :: S ( 0 ) {
120- let val = match int_const {
121- FullInt :: S ( s) => s. try_into ( ) . ok ( ) ?,
122- FullInt :: U ( u) => u,
123- } ;
124- Some ( ( val, other_op) )
125- } else {
126- None
112+ fn check_for_unsigned_int_constant < ' a > ( cx : & ' a LateContext < ' _ > , expr : & ' a Expr < ' _ > ) -> Option < u128 > {
113+ let Some ( int_const) = constant_full_int ( cx, cx. typeck_results ( ) , expr) else { return None } ;
114+ match int_const {
115+ FullInt :: S ( s) => s. try_into ( ) . ok ( ) ,
116+ FullInt :: U ( u) => Some ( u) ,
127117 }
128118}
0 commit comments