一、源码
int_traits.rs文件定义了两个核心 trait MinInt 和 Int,为整数类型提供统一的抽象接口,并通过宏为所有原生整数类型(i8 ~ i128/u8 ~ u128)实现这些 trait。
use core::{cmp, fmt, ops};/// Minimal integer implementations needed on all integer types, including wide integers.
pub trait MinInt:Copy+ fmt::Debug+ ops::BitOr<Output = Self>+ ops::Not<Output = Self>+ ops::Shl<u32, Output = Self>
{/// Type with the same width but other signednesstype OtherSign: MinInt;/// Unsigned version of Selftype Unsigned: MinInt;/// If `Self` is a signed integerconst SIGNED: bool;/// The bitwidth of the int typeconst BITS: u32;const ZERO: Self;const ONE: Self;const MIN: Self;const MAX: Self;
}/// Access the associated `OtherSign` type from an int (helper to avoid ambiguous associated
/// types).
pub type OtherSign<I> = <I as MinInt>::OtherSign;/// Trait for some basic operations on integers
#[allow(dead_code)]
pub trait Int:MinInt+ fmt::Display+ fmt::Binary+ fmt::LowerHex+ PartialEq+ PartialOrd+ ops::AddAssign+ ops::SubAssign+ ops::BitAndAssign+ ops::BitOrAssign+ ops::BitXorAssign+ ops::ShlAssign<i32>+ ops::ShlAssign<u32>+ ops::ShrAssign<u32>+ ops::ShrAssign<i32>+ ops::Add<Output = Self>+ ops::Sub<Output = Self>+ ops::Mul<Output = Self>+ ops::Div<Output = Self>+ ops::Shl<i32, Output = Self>+ ops::Shl<u32, Output = Self>+ ops::Shr<i32, Output = Self>+ ops::Shr<u32, Output = Self>+ ops::BitXor<Output = Self>+ ops::BitAnd<Output = Self>+ cmp::Ord+ From<bool>+ CastFrom<i32>+ CastFrom<u16>+ CastFrom<u32>+ CastFrom<u8>+ CastFrom<usize>+ CastInto<i32>+ CastInto<u16>+ CastInto<u32>+ CastInto<u8>+ CastInto<usize>
{fn signed(self) -> OtherSign<Self::Unsigned>;fn unsigned(self) -> Self::Unsigned;fn from_unsigned(unsigned: Self::Unsigned) -> Self;fn abs(self) -> Self;fn from_bool(b: bool) -> Self;/// Prevents the need for excessive conversions between signed and unsignedfn logical_shr(self, other: u32) -> Self;/// Absolute difference between two integers.fn abs_diff(self, other: Self) -> Self::Unsigned;// copied from primitive integers, but put in a traitfn is_zero(self) -> bool;fn checked_add(self, other: Self) -> Option<Self>;fn checked_sub(self, other: Self) -> Option<Self>;fn wrapping_neg(self) -> Self;fn wrapping_add(self, other: Self) -> Self;fn wrapping_mul(self, other: Self) -> Self;fn wrapping_sub(self, other: Self) -> Self;fn wrapping_shl(self, other: u32) -> Self;fn wrapping_shr(self, other: u32) -> Self;fn rotate_left(self, other: u32) -> Self;fn overflowing_add(self, other: Self) -> (Self, bool);fn overflowing_sub(self, other: Self) -> (Self, bool);fn leading_zeros(self) -> u32;fn ilog2(self) -> u32;
}macro_rules! int_impl_common {($ty:ty) => {fn from_bool(b: bool) -> Self {b as $ty}fn logical_shr(self, other: u32) -> Self {Self::from_unsigned(self.unsigned().wrapping_shr(other))}fn is_zero(self) -> bool {self == Self::ZERO}fn checked_add(self, other: Self) -> Option<Self> {self.checked_add(other)}fn checked_sub(self, other: Self) -> Option<Self> {self.checked_sub(other)}fn wrapping_neg(self) -> Self {<Self>::wrapping_neg(self)}fn wrapping_add(self, other: Self) -> Self {<Self>::wrapping_add(self, other)}fn wrapping_mul(self, other: Self) -> Self {<Self>::wrapping_mul(self, other)}fn wrapping_sub(self, other: Self) -> Self {<Self>::wrapping_sub(self, other)}fn wrapping_shl(self, other: u32) -> Self {<Self>::wrapping_shl(self, other)}fn wrapping_shr(self, other: u32) -> Self {<Self>::wrapping_shr(self, other)}fn rotate_left(self, other: u32) -> Self {<Self>::rotate_left(self, other)}fn overflowing_add(self, other: Self) -> (Self, bool) {<Self>::overflowing_add(self, other)}fn overflowing_sub(self, other: Self) -> (Self, bool) {<Self>::overflowing_sub(self, other)}fn leading_zeros(self) -> u32 {<Self>::leading_zeros(self)}fn ilog2(self) -> u32 {// On our older MSRV, this resolves to the trait method. Which won't actually work,// but this is only called behind other gates.#[allow(clippy::incompatible_msrv)]<Self>::ilog2(self)}};
}macro_rules! int_impl {($ity:ty, $uty:ty) => {impl MinInt for $uty {type OtherSign = $ity;type Unsigned = $uty;const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();const SIGNED: bool = Self::MIN != Self::ZERO;const ZERO: Self = 0;const ONE: Self = 1;const MIN: Self = <Self>::MIN;const MAX: Self = <Self>::MAX;}impl Int for $uty {fn signed(self) -> $ity {self as $ity}fn unsigned(self) -> Self {self}fn abs(self) -> Self {unimplemented!()}// It makes writing macros easier if this is implemented for both signed and unsigned#[allow(clippy::wrong_self_convention)]fn from_unsigned(me: $uty) -> Self {me}fn abs_diff(self, other: Self) -> Self {self.abs_diff(other)}int_impl_common!($uty);}impl MinInt for $ity {type OtherSign = $uty;type Unsigned = $uty;const BITS: u32 = <Self as MinInt>::ZERO.count_zeros();const SIGNED: bool = Self::MIN != Self::ZERO;const ZERO: Self = 0;const ONE: Self = 1;const MIN: Self = <Self>::MIN;const MAX: Self = <Self>::MAX;}impl Int for $ity {fn signed(self) -> Self {self}fn unsigned(self) -> $uty {self as $uty}fn abs(self) -> Self {self.abs()}fn from_unsigned(me: $uty) -> Self {me as $ity}fn abs_diff(self, other: Self) -> $uty {self.abs_diff(other)}int_impl_common!($ity);}};
}int_impl!(isize, usize);
int_impl!(i8, u8);
int_impl!(i16, u16);
int_impl!(i32, u32);
int_impl!(i64, u64);
int_impl!(i128, u128);/// Trait for integers twice the bit width of another integer. This is implemented for all
/// primitives except for `u8`, because there is not a smaller primitive.
pub trait DInt: MinInt {/// Integer that is half the bit width of the integer this trait is implemented fortype H: HInt<D = Self>;/// Returns the low half of `self`fn lo(self) -> Self::H;/// Returns the high half of `self`fn hi(self) -> Self::H;/// Returns the low and high halves of `self` as a tuplefn lo_hi(self) -> (Self::H, Self::H) {(self.lo(), self.hi())}/// Constructs an integer using lower and higher half parts#[allow(unused)]fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {lo.zero_widen() | hi.widen_hi()}
}/// Trait for integers half the bit width of another integer. This is implemented for all
/// primitives except for `u128`, because it there is not a larger primitive.
pub trait HInt: Int {/// Integer that is double the bit width of the integer this trait is implemented fortype D: DInt<H = Self> + 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// <https://github.com/rust-lang/compiler-builtins/pull/707> for context./// Widens (using default extension) the integer to have double bit widthfn 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<Othersign: DInt>`) being unstablefn zero_widen(self) -> Self::D;/// Widens the integer to have double bit width and shifts the integer into the higher bits#[allow(unused)]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.fn widen_mul(self, rhs: Self) -> Self::D;
}macro_rules! impl_d_int {($($X:ident $D:ident),*) => {$(impl DInt for $D {type H = $X;fn lo(self) -> Self::H {self as $X}fn hi(self) -> Self::H {(self >> <$X as MinInt>::BITS) as $X}})*};
}macro_rules! impl_h_int {($($H:ident $uH:ident $X:ident),*) => {$(impl HInt for $H {type D = $X;fn widen(self) -> Self::D {self as $X}fn zero_widen(self) -> Self::D {(self as $uH) as $X}fn zero_widen_mul(self, rhs: Self) -> Self::D {self.zero_widen().wrapping_mul(rhs.zero_widen())}fn widen_mul(self, rhs: Self) -> Self::D {self.widen().wrapping_mul(rhs.widen())}fn widen_hi(self) -> Self::D {(self as $X) << <Self as MinInt>::BITS}})*};
}impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
impl_h_int!(u8 u8 u16,u16 u16 u32,u32 u32 u64,u64 u64 u128,i8 u8 i16,i16 u16 i32,i32 u32 i64,i64 u64 i128
);/// Trait to express (possibly lossy) casting of integers
pub trait CastInto<T: Copy>: Copy {/// By default, casts should be exact.fn cast(self) -> T;/// Call for casts that are expected to truncate.fn cast_lossy(self) -> T;
}pub trait CastFrom<T: Copy>: Copy {/// By default, casts should be exact.fn cast_from(value: T) -> Self;/// Call for casts that are expected to truncate.fn cast_from_lossy(value: T) -> Self;
}impl<T: Copy, U: CastInto<T> + Copy> CastFrom<U> for T {fn cast_from(value: U) -> Self {value.cast()}fn cast_from_lossy(value: U) -> Self {value.cast_lossy()}
}macro_rules! cast_into {($ty:ty) => {cast_into!($ty; usize, isize, u8, i8, u16, i16, u32, i32, u64, i64, u128, i128);};($ty:ty; $($into:ty),*) => {$(impl CastInto<$into> for $ty {fn cast(self) -> $into {// All we can really do to enforce casting rules is check the rules when in// debug mode.#[cfg(not(feature = "compiler-builtins"))]debug_assert!(<$into>::try_from(self).is_ok(), "failed cast from {self}");self as $into}fn cast_lossy(self) -> $into {self as $into}})*};
}macro_rules! cast_into_float {($ty:ty) => {#[cfg(f16_enabled)]cast_into_float!($ty; f16);cast_into_float!($ty; f32, f64);#[cfg(f128_enabled)]cast_into_float!($ty; f128);};($ty:ty; $($into:ty),*) => {$(impl CastInto<$into> for $ty {fn cast(self) -> $into {#[cfg(not(feature = "compiler-builtins"))]debug_assert_eq!(self as $into as $ty, self, "inexact float cast");self as $into}fn cast_lossy(self) -> $into {self as $into}})*};
}cast_into!(usize);
cast_into!(isize);
cast_into!(u8);
cast_into!(i8);
cast_into!(u16);
cast_into!(i16);
cast_into!(u32);
cast_into!(i32);
cast_into!(u64);
cast_into!(i64);
cast_into!(u128);
cast_into!(i128);cast_into_float!(i8);
cast_into_float!(i16);
cast_into_float!(i32);
cast_into_float!(i64);
cast_into_float!(i128);
- 核心 Trait:MinInt
定义整数类型的最小通用操作集合:
pub trait MinInt: Copy + Debug + BitOr + Not + Shl<u32> {type OtherSign: MinInt; // 同宽度的相反符号类型(如 `i32` 的 `OtherSign` 是 `u32`)type Unsigned: MinInt; // 无符号版本const SIGNED: bool; // 是否为有符号整数const BITS: u32; // 位数(如 `i32` 是 32)const ZERO: Self; // 0 值const ONE: Self; // 1 值const MIN: Self; // 最小值const MAX: Self; // 最大值
}
- 扩展 Trait:Int
在 MinInt 基础上扩展更多操作:
pub trait Int: MinInt + Display + Binary + AddAssign + ... {fn signed(self) -> OtherSign<Self::Unsigned>; // 转为有符号类型fn unsigned(self) -> Self::Unsigned; // 转为无符号类型fn abs(self) -> Self; // 绝对值// 位操作fn logical_shr(self, other: u32) -> Self; // 逻辑右移(高位补 0)fn rotate_left(self, other: u32) -> Self; // 循环左移// 溢出安全运算fn wrapping_add(self, other: Self) -> Self;fn checked_mul(self, other: Self) -> Option<Self>;// 工具方法fn leading_zeros(self) -> u32;fn ilog2(self) -> u32;
}
- 宏实现
通过宏 int_impl! 为所有原生整数类型实现 MinInt 和 Int:
int_impl!(i32, u32); // 为 i32/u32 生成实现
宏展开后:
-
为 u32 实现 MinInt,关联 OtherSign = i32。
-
为 i32 实现 MinInt,关联 OtherSign = u32。
-
实现所有 Int 方法(委托给原生整数的方法,如 u32::wrapping_add)。
- 宽/窄整数 Trait
DInt(双宽度整数)
pub trait DInt: MinInt {type H: HInt<D = Self>; // 半宽度类型(如 `u64` 的 `H` 是 `u32`)fn lo(self) -> Self::H; // 取低半部分fn hi(self) -> Self::H; // 取高半部分fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self; // 合并高低部分
}
HInt(半宽度整数)
pub trait HInt: Int {type D: DInt<H = Self>; // 双宽度类型(如 `u32` 的 `D` 是 `u64`)fn widen(self) -> Self::D; // 符号扩展fn zero_widen(self) -> Self::D; // 零扩展fn widen_mul(self, rhs: Self) -> Self::D; // 扩展乘法
}
宏实现
impl_d_int!(u32 u64); // 为 u64 实现 DInt,关联 H = u32
impl_h_int!(u32 u32 u64); // 为 u32 实现 HInt,关联 D = u64
- 类型转换 Trait
CastInto/CastFrom
提供安全的类型转换接口:
pub trait CastInto<T: Copy>: Copy {fn cast(self) -> T; // 精确转换(失败时 debug 断言)fn cast_lossy(self) -> T; // 允许截断
}// 为所有整数实现 CastInto
cast_into!(u32; u8, u16, u64); // u32 可转换为 u8/u16/u64
二、设计亮点
-
统一抽象:通过 trait 为所有整数类型提供一致接口。
-
零成本:宏展开后直接调用原生整数操作,无运行时开销。
-
类型安全:
-
严格区分有/无符号类型(通过 OtherSign)。
-
转换方法提供编译时检查。
- 扩展性:支持自定义整数类型实现这些 trait。
###三、使用示例
let x: u32 = 42;
let y: i32 = x.signed(); // 转为有符号
let z: u64 = x.zero_widen(); // 零扩展为 u64let (lo, hi) = 0x12345678u32.lo_hi(); // 拆分为低 16 位和高 16 位
三、总结
这段代码是数学库的基础设施,通过 trait 和宏实现了:
-
整数类型的通用操作抽象。
-
安全且高效的类型转换。
-
宽/窄整数的互操作。
为上层算法(如浮点数解析、大数运算)提供了类型安全的底层支持。