1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
/// `==` 和 `!=` 等价于比较它们的底层字节的类型。
///
/// 重要的是,这意味着没有浮点类型,因为它们具有不同的字节表示 (如 `-0` 和 `+0`),它们比较相同。
/// 由于字节数组是 `Eq`,这意味着这些类型可能也是 `Eq`,但这在技术上并不是使用此 trait 所必需的。
///
/// `Rhs`*事实上*总是 `Self`,但单独的参数对于避免在使用它时出现 `specializing impl repeats parameter` 错误很重要。
///
///
/// # Safety
///
/// - `Self` 和 `Rhs` 没有填充。
/// - `Self` 和 `Rhs` 具有相同的布局 (大小和对齐方式)。
/// - `Self` 和 `Rhs` 都没有出处,因此整数比较是正确的。
/// - `<Self as PartialEq<Rhs>>::{eq,ne}` 相当于比较字节。
///
///
#[rustc_specialization_trait]
pub(crate) unsafe trait BytewiseEq<Rhs = Self>: PartialEq<Rhs> + Sized {}
macro_rules! is_bytewise_comparable {
($($t:ty),+ $(,)?) => {$(
unsafe impl BytewiseEq for $t {}
)+};
}
// SAFETY: 所有普通整数类型都没有填充,也不是指针。
is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
// SAFETY: 这些有*niches*,但没有*padding*也没有*provenance*,所以我们可以直接比较它们。
//
is_bytewise_comparable!(bool, char, super::Ordering);
// SAFETY: 类似地,非零类型有一个 niche,但没有 undef 和指针,它们比较像它们的底层数字类型。
//
is_bytewise_comparable!(
NonZeroU8,
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroU128,
NonZeroUsize,
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroI128,
NonZeroIsize,
);
// SAFETY: NonZero 类型保证了 "null" 优化,因此在 `Option` 中按位进行相等比较也是安全的。
// 为 `Option` 定义 `PartialOrd` 的方式意味着这对有符号类型的 `<` 或 `>` 不起作用,但因为我们只做 `==`,所以很好。
//
//
is_bytewise_comparable!(
Option<NonZeroU8>,
Option<NonZeroU16>,
Option<NonZeroU32>,
Option<NonZeroU64>,
Option<NonZeroU128>,
Option<NonZeroUsize>,
Option<NonZeroI8>,
Option<NonZeroI16>,
Option<NonZeroI32>,
Option<NonZeroI64>,
Option<NonZeroI128>,
Option<NonZeroIsize>,
);
macro_rules! is_bytewise_comparable_array_length {
($($n:literal),+ $(,)?) => {$(
// SAFETY: 数组在元素之间没有填充,所以如果元素是 `BytewiseEq`,那么整个数组也可以。
//
unsafe impl<T: BytewiseEq<U>, U> BytewiseEq<[U; $n]> for [T; $n] {}
)+};
}
// 令人沮丧的是,这不能成为 const - 泛型,因为它会出错: 特化 impl 重复参数 `N` 所以只对几个貌似常见的参数做。
//
//
is_bytewise_comparable_array_length!(0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64);