Commit 771f35c593

Tadeo Kondrak <me@tadeo.ca>
2020-08-26 21:38:58
Use less inefficient method of replacing TypeInfo.UnionField.enum_field
1 parent ac19ccf
lib/std/hash/auto_hash.zig
@@ -136,16 +136,10 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
 
         .Union => |info| {
             if (info.tag_type) |tag_type| {
-                const tag_info = @typeInfo(tag_type).Enum;
                 const tag = meta.activeTag(key);
                 const s = hash(hasher, tag, strat);
                 inline for (info.fields) |field| {
-                    comptime var tag_value: @TagType(tag_type) = undefined;
-                    inline for (tag_info.fields) |enum_field| {
-                        if (comptime mem.eql(u8, field.name, enum_field.name))
-                            tag_value = enum_field.value;
-                    }
-                    if (@enumToInt(tag) == tag_value) {
+                    if (@field(tag_type, field.name) == tag) {
                         hash(hasher, @field(key, field.name), strat);
                         // TODO use a labelled break when it does not crash the compiler. cf #2908
                         // break :blk;
lib/std/io/serialization.zig
@@ -149,7 +149,6 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
                 .Union => {
                     const info = @typeInfo(C).Union;
                     if (info.tag_type) |TagType| {
-                        const tag_info = @typeInfo(TagType).Enum;
                         //we avoid duplicate iteration over the enum tags
                         // by getting the int directly and casting it without
                         // safety. If it is bad, it will be caught anyway.
@@ -157,13 +156,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
                         const tag = try self.deserializeInt(TagInt);
 
                         inline for (info.fields) |field_info| {
-                            comptime var tag_value: TagInt = undefined;
-                            inline for (tag_info.fields) |enum_field_info| {
-                                if (comptime std.mem.eql(u8, field_info.name, enum_field_info.name)) {
-                                    tag_value = enum_field_info.value;
-                                }
-                            }
-                            if (tag_value == tag) {
+                            if (@enumToInt(@field(TagType, field_info.name)) == tag) {
                                 const name = field_info.name;
                                 const FieldType = field_info.field_type;
                                 ptr.* = @unionInit(C, name, undefined);
@@ -321,20 +314,13 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
                 .Union => {
                     const info = @typeInfo(T).Union;
                     if (info.tag_type) |TagType| {
-                        const tag_info = @typeInfo(TagType).Enum;
                         const active_tag = meta.activeTag(value);
                         try self.serialize(active_tag);
                         //This inline loop is necessary because active_tag is a runtime
                         // value, but @field requires a comptime value. Our alternative
                         // is to check each field for a match
                         inline for (info.fields) |field_info| {
-                            comptime var tag_value: @TagType(TagType) = undefined;
-                            inline for (tag_info.fields) |enum_field_info| {
-                                if (comptime std.mem.eql(u8, field_info.name, enum_field_info.name)) {
-                                    tag_value = enum_field_info.value;
-                                }
-                            }
-                            if (tag_value == @enumToInt(active_tag)) {
+                            if (@field(TagType, field_info.name) == active_tag) {
                                 const name = field_info.name;
                                 const FieldType = field_info.field_type;
                                 try self.serialize(@field(value, name));
lib/std/fmt.zig
@@ -395,17 +395,11 @@ pub fn formatType(
             }
             const info = @typeInfo(T).Union;
             if (info.tag_type) |UnionTagType| {
-                const tag_info = @typeInfo(UnionTagType).Enum;
                 try writer.writeAll("{ .");
                 try writer.writeAll(@tagName(@as(UnionTagType, value)));
                 try writer.writeAll(" = ");
                 inline for (info.fields) |u_field| {
-                    comptime var tag_value: @TagType(UnionTagType) = undefined;
-                    inline for (tag_info.fields) |e_field| {
-                        if (comptime mem.eql(u8, u_field.name, e_field.name))
-                            tag_value = e_field.value;
-                    }
-                    if (@enumToInt(@as(UnionTagType, value)) == tag_value) {
+                    if (value == @field(UnionTagType, u_field.name)) {
                         try formatType(@field(value, u_field.name), fmt, options, writer, max_depth - 1);
                     }
                 }
lib/std/json.zig
@@ -1612,14 +1612,8 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
         },
         .Union => |unionInfo| {
             if (unionInfo.tag_type) |UnionTagType| {
-                const tag_info = @typeInfo(UnionTagType).Enum;
                 inline for (unionInfo.fields) |u_field| {
-                    comptime var tag_value: @TagType(UnionTagType) = undefined;
-                    inline for (tag_info.fields) |e_field| {
-                        if (comptime mem.eql(u8, u_field.name, e_field.name))
-                            tag_value = e_field.value;
-                    }
-                    if (@enumToInt(@as(UnionTagType, value)) == tag_value) {
+                    if (value == @field(UnionTagType, u_field.name)) {
                         parseFree(u_field.field_type, @field(value, u_field.name), options);
                         break;
                     }
@@ -2463,14 +2457,8 @@ pub fn stringify(
 
             const info = @typeInfo(T).Union;
             if (info.tag_type) |UnionTagType| {
-                const tag_info = @typeInfo(UnionTagType).Enum;
                 inline for (info.fields) |u_field| {
-                    comptime var tag_value: @TagType(UnionTagType) = undefined;
-                    inline for (tag_info.fields) |e_field| {
-                        if (comptime mem.eql(u8, u_field.name, e_field.name))
-                            tag_value = e_field.value;
-                    }
-                    if (@enumToInt(@as(UnionTagType, value)) == tag_value) {
+                    if (value == @field(UnionTagType, u_field.name)) {
                         return try stringify(@field(value, u_field.name), options, out_stream);
                     }
                 }
lib/std/meta.zig
@@ -467,14 +467,8 @@ pub fn TagPayloadType(comptime U: type, tag: @TagType(U)) type {
     const info = @typeInfo(U).Union;
     const tag_info = @typeInfo(@TagType(U)).Enum;
 
-    comptime var name: []const u8 = undefined;
-    inline for (tag_info.fields) |enum_field_info| {
-        if (@enumToInt(tag) == enum_field_info.value)
-            name = enum_field_info.name;
-    }
-
     inline for (info.fields) |field_info| {
-        if (comptime mem.eql(u8, field_info.name, name))
+        if (comptime mem.eql(u8, field_info.name, @tagName(tag)))
             return field_info.field_type;
     }
 
@@ -518,14 +512,8 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool {
                 const tag_b = activeTag(b);
                 if (tag_a != tag_b) return false;
 
-                const tag_info = @typeInfo(Tag).Enum;
                 inline for (info.fields) |field_info| {
-                    comptime var tag_value: @TagType(Tag) = undefined;
-                    inline for (tag_info.fields) |enum_field_info| {
-                        if (comptime mem.eql(u8, field_info.name, enum_field_info.name))
-                            tag_value = enum_field_info.value;
-                    }
-                    if (tag_value == @enumToInt(tag_a)) {
+                    if (@field(Tag, field_info.name) == tag_a) {
                         return eql(@field(a, field_info.name), @field(b, field_info.name));
                     }
                 }