diff --git a/src/int/big.rs b/src/int/big.rs index e565da897..0ef3caaed 100644 --- a/src/int/big.rs +++ b/src/int/big.rs @@ -222,6 +222,10 @@ impl HInt for u128 { fn widen_mul(self, rhs: Self) -> Self::D { self.zero_widen_mul(rhs) } + + fn widen_hi(self) -> Self::D { + self.widen() << ::BITS + } } impl HInt for i128 { @@ -247,6 +251,10 @@ impl HInt for i128 { fn widen_mul(self, rhs: Self) -> Self::D { unimplemented!("signed i128 widening multiply is not used") } + + fn widen_hi(self) -> Self::D { + self.widen() << ::BITS + } } impl DInt for u256 { diff --git a/src/int/mod.rs b/src/int/mod.rs index 5f56c6b6e..e6f31c530 100644 --- a/src/int/mod.rs +++ b/src/int/mod.rs @@ -313,15 +313,17 @@ pub(crate) trait HInt: Int { /// Integer that is double the bit width of the integer this trait is implemented for type D: DInt + MinInt; + // NB: some of the below methods could have default implementations (e.g. `widen_hi`), but for + // unknown reasons this can cause infinite recursion when optimizations are disabled. See + // for context. + /// Widens (using default extension) the integer to have double bit width fn widen(self) -> Self::D; /// Widens (zero extension only) the integer to have double bit width. This is needed to get /// around problems with associated type bounds (such as `Int`) being unstable fn zero_widen(self) -> Self::D; /// Widens the integer to have double bit width and shifts the integer into the higher bits - fn widen_hi(self) -> Self::D { - self.widen() << ::BITS - } + fn widen_hi(self) -> Self::D; /// Widening multiplication with zero widening. This cannot overflow. fn zero_widen_mul(self, rhs: Self) -> Self::D; /// Widening multiplication. This cannot overflow. @@ -364,6 +366,9 @@ macro_rules! impl_h_int { fn widen_mul(self, rhs: Self) -> Self::D { self.widen().wrapping_mul(rhs.widen()) } + fn widen_hi(self) -> Self::D { + (self as $X) << ::BITS + } } )* };