@@ -102,12 +102,48 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil {
102102 {
103103 build_suggestion ( cx, expr, add_lhs, div_rhs, & mut applicability) ;
104104 }
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+ }
105123 }
106124 }
107125
108126 extract_msrv_attr ! ( LateContext ) ;
109127}
110128
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+
111147fn check_int_ty_and_feature ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
112148 let expr_ty = cx. typeck_results ( ) . expr_ty ( expr) ;
113149 match expr_ty. peel_refs ( ) . kind ( ) {
0 commit comments