]> git.proxmox.com Git - rustc.git/blob - src/librustc_const_math/int.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_const_math / int.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::cmp::Ordering;
12 use syntax::attr::IntType;
13 use syntax::ast::{IntTy, UintTy};
14
15 use super::is::*;
16 use super::us::*;
17 use super::err::*;
18
19 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
20 pub enum ConstInt {
21 I8(i8),
22 I16(i16),
23 I32(i32),
24 I64(i64),
25 Isize(ConstIsize),
26 U8(u8),
27 U16(u16),
28 U32(u32),
29 U64(u64),
30 Usize(ConstUsize),
31 Infer(u64),
32 InferSigned(i64),
33 }
34 pub use self::ConstInt::*;
35
36
37 macro_rules! bounds {
38 ($($t:ident $min:ident $max:ident)*) => {
39 mod as_u64 {
40 $(
41 #[allow(dead_code)]
42 pub const $min: u64 = ::std::$t::MIN as u64;
43 #[allow(dead_code)]
44 pub const $max: u64 = ::std::$t::MAX as u64;
45 )*
46 }
47 mod as_i64 {
48 $(
49 #[allow(dead_code)]
50 pub const $min: i64 = ::std::$t::MIN as i64;
51 #[allow(dead_code)]
52 pub const $max: i64 = ::std::$t::MAX as i64;
53 )*
54 }
55 }
56 }
57
58 bounds!{
59 i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX isize IMIN IMAX
60 u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX usize UMIN UMAX
61 }
62
63 impl ConstInt {
64 /// If either value is `Infer` or `InferSigned`, try to turn the value into the type of
65 /// the other value. If both values have no type, don't do anything
66 pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {
67 let inferred = match (self, other) {
68 (InferSigned(_), InferSigned(_))
69 | (Infer(_), Infer(_)) => self, // no inference possible
70 // kindof wrong, you could have had values > I64MAX during computation of a
71 (Infer(a @ 0...as_u64::I64MAX), InferSigned(_)) => InferSigned(a as i64),
72 (Infer(_), InferSigned(_)) => return Err(ConstMathErr::NotInRange),
73 (_, InferSigned(_))
74 | (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)),
75
76 (Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8),
77 (Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16),
78 (Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32),
79 (Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64),
80 (Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
81 (Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
82 (Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8),
83 (Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16),
84 (Infer(a @ 0...as_u64::U32MAX), U32(_)) => U32(a as u32),
85 (Infer(a), U64(_)) => U64(a),
86 (Infer(a @ 0...as_u64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
87 (Infer(a), Usize(Us64(_))) => Usize(Us64(a)),
88
89 (Infer(_), _) => return Err(ConstMathErr::NotInRange),
90
91 (InferSigned(a @ as_i64::I8MIN...as_i64::I8MAX), I8(_)) => I8(a as i8),
92 (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), I16(_)) => I16(a as i16),
93 (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), I32(_)) => I32(a as i32),
94 (InferSigned(a), I64(_)) => I64(a),
95 (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), Isize(Is32(_))) => {
96 Isize(Is32(a as i32))
97 },
98 (InferSigned(a), Isize(Is64(_))) => Isize(Is64(a)),
99 (InferSigned(a @ 0...as_i64::U8MAX), U8(_)) => U8(a as u8),
100 (InferSigned(a @ 0...as_i64::U16MAX), U16(_)) => U16(a as u16),
101 (InferSigned(a @ 0...as_i64::U32MAX), U32(_)) => U32(a as u32),
102 (InferSigned(a @ 0...as_i64::I64MAX), U64(_)) => U64(a as u64),
103 (InferSigned(a @ 0...as_i64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
104 (InferSigned(a @ 0...as_i64::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
105 (InferSigned(_), _) => return Err(ConstMathErr::NotInRange),
106 _ => self, // already known types
107 };
108 Ok((inferred, other))
109 }
110
111 /// Turn this value into an `Infer` or an `InferSigned`
112 pub fn erase_type(self) -> Self {
113 match self {
114 Infer(i) => Infer(i),
115 InferSigned(i) if i < 0 => InferSigned(i),
116 I8(i) if i < 0 => InferSigned(i as i64),
117 I16(i) if i < 0 => InferSigned(i as i64),
118 I32(i) if i < 0 => InferSigned(i as i64),
119 I64(i) if i < 0 => InferSigned(i as i64),
120 Isize(Is32(i)) if i < 0 => InferSigned(i as i64),
121 Isize(Is64(i)) if i < 0 => InferSigned(i as i64),
122 InferSigned(i) => Infer(i as u64),
123 I8(i) => Infer(i as u64),
124 I16(i) => Infer(i as u64),
125 I32(i) => Infer(i as u64),
126 I64(i) => Infer(i as u64),
127 Isize(Is32(i)) => Infer(i as u64),
128 Isize(Is64(i)) => Infer(i as u64),
129 U8(i) => Infer(i as u64),
130 U16(i) => Infer(i as u64),
131 U32(i) => Infer(i as u64),
132 U64(i) => Infer(i as u64),
133 Usize(Us32(i)) => Infer(i as u64),
134 Usize(Us64(i)) => Infer(i),
135 }
136 }
137
138 /// Description of the type, not the value
139 pub fn description(&self) -> &'static str {
140 match *self {
141 Infer(_) => "not yet inferred integral",
142 InferSigned(_) => "not yet inferred signed integral",
143 I8(_) => "i8",
144 I16(_) => "i16",
145 I32(_) => "i32",
146 I64(_) => "i64",
147 Isize(_) => "isize",
148 U8(_) => "u8",
149 U16(_) => "u16",
150 U32(_) => "u32",
151 U64(_) => "u64",
152 Usize(_) => "usize",
153 }
154 }
155
156 /// Erases the type and returns a u64.
157 /// This is not the same as `-5i8 as u64` but as `-5i8 as i64 as u64`
158 pub fn to_u64_unchecked(self) -> u64 {
159 match self.erase_type() {
160 ConstInt::Infer(i) => i,
161 ConstInt::InferSigned(i) => i as u64,
162 _ => unreachable!(),
163 }
164 }
165
166 /// Converts the value to a `u32` if it's in the range 0...std::u32::MAX
167 pub fn to_u32(&self) -> Option<u32> {
168 match *self {
169 I8(v) if v >= 0 => Some(v as u32),
170 I16(v) if v >= 0 => Some(v as u32),
171 I32(v) if v >= 0 => Some(v as u32),
172 InferSigned(v)
173 | Isize(Is64(v))
174 | I64(v) if v >= 0 && v <= ::std::u32::MAX as i64 => Some(v as u32),
175 Isize(Is32(v)) if v >= 0 => Some(v as u32),
176 U8(v) => Some(v as u32),
177 U16(v) => Some(v as u32),
178 U32(v) => Some(v),
179 Infer(v)
180 | Usize(Us64(v))
181 | U64(v) if v <= ::std::u32::MAX as u64 => Some(v as u32),
182 Usize(Us32(v)) => Some(v),
183 _ => None,
184 }
185 }
186
187 /// Converts the value to a `u64` if it's >= 0
188 pub fn to_u64(&self) -> Option<u64> {
189 match *self {
190 Infer(v) => Some(v),
191 InferSigned(v) if v >= 0 => Some(v as u64),
192 I8(v) if v >= 0 => Some(v as u64),
193 I16(v) if v >= 0 => Some(v as u64),
194 I32(v) if v >= 0 => Some(v as u64),
195 I64(v) if v >= 0 => Some(v as u64),
196 Isize(Is32(v)) if v >= 0 => Some(v as u64),
197 Isize(Is64(v)) if v >= 0 => Some(v as u64),
198 U8(v) => Some(v as u64),
199 U16(v) => Some(v as u64),
200 U32(v) => Some(v as u64),
201 U64(v) => Some(v),
202 Usize(Us32(v)) => Some(v as u64),
203 Usize(Us64(v)) => Some(v),
204 _ => None,
205 }
206 }
207
208 pub fn is_negative(&self) -> bool {
209 match *self {
210 I8(v) => v < 0,
211 I16(v) => v < 0,
212 I32(v) => v < 0,
213 I64(v) => v < 0,
214 Isize(Is32(v)) => v < 0,
215 Isize(Is64(v)) => v < 0,
216 InferSigned(v) => v < 0,
217 _ => false,
218 }
219 }
220
221 /// Compares the values if they are of the same type
222 pub fn try_cmp(self, rhs: Self) -> Result<::std::cmp::Ordering, ConstMathErr> {
223 match self.infer(rhs)? {
224 (I8(a), I8(b)) => Ok(a.cmp(&b)),
225 (I16(a), I16(b)) => Ok(a.cmp(&b)),
226 (I32(a), I32(b)) => Ok(a.cmp(&b)),
227 (I64(a), I64(b)) => Ok(a.cmp(&b)),
228 (Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)),
229 (Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)),
230 (U8(a), U8(b)) => Ok(a.cmp(&b)),
231 (U16(a), U16(b)) => Ok(a.cmp(&b)),
232 (U32(a), U32(b)) => Ok(a.cmp(&b)),
233 (U64(a), U64(b)) => Ok(a.cmp(&b)),
234 (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)),
235 (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)),
236 (Infer(a), Infer(b)) => Ok(a.cmp(&b)),
237 (InferSigned(a), InferSigned(b)) => Ok(a.cmp(&b)),
238 _ => Err(CmpBetweenUnequalTypes),
239 }
240 }
241
242 /// Adds 1 to the value and wraps around if the maximum for the type is reached
243 pub fn wrap_incr(self) -> Self {
244 macro_rules! add1 {
245 ($e:expr) => { ($e).wrapping_add(1) }
246 }
247 match self {
248 ConstInt::I8(i) => ConstInt::I8(add1!(i)),
249 ConstInt::I16(i) => ConstInt::I16(add1!(i)),
250 ConstInt::I32(i) => ConstInt::I32(add1!(i)),
251 ConstInt::I64(i) => ConstInt::I64(add1!(i)),
252 ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))),
253 ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))),
254 ConstInt::U8(i) => ConstInt::U8(add1!(i)),
255 ConstInt::U16(i) => ConstInt::U16(add1!(i)),
256 ConstInt::U32(i) => ConstInt::U32(add1!(i)),
257 ConstInt::U64(i) => ConstInt::U64(add1!(i)),
258 ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))),
259 ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))),
260 ConstInt::Infer(_) | ConstInt::InferSigned(_) => panic!("no type info for const int"),
261 }
262 }
263
264 pub fn int_type(self) -> Option<IntType> {
265 match self {
266 ConstInt::I8(_) => Some(IntType::SignedInt(IntTy::I8)),
267 ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)),
268 ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)),
269 ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)),
270 ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)),
271 ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)),
272 ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)),
273 ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)),
274 ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)),
275 ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)),
276 _ => None,
277 }
278 }
279 }
280
281 impl ::std::cmp::PartialOrd for ConstInt {
282 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
283 self.try_cmp(*other).ok()
284 }
285 }
286
287 impl ::std::cmp::Ord for ConstInt {
288 fn cmp(&self, other: &Self) -> Ordering {
289 self.try_cmp(*other).unwrap()
290 }
291 }
292
293 impl ::std::fmt::Display for ConstInt {
294 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
295 match *self {
296 Infer(i) => write!(fmt, "{}", i),
297 InferSigned(i) => write!(fmt, "{}", i),
298 I8(i) => write!(fmt, "{}i8", i),
299 I16(i) => write!(fmt, "{}i16", i),
300 I32(i) => write!(fmt, "{}i32", i),
301 I64(i) => write!(fmt, "{}i64", i),
302 Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i),
303 Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i),
304 U8(i) => write!(fmt, "{}u8", i),
305 U16(i) => write!(fmt, "{}u16", i),
306 U32(i) => write!(fmt, "{}u32", i),
307 U64(i) => write!(fmt, "{}u64", i),
308 Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i),
309 Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i),
310 }
311 }
312 }
313
314 macro_rules! overflowing {
315 ($e:expr, $err:expr) => {{
316 if $e.1 {
317 return Err(Overflow($err));
318 } else {
319 $e.0
320 }
321 }}
322 }
323
324 macro_rules! impl_binop {
325 ($op:ident, $func:ident, $checked_func:ident) => {
326 impl ::std::ops::$op for ConstInt {
327 type Output = Result<Self, ConstMathErr>;
328 fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
329 match self.infer(rhs)? {
330 (I8(a), I8(b)) => a.$checked_func(b).map(I8),
331 (I16(a), I16(b)) => a.$checked_func(b).map(I16),
332 (I32(a), I32(b)) => a.$checked_func(b).map(I32),
333 (I64(a), I64(b)) => a.$checked_func(b).map(I64),
334 (Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize),
335 (Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize),
336 (U8(a), U8(b)) => a.$checked_func(b).map(U8),
337 (U16(a), U16(b)) => a.$checked_func(b).map(U16),
338 (U32(a), U32(b)) => a.$checked_func(b).map(U32),
339 (U64(a), U64(b)) => a.$checked_func(b).map(U64),
340 (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize),
341 (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize),
342 (Infer(a), Infer(b)) => a.$checked_func(b).map(Infer),
343 (InferSigned(a), InferSigned(b)) => a.$checked_func(b).map(InferSigned),
344 _ => return Err(UnequalTypes(Op::$op)),
345 }.ok_or(Overflow(Op::$op))
346 }
347 }
348 }
349 }
350
351 macro_rules! derive_binop {
352 ($op:ident, $func:ident) => {
353 impl ::std::ops::$op for ConstInt {
354 type Output = Result<Self, ConstMathErr>;
355 fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
356 match self.infer(rhs)? {
357 (I8(a), I8(b)) => Ok(I8(a.$func(b))),
358 (I16(a), I16(b)) => Ok(I16(a.$func(b))),
359 (I32(a), I32(b)) => Ok(I32(a.$func(b))),
360 (I64(a), I64(b)) => Ok(I64(a.$func(b))),
361 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))),
362 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))),
363 (U8(a), U8(b)) => Ok(U8(a.$func(b))),
364 (U16(a), U16(b)) => Ok(U16(a.$func(b))),
365 (U32(a), U32(b)) => Ok(U32(a.$func(b))),
366 (U64(a), U64(b)) => Ok(U64(a.$func(b))),
367 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))),
368 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))),
369 (Infer(a), Infer(b)) => Ok(Infer(a.$func(b))),
370 (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a.$func(b))),
371 _ => Err(UnequalTypes(Op::$op)),
372 }
373 }
374 }
375 }
376 }
377
378 impl_binop!(Add, add, checked_add);
379 impl_binop!(Sub, sub, checked_sub);
380 impl_binop!(Mul, mul, checked_mul);
381 derive_binop!(BitAnd, bitand);
382 derive_binop!(BitOr, bitor);
383 derive_binop!(BitXor, bitxor);
384
385 fn check_division(
386 lhs: ConstInt,
387 rhs: ConstInt,
388 op: Op,
389 zerr: ConstMathErr,
390 ) -> Result<(), ConstMathErr> {
391 match (lhs, rhs) {
392 (I8(_), I8(0)) => Err(zerr),
393 (I16(_), I16(0)) => Err(zerr),
394 (I32(_), I32(0)) => Err(zerr),
395 (I64(_), I64(0)) => Err(zerr),
396 (Isize(_), Isize(Is32(0))) => Err(zerr),
397 (Isize(_), Isize(Is64(0))) => Err(zerr),
398 (InferSigned(_), InferSigned(0)) => Err(zerr),
399
400 (U8(_), U8(0)) => Err(zerr),
401 (U16(_), U16(0)) => Err(zerr),
402 (U32(_), U32(0)) => Err(zerr),
403 (U64(_), U64(0)) => Err(zerr),
404 (Usize(_), Usize(Us32(0))) => Err(zerr),
405 (Usize(_), Usize(Us64(0))) => Err(zerr),
406 (Infer(_), Infer(0)) => Err(zerr),
407
408 (I8(::std::i8::MIN), I8(-1)) => Err(Overflow(op)),
409 (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)),
410 (I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)),
411 (I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)),
412 (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)),
413 (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)),
414 (InferSigned(::std::i64::MIN), InferSigned(-1)) => Err(Overflow(op)),
415
416 _ => Ok(()),
417 }
418 }
419
420 impl ::std::ops::Div for ConstInt {
421 type Output = Result<Self, ConstMathErr>;
422 fn div(self, rhs: Self) -> Result<Self, ConstMathErr> {
423 let (lhs, rhs) = self.infer(rhs)?;
424 check_division(lhs, rhs, Op::Div, DivisionByZero)?;
425 match (lhs, rhs) {
426 (I8(a), I8(b)) => Ok(I8(a/b)),
427 (I16(a), I16(b)) => Ok(I16(a/b)),
428 (I32(a), I32(b)) => Ok(I32(a/b)),
429 (I64(a), I64(b)) => Ok(I64(a/b)),
430 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))),
431 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))),
432 (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a/b)),
433
434 (U8(a), U8(b)) => Ok(U8(a/b)),
435 (U16(a), U16(b)) => Ok(U16(a/b)),
436 (U32(a), U32(b)) => Ok(U32(a/b)),
437 (U64(a), U64(b)) => Ok(U64(a/b)),
438 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))),
439 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))),
440 (Infer(a), Infer(b)) => Ok(Infer(a/b)),
441
442 _ => Err(UnequalTypes(Op::Div)),
443 }
444 }
445 }
446
447 impl ::std::ops::Rem for ConstInt {
448 type Output = Result<Self, ConstMathErr>;
449 fn rem(self, rhs: Self) -> Result<Self, ConstMathErr> {
450 let (lhs, rhs) = self.infer(rhs)?;
451 // should INT_MIN%-1 be zero or an error?
452 check_division(lhs, rhs, Op::Rem, RemainderByZero)?;
453 match (lhs, rhs) {
454 (I8(a), I8(b)) => Ok(I8(a%b)),
455 (I16(a), I16(b)) => Ok(I16(a%b)),
456 (I32(a), I32(b)) => Ok(I32(a%b)),
457 (I64(a), I64(b)) => Ok(I64(a%b)),
458 (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))),
459 (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))),
460 (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a%b)),
461
462 (U8(a), U8(b)) => Ok(U8(a%b)),
463 (U16(a), U16(b)) => Ok(U16(a%b)),
464 (U32(a), U32(b)) => Ok(U32(a%b)),
465 (U64(a), U64(b)) => Ok(U64(a%b)),
466 (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))),
467 (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))),
468 (Infer(a), Infer(b)) => Ok(Infer(a%b)),
469
470 _ => Err(UnequalTypes(Op::Rem)),
471 }
472 }
473 }
474
475 impl ::std::ops::Shl<ConstInt> for ConstInt {
476 type Output = Result<Self, ConstMathErr>;
477 fn shl(self, rhs: Self) -> Result<Self, ConstMathErr> {
478 let b = rhs.to_u32().ok_or(ShiftNegative)?;
479 match self {
480 I8(a) => Ok(I8(overflowing!(a.overflowing_shl(b), Op::Shl))),
481 I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))),
482 I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))),
483 I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))),
484 Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
485 Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
486 U8(a) => Ok(U8(overflowing!(a.overflowing_shl(b), Op::Shl))),
487 U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))),
488 U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))),
489 U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))),
490 Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
491 Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
492 Infer(a) => Ok(Infer(overflowing!(a.overflowing_shl(b), Op::Shl))),
493 InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_shl(b), Op::Shl))),
494 }
495 }
496 }
497
498 impl ::std::ops::Shr<ConstInt> for ConstInt {
499 type Output = Result<Self, ConstMathErr>;
500 fn shr(self, rhs: Self) -> Result<Self, ConstMathErr> {
501 let b = rhs.to_u32().ok_or(ShiftNegative)?;
502 match self {
503 I8(a) => Ok(I8(overflowing!(a.overflowing_shr(b), Op::Shr))),
504 I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))),
505 I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))),
506 I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shl))),
507 Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
508 Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
509 U8(a) => Ok(U8(overflowing!(a.overflowing_shr(b), Op::Shr))),
510 U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))),
511 U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))),
512 U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))),
513 Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
514 Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
515 Infer(a) => Ok(Infer(overflowing!(a.overflowing_shr(b), Op::Shr))),
516 InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_shr(b), Op::Shr))),
517 }
518 }
519 }
520
521 impl ::std::ops::Neg for ConstInt {
522 type Output = Result<Self, ConstMathErr>;
523 fn neg(self) -> Result<Self, ConstMathErr> {
524 match self {
525 I8(a) => Ok(I8(overflowing!(a.overflowing_neg(), Op::Neg))),
526 I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))),
527 I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))),
528 I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))),
529 Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))),
530 Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))),
531 U8(0) => Ok(U8(0)),
532 U16(0) => Ok(U16(0)),
533 U32(0) => Ok(U32(0)),
534 U64(0) => Ok(U64(0)),
535 Usize(Us32(0)) => Ok(Usize(Us32(0))),
536 Usize(Us64(0)) => Ok(Usize(Us64(0))),
537 U8(_) => Err(UnsignedNegation),
538 U16(_) => Err(UnsignedNegation),
539 U32(_) => Err(UnsignedNegation),
540 U64(_) => Err(UnsignedNegation),
541 Usize(_) => Err(UnsignedNegation),
542 Infer(a @ 0...as_u64::I64MAX) => Ok(InferSigned(-(a as i64))),
543 Infer(_) => Err(Overflow(Op::Neg)),
544 InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))),
545 }
546 }
547 }
548
549 impl ::std::ops::Not for ConstInt {
550 type Output = Result<Self, ConstMathErr>;
551 fn not(self) -> Result<Self, ConstMathErr> {
552 match self {
553 I8(a) => Ok(I8(!a)),
554 I16(a) => Ok(I16(!a)),
555 I32(a) => Ok(I32(!a)),
556 I64(a) => Ok(I64(!a)),
557 Isize(Is32(a)) => Ok(Isize(Is32(!a))),
558 Isize(Is64(a)) => Ok(Isize(Is64(!a))),
559 U8(a) => Ok(U8(!a)),
560 U16(a) => Ok(U16(!a)),
561 U32(a) => Ok(U32(!a)),
562 U64(a) => Ok(U64(!a)),
563 Usize(Us32(a)) => Ok(Usize(Us32(!a))),
564 Usize(Us64(a)) => Ok(Usize(Us64(!a))),
565 Infer(a) => Ok(Infer(!a)),
566 InferSigned(a) => Ok(InferSigned(!a)),
567 }
568 }
569 }