compiler_builtins/int/traits.rs
1pub use crate::support::{CastFrom, CastInto, Int, MinInt};
2
3/// Trait for integers twice the bit width of another integer. This is implemented for all
4/// primitives except for `u8`, because there is not a smaller primitive.
5pub trait DInt: MinInt {
6 /// Integer that is half the bit width of the integer this trait is implemented for
7 type H: HInt<D = Self>;
8
9 /// Returns the low half of `self`
10 fn lo(self) -> Self::H;
11 /// Returns the high half of `self`
12 fn hi(self) -> Self::H;
13 /// Returns the low and high halves of `self` as a tuple
14 fn lo_hi(self) -> (Self::H, Self::H) {
15 (self.lo(), self.hi())
16 }
17 /// Constructs an integer using lower and higher half parts
18 fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {
19 lo.zero_widen() | hi.widen_hi()
20 }
21}
22
23/// Trait for integers half the bit width of another integer. This is implemented for all
24/// primitives except for `u128`, because it there is not a larger primitive.
25pub trait HInt: Int {
26 /// Integer that is double the bit width of the integer this trait is implemented for
27 type D: DInt<H = Self> + MinInt;
28
29 // NB: some of the below methods could have default implementations (e.g. `widen_hi`), but for
30 // unknown reasons this can cause infinite recursion when optimizations are disabled. See
31 // <https://github.com/rust-lang/compiler-builtins/pull/707> for context.
32
33 /// Widens (using default extension) the integer to have double bit width
34 fn widen(self) -> Self::D;
35 /// Widens (zero extension only) the integer to have double bit width. This is needed to get
36 /// around problems with associated type bounds (such as `Int<Othersign: DInt>`) being unstable
37 fn zero_widen(self) -> Self::D;
38 /// Widens the integer to have double bit width and shifts the integer into the higher bits
39 fn widen_hi(self) -> Self::D;
40 /// Widening multiplication with zero widening. This cannot overflow.
41 fn zero_widen_mul(self, rhs: Self) -> Self::D;
42 /// Widening multiplication. This cannot overflow.
43 fn widen_mul(self, rhs: Self) -> Self::D;
44}
45
46macro_rules! impl_d_int {
47 ($($X:ident $D:ident),*) => {
48 $(
49 impl DInt for $D {
50 type H = $X;
51
52 fn lo(self) -> Self::H {
53 self as $X
54 }
55 fn hi(self) -> Self::H {
56 (self >> <$X as MinInt>::BITS) as $X
57 }
58 }
59 )*
60 };
61}
62
63macro_rules! impl_h_int {
64 ($($H:ident $uH:ident $X:ident),*) => {
65 $(
66 impl HInt for $H {
67 type D = $X;
68
69 fn widen(self) -> Self::D {
70 self as $X
71 }
72 fn zero_widen(self) -> Self::D {
73 (self as $uH) as $X
74 }
75 fn zero_widen_mul(self, rhs: Self) -> Self::D {
76 self.zero_widen().wrapping_mul(rhs.zero_widen())
77 }
78 fn widen_mul(self, rhs: Self) -> Self::D {
79 self.widen().wrapping_mul(rhs.widen())
80 }
81 fn widen_hi(self) -> Self::D {
82 (self as $X) << <Self as MinInt>::BITS
83 }
84 }
85 )*
86 };
87}
88
89impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
90impl_h_int!(
91 u8 u8 u16,
92 u16 u16 u32,
93 u32 u32 u64,
94 u64 u64 u128,
95 i8 u8 i16,
96 i16 u16 i32,
97 i32 u32 i64,
98 i64 u64 i128
99);