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)); + } }