@@ -8,14 +8,15 @@ use rustc_hir as hir;
88use rustc_hir:: def:: Res ;
99use rustc_lint:: LateContext ;
1010use rustc_middle:: ty:: layout:: LayoutOf ;
11+ use rustc_span:: Symbol ;
1112
1213pub fn check (
1314 cx : & LateContext < ' _ > ,
1415 expr : & hir:: Expr < ' _ > ,
1516 arith_lhs : & hir:: Expr < ' _ > ,
1617 arith_rhs : & hir:: Expr < ' _ > ,
1718 unwrap_arg : & hir:: Expr < ' _ > ,
18- arith : & str ,
19+ arith : Symbol ,
1920) {
2021 let ty = cx. typeck_results ( ) . expr_ty ( arith_lhs) ;
2122 if !ty. is_integral ( ) {
@@ -26,42 +27,76 @@ pub fn check(
2627 return ;
2728 } ;
2829
29- if ty. is_signed ( ) {
30+ let Some ( checked_arith) = CheckedArith :: new ( arith) else {
31+ return ;
32+ } ;
33+
34+ {
3035 use self :: MinMax :: { Max , Min } ;
3136 use self :: Sign :: { Neg , Pos } ;
37+ use CheckedArith :: { Add , Mul , Sub } ;
3238
33- let Some ( sign) = lit_sign ( arith_rhs) else {
34- return ;
35- } ;
39+ if ty. is_signed ( ) {
40+ let Some ( sign) = lit_sign ( arith_rhs) else {
41+ return ;
42+ } ;
3643
37- match ( arith, sign, mm) {
38- ( "add" , Pos , Max ) | ( "add" , Neg , Min ) | ( "sub" , Neg , Max ) | ( "sub" , Pos , Min ) => ( ) ,
39- // "mul" is omitted because lhs can be negative.
40- _ => return ,
41- }
42- } else {
43- match ( mm, arith) {
44- ( MinMax :: Max , "add" | "mul" ) | ( MinMax :: Min , "sub" ) => ( ) ,
45- _ => return ,
44+ match ( & checked_arith, sign, mm) {
45+ ( Add , Pos , Max ) | ( Add , Neg , Min ) | ( Sub , Neg , Max ) | ( Sub , Pos , Min ) => ( ) ,
46+ // "mul" is omitted because lhs can be negative.
47+ _ => return ,
48+ }
49+ } else {
50+ match ( mm, & checked_arith) {
51+ ( Max , Add | Mul ) | ( Min , Sub ) => ( ) ,
52+ _ => return ,
53+ }
4654 }
4755 }
4856
4957 let mut applicability = Applicability :: MachineApplicable ;
58+ let saturating_arith = checked_arith. as_saturating ( ) ;
5059 span_lint_and_sugg (
5160 cx,
5261 super :: MANUAL_SATURATING_ARITHMETIC ,
5362 expr. span ,
5463 "manual saturating arithmetic" ,
55- format ! ( "consider using `saturating_{arith }`" ) ,
64+ format ! ( "consider using `{saturating_arith }`" ) ,
5665 format ! (
57- "{}.saturating_{arith }({})" ,
66+ "{}.{saturating_arith }({})" ,
5867 snippet_with_applicability( cx, arith_lhs. span, ".." , & mut applicability) ,
5968 snippet_with_applicability( cx, arith_rhs. span, ".." , & mut applicability) ,
6069 ) ,
6170 applicability,
6271 ) ;
6372}
6473
74+ enum CheckedArith {
75+ Add ,
76+ Sub ,
77+ Mul ,
78+ }
79+
80+ impl CheckedArith {
81+ fn new ( sym : Symbol ) -> Option < Self > {
82+ let res = match sym {
83+ sym:: checked_add => Self :: Add ,
84+ sym:: checked_sub => Self :: Sub ,
85+ sym:: checked_mul => Self :: Mul ,
86+ _ => return None ,
87+ } ;
88+ Some ( res)
89+ }
90+
91+ fn as_saturating ( & self ) -> & ' static str {
92+ match self {
93+ Self :: Add => "saturating_add" ,
94+ Self :: Sub => "saturating_sub" ,
95+ Self :: Mul => "saturating_mul" ,
96+ }
97+ }
98+ }
99+
65100#[ derive( PartialEq , Eq ) ]
66101enum MinMax {
67102 Min ,
0 commit comments