| ... | @@ -565,7 +565,7 @@ pub const Value = extern union { | ... | @@ -565,7 +565,7 @@ pub const Value = extern union { |
| 565 | .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(), | 565 | .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(), |
| 566 | .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(), | 566 | .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(), |
| 567 | .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(), | 567 | .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(), |
| 568 | .int_big_negative => return self.cast(Payload.IntBigPositive).?.asBigInt(), | 568 | .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt(), |
| 569 | } | 569 | } |
| 570 | } | 570 | } |
| 571 | | 571 | |
| ... | @@ -1255,7 +1255,6 @@ pub const Value = extern union { | ... | @@ -1255,7 +1255,6 @@ pub const Value = extern union { |
| 1255 | | 1255 | |
| 1256 | pub fn hash(self: Value) u64 { | 1256 | pub fn hash(self: Value) u64 { |
| 1257 | var hasher = std.hash.Wyhash.init(0); | 1257 | var hasher = std.hash.Wyhash.init(0); |
| 1258 | std.hash.autoHash(&hasher, self.tag()); | | |
| 1259 | | 1258 | |
| 1260 | switch (self.tag()) { | 1259 | switch (self.tag()) { |
| 1261 | .u8_type, | 1260 | .u8_type, |
| ... | @@ -1321,18 +1320,19 @@ pub const Value = extern union { | ... | @@ -1321,18 +1320,19 @@ pub const Value = extern union { |
| 1321 | } | 1320 | } |
| 1322 | }, | 1321 | }, |
| 1323 | | 1322 | |
| 1324 | .undef, | | |
| 1325 | .zero, | | |
| 1326 | .one, | | |
| 1327 | .void_value, | | |
| 1328 | .unreachable_value, | | |
| 1329 | .empty_struct_value, | 1323 | .empty_struct_value, |
| 1330 | .empty_array, | 1324 | .empty_array, |
| 1331 | .null_value, | | |
| 1332 | .bool_true, | | |
| 1333 | .bool_false, | | |
| 1334 | => {}, | 1325 | => {}, |
| 1335 | | 1326 | |
| | 1327 | .undef, |
| | 1328 | .null_value, |
| | 1329 | .void_value, |
| | 1330 | .unreachable_value, |
| | 1331 | => std.hash.autoHash(&hasher, self.tag()), |
| | 1332 | |
| | 1333 | .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)), |
| | 1334 | .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)), |
| | 1335 | |
| 1336 | .float_16, .float_32, .float_64, .float_128 => {}, | 1336 | .float_16, .float_32, .float_64, .float_128 => {}, |
| 1337 | .enum_literal, .bytes => { | 1337 | .enum_literal, .bytes => { |
| 1338 | const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise); | 1338 | const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise); |
| ... | @@ -1357,9 +1357,18 @@ pub const Value = extern union { | ... | @@ -1357,9 +1357,18 @@ pub const Value = extern union { |
| 1357 | .int_big_positive, .int_big_negative => { | 1357 | .int_big_positive, .int_big_negative => { |
| 1358 | var space: BigIntSpace = undefined; | 1358 | var space: BigIntSpace = undefined; |
| 1359 | const big = self.toBigInt(&space); | 1359 | const big = self.toBigInt(&space); |
| 1360 | std.hash.autoHash(&hasher, big.positive); | 1360 | if (big.limbs.len == 1) { |
| 1361 | for (big.limbs) |limb| { | 1361 | // handle like {u,i}64 to ensure same hash as with Int{i,u}64 |
| 1362 | std.hash.autoHash(&hasher, limb); | 1362 | if (big.positive) { |
| | 1363 | std.hash.autoHash(&hasher, @as(u64, big.limbs[0])); |
| | 1364 | } else { |
| | 1365 | std.hash.autoHash(&hasher, @as(u64, @bitCast(usize, -@bitCast(isize, big.limbs[0])))); |
| | 1366 | } |
| | 1367 | } else { |
| | 1368 | std.hash.autoHash(&hasher, big.positive); |
| | 1369 | for (big.limbs) |limb| { |
| | 1370 | std.hash.autoHash(&hasher, limb); |
| | 1371 | } |
| 1363 | } | 1372 | } |
| 1364 | }, | 1373 | }, |
| 1365 | .elem_ptr => { | 1374 | .elem_ptr => { |
| ... | @@ -1741,7 +1750,7 @@ pub const Value = extern union { | ... | @@ -1741,7 +1750,7 @@ pub const Value = extern union { |
| 1741 | .@"error", | 1750 | .@"error", |
| 1742 | .empty_struct_value, | 1751 | .empty_struct_value, |
| 1743 | .null_value, | 1752 | .null_value, |
| 1744 | => false, | 1753 | => false, |
| 1745 | | 1754 | |
| 1746 | .undef => unreachable, | 1755 | .undef => unreachable, |
| 1747 | .unreachable_value => unreachable, | 1756 | .unreachable_value => unreachable, |
| ... | @@ -1882,3 +1891,18 @@ pub const Value = extern union { | ... | @@ -1882,3 +1891,18 @@ pub const Value = extern union { |
| 1882 | limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb, | 1891 | limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb, |
| 1883 | }; | 1892 | }; |
| 1884 | }; | 1893 | }; |
| | 1894 | |
| | 1895 | test "hash same value different representation" { |
| | 1896 | const zero_1 = Value.initTag(.zero); |
| | 1897 | var payload_1 = Value.Payload.Int_u64{ .int = 0 }; |
| | 1898 | const zero_2 = Value.initPayload(&payload_1.base); |
| | 1899 | std.testing.expectEqual(zero_1.hash(), zero_2.hash()); |
| | 1900 | |
| | 1901 | var payload_2 = Value.Payload.Int_i64{ .int = 0 }; |
| | 1902 | const zero_3 = Value.initPayload(&payload_2.base); |
| | 1903 | std.testing.expectEqual(zero_2.hash(), zero_3.hash()); |
| | 1904 | |
| | 1905 | var payload_3 = Value.Payload.IntBigNegative{ .limbs = &[_]std.math.big.Limb{0} }; |
| | 1906 | const zero_4 = Value.initPayload(&payload_3.base); |
| | 1907 | std.testing.expectEqual(zero_3.hash(), zero_4.hash()); |
| | 1908 | } |