Commit f9506e9155

Julius Putra Tanu Setiaji <indocomsoft@gmail.com>
2020-12-26 12:16:53
Handle unions in autoHash
1 parent d9133b9
Changed files (2)
lib
lib/std/hash/auto_hash.zig
@@ -181,18 +181,25 @@ fn typeContainsSlice(comptime K: type) bool {
                 }
             }
         }
+        if (meta.trait.is(.Union)(K)) {
+            inline for (@typeInfo(K).Union.fields) |field| {
+                if (typeContainsSlice(field.field_type)) {
+                    return true;
+                }
+            }
+        }
         return false;
     }
 }
 
 /// Provides generic hashing for any eligible type.
 /// Only hashes `key` itself, pointers are not followed.
-/// Slices and structs containing slices are rejected to avoid ambiguity on the
-/// user's intention.
+/// Slices as well as unions and structs containing slices are rejected to avoid
+/// ambiguity on the user's intention.
 pub fn autoHash(hasher: anytype, key: anytype) void {
     const Key = @TypeOf(key);
     if (comptime typeContainsSlice(Key)) {
-        @compileError("std.auto_hash.autoHash does not allow slices or structs containing slices here (" ++ @typeName(Key) ++
+        @compileError("std.auto_hash.autoHash does not allow slices as well as unions and structs containing slices here (" ++ @typeName(Key) ++
             ") because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead.");
     }
 
lib/std/meta/trait.zig
@@ -530,10 +530,53 @@ test "std.meta.trait.hasUniqueRepresentation" {
 
     testing.expect(hasUniqueRepresentation(TestStruct3));
 
+    const TestStruct4 = struct {
+        a: []const u8
+    };
+
+    testing.expect(!hasUniqueRepresentation(TestStruct4));
+
+    const TestStruct5 = struct {
+        a: TestStruct4
+    };
+
+    testing.expect(!hasUniqueRepresentation(TestStruct5));
+
+    const TestUnion1 = packed union {
+        a: u32,
+        b: u16,
+    };
+
+    testing.expect(!hasUniqueRepresentation(TestUnion1));
+
+    const TestUnion2 = extern union {
+        a: u32,
+        b: u16,
+    };
+
+    testing.expect(!hasUniqueRepresentation(TestUnion2));
+
+    const TestUnion3 = union {
+        a: u32,
+        b: u16,
+    };
+
+    testing.expect(!hasUniqueRepresentation(TestUnion3));
+
+    const TestUnion4 = union(enum) {
+        a: u32,
+        b: u16,
+    };
+
+    testing.expect(!hasUniqueRepresentation(TestUnion4));
+
     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));
     }
+
+    testing.expect(!hasUniqueRepresentation([]u8));
+    testing.expect(!hasUniqueRepresentation([]const u8));
 }