@@ -102,12 +102,48 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil {
102
102
{
103
103
build_suggestion ( cx, expr, add_lhs, div_rhs, & mut applicability) ;
104
104
}
105
+
106
+ // (x + (Y - 1)) / Y
107
+ if inner_op. node == BinOpKind :: Add && differ_by_one ( inner_rhs, div_rhs) {
108
+ build_suggestion ( cx, expr, inner_lhs, div_rhs, & mut applicability) ;
109
+ }
110
+
111
+ // ((Y - 1) + x) / Y
112
+ if inner_op. node == BinOpKind :: Add && differ_by_one ( inner_lhs, div_rhs) {
113
+ build_suggestion ( cx, expr, inner_rhs, div_rhs, & mut applicability) ;
114
+ }
115
+
116
+ // (x - (-Y - 1)) / Y
117
+ if inner_op. node == BinOpKind :: Sub
118
+ && let ExprKind :: Unary ( UnOp :: Neg , abs_div_rhs) = div_rhs. kind
119
+ && differ_by_one ( abs_div_rhs, inner_rhs)
120
+ {
121
+ build_suggestion ( cx, expr, inner_lhs, div_rhs, & mut applicability) ;
122
+ }
105
123
}
106
124
}
107
125
108
126
extract_msrv_attr ! ( LateContext ) ;
109
127
}
110
128
129
+ /// Checks if two expressions represent non-zero integer literals such that `small_expr + 1 ==
130
+ /// large_expr`.
131
+ fn differ_by_one ( small_expr : & Expr < ' _ > , large_expr : & Expr < ' _ > ) -> bool {
132
+ if let ExprKind :: Lit ( small) = small_expr. kind
133
+ && let ExprKind :: Lit ( large) = large_expr. kind
134
+ && let LitKind :: Int ( s, _) = small. node
135
+ && let LitKind :: Int ( l, _) = large. node
136
+ {
137
+ Some ( l. get ( ) ) == s. get ( ) . checked_add ( 1 )
138
+ } else if let ExprKind :: Unary ( UnOp :: Neg , small_inner_expr) = small_expr. kind
139
+ && let ExprKind :: Unary ( UnOp :: Neg , large_inner_expr) = large_expr. kind
140
+ {
141
+ differ_by_one ( large_inner_expr, small_inner_expr)
142
+ } else {
143
+ false
144
+ }
145
+ }
146
+
111
147
fn check_int_ty_and_feature ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
112
148
let expr_ty = cx. typeck_results ( ) . expr_ty ( expr) ;
113
149
match expr_ty. peel_refs ( ) . kind ( ) {
0 commit comments