| author | |
| committer | |
| log | 501a2350ab804f3e5d4253826bcdfb7a3f5d92fb |
| tree | dd98936b4c0578f027d7ce82f8b4f2353c4184d2 |
| parent | 15f7a477d04b0a4a20c9a4489ea819e95939315b |
4 files changed, 99 insertions(+), 2 deletions(-)
src/Sema.zig+4-2| ... | ... | @@ -20888,7 +20888,7 @@ fn zirReify( |
| 20888 | 20888 | enum_field_names[i] = field_name; |
| 20889 | 20889 | } |
| 20890 | 20890 | |
| 20891 | if (explicit_tags_seen.len > 0) { | |
| 20891 | if (enum_tag_ty != .none) { | |
| 20892 | 20892 | const tag_info = ip.indexToKey(enum_tag_ty).enum_type; |
| 20893 | 20893 | const enum_index = tag_info.nameIndex(ip, field_name) orelse { |
| 20894 | 20894 | const msg = msg: { |
| ... | ... | @@ -20902,6 +20902,7 @@ fn zirReify( |
| 20902 | 20902 | }; |
| 20903 | 20903 | return sema.failWithOwnedErrorMsg(block, msg); |
| 20904 | 20904 | }; |
| 20905 | assert(explicit_tags_seen.len == tag_info.names.len); | |
| 20905 | 20906 | // No check for duplicate because the check already happened in order |
| 20906 | 20907 | // to create the enum type in the first place. |
| 20907 | 20908 | assert(!explicit_tags_seen[enum_index]); |
| ... | ... | @@ -20967,13 +20968,14 @@ fn zirReify( |
| 20967 | 20968 | } |
| 20968 | 20969 | } |
| 20969 | 20970 | |
| 20970 | if (explicit_tags_seen.len > 0) { | |
| 20971 | if (enum_tag_ty != .none) { | |
| 20971 | 20972 | const tag_info = ip.indexToKey(enum_tag_ty).enum_type; |
| 20972 | 20973 | if (tag_info.names.len > fields_len) { |
| 20973 | 20974 | const msg = msg: { |
| 20974 | 20975 | const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{}); |
| 20975 | 20976 | errdefer msg.destroy(gpa); |
| 20976 | 20977 | |
| 20978 | assert(explicit_tags_seen.len == tag_info.names.len); | |
| 20977 | 20979 | for (tag_info.names.get(ip), 0..) |field_name, field_index| { |
| 20978 | 20980 | if (explicit_tags_seen[field_index]) continue; |
| 20979 | 20981 | try sema.addFieldErrNote(Type.fromInterned(enum_tag_ty), field_index, msg, "field '{}' missing, declared here", .{ |
test/behavior/type.zig+33| ... | ... | @@ -482,6 +482,39 @@ test "Type.Union from regular enum" { |
| 482 | 482 | _ = @typeInfo(T).Union; |
| 483 | 483 | } |
| 484 | 484 | |
| 485 | test "Type.Union from empty regular enum" { | |
| 486 | const E = enum {}; | |
| 487 | const U = @Type(.{ | |
| 488 | .Union = .{ | |
| 489 | .layout = .Auto, | |
| 490 | .tag_type = E, | |
| 491 | .fields = &.{}, | |
| 492 | .decls = &.{}, | |
| 493 | }, | |
| 494 | }); | |
| 495 | try testing.expectEqual(@sizeOf(U), 0); | |
| 496 | } | |
| 497 | ||
| 498 | test "Type.Union from empty Type.Enum" { | |
| 499 | const E = @Type(.{ | |
| 500 | .Enum = .{ | |
| 501 | .tag_type = u0, | |
| 502 | .fields = &.{}, | |
| 503 | .decls = &.{}, | |
| 504 | .is_exhaustive = true, | |
| 505 | }, | |
| 506 | }); | |
| 507 | const U = @Type(.{ | |
| 508 | .Union = .{ | |
| 509 | .layout = .Auto, | |
| 510 | .tag_type = E, | |
| 511 | .fields = &.{}, | |
| 512 | .decls = &.{}, | |
| 513 | }, | |
| 514 | }); | |
| 515 | try testing.expectEqual(@sizeOf(U), 0); | |
| 516 | } | |
| 517 | ||
| 485 | 518 | test "Type.Fn" { |
| 486 | 519 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 487 | 520 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | const Tag = @Type(.{ | |
| 2 | .Enum = .{ | |
| 3 | .tag_type = u0, | |
| 4 | .fields = &.{}, | |
| 5 | .decls = &.{}, | |
| 6 | .is_exhaustive = true, | |
| 7 | }, | |
| 8 | }); | |
| 9 | const Tagged = @Type(.{ | |
| 10 | .Union = .{ | |
| 11 | .layout = .Auto, | |
| 12 | .tag_type = Tag, | |
| 13 | .fields = &.{ | |
| 14 | .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, | |
| 15 | .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, | |
| 16 | }, | |
| 17 | .decls = &.{}, | |
| 18 | }, | |
| 19 | }); | |
| 20 | export fn entry() void { | |
| 21 | const tagged: Tagged = undefined; | |
| 22 | _ = tagged; | |
| 23 | } | |
| 24 | ||
| 25 | // error | |
| 26 | // backend=stage2 | |
| 27 | // target=native | |
| 28 | // | |
| 29 | // :9:16: error: no field named 'signed' in enum 'tmp.Tag' | |
| 30 | // :1:13: note: enum declared here |
test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | const Tag = @Type(.{ | |
| 2 | .Enum = .{ | |
| 3 | .tag_type = u1, | |
| 4 | .fields = &.{ | |
| 5 | .{ .name = "signed", .value = 0 }, | |
| 6 | .{ .name = "unsigned", .value = 1 }, | |
| 7 | }, | |
| 8 | .decls = &.{}, | |
| 9 | .is_exhaustive = true, | |
| 10 | }, | |
| 11 | }); | |
| 12 | const Tagged = @Type(.{ | |
| 13 | .Union = .{ | |
| 14 | .layout = .Auto, | |
| 15 | .tag_type = Tag, | |
| 16 | .fields = &.{}, | |
| 17 | .decls = &.{}, | |
| 18 | }, | |
| 19 | }); | |
| 20 | export fn entry() void { | |
| 21 | const tagged: Tagged = undefined; | |
| 22 | _ = tagged; | |
| 23 | } | |
| 24 | ||
| 25 | // error | |
| 26 | // backend=stage2 | |
| 27 | // target=native | |
| 28 | // | |
| 29 | // :12:16: error: enum field(s) missing in union | |
| 30 | // :1:13: note: field 'signed' missing, declared here | |
| 31 | // :1:13: note: field 'unsigned' missing, declared here | |
| 32 | // :1:13: note: enum declared here |