authorgravatar for indocomsoft@gmail.comJulius Putra Tanu Setiaji <indocomsoft@gmail.com> 2020-12-26 12:58:52+08:00
committergravatar for indocomsoft@gmail.comJulius Putra Tanu Setiaji <indocomsoft@gmail.com> 2020-12-26 12:58:52+08:00
logd9133b9ae056aa70bf6ed83c4d080022127d3397
treee9e0014da673a9bee42ec1794078928013c9272f
parent1df601d5810d42f94bfe28bcbd8e9d082161bff9

Also check whether structs contain slices


1 files changed, 38 insertions(+), 11 deletions(-)

lib/std/hash/auto_hash.zig+38-11
...@@ -169,21 +169,31 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {...@@ -169,21 +169,31 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
169 }169 }
170}170}
171171
172fn typeContainsSlice(comptime K: type) bool {
173 comptime {
174 if (meta.trait.isSlice(K)) {
175 return true;
176 }
177 if (meta.trait.is(.Struct)(K)) {
178 inline for (@typeInfo(K).Struct.fields) |field| {
179 if (typeContainsSlice(field.field_type)) {
180 return true;
181 }
182 }
183 }
184 return false;
185 }
186}
187
172/// Provides generic hashing for any eligible type.188/// Provides generic hashing for any eligible type.
173/// Only hashes `key` itself, pointers are not followed.189/// Only hashes `key` itself, pointers are not followed.
174/// Slices are rejected to avoid ambiguity on the user's intention.190/// Slices and structs containing slices are rejected to avoid ambiguity on the
191/// user's intention.
175pub fn autoHash(hasher: anytype, key: anytype) void {192pub fn autoHash(hasher: anytype, key: anytype) void {
176 const Key = @TypeOf(key);193 const Key = @TypeOf(key);
177 if (comptime meta.trait.isSlice(Key)) {194 if (comptime typeContainsSlice(Key)) {
178 comptime assert(@hasDecl(std, "StringHashMap")); // detect when the following message needs updated195 @compileError("std.auto_hash.autoHash does not allow slices or structs containing slices here (" ++ @typeName(Key) ++
179 const extra_help = if (Key == []const u8)196 ") because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead.");
180 " Consider std.StringHashMap for hashing the contents of []const u8."
181 else
182 "";
183
184 @compileError("std.auto_hash.autoHash does not allow slices (here " ++ @typeName(Key) ++
185 ") because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead." ++
186 extra_help);
187 }197 }
188198
189 hash(hasher, key, .Shallow);199 hash(hasher, key, .Shallow);
...@@ -220,6 +230,23 @@ fn testHashDeepRecursive(key: anytype) u64 {...@@ -220,6 +230,23 @@ fn testHashDeepRecursive(key: anytype) u64 {
220 return hasher.final();230 return hasher.final();
221}231}
222232
233test "typeContainsSlice" {
234 comptime {
235 testing.expect(!typeContainsSlice(@TagType(std.builtin.TypeInfo)));
236
237 testing.expect(typeContainsSlice([]const u8));
238 testing.expect(!typeContainsSlice(u8));
239 const A = struct { x: []const u8 };
240 const B = struct { a: A };
241 const C = struct { b: B };
242 const D = struct { x: u8 };
243 testing.expect(typeContainsSlice(A));
244 testing.expect(typeContainsSlice(B));
245 testing.expect(typeContainsSlice(C));
246 testing.expect(!typeContainsSlice(D));
247 }
248}
249
223test "hash pointer" {250test "hash pointer" {
224 const array = [_]u32{ 123, 123, 123 };251 const array = [_]u32{ 123, 123, 123 };
225 const a = &array[0];252 const a = &array[0];