| author | |
| committer | |
| log | ac19ccf5955488a43b29ea13675c33426aada430 |
| tree | 267b3685db72d1a4b568404649ab31deeddbc329 |
| parent | ff2ed966bb37079217ee7a7753cb63a763b8c3b5 |
| signature | Commit is signed but in an unrecognized format. |
5 files changed, 64 insertions(+), 13 deletions(-)
lib/std/fmt.zig+7-1| ... | ... | @@ -395,11 +395,17 @@ pub fn formatType( |
| 395 | 395 | } |
| 396 | 396 | const info = @typeInfo(T).Union; |
| 397 | 397 | if (info.tag_type) |UnionTagType| { |
| 398 | const tag_info = @typeInfo(UnionTagType).Enum; | |
| 398 | 399 | try writer.writeAll("{ ."); |
| 399 | 400 | try writer.writeAll(@tagName(@as(UnionTagType, value))); |
| 400 | 401 | try writer.writeAll(" = "); |
| 401 | 402 | inline for (info.fields) |u_field| { |
| 402 | if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { | |
| 403 | comptime var tag_value: @TagType(UnionTagType) = undefined; | |
| 404 | inline for (tag_info.fields) |e_field| { | |
| 405 | if (comptime mem.eql(u8, u_field.name, e_field.name)) | |
| 406 | tag_value = e_field.value; | |
| 407 | } | |
| 408 | if (@enumToInt(@as(UnionTagType, value)) == tag_value) { | |
| 403 | 409 | try formatType(@field(value, u_field.name), fmt, options, writer, max_depth - 1); |
| 404 | 410 | } |
| 405 | 411 | } |
lib/std/hash/auto_hash.zig+8-3| ... | ... | @@ -136,12 +136,17 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void { |
| 136 | 136 | |
| 137 | 137 | .Union => |info| { |
| 138 | 138 | if (info.tag_type) |tag_type| { |
| 139 | const tag_info = @typeInfo(tag_type).Enum; | |
| 139 | 140 | const tag = meta.activeTag(key); |
| 140 | 141 | const s = hash(hasher, tag, strat); |
| 141 | 142 | inline for (info.fields) |field| { |
| 142 | const enum_field = field.enum_field.?; | |
| 143 | if (enum_field.value == @enumToInt(tag)) { | |
| 144 | hash(hasher, @field(key, enum_field.name), strat); | |
| 143 | comptime var tag_value: @TagType(tag_type) = undefined; | |
| 144 | inline for (tag_info.fields) |enum_field| { | |
| 145 | if (comptime mem.eql(u8, field.name, enum_field.name)) | |
| 146 | tag_value = enum_field.value; | |
| 147 | } | |
| 148 | if (@enumToInt(tag) == tag_value) { | |
| 149 | hash(hasher, @field(key, field.name), strat); | |
| 145 | 150 | // TODO use a labelled break when it does not crash the compiler. cf #2908 |
| 146 | 151 | // break :blk; |
| 147 | 152 | return; |
lib/std/io/serialization.zig+16-2| ... | ... | @@ -149,6 +149,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, |
| 149 | 149 | .Union => { |
| 150 | 150 | const info = @typeInfo(C).Union; |
| 151 | 151 | if (info.tag_type) |TagType| { |
| 152 | const tag_info = @typeInfo(TagType).Enum; | |
| 152 | 153 | //we avoid duplicate iteration over the enum tags |
| 153 | 154 | // by getting the int directly and casting it without |
| 154 | 155 | // safety. If it is bad, it will be caught anyway. |
| ... | ... | @@ -156,7 +157,13 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, |
| 156 | 157 | const tag = try self.deserializeInt(TagInt); |
| 157 | 158 | |
| 158 | 159 | inline for (info.fields) |field_info| { |
| 159 | if (field_info.enum_field.?.value == tag) { | |
| 160 | comptime var tag_value: TagInt = undefined; | |
| 161 | inline for (tag_info.fields) |enum_field_info| { | |
| 162 | if (comptime std.mem.eql(u8, field_info.name, enum_field_info.name)) { | |
| 163 | tag_value = enum_field_info.value; | |
| 164 | } | |
| 165 | } | |
| 166 | if (tag_value == tag) { | |
| 160 | 167 | const name = field_info.name; |
| 161 | 168 | const FieldType = field_info.field_type; |
| 162 | 169 | ptr.* = @unionInit(C, name, undefined); |
| ... | ... | @@ -314,13 +321,20 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co |
| 314 | 321 | .Union => { |
| 315 | 322 | const info = @typeInfo(T).Union; |
| 316 | 323 | if (info.tag_type) |TagType| { |
| 324 | const tag_info = @typeInfo(TagType).Enum; | |
| 317 | 325 | const active_tag = meta.activeTag(value); |
| 318 | 326 | try self.serialize(active_tag); |
| 319 | 327 | //This inline loop is necessary because active_tag is a runtime |
| 320 | 328 | // value, but @field requires a comptime value. Our alternative |
| 321 | 329 | // is to check each field for a match |
| 322 | 330 | inline for (info.fields) |field_info| { |
| 323 | if (field_info.enum_field.?.value == @enumToInt(active_tag)) { | |
| 331 | comptime var tag_value: @TagType(TagType) = undefined; | |
| 332 | inline for (tag_info.fields) |enum_field_info| { | |
| 333 | if (comptime std.mem.eql(u8, field_info.name, enum_field_info.name)) { | |
| 334 | tag_value = enum_field_info.value; | |
| 335 | } | |
| 336 | } | |
| 337 | if (tag_value == @enumToInt(active_tag)) { | |
| 324 | 338 | const name = field_info.name; |
| 325 | 339 | const FieldType = field_info.field_type; |
| 326 | 340 | try self.serialize(@field(value, name)); |
lib/std/json.zig+14-2| ... | ... | @@ -1612,8 +1612,14 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void { |
| 1612 | 1612 | }, |
| 1613 | 1613 | .Union => |unionInfo| { |
| 1614 | 1614 | if (unionInfo.tag_type) |UnionTagType| { |
| 1615 | const tag_info = @typeInfo(UnionTagType).Enum; | |
| 1615 | 1616 | inline for (unionInfo.fields) |u_field| { |
| 1616 | if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { | |
| 1617 | comptime var tag_value: @TagType(UnionTagType) = undefined; | |
| 1618 | inline for (tag_info.fields) |e_field| { | |
| 1619 | if (comptime mem.eql(u8, u_field.name, e_field.name)) | |
| 1620 | tag_value = e_field.value; | |
| 1621 | } | |
| 1622 | if (@enumToInt(@as(UnionTagType, value)) == tag_value) { | |
| 1617 | 1623 | parseFree(u_field.field_type, @field(value, u_field.name), options); |
| 1618 | 1624 | break; |
| 1619 | 1625 | } |
| ... | ... | @@ -2457,8 +2463,14 @@ pub fn stringify( |
| 2457 | 2463 | |
| 2458 | 2464 | const info = @typeInfo(T).Union; |
| 2459 | 2465 | if (info.tag_type) |UnionTagType| { |
| 2466 | const tag_info = @typeInfo(UnionTagType).Enum; | |
| 2460 | 2467 | inline for (info.fields) |u_field| { |
| 2461 | if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { | |
| 2468 | comptime var tag_value: @TagType(UnionTagType) = undefined; | |
| 2469 | inline for (tag_info.fields) |e_field| { | |
| 2470 | if (comptime mem.eql(u8, u_field.name, e_field.name)) | |
| 2471 | tag_value = e_field.value; | |
| 2472 | } | |
| 2473 | if (@enumToInt(@as(UnionTagType, value)) == tag_value) { | |
| 2462 | 2474 | return try stringify(@field(value, u_field.name), options, out_stream); |
| 2463 | 2475 | } |
| 2464 | 2476 | } |
lib/std/meta.zig+19-5| ... | ... | @@ -465,10 +465,19 @@ pub fn TagPayloadType(comptime U: type, tag: @TagType(U)) type { |
| 465 | 465 | testing.expect(trait.is(.Union)(U)); |
| 466 | 466 | |
| 467 | 467 | const info = @typeInfo(U).Union; |
| 468 | const tag_info = @typeInfo(@TagType(U)).Enum; | |
| 469 | ||
| 470 | comptime var name: []const u8 = undefined; | |
| 471 | inline for (tag_info.fields) |enum_field_info| { | |
| 472 | if (@enumToInt(tag) == enum_field_info.value) | |
| 473 | name = enum_field_info.name; | |
| 474 | } | |
| 468 | 475 | |
| 469 | 476 | inline for (info.fields) |field_info| { |
| 470 | if (field_info.enum_field.?.value == @enumToInt(tag)) return field_info.field_type; | |
| 477 | if (comptime mem.eql(u8, field_info.name, name)) | |
| 478 | return field_info.field_type; | |
| 471 | 479 | } |
| 480 | ||
| 472 | 481 | unreachable; |
| 473 | 482 | } |
| 474 | 483 | |
| ... | ... | @@ -504,15 +513,20 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool { |
| 504 | 513 | } |
| 505 | 514 | }, |
| 506 | 515 | .Union => |info| { |
| 507 | if (info.tag_type) |_| { | |
| 516 | if (info.tag_type) |Tag| { | |
| 508 | 517 | const tag_a = activeTag(a); |
| 509 | 518 | const tag_b = activeTag(b); |
| 510 | 519 | if (tag_a != tag_b) return false; |
| 511 | 520 | |
| 521 | const tag_info = @typeInfo(Tag).Enum; | |
| 512 | 522 | inline for (info.fields) |field_info| { |
| 513 | const enum_field = field_info.enum_field.?; | |
| 514 | if (enum_field.value == @enumToInt(tag_a)) { | |
| 515 | return eql(@field(a, enum_field.name), @field(b, enum_field.name)); | |
| 523 | comptime var tag_value: @TagType(Tag) = undefined; | |
| 524 | inline for (tag_info.fields) |enum_field_info| { | |
| 525 | if (comptime mem.eql(u8, field_info.name, enum_field_info.name)) | |
| 526 | tag_value = enum_field_info.value; | |
| 527 | } | |
| 528 | if (tag_value == @enumToInt(tag_a)) { | |
| 529 | return eql(@field(a, field_info.name), @field(b, field_info.name)); | |
| 516 | 530 | } |
| 517 | 531 | } |
| 518 | 532 | return false; |