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);