11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: msrvs:: { self , Msrv } ;
3+ use clippy_utils:: res:: { MaybeDef , MaybeQPath } ;
34use clippy_utils:: sugg:: { Sugg , has_enclosing_paren} ;
45use clippy_utils:: { SpanlessEq , sym} ;
56use rustc_ast:: { BinOpKind , LitIntType , LitKind , UnOp } ;
67use rustc_data_structures:: packed:: Pu128 ;
78use rustc_errors:: Applicability ;
89use rustc_hir:: { Expr , ExprKind } ;
910use rustc_lint:: LateContext ;
10- use rustc_middle:: ty:: { self } ;
11+ use rustc_middle:: ty:: { self , Ty } ;
1112use rustc_span:: source_map:: Spanned ;
1213
1314use super :: MANUAL_DIV_CEIL ;
@@ -16,59 +17,84 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, lhs: &
1617 let mut applicability = Applicability :: MachineApplicable ;
1718
1819 if op == BinOpKind :: Div
19- && check_int_ty_and_feature ( cx, lhs)
20- && check_int_ty_and_feature ( cx, rhs)
21- && let ExprKind :: Binary ( inner_op, inner_lhs, inner_rhs) = lhs. kind
20+ && check_int_ty_and_feature ( cx, cx. typeck_results ( ) . expr_ty ( lhs) )
21+ && check_int_ty_and_feature ( cx, cx. typeck_results ( ) . expr_ty ( rhs) )
2222 && msrv. meets ( cx, msrvs:: DIV_CEIL )
2323 {
24- // (x + (y - 1)) / y
25- if let ExprKind :: Binary ( sub_op, sub_lhs, sub_rhs) = inner_rhs. kind
26- && inner_op. node == BinOpKind :: Add
27- && sub_op. node == BinOpKind :: Sub
28- && check_literal ( sub_rhs)
29- && check_eq_expr ( cx, sub_lhs, rhs)
30- {
31- build_suggestion ( cx, expr, inner_lhs, rhs, & mut applicability) ;
32- return ;
33- }
24+ match lhs. kind {
25+ ExprKind :: Binary ( inner_op, inner_lhs, inner_rhs) => {
26+ // (x + (y - 1)) / y
27+ if let ExprKind :: Binary ( sub_op, sub_lhs, sub_rhs) = inner_rhs. kind
28+ && inner_op. node == BinOpKind :: Add
29+ && sub_op. node == BinOpKind :: Sub
30+ && check_literal ( sub_rhs)
31+ && check_eq_expr ( cx, sub_lhs, rhs)
32+ {
33+ build_suggestion ( cx, expr, inner_lhs, rhs, & mut applicability) ;
34+ return ;
35+ }
3436
35- // ((y - 1) + x) / y
36- if let ExprKind :: Binary ( sub_op, sub_lhs, sub_rhs) = inner_lhs. kind
37- && inner_op. node == BinOpKind :: Add
38- && sub_op. node == BinOpKind :: Sub
39- && check_literal ( sub_rhs)
40- && check_eq_expr ( cx, sub_lhs, rhs)
41- {
42- build_suggestion ( cx, expr, inner_rhs, rhs, & mut applicability) ;
43- return ;
44- }
37+ // ((y - 1) + x) / y
38+ if let ExprKind :: Binary ( sub_op, sub_lhs, sub_rhs) = inner_lhs. kind
39+ && inner_op. node == BinOpKind :: Add
40+ && sub_op. node == BinOpKind :: Sub
41+ && check_literal ( sub_rhs)
42+ && check_eq_expr ( cx, sub_lhs, rhs)
43+ {
44+ build_suggestion ( cx, expr, inner_rhs, rhs, & mut applicability) ;
45+ return ;
46+ }
4547
46- // (x + y - 1) / y
47- if let ExprKind :: Binary ( add_op, add_lhs, add_rhs) = inner_lhs. kind
48- && inner_op. node == BinOpKind :: Sub
49- && add_op. node == BinOpKind :: Add
50- && check_literal ( inner_rhs)
51- && check_eq_expr ( cx, add_rhs, rhs)
52- {
53- build_suggestion ( cx, expr, add_lhs, rhs, & mut applicability) ;
54- }
48+ // (x + y - 1) / y
49+ if let ExprKind :: Binary ( add_op, add_lhs, add_rhs) = inner_lhs. kind
50+ && inner_op. node == BinOpKind :: Sub
51+ && add_op. node == BinOpKind :: Add
52+ && check_literal ( inner_rhs)
53+ && check_eq_expr ( cx, add_rhs, rhs)
54+ {
55+ build_suggestion ( cx, expr, add_lhs, rhs, & mut applicability) ;
56+ }
5557
56- // (x + (Y - 1)) / Y
57- if inner_op. node == BinOpKind :: Add && differ_by_one ( inner_rhs, rhs) {
58- build_suggestion ( cx, expr, inner_lhs, rhs, & mut applicability) ;
59- }
58+ // (x + (Y - 1)) / Y
59+ if inner_op. node == BinOpKind :: Add && differ_by_one ( inner_rhs, rhs) {
60+ build_suggestion ( cx, expr, inner_lhs, rhs, & mut applicability) ;
61+ }
6062
61- // ((Y - 1) + x) / Y
62- if inner_op. node == BinOpKind :: Add && differ_by_one ( inner_lhs, rhs) {
63- build_suggestion ( cx, expr, inner_rhs, rhs, & mut applicability) ;
64- }
63+ // ((Y - 1) + x) / Y
64+ if inner_op. node == BinOpKind :: Add && differ_by_one ( inner_lhs, rhs) {
65+ build_suggestion ( cx, expr, inner_rhs, rhs, & mut applicability) ;
66+ }
6567
66- // (x - (-Y - 1)) / Y
67- if inner_op. node == BinOpKind :: Sub
68- && let ExprKind :: Unary ( UnOp :: Neg , abs_div_rhs) = rhs. kind
69- && differ_by_one ( abs_div_rhs, inner_rhs)
70- {
71- build_suggestion ( cx, expr, inner_lhs, rhs, & mut applicability) ;
68+ // (x - (-Y - 1)) / Y
69+ if inner_op. node == BinOpKind :: Sub
70+ && let ExprKind :: Unary ( UnOp :: Neg , abs_div_rhs) = rhs. kind
71+ && differ_by_one ( abs_div_rhs, inner_rhs)
72+ {
73+ build_suggestion ( cx, expr, inner_lhs, rhs, & mut applicability) ;
74+ }
75+ } ,
76+ ExprKind :: MethodCall ( method, receiver, [ next_multiple_of_arg] , _) => {
77+ // x.next_multiple_of(Y) / Y
78+ if method. ident . name == sym:: next_multiple_of
79+ && check_int_ty_and_feature ( cx, cx. typeck_results ( ) . expr_ty ( receiver) )
80+ && check_eq_expr ( cx, next_multiple_of_arg, rhs)
81+ {
82+ build_suggestion ( cx, expr, receiver, rhs, & mut applicability) ;
83+ }
84+ } ,
85+ ExprKind :: Call ( callee, [ receiver, next_multiple_of_arg] ) => {
86+ // int_type::next_multiple_of(x, Y)
87+ if let Some ( impl_ty_binder) = callee
88+ . ty_rel_def_if_named ( cx, sym:: next_multiple_of)
89+ . assoc_fn_parent ( cx)
90+ . opt_impl_ty ( cx)
91+ && check_int_ty_and_feature ( cx, impl_ty_binder. skip_binder ( ) )
92+ && check_eq_expr ( cx, next_multiple_of_arg, rhs)
93+ {
94+ build_suggestion ( cx, expr, receiver, rhs, & mut applicability) ;
95+ }
96+ } ,
97+ _ => ( ) ,
7298 }
7399 }
74100}
@@ -91,8 +117,7 @@ fn differ_by_one(small_expr: &Expr<'_>, large_expr: &Expr<'_>) -> bool {
91117 }
92118}
93119
94- fn check_int_ty_and_feature ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
95- let expr_ty = cx. typeck_results ( ) . expr_ty ( expr) ;
120+ fn check_int_ty_and_feature ( cx : & LateContext < ' _ > , expr_ty : Ty < ' _ > ) -> bool {
96121 match expr_ty. peel_refs ( ) . kind ( ) {
97122 ty:: Uint ( _) => true ,
98123 ty:: Int ( _) => cx. tcx . features ( ) . enabled ( sym:: int_roundings) ,
0 commit comments