aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/std/hash/auto_hash.zig11
-rw-r--r--lib/std/meta/trait.zig24
2 files changed, 22 insertions, 13 deletions
diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig
index 2e707d5450..e42d55a0a9 100644
--- a/lib/std/hash/auto_hash.zig
+++ b/lib/std/hash/auto_hash.zig
@@ -99,7 +99,16 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
// Help the optimizer see that hashing an int is easy by inlining!
// TODO Check if the situation is better after #561 is resolved.
- .Int => @call(.{ .modifier = .always_inline }, hasher.update, .{std.mem.asBytes(&key)}),
+ .Int => {
+ if (comptime meta.trait.hasUniqueRepresentation(Key)) {
+ @call(.{ .modifier = .always_inline }, hasher.update, .{std.mem.asBytes(&key)});
+ } else {
+ // Take only the part containing the key value, the remaining
+ // bytes are undefined and must not be hashed!
+ const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Key), 8) catch unreachable;
+ @call(.{ .modifier = .always_inline }, hasher.update, .{std.mem.asBytes(&key)[0..byte_size]});
+ }
+ },
.Bool => hash(hasher, @boolToInt(key), strat),
.Enum => hash(hasher, @enumToInt(key), strat),
diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig
index eb294a857c..ae3b77b8cc 100644
--- a/lib/std/meta/trait.zig
+++ b/lib/std/meta/trait.zig
@@ -476,15 +476,19 @@ pub fn hasUniqueRepresentation(comptime T: type) bool {
else => return false, // TODO can we know if it's true for some of these types ?
.AnyFrame,
- .Bool,
.BoundFn,
.Enum,
.ErrorSet,
.Fn,
- .Int, // TODO check that it is still true
.Pointer,
=> return true,
+ .Bool => return false,
+
+ // The padding bits are undefined.
+ .Int => |info| return (info.bits % 8) == 0 and
+ (info.bits == 0 or std.math.isPowerOfTwo(info.bits)),
+
.Array => |info| return comptime hasUniqueRepresentation(info.child),
.Struct => |info| {
@@ -525,14 +529,10 @@ test "std.meta.trait.hasUniqueRepresentation" {
testing.expect(hasUniqueRepresentation(TestStruct3));
- testing.expect(hasUniqueRepresentation(i1));
- testing.expect(hasUniqueRepresentation(u2));
- testing.expect(hasUniqueRepresentation(i3));
- testing.expect(hasUniqueRepresentation(u4));
- testing.expect(hasUniqueRepresentation(i5));
- testing.expect(hasUniqueRepresentation(u6));
- testing.expect(hasUniqueRepresentation(i7));
- testing.expect(hasUniqueRepresentation(u8));
- testing.expect(hasUniqueRepresentation(i9));
- testing.expect(hasUniqueRepresentation(u10));
+ inline for ([_]type{ i0, u8, i16, u32, i64 }) |T| {
+ testing.expect(hasUniqueRepresentation(T));
+ }
+ inline for ([_]type{ i1, u9, i17, u33, i24 }) |T| {
+ testing.expect(!hasUniqueRepresentation(T));
+ }
}