Commit e2e0b6272b
Changed files (2)
src/value.zig
@@ -565,7 +565,7 @@ pub const Value = extern union {
.int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),
.int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),
.int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(),
- .int_big_negative => return self.cast(Payload.IntBigPositive).?.asBigInt(),
+ .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt(),
}
}
@@ -1255,7 +1255,6 @@ pub const Value = extern union {
pub fn hash(self: Value) u64 {
var hasher = std.hash.Wyhash.init(0);
- std.hash.autoHash(&hasher, self.tag());
switch (self.tag()) {
.u8_type,
@@ -1321,18 +1320,19 @@ pub const Value = extern union {
}
},
- .undef,
- .zero,
- .one,
- .void_value,
- .unreachable_value,
.empty_struct_value,
.empty_array,
- .null_value,
- .bool_true,
- .bool_false,
=> {},
+ .undef,
+ .null_value,
+ .void_value,
+ .unreachable_value,
+ => std.hash.autoHash(&hasher, self.tag()),
+
+ .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)),
+ .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),
+
.float_16, .float_32, .float_64, .float_128 => {},
.enum_literal, .bytes => {
const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
@@ -1357,9 +1357,18 @@ pub const Value = extern union {
.int_big_positive, .int_big_negative => {
var space: BigIntSpace = undefined;
const big = self.toBigInt(&space);
- std.hash.autoHash(&hasher, big.positive);
- for (big.limbs) |limb| {
- std.hash.autoHash(&hasher, limb);
+ if (big.limbs.len == 1) {
+ // handle like {u,i}64 to ensure same hash as with Int{i,u}64
+ if (big.positive) {
+ std.hash.autoHash(&hasher, @as(u64, big.limbs[0]));
+ } else {
+ std.hash.autoHash(&hasher, @as(u64, @bitCast(usize, -@bitCast(isize, big.limbs[0]))));
+ }
+ } else {
+ std.hash.autoHash(&hasher, big.positive);
+ for (big.limbs) |limb| {
+ std.hash.autoHash(&hasher, limb);
+ }
}
},
.elem_ptr => {
@@ -1741,7 +1750,7 @@ pub const Value = extern union {
.@"error",
.empty_struct_value,
.null_value,
- => false,
+ => false,
.undef => unreachable,
.unreachable_value => unreachable,
@@ -1882,3 +1891,18 @@ pub const Value = extern union {
limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
};
};
+
+test "hash same value different representation" {
+ const zero_1 = Value.initTag(.zero);
+ var payload_1 = Value.Payload.Int_u64{ .int = 0 };
+ const zero_2 = Value.initPayload(&payload_1.base);
+ std.testing.expectEqual(zero_1.hash(), zero_2.hash());
+
+ var payload_2 = Value.Payload.Int_i64{ .int = 0 };
+ const zero_3 = Value.initPayload(&payload_2.base);
+ std.testing.expectEqual(zero_2.hash(), zero_3.hash());
+
+ var payload_3 = Value.Payload.IntBigNegative{ .limbs = &[_]std.math.big.Limb{0} };
+ const zero_4 = Value.initPayload(&payload_3.base);
+ std.testing.expectEqual(zero_3.hash(), zero_4.hash());
+}
src/zir_sema.zig
@@ -1253,6 +1253,12 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In
return mod.constNoReturn(scope, inst.base.src);
}
+ if (inst.positionals.cases.len == 0) {
+ // no cases just analyze else_branch
+ try analyzeBody(mod, scope, inst.positionals.else_body);
+ return mod.constNoReturn(scope, inst.base.src);
+ }
+
const parent_block = try mod.requireRuntimeBlock(scope, inst.base.src);
const cases = try parent_block.arena.alloc(Inst.SwitchBr.Case, inst.positionals.cases.len);