mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
Merge pull request #7483 from indocomsoft/autohashmap
Make hasUniqueRepresentation false for slices
This commit is contained in:
commit
8aab1e2e8a
@ -169,21 +169,38 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn typeContainsSlice(comptime K: type) bool {
|
||||
comptime {
|
||||
if (meta.trait.isSlice(K)) {
|
||||
return true;
|
||||
}
|
||||
if (meta.trait.is(.Struct)(K)) {
|
||||
inline for (@typeInfo(K).Struct.fields) |field| {
|
||||
if (typeContainsSlice(field.field_type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 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 meta.trait.isSlice(Key)) {
|
||||
comptime assert(@hasDecl(std, "StringHashMap")); // detect when the following message needs updated
|
||||
const extra_help = if (Key == []const u8)
|
||||
" Consider std.StringHashMap for hashing the contents of []const u8."
|
||||
else
|
||||
"";
|
||||
|
||||
@compileError("std.auto_hash.autoHash does not allow slices (here " ++ @typeName(Key) ++
|
||||
") because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead." ++
|
||||
extra_help);
|
||||
if (comptime typeContainsSlice(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.");
|
||||
}
|
||||
|
||||
hash(hasher, key, .Shallow);
|
||||
@ -220,6 +237,23 @@ fn testHashDeepRecursive(key: anytype) u64 {
|
||||
return hasher.final();
|
||||
}
|
||||
|
||||
test "typeContainsSlice" {
|
||||
comptime {
|
||||
testing.expect(!typeContainsSlice(@TagType(std.builtin.TypeInfo)));
|
||||
|
||||
testing.expect(typeContainsSlice([]const u8));
|
||||
testing.expect(!typeContainsSlice(u8));
|
||||
const A = struct { x: []const u8 };
|
||||
const B = struct { a: A };
|
||||
const C = struct { b: B };
|
||||
const D = struct { x: u8 };
|
||||
testing.expect(typeContainsSlice(A));
|
||||
testing.expect(typeContainsSlice(B));
|
||||
testing.expect(typeContainsSlice(C));
|
||||
testing.expect(!typeContainsSlice(D));
|
||||
}
|
||||
}
|
||||
|
||||
test "hash pointer" {
|
||||
const array = [_]u32{ 123, 123, 123 };
|
||||
const a = &array[0];
|
||||
|
||||
@ -480,7 +480,6 @@ pub fn hasUniqueRepresentation(comptime T: type) bool {
|
||||
.Enum,
|
||||
.ErrorSet,
|
||||
.Fn,
|
||||
.Pointer,
|
||||
=> return true,
|
||||
|
||||
.Bool => return false,
|
||||
@ -489,6 +488,8 @@ pub fn hasUniqueRepresentation(comptime T: type) bool {
|
||||
.Int => |info| return (info.bits % 8) == 0 and
|
||||
(info.bits == 0 or std.math.isPowerOfTwo(info.bits)),
|
||||
|
||||
.Pointer => |info| return info.size != .Slice,
|
||||
|
||||
.Array => |info| return comptime hasUniqueRepresentation(info.child),
|
||||
|
||||
.Struct => |info| {
|
||||
@ -529,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));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user