clippy_utilities/
arithmetic.rs

1//! A trait for overflowing arithmetic
2
3use crate::conversion::NumericCast;
4use std::any::type_name;
5
6/// Macros for checking arithmetic overflow, panicing when overflow happens.
7macro_rules! impl_overflow_arithmetic {
8    ($target: ty) => {
9        #[allow(clippy::use_self)]
10        impl OverflowArithmetic for $target {
11            #[inline]
12            fn overflow_add(self, other: Self) -> Self {
13                let (res, overflow) = self.overflowing_add(other);
14                assert!(
15                    !overflow,
16                    "number = {}({}) add number = {}({}) overflowed",
17                    self,
18                    type_name::<Self>(),
19                    other,
20                    type_name::<Self>()
21                );
22                res
23            }
24
25            #[inline]
26            fn overflow_sub(self, other: Self) -> Self {
27                let (res, overflow) = self.overflowing_sub(other);
28                assert!(
29                    !overflow,
30                    "number = {}({}) substract number = {}({}) overflowed",
31                    self,
32                    type_name::<Self>(),
33                    other,
34                    type_name::<Self>()
35                );
36                res
37            }
38
39            #[inline]
40            fn overflow_mul(self, other: Self) -> Self {
41                let (res, overflow) = self.overflowing_mul(other);
42                assert!(
43                    !overflow,
44                    "number = {}({}) multiply number = {}({}) overflowed",
45                    self,
46                    type_name::<Self>(),
47                    other,
48                    type_name::<Self>()
49                );
50                res
51            }
52
53            #[inline]
54            fn overflow_div(self, other: Self) -> Self {
55                let (res, overflow) = self.overflowing_div(other);
56                assert!(
57                    !overflow,
58                    "number = {}({}) divide number = {}({}) overflowed",
59                    self,
60                    type_name::<Self>(),
61                    other,
62                    type_name::<Self>()
63                );
64                res
65            }
66
67            #[inline]
68            fn overflow_shl(self, other: Self) -> Self {
69                let (res, overflow) = self.overflowing_shl(other.numeric_cast());
70                assert!(
71                    !overflow,
72                    "number = {}({}) left shift number = {}({}) overflowed",
73                    self,
74                    type_name::<Self>(),
75                    other,
76                    type_name::<Self>()
77                );
78                res
79            }
80
81            #[inline]
82            fn overflow_shr(self, other: Self) -> Self {
83                let (res, overflow) = self.overflowing_shr(other.numeric_cast());
84                assert!(
85                    !overflow,
86                    "number = {}({}) right shift number = {}({}) overflowed",
87                    self,
88                    type_name::<Self>(),
89                    other,
90                    type_name::<Self>()
91                );
92                res
93            }
94
95            #[inline]
96            fn overflow_neg(self) -> Self {
97                let (res, overflow) = self.overflowing_neg();
98                assert!(
99                    !overflow,
100                    "number = {}({}) negate overflowed",
101                    self,
102                    type_name::<Self>(),
103                );
104                res
105            }
106
107            #[inline]
108            fn overflow_rem(self, other: Self) -> Self {
109                let (res, overflow) = self.overflowing_rem(other.numeric_cast());
110                assert!(
111                    !overflow,
112                    "number = {}({}) remainder number = {}({}) overflowed",
113                    self,
114                    type_name::<Self>(),
115                    other,
116                    type_name::<Self>()
117                );
118                res
119            }
120        }
121    };
122}
123
124impl_overflow_arithmetic!(u8);
125impl_overflow_arithmetic!(u16);
126impl_overflow_arithmetic!(u32);
127impl_overflow_arithmetic!(u64);
128impl_overflow_arithmetic!(u128);
129impl_overflow_arithmetic!(i8);
130impl_overflow_arithmetic!(i16);
131impl_overflow_arithmetic!(i32);
132impl_overflow_arithmetic!(i64);
133impl_overflow_arithmetic!(i128);
134impl_overflow_arithmetic!(usize);
135impl_overflow_arithmetic!(isize);
136
137/// A type cast trait used to do the integer arithmetic.
138pub trait OverflowArithmetic {
139    /// Overflow add.
140    #[must_use]
141    fn overflow_add(self, other: Self) -> Self;
142
143    /// Overflow sub.
144    #[must_use]
145    fn overflow_sub(self, other: Self) -> Self;
146
147    /// Overflow mul.
148    #[must_use]
149    fn overflow_mul(self, other: Self) -> Self;
150
151    /// Overflow div.
152    #[must_use]
153    fn overflow_div(self, other: Self) -> Self;
154
155    /// Overflow shl.
156    #[must_use]
157    fn overflow_shl(self, other: Self) -> Self;
158
159    /// Overflow shr.
160    #[must_use]
161    fn overflow_shr(self, other: Self) -> Self;
162
163    /// Overflow neg.
164    #[must_use]
165    fn overflow_neg(self) -> Self;
166
167    /// Overflow rem.
168    #[must_use]
169    fn overflow_rem(self, other: Self) -> Self;
170}