···29}
3031/// An owned pair of [`Token`]s.
32-#[derive(Copy, Clone, Debug)]
33// Alignment repr necessary to allow LLVM to better output
34-// optimized codegen for `to_bits`, `PartialEq`
35// Prior art taken from my contribution to Bevy:
36// https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/entity/mod.rs#L309
37#[repr(C, align(16))]
38pub struct TokenPair {
39 // Do not reorder the fields here. The ordering is explicitly used by repr(C)
40- // to make this struct equivalent to a u64.
41 #[cfg(target_endian = "little")]
42 pub left: Token,
43 pub right: Token,
···45 pub left: Token,
46}
4748-// By not short-circuiting in comparisons, we get better codegen.
49-// See <https://github.com/rust-lang/rust/issues/117800>
50-impl PartialEq for TokenPair {
51- #[inline(always)]
52- fn eq(&self, other: &TokenPair) -> bool {
53- // By using `to_bits`, the codegen can be optimized out even
54- // further potentially. Relies on the correct alignment/field
55- // order of `TokenPair`.
56- self.to_bits() == other.to_bits()
57- }
58-}
59-60-impl Eq for TokenPair {}
61-62impl core::hash::Hash for TokenPair {
63- #[inline(always)]
64 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
65- self.to_bits().hash(state);
66 }
67}
68···73 }
7475 #[inline(always)]
76- fn to_bits(self) -> u128 {
77- (self.left.0.digest().hash() as u128) | ((self.right.0.digest().hash() as u128) << 64)
0000078 }
79}
80
···29}
3031/// An owned pair of [`Token`]s.
32+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
33// Alignment repr necessary to allow LLVM to better output
034// Prior art taken from my contribution to Bevy:
35// https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/entity/mod.rs#L309
36#[repr(C, align(16))]
37pub struct TokenPair {
38 // Do not reorder the fields here. The ordering is explicitly used by repr(C)
39+ // to make this struct equivalent to a u128.
40 #[cfg(target_endian = "little")]
41 pub left: Token,
42 pub right: Token,
···44 pub left: Token,
45}
460000000000000047impl core::hash::Hash for TokenPair {
48+ #[inline]
49 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
50+ self.double_hash().hash(state);
51 }
52}
53···58 }
5960 #[inline(always)]
61+ fn double_hash(&self) -> u64 {
62+ self.right
63+ .0
64+ .digest()
65+ .hash()
66+ .wrapping_add(self.left.0.digest().hash())
67+ .rotate_left(5)
68 }
69}
70